videocrop: Add NV12/NV21 support
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Fri, 9 Nov 2012 12:27:16 +0000 (13:27 +0100)
committerOlivier CrĂȘte <olivier.crete@collabora.com>
Sat, 10 Nov 2012 00:52:44 +0000 (01:52 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=687964

gst/videocrop/gstvideocrop.c
gst/videocrop/gstvideocrop.h

index eeac548..dc18c2b 100644 (file)
@@ -80,7 +80,7 @@ enum
 #define VIDEO_CROP_CAPS                                \
   GST_VIDEO_CAPS_MAKE ("{ RGBx, xRGB, BGRx, xBGR, "    \
       "RGBA, ARGB, BGRA, ABGR, RGB, BGR, AYUV, YUY2, " \
-      "YVYU, UYVY, I420, RGB16, RGB15, GRAY8 }")
+      "YVYU, UYVY, I420, RGB16, RGB15, GRAY8, NV12, NV21 }")
 
 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -373,6 +373,47 @@ gst_video_crop_transform_planar (GstVideoCrop * vcrop,
   }
 }
 
+static void
+gst_video_crop_transform_semi_planar (GstVideoCrop * vcrop,
+    GstVideoFrame * in_frame, GstVideoFrame * out_frame)
+{
+  gint width, height;
+  guint8 *y_out, *uv_out;
+  guint8 *y_in, *uv_in;
+  guint i, dx;
+
+  width = GST_VIDEO_FRAME_WIDTH (out_frame);
+  height = GST_VIDEO_FRAME_HEIGHT (out_frame);
+
+  /* Y plane */
+  y_in = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
+  y_out = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
+
+  /* UV plane */
+  uv_in = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 1);
+  uv_out = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 1);
+
+  y_in += vcrop->crop_top * GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0) +
+      vcrop->crop_left;
+  dx = width;
+
+  for (i = 0; i < height; ++i) {
+    memcpy (y_out, y_in, dx);
+    y_in += GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0);
+    y_out += GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0);
+  }
+
+  uv_in += (vcrop->crop_top / 2) * GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 1);
+  uv_in += GST_ROUND_DOWN_2 (vcrop->crop_left);
+  dx = GST_ROUND_UP_2 (width);
+
+  for (i = 0; i < GST_ROUND_UP_2 (height) / 2; i++) {
+    memcpy (uv_out, uv_in, dx);
+    uv_in += GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 1);
+    uv_out += GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 1);
+  }
+}
+
 static GstFlowReturn
 gst_video_crop_transform_frame (GstVideoFilter * vfilter,
     GstVideoFrame * in_frame, GstVideoFrame * out_frame)
@@ -390,6 +431,9 @@ gst_video_crop_transform_frame (GstVideoFilter * vfilter,
     case VIDEO_CROP_PIXEL_FORMAT_PLANAR:
       gst_video_crop_transform_planar (vcrop, in_frame, out_frame);
       break;
+    case VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR:
+      gst_video_crop_transform_semi_planar (vcrop, in_frame, out_frame);
+      break;
     default:
       g_assert_not_reached ();
   }
@@ -657,6 +701,10 @@ gst_video_crop_set_info (GstVideoFilter * vfilter, GstCaps * in,
       case GST_VIDEO_FORMAT_YV12:
         crop->packing = VIDEO_CROP_PIXEL_FORMAT_PLANAR;
         break;
+      case GST_VIDEO_FORMAT_NV12:
+      case GST_VIDEO_FORMAT_NV21:
+        crop->packing = VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR;
+        break;
       default:
         goto unknown_format;
     }
index 346e9bc..cd8ad06 100644 (file)
@@ -38,7 +38,8 @@ G_BEGIN_DECLS
 typedef enum {
   VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE = 0,  /* RGBx, AYUV */
   VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX,     /* UYVY, YVYU */
-  VIDEO_CROP_PIXEL_FORMAT_PLANAR              /* I420, YV12 */
+  VIDEO_CROP_PIXEL_FORMAT_PLANAR,             /* I420, YV12 */
+  VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR         /* NV12, NV21 */
 } VideoCropPixelFormat;
 
 typedef struct _GstVideoCropImageDetails GstVideoCropImageDetails;