diff -urNad xine-lib-vdr-1.1.3~/src/post/planar/expand.c xine-lib-vdr-1.1.3/src/post/planar/expand.c --- xine-lib-vdr-1.1.3~/src/post/planar/expand.c 2006-12-10 21:50:18.000000000 +0000 +++ xine-lib-vdr-1.1.3/src/post/planar/expand.c 2006-12-10 21:53:21.883834541 +0000 @@ -27,6 +27,7 @@ * */ +#include #include "xine_internal.h" #include "post.h" @@ -68,6 +69,8 @@ typedef struct expand_parameters_s { int enable_automatic_shift; int overlay_y_offset; + int afd_mode; + int afd_shoot_protect; double aspect; int centre_cut_out_mode; } expand_parameters_t; @@ -77,6 +80,10 @@ "enable automatic overlay shifting") PARAM_ITEM(POST_PARAM_TYPE_INT, overlay_y_offset, NULL, -500, 500, 0, "manually shift the overlay vertically") +PARAM_ITEM(POST_PARAM_TYPE_BOOL, afd_mode, NULL, 0, 1, 0, + "use AFD information if available") +PARAM_ITEM(POST_PARAM_TYPE_BOOL, afd_shoot_protect, NULL, 0, 1, 0, + "enable shoot&protect (intended for 4:3 display)") PARAM_ITEM(POST_PARAM_TYPE_DOUBLE, aspect, NULL, 1.0, 3.5, 0, "target aspect ratio") PARAM_ITEM(POST_PARAM_TYPE_BOOL, centre_cut_out_mode, NULL, 0, 1, 0, @@ -90,10 +97,17 @@ int enable_automatic_shift; int overlay_y_offset; + int afd_mode; + int afd_shoot_protect; double aspect; int top_bar_height; int centre_cut_out_mode; int cropping_active; + double stream_ratio, afd_ratio; + double prev_ratio; + int prev_afd; + int prev_shoot_protect; + int crop_x, crop_y; } post_expand_t; /* plugin class functions */ @@ -165,9 +179,13 @@ this->enable_automatic_shift = 0; this->overlay_y_offset = 0; + this->afd_mode = 1; + this->afd_shoot_protect = 0; this->aspect = 4.0 / 3.0; this->centre_cut_out_mode = 0; this->cropping_active = 0; + this->crop_x = this->crop_y = 0; + this->prev_shoot_protect = -1; /* won't happen */ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->new_port.get_frame = expand_get_frame; @@ -228,6 +246,8 @@ this->enable_automatic_shift = param->enable_automatic_shift; this->overlay_y_offset = param->overlay_y_offset; + this->afd_mode = param->afd_mode; + this->afd_shoot_protect = param->afd_shoot_protect; this->aspect = param->aspect; this->centre_cut_out_mode = param->centre_cut_out_mode; @@ -241,6 +261,8 @@ param->enable_automatic_shift = this->enable_automatic_shift; param->overlay_y_offset = this->overlay_y_offset; + param->afd_mode = this->afd_mode; + param->afd_shoot_protect = this->afd_shoot_protect; param->aspect = this->aspect; param->centre_cut_out_mode = this->centre_cut_out_mode; @@ -292,13 +314,181 @@ } +/* Mode matrix: + * 4:3 16:9 + * Crop + * Nocrop + */ + +static inline int approx_eq (double a, double b) +{ + return fabs (a - b) < 1.0/64.0; +} + +static int translate_ratio(double ratio) +{ + if (approx_eq (ratio, 4.0/3.0)) + return 4; + if (approx_eq (ratio, 16.0/9.0)) + return 16; +/* + if (approx_eq (ratio, 14.0/9.0)) + return 14; +*/ + return 0; +} + +static int expand_afd(vo_frame_t *frame, xine_stream_t *stream) +{ + int afd = _x_stream_info_get_public(stream, XINE_STREAM_INFO_VIDEO_AFD); + post_video_port_t *port = (post_video_port_t *)frame->port; + post_expand_t *this = (post_expand_t *)port->post; + int ratio = translate_ratio (frame->ratio); + + if (afd == this->prev_afd && frame->ratio == this->prev_ratio && + this->afd_shoot_protect == this->prev_shoot_protect) + goto unchanged; + + this->prev_afd = afd; + this->prev_ratio = frame->ratio; + + this->crop_x = 0; + this->crop_y = 0; + this->afd_ratio = 0; + this->cropping_active = 0; + + if (!ratio) + goto unchanged; + + switch (afd) + { + case XINE_VIDEO_AFD_NOT_PRESENT: + case XINE_VIDEO_AFD_SAME_AS_FRAME: + case XINE_VIDEO_AFD_RESERVED_12: + /* nothing to do */ + break; + + case XINE_VIDEO_AFD_4_3_CENTRE: + /* if stream is 16:9, crop it to 4:3 (3/4 width) */ + if (ratio == 16) + { + this->crop_x = frame->width / 8; + this->crop_y = 0; + this->afd_ratio = 4.0 / 3.0; + this->cropping_active = 1; + } + break; + + case XINE_VIDEO_AFD_16_9_CENTRE: + /* if stream is 4:3, crop it to 16:9 (3/4 height) */ + if (ratio == 4) + { + this->crop_x = 0; + this->crop_y = frame->height / 8; + this->afd_ratio = 16.0 / 9.0; + this->cropping_active = 1; + } + break; + + case XINE_VIDEO_AFD_14_9_CENTRE: + /* video is 14:9 - always crop */ + if (ratio == 4) + { + /* crop top & bottom (6/7 height) */ + this->crop_x = 0; + this->crop_y = frame->height / 14; + } + else /* ratio == 16 */ + { + /* crop sides (7/8 width) */ + this->crop_x = frame->width / 16; + this->crop_y = 0; + } + this->afd_ratio = 14.0 / 9.0; + this->cropping_active = 1; + break; + + case XINE_VIDEO_AFD_4_3_PROTECT_14_9: + /* optional cropping from 4:3 to 14:9 */ + this->crop_x = 0; + if (this->afd_shoot_protect) + { + this->crop_y = frame->height / 14; + this->afd_ratio = 14.0 / 9.0; + } + else + { + this->crop_y = 0; + this->afd_ratio = 4.0 / 3.0; + } + this->cropping_active = 1; + break; + + case XINE_VIDEO_AFD_16_9_PROTECT_14_9: + /* optional cropping from 16:9 to 14:9 */ + if (this->afd_shoot_protect) + { + this->crop_x = frame->width / 16; + this->afd_ratio = 14.0 / 9.0; + } + else + { + this->crop_x = 0; + this->afd_ratio = 16.0 / 9.0; + } + this->crop_y = 0; + this->cropping_active = 1; + break; + + case XINE_VIDEO_AFD_16_9_PROTECT_4_3: + /* optional cropping from 16:9 to 14:9 */ + if (this->afd_shoot_protect) + { + this->crop_x = frame->width / 8; + this->afd_ratio = 4.0 / 3.0; + } + else + { + this->crop_x = 0; + this->afd_ratio = 16.0 / 9.0; + } + this->crop_y = 0; + this->cropping_active = 1; + break; + + default: + /* unknown or reserved values; do nothing */ + break; + } + + /* DEBUG - development */ + (printf) ("AFD %d, stream = %d, using = %d, crop %d×%d\n", afd, + translate_ratio (frame->ratio), + translate_ratio (this->afd_ratio), + this->crop_x, this->crop_y); + +unchanged: + frame->crop_left += this->crop_x; + frame->crop_right += this->crop_x; + frame->crop_top += this->crop_y; + frame->crop_bottom += this->crop_y; + +printf ("crop ←%d →%d ↑%d ↓%d\n", frame->crop_left, frame->crop_right, frame->crop_top, frame->crop_bottom); + + return this->cropping_active; +} + + static int expand_draw(vo_frame_t *frame, xine_stream_t *stream) { post_video_port_t *port = (post_video_port_t *)frame->port; post_expand_t *this = (post_expand_t *)port->post; int skip; - if (this->centre_cut_out_mode && !frame->bad_frame) + if (!frame->bad_frame && this->afd_mode && expand_afd (frame, stream)) + goto done; + + if (!frame->bad_frame && this->centre_cut_out_mode) { /* expected area of inner 4:3 image */ int centre_width = frame->width * (9 * 4) / (16 * 3); @@ -331,6 +521,8 @@ } } + done: + frame->ratio = this->aspect; _x_post_frame_copy_down(frame, frame->next); skip = frame->next->draw(frame->next, stream); @@ -355,13 +547,25 @@ if (ratio <= 0.0) ratio = (double)width / (double)height; /* Calculate height of expanded frame */ - new_height = (double)height * ratio / this->aspect; + new_height = this->afd_mode ? height : ((double)height * ratio / this->aspect); new_height = (new_height + 1) & ~1; top_bar_height = (new_height - height) / 2; top_bar_height = (top_bar_height + 1) & ~1; this->top_bar_height = top_bar_height; + if (this->afd_mode && + (format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2)) + { + frame = port->original_port->get_frame + (port->original_port, width, height, + this->afd_ratio ? this->afd_ratio : ratio, format, flags); + _x_post_inc_usage(port); + this->stream_ratio = frame->ratio = ratio; + frame = _x_post_intercept_video_frame(frame, port); + return frame; + } + if (new_height > height && (format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2)) { frame = port->original_port->get_frame(port->original_port, @@ -423,13 +627,12 @@ { post_expand_t *this = (post_expand_t *)port->post; - if (this->centre_cut_out_mode && this->cropping_active) return 0; + if ((this->centre_cut_out_mode | this->afd_mode) && this->cropping_active) + return 0; /* we always intercept overlay manager */ return 1; } - - static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen, void *event_gen) { video_overlay_event_t *event = (video_overlay_event_t *)event_gen;