Search
SailfishOS Open Build Service
>
Projects
>
home:sledge
:
branches:nemo:devel:hw:ti:omap4:common
>
gst-plugins-base
> 0008-add-basic-support-for-I420-NV12-colorspace-conversio.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File 0008-add-basic-support-for-I420-NV12-colorspace-conversio.patch of Package gst-plugins-base
From 6a8be0fa9f9b7ea0180173f37103b8734fa8b0b6 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 27 Nov 2009 11:13:47 -0600 Subject: [PATCH 08/38] add basic support for I420->NV12 colorspace conversion --- gst/stride/gststridetransform.c | 109 ++++++++++++++++++++++++++++++++++++--- gst/stride/gststridetransform.h | 2 +- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 56207d0..03deeb1 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -227,11 +227,43 @@ add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rows idx = gst_structure_n_fields (s) - 1; while (idx >= 0) { const gchar *name = gst_structure_nth_field_name (s, idx); + idx--; + if (!strcmp ("format", name)) { + // we can do simple color format translations, such as converting from one + // YUV420 format to another: + GValue formats = {0}; + GValue fourccval = {0}; + guint fourcc; + if (gst_structure_get_fourcc (s, name, &fourcc)) { + switch (gst_video_format_from_fourcc (fourcc)) { + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_I420: +GST_DEBUG ("Hmm, let's say I can convert I420<-->NV12.."); + g_value_init (&formats, GST_TYPE_LIST); + g_value_init (&fourccval, GST_TYPE_FOURCC); + gst_value_set_fourcc (&fourccval, + GST_MAKE_FOURCC ('I', '4', '2', '0')); + gst_value_list_append_value (&formats, &fourccval); + gst_value_set_fourcc (&fourccval, + GST_MAKE_FOURCC ('N', 'V', '1', '2')); + gst_value_list_append_value (&formats, &fourccval); + gst_structure_set_value (new_s, "format", &formats); + continue; +/* maybe handle other cases later.. + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: +*/ + default: + break; + } + } + } + if (strcmp ("rowstride", name)) { const GValue *val = gst_structure_get_value (s, name); gst_structure_set_value (new_s, name, val); } - idx--; } gst_caps_merge_structure (caps, new_s); @@ -287,18 +319,16 @@ gst_stride_transform_set_caps (GstBaseTransform *base, GstCaps *incaps, GstCaps *outcaps) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GstVideoFormat format; gint width, height; LOG_CAPS (self, incaps); LOG_CAPS (self, outcaps); g_return_val_if_fail (gst_video_format_parse_caps_strided (incaps, - &self->format, &self->width, &self->height, &self->in_rowstride), FALSE); + &self->in_format, &self->width, &self->height, &self->in_rowstride), FALSE); g_return_val_if_fail (gst_video_format_parse_caps_strided (outcaps, - &format, &width, &height, &self->out_rowstride), FALSE); + &self->out_format, &width, &height, &self->out_rowstride), FALSE); - g_return_val_if_fail (self->format == format, FALSE); g_return_val_if_fail (self->width == width, FALSE); g_return_val_if_fail (self->height == height, FALSE); @@ -307,6 +337,49 @@ gst_stride_transform_set_caps (GstBaseTransform *base, /* ************************************************************************* */ +static void +memmove_demux (guchar *new_buf, guchar *orig_buf, gint sz, gint pxstride) +{ + if (new_buf > orig_buf) { + /* copy backwards */ + new_buf += (sz * pxstride); + orig_buf += sz; + while(sz--) { + *new_buf = *orig_buf; + new_buf -= pxstride; + orig_buf--; + } + } else { + while(sz--) { + *new_buf = *orig_buf; + new_buf += pxstride; + orig_buf++; + } + } +} + +static void +stridemove_demux (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, gint height, gint pxstride) +{ + int row; + + GST_DEBUG ("new_buf=%p, orig_buf=%p, new_width=%d, orig_width=%d, height=%d", + new_buf, orig_buf, new_width, orig_width, height); + /* if increasing the stride, work from bottom-up to avoid overwriting data + * that has not been moved yet.. otherwise, work in the opposite order, + * for the same reason. + */ + if (new_width > orig_width) { + for (row=height-1; row>=0; row--) { + memmove_demux (new_buf+(new_width*row), orig_buf+(orig_width*row), orig_width, pxstride); + } + } else { + for (row=0; row<height; row++) { + memmove_demux (new_buf+(new_width*row), orig_buf+(orig_width*row), new_width, pxstride); + } + } +} + /** * Convert from one stride to another... like memmove, but can convert stride in * the process. This function is not aware of pixels, only of bytes. So widths @@ -356,7 +429,29 @@ stridify (GstStrideTransform *self, guchar *strided, guchar *unstrided) gint height = self->height; gint stride = self->out_rowstride; - switch (self->format) { + if (self->out_format != self->in_format) { + + if ((self->in_format == GST_VIDEO_FORMAT_I420) && + (self->out_format == GST_VIDEO_FORMAT_NV12)) { + /* note: if not an in-place conversion, then doing the U&V in one pass + * would be more efficient... but if it is an in-place conversion, I'd + * need to think about whether it is potential for the new UV plane to + * corrupt the V plane before it is done copying.. + */ + stridemove_demux ( + strided + (height*stride) + 1, + unstrided + (int)(height*width*1.25), + stride, width/2, height/2, 2); /* move V */ + stridemove_demux ( + strided + (height*stride), + unstrided + (height*width), + stride, width/2, height/2, 2); /* move U */ + stridemove (strided, unstrided, stride, width, height); /* move Y */ + return GST_FLOW_OK; + } + } + + switch (self->out_format) { case GST_VIDEO_FORMAT_NV12: g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); stridemove (strided, unstrided, stride, width, (GST_ROUND_UP_2 (height) * 3) / 2); @@ -400,7 +495,7 @@ unstridify (GstStrideTransform *self, guchar *unstrided, guchar *strided) gint height = self->height; gint stride = self->in_rowstride; - switch (self->format) { + switch (self->out_format) { case GST_VIDEO_FORMAT_NV12: g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); stridemove (unstrided, strided, width, stride, (GST_ROUND_UP_2 (height) * 3) / 2); diff --git a/gst/stride/gststridetransform.h b/gst/stride/gststridetransform.h index 481959e..0141571 100644 --- a/gst/stride/gststridetransform.h +++ b/gst/stride/gststridetransform.h @@ -55,7 +55,7 @@ struct _GstStrideTransform { GstVideoFilter videofilter; /*< private >*/ - GstVideoFormat format; + GstVideoFormat in_format, out_format; gint width, height; gint in_rowstride; gint out_rowstride; -- 1.7.5.4