From e111068f7bd348c34082da2513f527185547e892 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Fri, 9 Nov 2012 13:27:16 +0100 Subject: [PATCH] videocrop: Add NV12/NV21 support https://bugzilla.gnome.org/show_bug.cgi?id=687964 --- gst/videocrop/gstvideocrop.c | 50 +++++++++++++++++++++++++++++++++++++++++++- gst/videocrop/gstvideocrop.h | 3 ++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c index eeac548..dc18c2b 100644 --- a/gst/videocrop/gstvideocrop.c +++ b/gst/videocrop/gstvideocrop.c @@ -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; } diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h index 346e9bc..cd8ad06 100644 --- a/gst/videocrop/gstvideocrop.h +++ b/gst/videocrop/gstvideocrop.h @@ -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; -- 2.7.4