@@ -27,6 +27,7 @@
*
*/
+#include <math.h>
#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;