Search
SailfishOS Open Build Service
>
Projects
>
home:sledge
:
branches:nemo:devel:hw:ti:omap4:common
>
gst-plugins-base
> 0004-stridetransform-implement-transform-function.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File 0004-stridetransform-implement-transform-function.patch of Package gst-plugins-base
From 74dfcccea832131155ce7b5613ebca0ffacc63ab Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 31 Jul 2009 17:39:47 -0500 Subject: [PATCH 04/38] stridetransform: implement transform function Still needed are a few details, like conversion from one stride to another (instead of just strided->nonstrided or visa versa), and support for RGB and more YUV color formats. --- gst/stride/gststridetransform.c | 163 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 157 insertions(+), 6 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index e31bf11..a911cd0 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -187,7 +187,7 @@ add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rows GstStructure *new_s = gst_structure_new (name, NULL); if (rowstride) { - gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, 1000, NULL); // XXX + gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, 1000, NULL); // TODO } idx = gst_structure_n_fields (s) - 1; @@ -253,6 +253,8 @@ 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); @@ -260,17 +262,166 @@ gst_stride_transform_set_caps (GstBaseTransform *base, g_return_val_if_fail (gst_video_format_parse_caps_strided (incaps, &self->format, &self->width, &self->height, &self->in_rowstride), FALSE); g_return_val_if_fail (gst_video_format_parse_caps_strided (outcaps, - NULL, NULL, NULL, &self->out_rowstride), FALSE); + &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); return TRUE; } +/* ************************************************************************* */ + +/** + * 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 + * are given in bytes, not pixels. The new_buf and orig_buf can point to the + * same buffers to do an in-place conversion, but the buffer should be large + * enough. + */ +static void +stridemove (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, gint height) +{ + 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 (new_buf+(new_width*row), orig_buf+(orig_width*row), orig_width); + } + } else { + for (row=0; row<height; row++) { + memmove (new_buf+(new_width*row), orig_buf+(orig_width*row), orig_width); + } + } +} + + +/** + * Convert from a non-strided buffer to strided. The two buffer pointers could + * be pointing to the same memory block for in-place transform.. assuming that + * the buffer is large enough + * + * @strided: the pointer to the resulting strided buffer + * @unstrided: the pointer to the initial unstrided buffer + * @fourcc: the color format + * @stride: the stride, in bytes + * @width: the width in pixels + * @height: the height in pixels + */ +static GstFlowReturn +stridify (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + switch (self->format) { +#if 0 /* TODO */ + case GST_VIDEO_FORMAT_NV12: + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + stridemove (strided, unstrided, stride, width, height * 1.5); + return GST_FLOW_OK; +#endif + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + stridemove ( + strided + (int)(height*stride*1.5), + unstrided + (int)(height*width*1.5), + stride, width/2, height); /* move U/V */ + stridemove ( + strided + (height*stride), + unstrided + (height*width), + stride, width/2, height); /* move V/U */ + stridemove (strided, unstrided, stride, width, height); /* move Y */ + return GST_FLOW_OK; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + stridemove (strided, unstrided, stride, width*2, height); + return GST_FLOW_OK; + default: + GST_WARNING ("unknown color format!\n"); + return GST_FLOW_ERROR; + } +} + + +/** + * Convert from a strided buffer to non-strided. The two buffer pointers could + * be pointing to the same memory block for in-place transform.. + * + * @unstrided: the pointer to the resulting unstrided buffer + * @strided: the pointer to the initial strided buffer + */ +static GstFlowReturn +unstridify (GstStrideTransform *self, guchar *unstrided, guchar *strided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->in_rowstride; + + switch (self->format) { +#if 0 /* TODO */ + case GST_VIDEO_FORMAT_NV12: + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + stridemove (unstrided, strided, width, stride, height * 1.5); + return GST_FLOW_OK; +#endif + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + stridemove (unstrided, strided, width, stride, height); /* move Y */ + stridemove ( + unstrided + (height*width), + strided + (height*stride), + width/2, stride, height); /* move V/U */ + stridemove ( + unstrided + (int)(height*width*1.5), + strided + (int)(height*stride*1.5), + width/2, stride, height); /* move U/V */ + return GST_FLOW_OK; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + stridemove (unstrided, strided, width*2, stride, height); + return GST_FLOW_OK; + default: + GST_WARNING ("unknown color format!\n"); + return GST_FLOW_ERROR; + } +} + + static GstFlowReturn gst_stride_transform_transform (GstBaseTransform *base, GstBuffer *inbuf, GstBuffer *outbuf) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "not implemented"); + + GST_DEBUG_OBJECT (self, "inbuf=%p, outbuf=%p", inbuf, outbuf); + + if (self->in_rowstride && self->out_rowstride) { + GST_DEBUG_OBJECT (self, "not implemented"); // TODO + return GST_FLOW_ERROR; + } else if (self->in_rowstride) { + return unstridify (self, + GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); + } else if (self->out_rowstride) { + return stridify (self, + GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); + } + + GST_DEBUG_OBJECT (self, "this shouldn't happen! in_rowstride=%d, out_rowstride=%d", + self->in_rowstride, self->out_rowstride); + return GST_FLOW_ERROR; } @@ -278,7 +429,7 @@ static GstFlowReturn gst_stride_transform_transform_ip (GstBaseTransform *base, GstBuffer *buf) { - GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "not implemented"); - return GST_FLOW_ERROR; + /* transform function is safe to call with same buffer ptr: + */ + return gst_stride_transform_transform (base, buf, buf); } -- 1.7.5.4