Fix row strides for I420 (fixes #163159)
authorTim-Philipp Müller <tim@centricular.net>
Wed, 19 Jan 2005 17:09:57 +0000 (17:09 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Wed, 19 Jan 2005 17:09:57 +0000 (17:09 +0000)
Original commit message from CVS:
Fix row strides for I420 (fixes #163159)

ChangeLog
gst/videobox/gstvideobox.c

index d0a3f07..1a1c6f6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2005-01-19  Tim-Philipp Müller  <tim at centricular dot net>
+
+       * gst/videobox/gstvideobox.c: (gst_video_box_copy_plane_i420),
+       (gst_video_box_i420), (gst_video_box_chain):
+         Fix row strides for I420 (fixes #163159)
+         
 2005-01-19  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
 
        * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_parse_packhead):
index 3e29dcd..bfe738c 100644 (file)
@@ -84,13 +84,6 @@ GST_ELEMENT_DETAILS ("video box filter",
     "Wim Taymans <wim@fluendo.com>");
 
 
-/* VideoBox signals and args */
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
 #define DEFAULT_LEFT      0
 #define DEFAULT_RIGHT     0
 #define DEFAULT_TOP       0
@@ -397,29 +390,65 @@ gst_video_box_sink_link (GstPad * pad, const GstCaps * caps)
   return GST_PAD_LINK_OK;
 }
 
-#define GST_VIDEO_I420_Y_OFFSET(width,height) (0)
-#define GST_VIDEO_I420_U_OFFSET(width,height) ((width)*(height))
-#define GST_VIDEO_I420_V_OFFSET(width,height) ((width)*(height) + ((width/2)*(height/2)))
+#define ROUND_UP_2(x)  (((x)+1)&~1)
+#define ROUND_UP_4(x)  (((x)+3)&~3)
+#define ROUND_UP_8(x)  (((x)+7)&~7)
+
+/* see gst-plugins/gst/games/gstvideoimage.c, paint_setup_I420() */
+#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (ROUND_UP_4(width))
+#define GST_VIDEO_I420_U_ROWSTRIDE(width) (ROUND_UP_8(width)/2)
+#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2)
 
-#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (width)
-#define GST_VIDEO_I420_U_ROWSTRIDE(width) ((width)/2)
-#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((width)/2)
+#define GST_VIDEO_I420_Y_OFFSET(w,h) (0)
+#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*ROUND_UP_2(h)))
+#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*ROUND_UP_2(h)/2))
+
+#define GST_VIDEO_I420_SIZE(w,h)     (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*ROUND_UP_2(h)/2))
 
 static int yuv_colors_Y[] = { 16, 150, 29 };
 static int yuv_colors_U[] = { 128, 46, 255 };
 static int yuv_colors_V[] = { 128, 21, 107 };
 
 static void
+gst_video_box_copy_plane_i420 (GstVideoBox * video_box, guint8 * src,
+    guint8 * dest, gint br, gint bl, gint bt, gint bb, gint src_crop_width,
+    gint src_crop_height, gint src_stride, gint dest_width, gint dest_stride,
+    guint8 fill_color)
+{
+  gint j;
+
+  /* top border */
+  for (j = 0; j < bt; j++) {
+    memset (dest, fill_color, dest_width);
+    dest += dest_stride;
+  }
+
+  /* copy and add left and right border */
+  for (j = 0; j < src_crop_height; j++) {
+    memset (dest, fill_color, bl);
+    memcpy (dest + bl, src, src_crop_width);
+    memset (dest + bl + src_crop_width, fill_color, br);
+    dest += dest_stride;
+    src += src_stride;
+  }
+
+  /* bottom border */
+  for (j = 0; j < bb; j++) {
+    memset (dest, fill_color, dest_width);
+    dest += dest_stride;
+  }
+}
+
+static void
 gst_video_box_i420 (GstVideoBox * video_box, guint8 * src, guint8 * dest)
 {
   guint8 *srcY, *srcU, *srcV;
   guint8 *destY, *destU, *destV;
   gint crop_width, crop_height;
   gint out_width, out_height;
-  gint src_stride;
+  gint src_width, src_height;
+  gint src_stride, dest_stride;
   gint br, bl, bt, bb;
-  gint j;
-  gint color1, color2;
 
   br = video_box->border_right;
   bl = video_box->border_left;
@@ -429,97 +458,55 @@ gst_video_box_i420 (GstVideoBox * video_box, guint8 * src, guint8 * dest)
   out_width = video_box->out_width;
   out_height = video_box->out_height;
 
-  destY = dest + GST_VIDEO_I420_Y_OFFSET (out_width, out_height);
+  src_width = video_box->in_width;
+  src_height = video_box->in_height;
 
-  srcY =
-      src + GST_VIDEO_I420_Y_OFFSET (video_box->in_width, video_box->in_height);
-  src_stride = GST_VIDEO_I420_Y_ROWSTRIDE (video_box->in_width);
+  crop_width = src_width - (video_box->crop_left + video_box->crop_right);
+  crop_height = src_height - (video_box->crop_top + video_box->crop_bottom);
 
-  crop_width =
-      video_box->in_width - (video_box->crop_left + video_box->crop_right);
-  crop_height =
-      video_box->in_height - (video_box->crop_top + video_box->crop_bottom);
+  /* Y plane */
+  src_stride = GST_VIDEO_I420_Y_ROWSTRIDE (src_width);
+  dest_stride = GST_VIDEO_I420_Y_ROWSTRIDE (out_width);
 
-  srcY += src_stride * video_box->crop_top + video_box->crop_left;
+  destY = dest + GST_VIDEO_I420_Y_OFFSET (out_width, out_height);
 
-  color1 = yuv_colors_Y[video_box->fill_type];
+  srcY = src + GST_VIDEO_I420_Y_OFFSET (src_width, src_height);
+  srcY += src_stride * video_box->crop_top + video_box->crop_left;
 
-  /* copy Y plane first */
-  for (j = 0; j < bt; j++) {
-    memset (destY, color1, out_width);
-    destY += out_width;
-  }
-  for (j = 0; j < crop_height; j++) {
-    memset (destY, color1, bl);
-    destY += bl;
-    memcpy (destY, srcY, crop_width);
-    destY += crop_width;
-    memset (destY, color1, br);
-    destY += br;
-    srcY += src_stride;
-  }
-  for (j = 0; j < bb; j++) {
-    memset (destY, color1, out_width);
-    destY += out_width;
-  }
+  gst_video_box_copy_plane_i420 (video_box, srcY, destY, br, bl, bt, bb,
+      crop_width, crop_height, src_stride, out_width, dest_stride,
+      yuv_colors_Y[video_box->fill_type]);
 
-  src_stride = GST_VIDEO_I420_U_ROWSTRIDE (video_box->in_width);
+  /* U plane */
+  src_stride = GST_VIDEO_I420_U_ROWSTRIDE (src_width);
+  dest_stride = GST_VIDEO_I420_U_ROWSTRIDE (out_width);
 
   destU = dest + GST_VIDEO_I420_U_OFFSET (out_width, out_height);
-  destV = dest + GST_VIDEO_I420_V_OFFSET (out_width, out_height);
 
-  crop_width /= 2;
-  crop_height /= 2;
-  out_width /= 2;
-  out_height /= 2;
-  bb /= 2;
-  bt /= 2;
-  br /= 2;
-  bl /= 2;
-
-  srcU =
-      src + GST_VIDEO_I420_U_OFFSET (video_box->in_width, video_box->in_height);
-  srcV =
-      src + GST_VIDEO_I420_V_OFFSET (video_box->in_width, video_box->in_height);
+  srcU = src + GST_VIDEO_I420_U_OFFSET (src_width, src_height);
   srcU += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
-  srcV += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
 
-  color1 = yuv_colors_U[video_box->fill_type];
-  color2 = yuv_colors_V[video_box->fill_type];
+  gst_video_box_copy_plane_i420 (video_box, srcU, destU, br / 2, bl / 2, bt / 2,
+      bb / 2, crop_width / 2, crop_height / 2, src_stride, out_width / 2,
+      dest_stride, yuv_colors_U[video_box->fill_type]);
 
-  for (j = 0; j < bt; j++) {
-    memset (destU, color1, out_width);
-    memset (destV, color2, out_width);
-    destU += out_width;
-    destV += out_width;
-  }
-  for (j = 0; j < crop_height; j++) {
-    memset (destU, color1, bl);
-    destU += bl;
-    /* copy U plane */
-    memcpy (destU, srcU, crop_width);
-    destU += crop_width;
-    memset (destU, color1, br);
-    destU += br;
-    srcU += src_stride;
-
-    memset (destV, color2, bl);
-    destV += bl;
-    /* copy V plane */
-    memcpy (destV, srcV, crop_width);
-    destV += crop_width;
-    memset (destV, color2, br);
-    destV += br;
-    srcV += src_stride;
-  }
-  for (j = 0; j < bb; j++) {
-    memset (destU, color1, out_width);
-    memset (destV, color2, out_width);
-    destU += out_width;
-    destV += out_width;
-  }
+  /* V plane */
+  src_stride = GST_VIDEO_I420_V_ROWSTRIDE (src_width);
+  dest_stride = GST_VIDEO_I420_V_ROWSTRIDE (out_width);
+
+  destV = dest + GST_VIDEO_I420_V_OFFSET (out_width, out_height);
+
+  srcV = src + GST_VIDEO_I420_V_OFFSET (src_width, src_height);
+  srcV += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+
+  gst_video_box_copy_plane_i420 (video_box, srcV, destV, br / 2, bl / 2, bt / 2,
+      bb / 2, crop_width / 2, crop_height / 2, src_stride, out_width / 2,
+      dest_stride, yuv_colors_V[video_box->fill_type]);
 }
 
+/* Note the source image is always I420, we
+ * are converting to AYUV on the fly here */
+
 static void
 gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
 {
@@ -685,7 +672,7 @@ gst_video_box_chain (GstPad * pad, GstData * _data)
         GST_BUFFER_DATA (buffer), GST_BUFFER_DATA (outbuf));
   } else {
     outbuf = gst_pad_alloc_buffer (video_box->srcpad,
-        GST_BUFFER_OFFSET_NONE, (new_width * new_height * 3) / 2);
+        GST_BUFFER_OFFSET_NONE, GST_VIDEO_I420_SIZE (new_width, new_height));
 
     gst_video_box_i420 (video_box,
         GST_BUFFER_DATA (buffer), GST_BUFFER_DATA (outbuf));