[vdr] [ANNOUNCE] vdr-xine-0.7.10 plugin

Darren Salt linux at youmustbejoking.demon.co.uk
Mon Dec 11 00:36:48 CET 2006


I demand that Reinhard Nissl may or may not have written...

> Darren Salt wrote:
>> I demand that Reinhard Nissl may or may not have written...
>>> it's been a long time being busy at work and home, so I'm very pleased to
>>> announce maintenance release 0.7.10 today:
>>>      http://home.vr-web.de/~rnissl/vdr-xine-0.7.10.tgz
>> [snip]
>> The change to src/libffmpeg/libavcodec/i386/Makefile.am is wrong - you
>> could change the second replacement to 's/-O\([0-9]\|s\|$\)/-Os /g' (or
>> use "sed -re"), but this won't catch -O except at the end. 's/$/ -Os/',
>> perhaps...

> Well, in xine-devel ML you wrote

> 	"s/-O\([0-9]\|\s\|$\)/-Os /g" should fix it.
                      ^
Should; not does. And you have an extra \ (or perhaps I did) :-)

> So I thought those backslashes were necessary when using double quotes. As
> the Makefile used single quotes I've dropped the backslashes.

I used double quotation marks purely as delimiters. With the command given in
full, I would have used single quotation marks or doubled the backslashes.

[snip]
>> I should have updated .debs available within a day or two. libxine1
>> 1.1.3-2 will include an *experimental* AFD patch in the expand plugin -
>> I'm not interested in bug reports concerning this unless they're
>> accompanied by patches.

> Cool -- are you relying on XINE_STREAM_INFO_VIDEO_AFD?

Yes.

> My implementation in libmpeg2 is not perfect. It lacks stacking (AFD
> information may be valid for a sequence, group or frame, i. e. the AFD for
> a sequence could be overridden for a single frame duration by a frame AFD)
> and cannot detect XINE_VIDEO_AFD_NOT_PRESENT.

My code is currently broken wrt some transitions and when paused, but this
could be an effect of breakage in your code. (I'm attaching the patch for
reference.)

> Would you provide me a sample stream which contains some transitions
> between different XINE_VIDEO_AFD_* values?

<URL:http://zap.tartarus.org/~ds/001.vdr> is a short clip with one transition
and a corresponding aspect change - AFD 14 to AFD 9, 16:9 to 4:3.

I had some with transitions to/from pillar-boxed 4:3 (sourced from BBC
transmissions), but I've edited them. Star Trek TNG (BBC 2, Saturday,
terrestrial) has such a transition pair, just in case somebody else has
recorded it...

-- 
| Darren Salt    | linux or ds at              | nr. Ashington, | Toon
| RISC OS, Linux | youmustbejoking,demon,co,uk | Northumberland | Army
| + Output less CO2 => avoid boiling weather.     TIME IS RUNNING OUT *FAST*.

Minds, like parachutes, work only when open.
-------------- next part --------------
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 <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;


More information about the vdr mailing list