summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2012-11-13 10:24:27 +0100
committerOlivier CrĂȘte <olivier.crete@collabora.com>2012-11-13 13:58:42 +0100
commitb6d824c2d9e458f497d3cb16fd658baf1bddbe6d (patch)
treeed4b5d44292a5c7370164fdac31076d1b8b7a261
parent3175a5d82211bd87b6280abfa048f153f2fa440f (diff)
videoflip: Add NV12/NV21 support
https://bugzilla.gnome.org/show_bug.cgi?id=688225
-rw-r--r--gst/videofilter/gstvideoflip.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/gst/videofilter/gstvideoflip.c b/gst/videofilter/gstvideoflip.c
index 713705751..3c03a09fc 100644
--- a/gst/videofilter/gstvideoflip.c
+++ b/gst/videofilter/gstvideoflip.c
@@ -78,6 +78,7 @@ static GstStaticPadTemplate gst_video_flip_src_template =
GST_VIDEO_CAPS_YUV ("I420") ";"
GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("IYUV") ";"
GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("UYVY") ";"
+ GST_VIDEO_CAPS_YUV ("NV12") ";" GST_VIDEO_CAPS_YUV ("NV21") ";"
GST_VIDEO_CAPS_YUV ("YVYU")
)
@@ -97,6 +98,7 @@ static GstStaticPadTemplate gst_video_flip_sink_template =
GST_VIDEO_CAPS_YUV ("I420") ";"
GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("IYUV") ";"
GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("UYVY") ";"
+ GST_VIDEO_CAPS_YUV ("NV12") ";" GST_VIDEO_CAPS_YUV ("NV21") ";"
GST_VIDEO_CAPS_YUV ("YVYU")
)
);
@@ -471,6 +473,216 @@ gst_video_flip_planar_yuv (GstVideoFlip * videoflip, guint8 * dest,
}
static void
+gst_video_flip_semi_planar_yuv (GstVideoFlip * videoflip, guint8 * dest,
+ const guint8 * src)
+{
+ gint x, y;
+ guint8 const *s;
+ guint8 *d;
+ gint s_off, d_off;
+ GstVideoFormat format = videoflip->format;
+ gint sw = videoflip->from_width;
+ gint sh = videoflip->from_height;
+ gint dw = videoflip->to_width;
+ gint dh = videoflip->to_height;
+ gint src_y_stride, src_uv_stride;
+ gint src_y_offset, src_uv_offset;
+ gint src_y_height, src_uv_height;
+ gint src_y_width, src_uv_width;
+ gint dest_y_stride, dest_uv_stride;
+ gint dest_y_offset, dest_uv_offset;
+ gint dest_y_height, dest_uv_height;
+ gint dest_y_width, dest_uv_width;
+
+ src_y_stride = gst_video_format_get_row_stride (format, 0, sw);
+ src_uv_stride = gst_video_format_get_row_stride (format, 1, sw);
+
+ dest_y_stride = gst_video_format_get_row_stride (format, 0, dw);
+ dest_uv_stride = gst_video_format_get_row_stride (format, 1, dw);
+
+ src_y_offset = gst_video_format_get_component_offset (format, 0, sw, sh);
+ src_uv_offset = gst_video_format_get_component_offset (format, 1, sw, sh);
+
+ dest_y_offset = gst_video_format_get_component_offset (format, 0, dw, dh);
+ dest_uv_offset = gst_video_format_get_component_offset (format, 1, dw, dh);
+
+ src_y_width = gst_video_format_get_component_width (format, 0, sw);
+ src_uv_width = gst_video_format_get_component_width (format, 1, sw);
+
+ dest_y_width = gst_video_format_get_component_width (format, 0, dw);
+ dest_uv_width = gst_video_format_get_component_width (format, 1, dw);
+
+ src_y_height = gst_video_format_get_component_height (format, 0, sh);
+ src_uv_height = gst_video_format_get_component_height (format, 1, sh);
+
+ dest_y_height = gst_video_format_get_component_height (format, 0, dh);
+ dest_uv_height = gst_video_format_get_component_height (format, 1, dh);
+
+ switch (videoflip->method) {
+ case GST_VIDEO_FLIP_METHOD_90R:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] =
+ s[(src_y_height - 1 - x) * src_y_stride + y];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = (src_uv_height - 1 - x) * src_uv_stride + y * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ break;
+ case GST_VIDEO_FLIP_METHOD_90L:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] =
+ s[x * src_y_stride + (src_y_width - 1 - y)];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = x * src_uv_stride + (src_uv_width - 1 - y) * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ break;
+ case GST_VIDEO_FLIP_METHOD_180:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] =
+ s[(src_y_height - 1 - y) * src_y_stride + (src_y_width - 1 - x)];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = (src_uv_height - 1 - y) * src_uv_stride + (src_uv_width - 1 -
+ x) * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ break;
+ case GST_VIDEO_FLIP_METHOD_HORIZ:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] =
+ s[y * src_y_stride + (src_y_width - 1 - x)];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = y * src_uv_stride + (src_uv_width - 1 - x) * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ break;
+ case GST_VIDEO_FLIP_METHOD_VERT:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] =
+ s[(src_y_height - 1 - y) * src_y_stride + x];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = (src_uv_height - 1 - y) * src_uv_stride + x * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ break;
+ case GST_VIDEO_FLIP_METHOD_TRANS:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] = s[x * src_y_stride + y];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = x * src_uv_stride + y * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ case GST_VIDEO_FLIP_METHOD_OTHER:
+ /* Flip Y */
+ s = src + src_y_offset;
+ d = dest + dest_y_offset;
+ for (y = 0; y < dest_y_height; y++) {
+ for (x = 0; x < dest_y_width; x++) {
+ d[y * dest_y_stride + x] =
+ s[(src_y_height - 1 - x) * src_y_stride + (src_y_width - 1 - y)];
+ }
+ }
+ /* Flip UV */
+ s = src + src_uv_offset;
+ d = dest + dest_uv_offset;
+ for (y = 0; y < dest_uv_height; y++) {
+ for (x = 0; x < dest_uv_width; x++) {
+ d_off = y * dest_uv_stride + x * 2;
+ s_off = (src_uv_height - 1 - x) * src_uv_stride + (src_uv_width - 1 -
+ y) * 2;
+ d[d_off] = s[s_off];
+ d[d_off + 1] = s[s_off + 1];
+ }
+ }
+ break;
+ case GST_VIDEO_FLIP_METHOD_IDENTITY:
+ g_assert_not_reached ();
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
gst_video_flip_packed_simple (GstVideoFlip * videoflip, guint8 * dest,
const guint8 * src)
{
@@ -863,6 +1075,10 @@ gst_video_flip_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
case GST_VIDEO_FORMAT_BGR:
vf->process = gst_video_flip_packed_simple;
break;
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV21:
+ vf->process = gst_video_flip_semi_planar_yuv;
+ break;
default:
break;
}