videoscale: scale each field in interlace mode
authorWim Taymans <wim.taymans@collabora.co.uk>
Tue, 5 Feb 2013 09:46:50 +0000 (10:46 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 5 Feb 2013 09:49:57 +0000 (10:49 +0100)
When we are dealing with interlaced content, scale each field intependently so
that we don't destroy the interlacing.

See https://bugzilla.gnome.org/show_bug.cgi?id=588535

gst/videoscale/gstvideoscale.c

index 5771371..2c8e9a1 100644 (file)
@@ -203,6 +203,9 @@ static void gst_video_scale_set_property (GObject * object, guint prop_id,
 static void gst_video_scale_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static GstFlowReturn do_scale (GstVideoFilter * filter, VSImage dest[4],
+    VSImage src[4]);
+
 #define gst_video_scale_parent_class parent_class
 G_DEFINE_TYPE (GstVideoScale, gst_video_scale, GST_TYPE_VIDEO_FILTER);
 
@@ -1002,7 +1005,7 @@ done:
 
 static void
 gst_video_scale_setup_vs_image (VSImage * image, GstVideoFrame * frame,
-    gint component, gint b_w, gint b_h)
+    gint component, gint b_w, gint b_h, gboolean interlaced, gint field)
 {
   GstVideoFormat format;
   gint width, height;
@@ -1018,6 +1021,11 @@ gst_video_scale_setup_vs_image (VSImage * image, GstVideoFrame * frame,
   image->height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (frame->info.finfo,
       component, MAX (1, height - b_h));
 
+  if (interlaced) {
+    image->real_height /= 2;
+    image->height /= 2;
+  }
+
   image->border_top = (image->real_height - image->height) / 2;
   image->border_bottom = image->real_height - image->height - image->border_top;
 
@@ -1035,12 +1043,19 @@ gst_video_scale_setup_vs_image (VSImage * image, GstVideoFrame * frame,
     image->border_right = image->real_width - image->width - image->border_left;
   }
 
-  image->real_pixels = frame->data[component];
-  image->stride = frame->info.stride[component];
+  image->real_pixels = GST_VIDEO_FRAME_PLANE_DATA (frame, component);
+  image->stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, component);
+
+  if (interlaced) {
+    if (field == 1)
+      image->real_pixels += image->stride;
+    image->stride *= 2;
+  }
 
   image->pixels =
       image->real_pixels + image->border_top * image->stride +
       image->border_left * GST_VIDEO_FRAME_COMP_PSTRIDE (frame, component);
+
 }
 
 static const guint8 *
@@ -1111,11 +1126,39 @@ gst_video_scale_transform_frame (GstVideoFilter * filter,
   GstFlowReturn ret = GST_FLOW_OK;
   VSImage dest[4] = { {NULL,}, };
   VSImage src[4] = { {NULL,}, };
+  gint i;
+  gboolean interlaced;
+
+  interlaced = GST_VIDEO_FRAME_IS_INTERLACED (in_frame);
+
+  for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (in_frame); i++) {
+    gst_video_scale_setup_vs_image (&src[i], in_frame, i, 0, 0, interlaced, 0);
+    gst_video_scale_setup_vs_image (&dest[i], out_frame, i,
+        videoscale->borders_w, videoscale->borders_h, interlaced, 0);
+  }
+  ret = do_scale (filter, dest, src);
+
+  if (interlaced) {
+    for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (in_frame); i++) {
+      gst_video_scale_setup_vs_image (&src[i], in_frame, i, 0, 0, interlaced,
+          1);
+      gst_video_scale_setup_vs_image (&dest[i], out_frame, i,
+          videoscale->borders_w, videoscale->borders_h, interlaced, 1);
+    }
+    ret = do_scale (filter, dest, src);
+  }
+  return ret;
+}
+
+static GstFlowReturn
+do_scale (GstVideoFilter * filter, VSImage dest[4], VSImage src[4])
+{
+  GstVideoScale *videoscale = GST_VIDEO_SCALE (filter);
+  GstFlowReturn ret = GST_FLOW_OK;
   gint method;
   const guint8 *black;
-  gboolean add_borders;
   GstVideoFormat format;
-  gint i;
+  gboolean add_borders;
 
   GST_OBJECT_LOCK (videoscale);
   method = videoscale->method;
@@ -1133,12 +1176,6 @@ gst_video_scale_transform_frame (GstVideoFilter * filter,
     method = GST_VIDEO_SCALE_BILINEAR;
   }
 
-  for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (in_frame); i++) {
-    gst_video_scale_setup_vs_image (&src[i], in_frame, i, 0, 0);
-    gst_video_scale_setup_vs_image (&dest[i], out_frame, i,
-        videoscale->borders_w, videoscale->borders_h);
-  }
-
   GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, filter,
       "doing videoscale format %s", GST_VIDEO_INFO_NAME (&filter->in_info));