diff options
-rw-r--r-- | gst/videocrop/gstvideocrop.c | 50 | ||||
-rw-r--r-- | gst/videocrop/gstvideocrop.h | 6 | ||||
-rw-r--r-- | tests/check/elements/videocrop.c | 10 |
3 files changed, 65 insertions, 1 deletions
diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c index 082ca1184..a6b4562d8 100644 --- a/gst/videocrop/gstvideocrop.c +++ b/gst/videocrop/gstvideocrop.c @@ -102,6 +102,8 @@ enum GST_VIDEO_CAPS_YUV ("Y800") ";" \ GST_VIDEO_CAPS_YUV ("I420") ";" \ GST_VIDEO_CAPS_YUV ("YV12") ";" \ + GST_VIDEO_CAPS_YUV ("NV12") ";" \ + GST_VIDEO_CAPS_YUV ("NV21") ";" \ GST_VIDEO_CAPS_RGB_16 ";" \ GST_VIDEO_CAPS_RGB_15 ";" \ GST_VIDEO_CAPS_GRAY @@ -327,6 +329,15 @@ gst_video_crop_get_image_details_from_caps (GstVideoCrop * vcrop, details->size = details->v_off + details->v_stride * (GST_ROUND_UP_2 (height) / 2); break; + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + case GST_MAKE_FOURCC ('N', 'V', '2', '1'): + details->packing = VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR; + details->y_stride = GST_ROUND_UP_4 (width); + details->uv_stride = details->y_stride; + details->y_off = 0; + details->uv_off = details->y_stride * GST_ROUND_UP_2 (height); + details->size = details->y_stride * GST_ROUND_UP_2 (height) * 3 / 2; + break; } default: goto unknown_format; @@ -480,6 +491,42 @@ gst_video_crop_transform_planar (GstVideoCrop * vcrop, GstBuffer * inbuf, } } +static void +gst_video_crop_transform_semi_planar (GstVideoCrop * vcrop, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + guint8 *y_out, *uv_out; + guint8 *y_in, *uv_in; + guint i, dx; + + /* Y plane */ + y_in = GST_BUFFER_DATA (inbuf); + y_out = GST_BUFFER_DATA (outbuf); + + y_in += vcrop->crop_top * vcrop->in.y_stride + vcrop->crop_left; + dx = vcrop->out.width; + + for (i = 0; i < vcrop->out.height; ++i) { + memcpy (y_out, y_in, dx); + y_in += vcrop->in.y_stride; + y_out += vcrop->out.y_stride; + } + + /* UV plane */ + uv_in = GST_BUFFER_DATA (inbuf) + vcrop->in.uv_off; + uv_out = GST_BUFFER_DATA (outbuf) + vcrop->out.uv_off; + + uv_in += (vcrop->crop_top / 2) * vcrop->in.uv_stride; + uv_in += GST_ROUND_DOWN_2 (vcrop->crop_left); + dx = GST_ROUND_UP_2 (vcrop->out.width); + + for (i = 0; i < GST_ROUND_UP_2 (vcrop->out.height) / 2; i++) { + memcpy (uv_out, uv_in, dx); + uv_in += vcrop->in.uv_stride; + uv_out += vcrop->out.uv_stride; + } +} + static GstFlowReturn gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf, GstBuffer * outbuf) @@ -496,6 +543,9 @@ gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf, case VIDEO_CROP_PIXEL_FORMAT_PLANAR: gst_video_crop_transform_planar (vcrop, inbuf, outbuf); break; + case VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR: + gst_video_crop_transform_semi_planar (vcrop, inbuf, outbuf); + break; default: g_assert_not_reached (); } diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h index d13ca9b2d..994b73dba 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; @@ -60,6 +61,9 @@ struct _GstVideoCropImageDetails guint y_stride, y_off; guint u_stride, u_off; guint v_stride, v_off; + + /* For bi-planar UV or VU plane */ + guint uv_stride, uv_off; }; typedef struct _GstVideoCrop GstVideoCrop; diff --git a/tests/check/elements/videocrop.c b/tests/check/elements/videocrop.c index 9f68e9575..fd0d6381d 100644 --- a/tests/check/elements/videocrop.c +++ b/tests/check/elements/videocrop.c @@ -281,6 +281,16 @@ check_1x1_buffer (GstBuffer * buf) fail_unless_equals_int (GST_BUFFER_DATA (buf)[3], 240); /* no chroma planes */ break; + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + fail_unless_equals_int (GST_BUFFER_DATA (buf)[0], 81); + fail_unless_equals_int (GST_BUFFER_DATA (buf)[8], 90); + fail_unless_equals_int (GST_BUFFER_DATA (buf)[9], 240); + break; + case GST_MAKE_FOURCC ('N', 'V', '2', '1'): + fail_unless_equals_int (GST_BUFFER_DATA (buf)[0], 81); + fail_unless_equals_int (GST_BUFFER_DATA (buf)[8], 240); + fail_unless_equals_int (GST_BUFFER_DATA (buf)[9], 90); + break; default: GST_LOG ("not checking %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (format)); break; |