From f1a17a0a51826f00e08a818d0fd35da022bce1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 4 Jan 2009 17:55:59 +0100 Subject: Implement new features for vdr-xine-0.9.0. --- include/xine.h | 1 + include/xine/vdr.h | 123 ++++++++++++++++++--------- src/vdr/input_vdr.c | 241 ++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 270 insertions(+), 95 deletions(-) diff --git a/include/xine.h b/include/xine.h index d92c48077..c6d240d5e 100644 --- a/include/xine.h +++ b/include/xine.h @@ -1731,6 +1731,7 @@ void xine_config_reset (xine_t *self) XINE_PROTECTED; #define XINE_EVENT_VDR_SELECTAUDIO 352 #define XINE_EVENT_VDR_TRICKSPEEDMODE 353 #define XINE_EVENT_VDR_PLUGINSTARTED 354 +#define XINE_EVENT_VDR_DISCONTINUITY 355 /* events generated from post plugins */ #define XINE_EVENT_POST_TVTIME_FILMMODE_CHANGE 400 diff --git a/include/xine/vdr.h b/include/xine/vdr.h index a2a3e800f..392d1e404 100644 --- a/include/xine/vdr.h +++ b/include/xine/vdr.h @@ -22,7 +22,7 @@ #define __VDR_H -#define XINE_VDR_VERSION 802 +#define XINE_VDR_VERSION 900 enum funcs @@ -60,6 +60,8 @@ enum funcs , func_select_audio , func_trick_speed_mode , func_get_version + , func_discontinuity + , func_query_capabilities }; enum keys @@ -154,6 +156,8 @@ typedef struct __attribute__((packed)) data_osd_new_s int16_t y; uint16_t width; uint16_t height; + uint16_t w_ref; + uint16_t h_ref; } data_osd_new_t; @@ -226,6 +230,7 @@ typedef struct __attribute__((packed)) data_osd_draw_bitmap_s int16_t y; uint16_t width; uint16_t height; + uint8_t argb; } data_osd_draw_bitmap_t; @@ -422,6 +427,11 @@ typedef struct __attribute__((packed)) result_grab_image_s int32_t height; int32_t ratio; int32_t format; + int32_t interlaced; + int32_t crop_left; + int32_t crop_right; + int32_t crop_top; + int32_t crop_bottom; } result_grab_image_t; @@ -550,39 +560,72 @@ data_trick_speed_mode_t; +typedef struct __attribute__((packed)) event_discontinuity_s +{ + event_header_t header; + + int32_t type; +} +event_discontinuity_t; + + + +typedef struct __attribute__((packed)) data_query_capabilities_s +{ + data_header_t header; +} +data_query_capabilities_t; + + + +typedef struct __attribute__((packed)) result_query_capabilities_s +{ + result_header_t header; + + uint8_t osd_max_num_windows; + uint8_t osd_palette_max_depth; + uint8_t osd_palette_is_shared; + uint8_t osd_supports_argb_layer; + uint8_t osd_supports_custom_extent; +} +result_query_capabilities_t; + + + typedef union __attribute__((packed)) data_union_u { - data_header_t header; - data_nop_t nop; - data_osd_new_t osd_new; - data_osd_free_t osd_free; - data_osd_show_t osd_show; - data_osd_hide_t osd_hide; - data_osd_set_position_t osd_set_position; - data_osd_draw_bitmap_t osd_draw_bitmap; - data_set_color_t set_color; - data_flush_t flush; - data_clear_t clear; - data_mute_t mute; - data_set_volume_t set_volume; - data_set_speed_t set_speed; - data_set_prebuffer_t set_prebuffer; - data_metronom_t metronom; - data_start_t start; - data_wait_t wait; - data_setup_t setup; - data_grab_image_t grab_image; - data_get_pts_t get_pts; - data_first_frame_t first_frame; - data_still_frame_t still_frame; - data_video_size_t video_size; - data_set_video_window_t set_video_window; - data_osd_flush_t osd_flush; - data_play_external_t play_external; - data_reset_audio_t reset_audio; - data_select_audio_t select_audio; - data_trick_speed_mode_t trick_speed_mode; - data_get_version_t get_version; + data_header_t header; + data_nop_t nop; + data_osd_new_t osd_new; + data_osd_free_t osd_free; + data_osd_show_t osd_show; + data_osd_hide_t osd_hide; + data_osd_set_position_t osd_set_position; + data_osd_draw_bitmap_t osd_draw_bitmap; + data_set_color_t set_color; + data_flush_t flush; + data_clear_t clear; + data_mute_t mute; + data_set_volume_t set_volume; + data_set_speed_t set_speed; + data_set_prebuffer_t set_prebuffer; + data_metronom_t metronom; + data_start_t start; + data_wait_t wait; + data_setup_t setup; + data_grab_image_t grab_image; + data_get_pts_t get_pts; + data_first_frame_t first_frame; + data_still_frame_t still_frame; + data_video_size_t video_size; + data_set_video_window_t set_video_window; + data_osd_flush_t osd_flush; + data_play_external_t play_external; + data_reset_audio_t reset_audio; + data_select_audio_t select_audio; + data_trick_speed_mode_t trick_speed_mode; + data_get_version_t get_version; + data_query_capabilities_t query_capabilities; } data_union_t; @@ -590,13 +633,14 @@ data_union_t; typedef union __attribute__((packed)) result_union_u { - result_header_t header; - result_grab_image_t grab_image; - result_get_pts_t get_pts; - result_flush_t flush; - result_video_size_t video_size; - result_get_version_t get_version; - result_wait_t wait; + result_header_t header; + result_grab_image_t grab_image; + result_get_pts_t get_pts; + result_flush_t flush; + result_video_size_t video_size; + result_get_version_t get_version; + result_wait_t wait; + result_query_capabilities_t query_capabilities; } result_union_t; @@ -608,6 +652,7 @@ typedef union __attribute__((packed)) event_union_u event_key_t key; event_frame_size_t frame_size; event_play_external_t play_external; + event_discontinuity_t discontinuity; } event_union_t; diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c index 6927ed255..29fcd0660 100644 --- a/src/vdr/input_vdr.c +++ b/src/vdr/input_vdr.c @@ -72,6 +72,16 @@ typedef struct vdr_metronom_t; +typedef struct vdr_osd_s +{ + xine_osd_t *window; + uint8_t *argb_buffer; + int width; + int height; +} +vdr_osd_t; + + struct vdr_input_plugin_s { input_plugin_t input_plugin; @@ -96,10 +106,12 @@ struct vdr_input_plugin_s off_t cur_size; off_t cur_done; - xine_osd_t *osd_window[ VDR_MAX_NUM_WINDOWS ]; + vdr_osd_t osd[ VDR_MAX_NUM_WINDOWS ]; uint8_t *osd_buffer; uint32_t osd_buffer_size; uint8_t osd_unscaled_blending; + uint8_t osd_supports_custom_extent; + uint8_t osd_supports_argb_layer; uint8_t audio_channels; uint8_t trick_speed_mode; @@ -336,24 +348,30 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) { READ_DATA_OR_FAIL(osd_new, LOG_OSD(lprintf("got OSDNEW\n"))); /* - LOG_OSD(lprintf("... (%d,%d)-(%d,%d)\n", data->x, data->y, data->width, data->height)); + LOG_OSD(lprintf("... (%d,%d)-(%d,%d)@(%d,%d)\n", data->x, data->y, data->width, data->height, data->w_ref, data->h_ref)); fprintf(stderr, "vdr: osdnew %d\n", data->window); */ if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) + if (0 != this->osd[ data->window ].window) return -1; - - this->osd_window[ data->window ] = xine_osd_new(this->stream + + this->osd[ data->window ].window = xine_osd_new(this->stream , data->x , data->y , data->width , data->height); + + this->osd[ data->window ].width = data->width; + this->osd[ data->window ].height = data->height; - if (0 == this->osd_window[ data->window ]) + if (0 == this->osd[ data->window ].window) return -1; + + if (this->osd_supports_custom_extent && data->w_ref > 0 && data->h_ref > 0) + xine_osd_set_extent(this->osd[ data->window ].window, data->w_ref, data->h_ref); } break; @@ -366,10 +384,13 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) - xine_osd_free(this->osd_window[ data->window ]); - - this->osd_window[ data->window ] = 0; + if (0 != this->osd[ data->window ].window) + xine_osd_free(this->osd[ data->window ].window); + + this->osd[ data->window ].window = 0; + + free(this->osd[ data->window ].argb_buffer); + this->osd[ data->window ].argb_buffer = 0; } break; @@ -382,12 +403,12 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) + if (0 != this->osd[ data->window ].window) { if (this->osd_unscaled_blending) - xine_osd_show_unscaled(this->osd_window[ data->window ], 0); + xine_osd_show_unscaled(this->osd[ data->window ].window, 0); else - xine_osd_show(this->osd_window[ data->window ], 0); + xine_osd_show(this->osd[ data->window ].window, 0); } } break; @@ -401,12 +422,12 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) + if (0 != this->osd[ data->window ].window) { if (this->osd_unscaled_blending) - xine_osd_show_unscaled(this->osd_window[ data->window ], 0); + xine_osd_show_unscaled(this->osd[ data->window ].window, 0); else - xine_osd_show(this->osd_window[ data->window ], 0); + xine_osd_show(this->osd[ data->window ].window, 0); } } break; @@ -458,8 +479,8 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) - xine_osd_set_position(this->osd_window[ data->window ], data->x, data->y); + if (0 != this->osd[ data->window ].window) + xine_osd_set_position(this->osd[ data->window ].window, data->x, data->y); } break; @@ -492,8 +513,41 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) - xine_osd_draw_bitmap(this->osd_window[ data->window ], this->osd_buffer, data->x, data->y, data->width, data->height, 0); + if (0 != this->osd[ data->window ].window) + { + vdr_osd_t *osd = &this->osd[ data->window ]; + + if (data->argb) + { + if (!osd->argb_buffer) + osd->argb_buffer = calloc(4 * osd->width, osd->height); + + { + int src_stride = 4 * data->width; + int dst_stride = 4 * osd->width; + + uint8_t *src = this->osd_buffer; + uint8_t *dst = osd->argb_buffer + data->y * dst_stride + data->x * 4; + int y; + + if (src_stride == dst_stride) + xine_fast_memcpy(dst, src, src_stride * data->height); + else + { + for (y = 0; y < data->height; y++) + { + xine_fast_memcpy(dst, src, src_stride); + dst += dst_stride; + src += src_stride; + } + } + } + + xine_osd_set_argb_buffer(osd->window, (uint32_t *)osd->argb_buffer, data->x, data->y, data->width, data->height); + } + else + xine_osd_draw_bitmap(osd->window, this->osd_buffer, data->x, data->y, data->width, data->height, 0); + } } break; @@ -515,12 +569,12 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) if (data->window >= VDR_MAX_NUM_WINDOWS) return -1; - if (0 != this->osd_window[ data->window ]) + if (0 != this->osd[ data->window ].window) { uint32_t color[ 256 ]; uint8_t trans[ 256 ]; - xine_osd_get_palette(this->osd_window[ data->window ], color, trans); + xine_osd_get_palette(this->osd[ data->window ].window, color, trans); { int i; @@ -546,7 +600,7 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this) } } - xine_osd_set_palette(this->osd_window[ data->window ], color, trans); + xine_osd_set_palette(this->osd[ data->window ].window, color, trans); } } break; @@ -964,46 +1018,48 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a'); { off_t ret_val = -1; - xine_current_frame_data_t frame; - - if (xine_get_current_frame_data(this->stream, &frame, XINE_FRAME_DATA_ALLOCATE_IMG)) + + xine_current_frame_data_t frame_data; + memset(&frame_data, 0, sizeof (frame_data)); + + if (xine_get_current_frame_data(this->stream, &frame_data, XINE_FRAME_DATA_ALLOCATE_IMG)) { - if (frame.ratio_code == XINE_VO_ASPECT_SQUARE) - frame.ratio_code = 10000; - else if (frame.ratio_code == XINE_VO_ASPECT_4_3) - frame.ratio_code = 13333; - else if (frame.ratio_code == XINE_VO_ASPECT_ANAMORPHIC) - frame.ratio_code = 17778; - else if (frame.ratio_code == XINE_VO_ASPECT_DVB) - frame.ratio_code = 21100; + if (frame_data.ratio_code == XINE_VO_ASPECT_SQUARE) + frame_data.ratio_code = 10000; + else if (frame_data.ratio_code == XINE_VO_ASPECT_4_3) + frame_data.ratio_code = 13333; + else if (frame_data.ratio_code == XINE_VO_ASPECT_ANAMORPHIC) + frame_data.ratio_code = 17778; + else if (frame_data.ratio_code == XINE_VO_ASPECT_DVB) + frame_data.ratio_code = 21100; } - if (!frame.img) - { - frame.img_size = 0, - frame.width = 0; - frame.height = 0; - frame.ratio_code = 0; - } - + if (!frame_data.img) + memset(&frame_data, 0, sizeof (frame_data)); + { result_grab_image_t result_grab_image; result_grab_image.header.func = data->header.func; - result_grab_image.header.len = sizeof (result_grab_image) + frame.img_size; + result_grab_image.header.len = sizeof (result_grab_image) + frame_data.img_size; - result_grab_image.width = frame.width; - result_grab_image.height = frame.height; - result_grab_image.ratio = frame.ratio_code; - result_grab_image.format = frame.format; + result_grab_image.width = frame_data.width; + result_grab_image.height = frame_data.height; + result_grab_image.ratio = frame_data.ratio_code; + result_grab_image.format = frame_data.format; + result_grab_image.interlaced = frame_data.interlaced; + result_grab_image.crop_left = frame_data.crop_left; + result_grab_image.crop_right = frame_data.crop_right; + result_grab_image.crop_top = frame_data.crop_top; + result_grab_image.crop_bottom = frame_data.crop_bottom; if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image))) { - if (!frame.img_size || (frame.img_size == vdr_write(this->fh_result, frame.img, frame.img_size))) + if (!frame_data.img_size || (frame_data.img_size == vdr_write(this->fh_result, frame_data.img, frame_data.img_size))) ret_val = 0; } } - free(frame.img); + free(frame_data.img); if (ret_val != 0) return ret_val; @@ -1146,6 +1202,27 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a'); } break; + case func_query_capabilities: + { + READ_DATA_OR_FAIL(query_capabilities, lprintf("got QUERYCAPABILITIES\n")); + + { + result_query_capabilities_t result_query_capabilities; + result_query_capabilities.header.func = data->header.func; + result_query_capabilities.header.len = sizeof (result_query_capabilities); + + result_query_capabilities.osd_max_num_windows = MAX_SHOWING; + result_query_capabilities.osd_palette_max_depth = 8; + result_query_capabilities.osd_palette_is_shared = 0; + result_query_capabilities.osd_supports_argb_layer = this->osd_supports_argb_layer; + result_query_capabilities.osd_supports_custom_extent = this->osd_supports_custom_extent; + + if (sizeof (result_query_capabilities) != vdr_write(this->fh_result, &result_query_capabilities, sizeof (result_query_capabilities))) + return -1; + } + } + break; + default: lprintf("unknown function: %d\n", this->cur_func); } @@ -1292,6 +1369,20 @@ static int internal_write_event_play_external(vdr_input_plugin_t *this, uint32_t return 0; } +static int internal_write_event_discontinuity(vdr_input_plugin_t *this, int32_t type) +{ + event_discontinuity_t event; + event.header.func = func_discontinuity; + event.header.len = sizeof (event); + + event.type = type; + + if (sizeof (event) != vdr_write(this->fh_event, &event, sizeof (event))) + return -1; + + return 0; +} + static off_t vdr_plugin_read(input_plugin_t *this_gen, void *buf_gen, off_t len) { @@ -1558,11 +1649,13 @@ static void vdr_plugin_dispose(input_plugin_t *this_gen) for (i = 0; i < VDR_MAX_NUM_WINDOWS; i++) { - if (0 == this->osd_window[ i ]) + if (0 == this->osd[ i ].window) continue; - xine_osd_hide(this->osd_window[ i ], 0); - xine_osd_free(this->osd_window[ i ]); + xine_osd_hide(this->osd[ i ].window, 0); + xine_osd_free(this->osd[ i ].window); + + free(this->osd[ i ].argb_buffer); } if (this->osd_buffer) @@ -1893,7 +1986,17 @@ static void event_handler(void *user_data, const xine_event_t *event) adjust_zoom(this); return; } - else if (XINE_EVENT_VDR_PLUGINSTARTED == event->type) + + if (XINE_EVENT_VDR_DISCONTINUITY == event->type) + { + if (0 != internal_write_event_discontinuity(this, event->data_length)) + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("%s: input event write: %s.\n"), LOG_MODULE, strerror(errno)); + + return; + } + + if (XINE_EVENT_VDR_PLUGINSTARTED == event->type) { if (0 == event->data_length) /* vdr_video */ { @@ -1922,6 +2025,8 @@ static void event_handler(void *user_data, const xine_event_t *event) { fprintf(stderr, "input_vdr: illegal XINE_EVENT_VDR_PLUGINSTARTED: %d\n", event->data_length); } + + return; } switch (event->type) @@ -2014,18 +2119,33 @@ static int64_t vdr_metronom_got_spu_packet(metronom_t *self, int64_t pts) return this->stream_metronom->got_spu_packet(this->stream_metronom, pts); } +static void vdr_handle_discontinuity(vdr_input_plugin_t *this, int type) +{ + this->last_disc_type = type; + + { + xine_event_t event; + + event.type = XINE_EVENT_VDR_DISCONTINUITY; + event.data = 0; + event.data_length = type; + + xine_event_send(this->stream, &event); + } +} + static void vdr_metronom_handle_audio_discontinuity(metronom_t *self, int type, int64_t disc_off) { vdr_metronom_t *this = (vdr_metronom_t *)self; this->stream_metronom->handle_audio_discontinuity(this->stream_metronom, type, disc_off); - this->input->last_disc_type = type; + vdr_handle_discontinuity(this->input, type); } static void vdr_metronom_handle_video_discontinuity(metronom_t *self, int type, int64_t disc_off) { vdr_metronom_t *this = (vdr_metronom_t *)self; this->stream_metronom->handle_video_discontinuity(this->stream_metronom, type, disc_off); - this->input->last_disc_type = type; + vdr_handle_discontinuity(this->input, type); } static void vdr_metronom_set_option(metronom_t *self, int option, int64_t value) @@ -2101,7 +2221,16 @@ static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_strea this->cur_size = 0; this->cur_done = 0; - memset(this->osd_window, 0, sizeof (this->osd_window)); + memset(this->osd, 0, sizeof (this->osd)); + + { + xine_osd_t *osd = xine_osd_new(this->stream, 0, 0, 16, 16); + uint32_t caps = xine_osd_get_capabilities(osd); + xine_osd_free(osd); + + this->osd_supports_argb_layer = !!(caps & XINE_OSD_CAP_ARGB_LAYER); + this->osd_supports_custom_extent = !!(caps & XINE_OSD_CAP_CUSTOM_EXTENT); + } this->osd_buffer = 0; this->osd_buffer_size = 0; -- cgit v1.2.3 From 67346ce9f69ef46634ad151c9b4d096e59a0d3b8 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Sun, 4 Jan 2009 17:47:54 +0100 Subject: use compiled in default for fifo dir if none specified. This way one can just run xine vdr:// --- src/vdr/input_vdr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c index 29fcd0660..ee4a7fd7a 100644 --- a/src/vdr/input_vdr.c +++ b/src/vdr/input_vdr.c @@ -1704,7 +1704,13 @@ static inline const char *mrl_to_host (const char *mrl) static int vdr_plugin_open_fifo_mrl(input_plugin_t *this_gen) { vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; - char *filename = strdup (mrl_to_fifo (this->mrl)); + char *filename = mrl_to_fifo (this->mrl); + + if(!strcmp(filename, "/")) { + filename = VDR_ABS_FIFO_DIR "/stream"; + } + + filename = strdup(filename); _x_mrl_unescape (filename); this->fh = open(filename, O_RDONLY | O_NONBLOCK); -- cgit v1.2.3 From f6e6a60331a9ee14a06790c58cee7a24a1a307ce Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Sun, 4 Jan 2009 17:48:39 +0100 Subject: fake some data to make demuxer auto detection work --- src/vdr/input_vdr.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c index ee4a7fd7a..b2dea3864 100644 --- a/src/vdr/input_vdr.c +++ b/src/vdr/input_vdr.c @@ -1559,7 +1559,7 @@ static off_t vdr_plugin_get_length(input_plugin_t *this_gen) static uint32_t vdr_plugin_get_capabilities(input_plugin_t *this_gen) { - return INPUT_CAP_NOCAP; /* INPUT_CAP_PREVIEW; */ + return INPUT_CAP_PREVIEW; } static uint32_t vdr_plugin_get_blocksize(input_plugin_t *this_gen) @@ -1676,16 +1676,13 @@ static int vdr_plugin_get_optional_data(input_plugin_t *this_gen, void *data, int data_type) { vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen; - int preview_size = (this->preview_size > MAX_PREVIEW_SIZE) ? MAX_PREVIEW_SIZE : this->preview_size; - (void)preview_size; -/* switch (data_type) { case INPUT_OPTIONAL_DATA_PREVIEW: - memcpy (data, this->preview, preview_size); - return preview_size; + /* just fake what mpeg_pes demuxer expects */ + memcpy (data, "\x00\x00\x01\xe0\x00\x00", 6); + return 6; } -*/ return INPUT_OPTIONAL_UNSUPPORTED; } -- cgit v1.2.3