Search
SailfishOS Open Build Service
>
Projects
>
home:sledge
:
branches:nemo:devel:hw:ti:omap4:common
>
gst-plugins-base
> cumulative.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File cumulative.patch of Package gst-plugins-base
From 616e6f0971a21711021a34ff724490f170a48b29 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Thu, 30 Jul 2009 20:41:18 -0500 Subject: [PATCH] stridetransform: skeletal implementation of stridetransform element --- configure.ac | 2 + gst/stride/Makefile.am | 15 ++++ gst/stride/gststridetransform.c | 178 +++++++++++++++++++++++++++++++++++++++ gst/stride/gststridetransform.h | 66 +++++++++++++++ gst/stride/plugin.c | 45 ++++++++++ 5 files changed, 306 insertions(+) create mode 100644 gst/stride/Makefile.am create mode 100644 gst/stride/gststridetransform.c create mode 100644 gst/stride/gststridetransform.h create mode 100644 gst/stride/plugin.c diff --git a/configure.ac b/configure.ac index 1901bcf..f3dc2b3 100644 --- a/configure.ac +++ b/configure.ac @@ -424,6 +424,7 @@ AG_GST_CHECK_PLUGIN(ffmpegcolorspace) AG_GST_CHECK_PLUGIN(gdp) AG_GST_CHECK_PLUGIN(playback) AG_GST_CHECK_PLUGIN(audioresample) +AG_GST_CHECK_PLUGIN(stride) AG_GST_CHECK_PLUGIN(subparse) AG_GST_CHECK_PLUGIN(tcp) AG_GST_CHECK_PLUGIN(typefind) @@ -939,6 +940,7 @@ gst/ffmpegcolorspace/Makefile gst/gdp/Makefile gst/playback/Makefile gst/audioresample/Makefile +gst/stride/Makefile gst/subparse/Makefile gst/tcp/Makefile gst/typefind/Makefile diff --git a/gst/stride/Makefile.am b/gst/stride/Makefile.am new file mode 100644 index 0000000..1adc197 --- /dev/null +++ b/gst/stride/Makefile.am @@ -0,0 +1,15 @@ +plugin_LTLIBRARIES = libgststridetransform.la + +libgststridetransform_la_SOURCES = \ + gststridetransform.c \ + plugin.c + +libgststridetransform_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgststridetransform_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgststridetransform_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) +libgststridetransform_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gststridetransform.h diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c new file mode 100644 index 0000000..21f2d6e --- /dev/null +++ b/gst/stride/gststridetransform.c @@ -0,0 +1,178 @@ +/* GStreamer + * + * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ + * + * Description: V4L2 sink element + * Created on: Jul 30, 2009 + * Author: Rob Clark <rob@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/** + * SECTION:element-stridetransform + * + * stridetransform can be used to convert between video buffers + * with and without stride, or between buffers with differing + * stride + * + * <refsect2> + * <title>Example launch lines</title> + * |[ + * gst-launch ???? TODO + * ]| This pipeline ???? TODO + * </refsect2> + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "gststridetransform.h" +#include "gst/gst-i18n-plugin.h" + + +static const GstElementDetails stridetransform_details = +GST_ELEMENT_DETAILS ("Stride transform", + "Filter/Converter/Video", + "Convert between video buffers with and without stride, or with differing stride", + "Rob Clark <rob@ti.com>,"); + +GST_DEBUG_CATEGORY (stridetransform_debug); +#define GST_CAT_DEFAULT stridetransform_debug + +/* type functions */ +static void gst_stride_transform_dispose (GObject * obj); + +/* GstBaseTransform functions */ +static gboolean gst_stride_transform_get_unit_size (GstBaseTransform * base, + GstCaps * caps, guint * size); +static GstCaps *gst_stride_transform_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps); +static void gst_stride_transform_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); +static gboolean gst_stride_transform_set_caps (GstBaseTransform * base, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, + GstBuffer * inbuf, GstBuffer * outbuf); +static GstFlowReturn gst_stride_transform_transform_ip (GstBaseTransform * base, + GstBuffer * buf); + +GST_BOILERPLATE (GstStrideTransform, gst_stride_transform, GstVideoFilter, GST_TYPE_VIDEO_FILTER); + + +static void +gst_stride_transform_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (stridetransform_debug, "stride", 0, "stride transform element"); + + gst_element_class_set_details (gstelement_class, &stridetransform_details); +} + +static void +gst_stride_transform_class_init (GstStrideTransformClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->dispose = gst_stride_transform_dispose; + + basetransform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_stride_transform_get_unit_size); + basetransform_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_stride_transform_transform_caps); + basetransform_class->fixate_caps = + GST_DEBUG_FUNCPTR (gst_stride_transform_fixate_caps); + basetransform_class->set_caps = + GST_DEBUG_FUNCPTR (gst_stride_transform_set_caps); + basetransform_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_stride_transform_transform_ip); + basetransform_class->transform = + GST_DEBUG_FUNCPTR (gst_stride_transform_transform); + + basetransform_class->passthrough_on_same_caps = TRUE; +} + +static void +gst_stride_transform_init (GstStrideTransform * self, GstStrideTransformClass * klass) +{ + GST_DEBUG_OBJECT (self, "not implemented"); +} + + +static void +gst_stride_transform_dispose (GObject * object) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (object); + GST_DEBUG_OBJECT (self, "not implemented"); + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static gboolean +gst_stride_transform_get_unit_size (GstBaseTransform * base, + GstCaps * caps, guint * size) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); + GST_DEBUG_OBJECT (self, "not implemented"); + return FALSE; +} + +static GstCaps * +gst_stride_transform_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); + GST_DEBUG_OBJECT (self, "not implemented"); + return NULL; +} + +static void +gst_stride_transform_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); + GST_DEBUG_OBJECT (self, "not implemented"); +} + +static gboolean +gst_stride_transform_set_caps (GstBaseTransform * base, + GstCaps * incaps, GstCaps * outcaps) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); + GST_DEBUG_OBJECT (self, "not implemented"); + return FALSE; +} + +static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, + GstBuffer * inbuf, GstBuffer * outbuf) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); + GST_DEBUG_OBJECT (self, "not implemented"); + return GST_FLOW_ERROR; +} + +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; +} diff --git a/gst/stride/gststridetransform.h b/gst/stride/gststridetransform.h new file mode 100644 index 0000000..b4f7d59 --- /dev/null +++ b/gst/stride/gststridetransform.h @@ -0,0 +1,66 @@ +/* GStreamer + * + * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ + * + * Description: V4L2 sink element + * Created on: Jul 2, 2009 + * Author: Rob Clark <rob@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GSTSTRIDETRANSFORM_H__ +#define __GSTSTRIDETRANSFORM_H__ + + +#include <gst/video/gstvideofilter.h> + +G_BEGIN_DECLS + +#define GST_TYPE_STRIDE_TRANSFORM \ + (gst_stride_transform_get_type()) +#define GST_STRIDE_TRANSFORM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STRIDE_TRANSFORM,GstStrideTransform)) +#define GST_STRIDE_TRANSFORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STRIDE_TRANSFORM,GstStrideTransformClass)) +#define GST_IS_STRIDE_TRANSFORM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STRIDE_TRANSFORM)) +#define GST_IS_STRIDE_TRANSFORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STRIDE_TRANSFORM)) + +typedef struct _GstStrideTransform GstStrideTransform; +typedef struct _GstStrideTransformClass GstStrideTransformClass; + +/** + * GstStrideTransform: + * + * Opaque datastructure. + */ +struct _GstStrideTransform { + GstVideoFilter videofilter; + +}; + +struct _GstStrideTransformClass { + GstVideoFilterClass parent_class; +}; + +GType gst_stride_transform_get_type (void); + +G_END_DECLS + + +#endif /* __GSTSTRIDETRANSFORM_H__ */ diff --git a/gst/stride/plugin.c b/gst/stride/plugin.c new file mode 100644 index 0000000..7672bdc --- /dev/null +++ b/gst/stride/plugin.c @@ -0,0 +1,45 @@ +/* GStreamer + * + * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ + * + * Description: V4L2 sink element + * Created on: Jul 30, 2009 + * Author: Rob Clark <rob@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gststridetransform.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "stridetransform", + GST_RANK_PRIMARY, gst_stride_transform_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "stridetransform", + "Convert video from strided to non-strided, or between different row-strides", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) -- 1.7.9.5 From a86ee95238e1a1a62c5a6de20a281ba415ba09ed Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 31 Jul 2009 16:31:42 -0500 Subject: [PATCH] stridetransform: implement caps negotiation and related parts now all that is left is to implement the actual transform functions --- gst-libs/gst/video/video.h | 10 +++ gst/stride/gststridetransform.c | 190 ++++++++++++++++++++++++++++++--------- gst/stride/gststridetransform.h | 38 ++++++++ 3 files changed, 196 insertions(+), 42 deletions(-) diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h index 36750e9..717c59a 100644 --- a/gst-libs/gst/video/video.h +++ b/gst-libs/gst/video/video.h @@ -393,6 +393,16 @@ typedef enum { "height = " GST_VIDEO_SIZE_RANGE ", " \ "framerate = " GST_VIDEO_FPS_RANGE + +#define GST_VIDEO_CAPS_YUV_STRIDED(fourcc, rowstride) \ + GST_VIDEO_CAPS_YUV(fourcc) "; " \ + "video/x-raw-yuv-strided, " \ + "format = (fourcc) " fourcc ", " \ + "rowstride = (int) " rowstride ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + /* buffer flags */ /** diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 21f2d6e..e31bf11 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -33,7 +33,10 @@ * <refsect2> * <title>Example launch lines</title> * |[ - * gst-launch ???? TODO + * gst-launch videotestsrc ! video/x-raw-yuv,format=(fourcc)YUY2,width=320,height=240,framerate=30/1 ! + * stridetransform ! video/x-raw-yuv-strided,format=(fourcc)YUY2,width=320,height=240,rowstride=700,framerate=30/1 ! + * stridetransform ! video/x-raw-yuv,format=(fourcc)YUY2,width=320,height=240,framerate=30/1 ! + * v4l2sink * ]| This pipeline ???? TODO * </refsect2> */ @@ -43,8 +46,11 @@ #include <config.h> #endif -#include "gststridetransform.h" +#include <string.h> +#include <gst/video/video.h> + #include "gst/gst-i18n-plugin.h" +#include "gststridetransform.h" static const GstElementDetails stridetransform_details = @@ -53,25 +59,44 @@ GST_ELEMENT_DETAILS ("Stride transform", "Convert between video buffers with and without stride, or with differing stride", "Rob Clark <rob@ti.com>,"); + +/* TODO: add rgb formats too! */ +#define SUPPORTED_CAPS \ + GST_VIDEO_CAPS_YUV_STRIDED ("{ I420, YV12, YUY2 }", "[ 0, max ]") + + +static GstStaticPadTemplate src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (SUPPORTED_CAPS) + ); + +static GstStaticPadTemplate sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (SUPPORTED_CAPS) + ); + + GST_DEBUG_CATEGORY (stridetransform_debug); #define GST_CAT_DEFAULT stridetransform_debug /* type functions */ -static void gst_stride_transform_dispose (GObject * obj); +static void gst_stride_transform_dispose (GObject *obj); /* GstBaseTransform functions */ -static gboolean gst_stride_transform_get_unit_size (GstBaseTransform * base, - GstCaps * caps, guint * size); -static GstCaps *gst_stride_transform_transform_caps (GstBaseTransform * base, - GstPadDirection direction, GstCaps * caps); -static void gst_stride_transform_fixate_caps (GstBaseTransform * base, - GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); -static gboolean gst_stride_transform_set_caps (GstBaseTransform * base, - GstCaps * incaps, GstCaps * outcaps); -static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, - GstBuffer * inbuf, GstBuffer * outbuf); -static GstFlowReturn gst_stride_transform_transform_ip (GstBaseTransform * base, - GstBuffer * buf); +static gboolean gst_stride_transform_get_unit_size (GstBaseTransform *base, + GstCaps *caps, guint *size); +static GstCaps *gst_stride_transform_transform_caps (GstBaseTransform *base, + GstPadDirection direction, GstCaps *caps); +static gboolean gst_stride_transform_set_caps (GstBaseTransform *base, + GstCaps *incaps, GstCaps *outcaps); +static GstFlowReturn gst_stride_transform_transform (GstBaseTransform *base, + GstBuffer *inbuf, GstBuffer *outbuf); +static GstFlowReturn gst_stride_transform_transform_ip (GstBaseTransform *base, + GstBuffer *buf); GST_BOILERPLATE (GstStrideTransform, gst_stride_transform, GstVideoFilter, GST_TYPE_VIDEO_FILTER); @@ -84,10 +109,15 @@ gst_stride_transform_base_init (gpointer g_class) GST_DEBUG_CATEGORY_INIT (stridetransform_debug, "stride", 0, "stride transform element"); gst_element_class_set_details (gstelement_class, &stridetransform_details); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_template)); } static void -gst_stride_transform_class_init (GstStrideTransformClass * klass) +gst_stride_transform_class_init (GstStrideTransformClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS (klass); @@ -98,8 +128,6 @@ gst_stride_transform_class_init (GstStrideTransformClass * klass) GST_DEBUG_FUNCPTR (gst_stride_transform_get_unit_size); basetransform_class->transform_caps = GST_DEBUG_FUNCPTR (gst_stride_transform_transform_caps); - basetransform_class->fixate_caps = - GST_DEBUG_FUNCPTR (gst_stride_transform_fixate_caps); basetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_stride_transform_set_caps); basetransform_class->transform_ip = @@ -111,57 +139,135 @@ gst_stride_transform_class_init (GstStrideTransformClass * klass) } static void -gst_stride_transform_init (GstStrideTransform * self, GstStrideTransformClass * klass) +gst_stride_transform_init (GstStrideTransform *self, GstStrideTransformClass *klass) { GST_DEBUG_OBJECT (self, "not implemented"); } static void -gst_stride_transform_dispose (GObject * object) +gst_stride_transform_dispose (GObject *object) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (object); GST_DEBUG_OBJECT (self, "not implemented"); G_OBJECT_CLASS (parent_class)->dispose (object); } +/** + * figure out the required buffer size based on @caps + */ static gboolean -gst_stride_transform_get_unit_size (GstBaseTransform * base, - GstCaps * caps, guint * size) +gst_stride_transform_get_unit_size (GstBaseTransform *base, + GstCaps *caps, guint *size) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "not implemented"); - return FALSE; + GstVideoFormat format; + gint width, height, rowstride; + + g_return_val_if_fail (gst_video_format_parse_caps_strided ( + caps, &format, &width, &height, &rowstride), FALSE); + + *size = gst_video_format_get_size_strided (format, width, height, rowstride); + + GST_DEBUG_OBJECT (self, + "format=%d, width=%d, height=%d, rowstride=%d -> size=%d", + format, width, height, rowstride, *size); + + return TRUE; } -static GstCaps * -gst_stride_transform_transform_caps (GstBaseTransform * base, - GstPadDirection direction, GstCaps * caps) + +/** + * helper to add all fields, other than rowstride to @caps, copied from @s. + */ +static void +add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rowstride) { - GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "not implemented"); - return NULL; + gint idx; + GstStructure *new_s = gst_structure_new (name, NULL); + + if (rowstride) { + gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, 1000, NULL); // XXX + } + + idx = gst_structure_n_fields (s) - 1; + while (idx >= 0) { + const gchar *name = gst_structure_nth_field_name (s, idx); + 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); } -static void -gst_stride_transform_fixate_caps (GstBaseTransform * base, - GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) + +/** + * we can transform @caps to strided or non-strided caps with otherwise + * identical parameters + */ +static GstCaps * +gst_stride_transform_transform_caps (GstBaseTransform *base, + GstPadDirection direction, GstCaps *caps) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "not implemented"); + GstCaps *ret; + GstStructure *s; + + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL); + + GST_DEBUG_OBJECT (self, "direction=%d, caps=%p", direction, caps); + LOG_CAPS (self, caps); + + ret = gst_caps_new_empty (); + s = gst_caps_get_structure (caps, 0); + + if (gst_structure_has_name (s, "video/x-raw-yuv") || + gst_structure_has_name (s, "video/x-raw-yuv-strided")) { + + add_all_fields (ret, "video/x-raw-yuv", s, FALSE); + add_all_fields (ret, "video/x-raw-yuv-strided", s, TRUE); + + } else if (gst_structure_has_name (s, "video/x-raw-rgb") || + gst_structure_has_name (s, "video/x-raw-rgb-strided")) { + + add_all_fields (ret, "video/x-raw-rgb", s, FALSE); + add_all_fields (ret, "video/x-raw-rgb-strided", s, TRUE); + + } + + LOG_CAPS (self, ret); + + return ret; } +/** + * at this point, we have identical fourcc, width, and height for @incaps + * and @outcaps.. so we need to extract these to use for transforming, + * plus the requested rowstride of the @incaps and @outcaps + */ static gboolean -gst_stride_transform_set_caps (GstBaseTransform * base, - GstCaps * incaps, GstCaps * outcaps) +gst_stride_transform_set_caps (GstBaseTransform *base, + GstCaps *incaps, GstCaps *outcaps) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "not implemented"); - return FALSE; + + 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); + g_return_val_if_fail (gst_video_format_parse_caps_strided (outcaps, + NULL, NULL, NULL, &self->out_rowstride), FALSE); + + return TRUE; } -static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, - GstBuffer * inbuf, GstBuffer * outbuf) +static GstFlowReturn +gst_stride_transform_transform (GstBaseTransform *base, + GstBuffer *inbuf, GstBuffer *outbuf) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); GST_DEBUG_OBJECT (self, "not implemented"); @@ -169,8 +275,8 @@ static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, } static GstFlowReturn -gst_stride_transform_transform_ip (GstBaseTransform * base, - GstBuffer * buf) +gst_stride_transform_transform_ip (GstBaseTransform *base, + GstBuffer *buf) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); GST_DEBUG_OBJECT (self, "not implemented"); diff --git a/gst/stride/gststridetransform.h b/gst/stride/gststridetransform.h index b4f7d59..d80197f 100644 --- a/gst/stride/gststridetransform.h +++ b/gst/stride/gststridetransform.h @@ -27,6 +27,8 @@ #include <gst/video/gstvideofilter.h> +#include <gst/video/video.h> + G_BEGIN_DECLS @@ -52,6 +54,11 @@ typedef struct _GstStrideTransformClass GstStrideTransformClass; struct _GstStrideTransform { GstVideoFilter videofilter; + /*< private >*/ + GstVideoFormat format; + gint width, height; + gint in_rowstride; + gint out_rowstride; }; struct _GstStrideTransformClass { @@ -63,4 +70,35 @@ GType gst_stride_transform_get_type (void); G_END_DECLS + + +/* note: in case this is a build with TTIF logging, we can optimize slightly + * and avoid the gst_caps_to_string() in case logging isn't enabled by using + * the TTIF_TRACE_ARG_PROCESSOR feature of ttif_trace_fprintf(): + */ +#ifdef GST_LOG_OVER_TTIF +# define LOG_CAPS(obj, caps) G_STMT_START { \ + if (caps) { \ + static TTIF_TRACE_ARG_PROCESSOR proc = { \ + .convert = (char (*)(void *))gst_caps_to_string, \ + .free = (void (*)(char *))g_free \ + }; \ + GST_DEBUG_OBJECT (obj, "%s: %qs", #caps, &proc, (caps)); \ + } else { \ + GST_DEBUG_OBJECT (obj, "null"); \ + } \ + } G_STMT_END +#else +# define LOG_CAPS(obj, caps) G_STMT_START { \ + if (caps) { \ + gchar *capstr = gst_caps_to_string (caps); \ + GST_DEBUG_OBJECT (obj, "%s: %s", #caps, capstr); \ + g_free (capstr); \ + } else { \ + GST_DEBUG_OBJECT (obj, "null"); \ + } \ + } G_STMT_END +#endif + + #endif /* __GSTSTRIDETRANSFORM_H__ */ -- 1.7.9.5 From 4819a17561e36a6bb01ff0062b364c607cb5ea14 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 31 Jul 2009 17:39:47 -0500 Subject: [PATCH] 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 file 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.9.5 From ea25f2e4167a8b1f3ed691a5b0d54addb1a85ead Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Sun, 16 Aug 2009 21:04:40 -0500 Subject: [PATCH] add gst_stride_transform_transform_size() input buffer size and output buffer size many not be multiples of a common unit size, so the transform_size() method should be used --- gst/stride/gststridetransform.c | 38 ++++++++++++++++++++++++++++++++++++-- gst/stride/gststridetransform.h | 34 +++++----------------------------- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index a911cd0..adc22ce 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -62,7 +62,7 @@ GST_ELEMENT_DETAILS ("Stride transform", /* TODO: add rgb formats too! */ #define SUPPORTED_CAPS \ - GST_VIDEO_CAPS_YUV_STRIDED ("{ I420, YV12, YUY2 }", "[ 0, max ]") + GST_VIDEO_CAPS_YUV_STRIDED ("{ I420, YV12, YUY2, UYVY }", "[ 0, max ]") static GstStaticPadTemplate src_template = @@ -89,6 +89,10 @@ static void gst_stride_transform_dispose (GObject *obj); /* GstBaseTransform functions */ static gboolean gst_stride_transform_get_unit_size (GstBaseTransform *base, GstCaps *caps, guint *size); +static gboolean gst_stride_transform_transform_size (GstBaseTransform *base, + GstPadDirection direction, + GstCaps *caps, guint size, + GstCaps *othercaps, guint *othersize); static GstCaps *gst_stride_transform_transform_caps (GstBaseTransform *base, GstPadDirection direction, GstCaps *caps); static gboolean gst_stride_transform_set_caps (GstBaseTransform *base, @@ -126,6 +130,8 @@ gst_stride_transform_class_init (GstStrideTransformClass *klass) basetransform_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_stride_transform_get_unit_size); + basetransform_class->transform_size = + GST_DEBUG_FUNCPTR (gst_stride_transform_transform_size); basetransform_class->transform_caps = GST_DEBUG_FUNCPTR (gst_stride_transform_transform_caps); basetransform_class->set_caps = @@ -176,6 +182,34 @@ gst_stride_transform_get_unit_size (GstBaseTransform *base, return TRUE; } +/** + * Default transform_size function is no good, as it assumes that the output + * buffer size is a multiple of the unit size.. which doesn't hold true. + */ +static gboolean +gst_stride_transform_transform_size (GstBaseTransform *base, + GstPadDirection direction, + GstCaps *caps, guint size, + GstCaps *othercaps, guint *othersize) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); + guint idx = (direction == GST_PAD_SINK) ? 0 : 1; + + if (self->cached_caps[idx] != othercaps) + { + if (!gst_stride_transform_get_unit_size (base, othercaps, + &(self->cached_size[idx]))) + { + return FALSE; + } + } + + *othersize = self->cached_size[idx]; + + return TRUE; +} + + /** * helper to add all fields, other than rowstride to @caps, copied from @s. @@ -187,7 +221,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); // TODO + gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); } idx = gst_structure_n_fields (s) - 1; diff --git a/gst/stride/gststridetransform.h b/gst/stride/gststridetransform.h index d80197f..481959e 100644 --- a/gst/stride/gststridetransform.h +++ b/gst/stride/gststridetransform.h @@ -59,6 +59,10 @@ struct _GstStrideTransform { gint width, height; gint in_rowstride; gint out_rowstride; + + /* for caching the tranform_size() results.. */ + GstCaps *cached_caps[2]; + guint cached_size[2]; }; struct _GstStrideTransformClass { @@ -70,35 +74,7 @@ GType gst_stride_transform_get_type (void); G_END_DECLS - - -/* note: in case this is a build with TTIF logging, we can optimize slightly - * and avoid the gst_caps_to_string() in case logging isn't enabled by using - * the TTIF_TRACE_ARG_PROCESSOR feature of ttif_trace_fprintf(): - */ -#ifdef GST_LOG_OVER_TTIF -# define LOG_CAPS(obj, caps) G_STMT_START { \ - if (caps) { \ - static TTIF_TRACE_ARG_PROCESSOR proc = { \ - .convert = (char (*)(void *))gst_caps_to_string, \ - .free = (void (*)(char *))g_free \ - }; \ - GST_DEBUG_OBJECT (obj, "%s: %qs", #caps, &proc, (caps)); \ - } else { \ - GST_DEBUG_OBJECT (obj, "null"); \ - } \ - } G_STMT_END -#else -# define LOG_CAPS(obj, caps) G_STMT_START { \ - if (caps) { \ - gchar *capstr = gst_caps_to_string (caps); \ - GST_DEBUG_OBJECT (obj, "%s: %s", #caps, capstr); \ - g_free (capstr); \ - } else { \ - GST_DEBUG_OBJECT (obj, "null"); \ - } \ - } G_STMT_END -#endif +#define LOG_CAPS(obj, caps) GST_DEBUG_OBJECT (obj, "%s: %"GST_PTR_FORMAT, #caps, caps) #endif /* __GSTSTRIDETRANSFORM_H__ */ -- 1.7.9.5 From 4670f9a817b7543c83191e3ae346a7f1a671d02d Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Wed, 19 Aug 2009 15:33:50 -0500 Subject: [PATCH] fix a small typo.. need to use the smaller of {new_width, orig_width} for the line-by-line copy to avoid overwriting past end of buffer --- gst/stride/gststridetransform.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index adc22ce..ea52500 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -331,7 +331,7 @@ stridemove (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, } } else { for (row=0; row<height; row++) { - memmove (new_buf+(new_width*row), orig_buf+(orig_width*row), orig_width); + memmove (new_buf+(new_width*row), orig_buf+(orig_width*row), new_width); } } } @@ -440,7 +440,9 @@ gst_stride_transform_transform (GstBaseTransform *base, { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GST_DEBUG_OBJECT (self, "inbuf=%p, outbuf=%p", inbuf, outbuf); + GST_DEBUG_OBJECT (self, "inbuf=%p (size=%d), outbuf=%p (size=%d)", + inbuf, GST_BUFFER_SIZE (inbuf), + outbuf, GST_BUFFER_SIZE (outbuf)); if (self->in_rowstride && self->out_rowstride) { GST_DEBUG_OBJECT (self, "not implemented"); // TODO -- 1.7.9.5 From 1310a312770281f3beabb108db6810d534c4f8ec Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Thu, 30 Jul 2009 14:50:05 -0500 Subject: [PATCH] add rowstride support to video utility functions --- gst-libs/gst/video/gstvideofilter.c | 8 +- gst-libs/gst/video/video.c | 234 ++++++++++++++++++++++++++++------- gst-libs/gst/video/video.h | 26 ++-- 3 files changed, 213 insertions(+), 55 deletions(-) diff --git a/gst-libs/gst/video/gstvideofilter.c b/gst-libs/gst/video/gstvideofilter.c index 2d08a60..6b2d7b7 100644 --- a/gst-libs/gst/video/gstvideofilter.c +++ b/gst-libs/gst/video/gstvideofilter.c @@ -21,7 +21,7 @@ /** * SECTION:gstvideofilter * @short_description: Base class for video filters - * + * * <refsect2> * <para> * Provides useful functions and a base class for video filters. @@ -78,14 +78,14 @@ gst_video_filter_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, guint * size) { GstVideoFormat fmt; - gint width, height; + gint width, height, rowstride; - if (!gst_video_format_parse_caps (caps, &fmt, &width, &height)) { + if (!gst_video_format_parse_caps_strided (caps, &fmt, &width, &height, &rowstride)) { GST_WARNING_OBJECT (btrans, "Failed to parse caps %" GST_PTR_FORMAT, caps); return FALSE; } - *size = gst_video_format_get_size (fmt, width, height); + *size = gst_video_format_get_size_strided (fmt, width, height, rowstride); GST_DEBUG_OBJECT (btrans, "Returning size %u bytes for caps %" GST_PTR_FORMAT, *size, caps); diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index f22ff4c..9211c4e 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -308,30 +308,15 @@ gst_video_parse_caps_chroma_site (GstCaps * caps) } /** - * gst_video_format_parse_caps: - * @caps: the #GstCaps to parse - * @format: the #GstVideoFormat of the video represented by @caps (output) - * @width: the width of the video represented by @caps, may be NULL (output) - * @height: the height of the video represented by @caps, may be NULL (output) - * - * Determines the #GstVideoFormat of @caps and places it in the location - * pointed to by @format. Extracts the size of the video and places it - * in the location pointed to by @width and @height. If @caps does not - * represent a video format or does not contain height and width, the - * function will fail and return FALSE. If @caps does not represent a raw - * video format listed in #GstVideoFormat, but still contains video caps, - * this function will return TRUE and set @format to #GST_VIDEO_FORMAT_UNKNOWN. - * - * Since: 0.10.16 - * - * Returns: TRUE if @caps was parsed correctly. + * see gst_video_format_parse_caps_strided and gst_video_format_parse_caps */ -gboolean -gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format, - int *width, int *height) +static gboolean +parse_caps (GstCaps * caps, GstVideoFormat * format, gint * width, + gint * height, gboolean stride_ok, gint * rowstride) { GstStructure *structure; gboolean ok = TRUE; + gboolean strided = FALSE; if (!gst_caps_is_fixed (caps)) return FALSE; @@ -339,7 +324,10 @@ gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format, structure = gst_caps_get_structure (caps, 0); if (format) { - if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + if (gst_structure_has_name (structure, "video/x-raw-yuv") || + (stride_ok && + gst_structure_has_name (structure, "video/x-raw-yuv-strided") && + (strided = TRUE) /* single '=' intentional */ )) { guint32 fourcc; ok &= gst_structure_get_fourcc (structure, "format", &fourcc); @@ -348,7 +336,10 @@ gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format, if (*format == GST_VIDEO_FORMAT_UNKNOWN) { ok = FALSE; } - } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) { + } else if (gst_structure_has_name (structure, "video/x-raw-rgb") || + (stride_ok && + gst_structure_has_name (structure, "video/x-raw-rgb-strided") && + (strided = TRUE) /* single '=' intentional */ )) { int depth; int bpp; int endianness = 0; @@ -438,6 +429,10 @@ gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format, } } + /* note: should we require that the caps have these fields, even if + * the caller does not particularly request them?? + */ + if (width) { ok &= gst_structure_get_int (structure, "width", width); } @@ -446,11 +441,70 @@ gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format, ok &= gst_structure_get_int (structure, "height", height); } + if (rowstride) { + if (strided) { + ok &= gst_structure_get_int (structure, "rowstride", rowstride); + } else { + *rowstride = 0; /* not a strided format */ + } + } + return ok; } /** + * gst_video_format_parse_caps_strided: + * @caps: the #GstCaps to parse + * @format: the #GstVideoFormat of the video represented by @caps (output) + * @width: the width of the video represented by @caps, may be NULL (output) + * @height: the height of the video represented by @caps, may be NULL (output) + * @rowstride: the rowstride (in bytes) represented by @caps, or 0 if there + * is no rowstride, may be NULL (output) + * + * Determines the #GstVideoFormat of @caps and places it in the location + * pointed to by @format. Extracts the size of the video and places it + * in the location pointed to by @width and @height. Extracts the row- + * stride and places it in the location pointed to by @rowstride. If + * @caps does not represent one of the raw video formats listed in + * #GstVideoFormat, the function will fail and return FALSE. + * + * Since: ??? + * + * Returns: TRUE if @caps was parsed correctly. + */ +gboolean +gst_video_format_parse_caps_strided (GstCaps * caps, GstVideoFormat * format, + int *width, int *height, int *rowstride) +{ + return parse_caps (caps, format, width, height, TRUE, rowstride); +} + +/** + * gst_video_format_parse_caps: + * @caps: the #GstCaps to parse + * @format: the #GstVideoFormat of the video represented by @caps (output) + * @width: the width of the video represented by @caps, may be NULL (output) + * @height: the height of the video represented by @caps, may be NULL (output) + * + * Determines the #GstVideoFormat of @caps and places it in the location + * pointed to by @format. Extracts the size of the video and places it + * in the location pointed to by @width and @height. If @caps does not + * represent one of the raw video formats listed in #GstVideoFormat, the + * function will fail and return FALSE. + * + * Since: 0.10.16 + * + * Returns: TRUE if @caps was parsed correctly. + */ +gboolean +gst_video_format_parse_caps (const GstCaps * caps, GstVideoFormat * format, + int *width, int *height) +{ + return parse_caps (caps, format, width, height, FALSE, NULL); +} + +/** * gst_video_parse_caps_framerate: * @caps: pointer to a #GstCaps instance * @fps_n: pointer to integer to hold numerator of frame rate (output) @@ -549,16 +603,17 @@ gst_video_format_new_caps_interlaced (GstVideoFormat format, } static GstCaps * -gst_video_format_new_caps_raw (GstVideoFormat format) +gst_video_format_new_caps_raw_strided (GstVideoFormat format, int rowstride) { + GstCaps *caps = NULL; + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); if (gst_video_format_is_yuv (format)) { - return gst_caps_new_simple ("video/x-raw-yuv", + caps = gst_caps_new_simple (rowstride ? + "video/x-raw-yuv-strided" : "video/x-raw-yuv", "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), NULL); - } - if (gst_video_format_is_rgb (format)) { - GstCaps *caps; + } else if (gst_video_format_is_rgb (format)) { int red_mask = 0; int blue_mask = 0; int green_mask = 0; @@ -668,7 +723,8 @@ gst_video_format_new_caps_raw (GstVideoFormat format) g_assert_not_reached (); } - caps = gst_caps_new_simple ("video/x-raw-rgb", + caps = gst_caps_new_simple (rowstride ? + "video/x-raw-rgb-strided" : "video/x-raw-rgb", "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); if (bpp != 8) { @@ -684,11 +740,7 @@ gst_video_format_new_caps_raw (GstVideoFormat format) mask >> (8 * gst_video_format_get_component_offset (format, 3, 0, 0)); gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL); } - return caps; - } - - if (gst_video_format_is_gray (format)) { - GstCaps *caps; + } else if (gst_video_format_is_gray (format)) { int bpp; int depth; int endianness; @@ -720,11 +772,39 @@ gst_video_format_new_caps_raw (GstVideoFormat format) "depth", G_TYPE_INT, depth, "endianness", G_TYPE_INT, endianness, NULL); } + } else { + return NULL; + } - return caps; + if (rowstride) { + gst_caps_set_simple (caps, "rowstride", G_TYPE_INT, rowstride, NULL); } - return NULL; + return caps; +} + +/** + * gst_video_format_new_caps: + * @format: the #GstVideoFormat describing the raw video format + * @width: width of video + * @height: height of video + * @framerate_n: numerator of frame rate + * @framerate_d: denominator of frame rate + * @par_n: numerator of pixel aspect ratio + * @par_d: denominator of pixel aspect ratio + * + * Creates a new #GstCaps object based on the parameters provided. + * + * Since: 0.10.16 + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_caps (GstVideoFormat format, int width, int height, + int framerate_n, int framerate_d, int par_n, int par_d) +{ + return gst_video_format_new_caps_strided (format, width, height, 0, + framerate_n, framerate_d, par_n, par_d); } /** @@ -747,7 +827,7 @@ gst_video_format_new_template_caps (GstVideoFormat format) g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); - caps = gst_video_format_new_caps_raw (format); + caps = gst_video_format_new_caps_raw_strided (format, 0); if (caps) { GValue value = { 0 }; GValue v = { 0 }; @@ -775,10 +855,11 @@ gst_video_format_new_template_caps (GstVideoFormat format) } /** - * gst_video_format_new_caps: + * gst_video_format_new_caps_strided: * @format: the #GstVideoFormat describing the raw video format * @width: width of video * @height: height of video + * @rowstride: the rowstride (in bytes), or 0 if no rowstride * @framerate_n: numerator of frame rate * @framerate_d: denominator of frame rate * @par_n: numerator of pixel aspect ratio @@ -786,13 +867,14 @@ gst_video_format_new_template_caps (GstVideoFormat format) * * Creates a new #GstCaps object based on the parameters provided. * - * Since: 0.10.16 + * Since: ??? * * Returns: a new #GstCaps object, or NULL if there was an error */ GstCaps * -gst_video_format_new_caps (GstVideoFormat format, int width, - int height, int framerate_n, int framerate_d, int par_n, int par_d) +gst_video_format_new_caps_strided (GstVideoFormat format, + int width, int height, int rowstride, + int framerate_n, int framerate_d, int par_n, int par_d) { GstCaps *caps; GstStructure *structure; @@ -800,7 +882,7 @@ gst_video_format_new_caps (GstVideoFormat format, int width, g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); g_return_val_if_fail (width > 0 && height > 0, NULL); - caps = gst_video_format_new_caps_raw (format); + caps = gst_video_format_new_caps_raw_strided (format, rowstride); if (caps) { structure = gst_caps_get_structure (caps, 0); @@ -814,7 +896,6 @@ gst_video_format_new_caps (GstVideoFormat format, int width, return caps; } - /** * gst_video_format_from_fourcc: * @fourcc: a FOURCC value representing raw YUV video @@ -2106,6 +2187,75 @@ gst_video_get_size_from_caps (const GstCaps * caps, gint * size) } /** + * gst_video_format_get_size_strided: + * @format: a #GstVideoFormat + * @width: the width of video (in pixels) + * @height: the height of video (in pixels) + * @rowstride: the rowstride (in bytes), or 0 if no rowstride (in which + * case the returned value is same as #gst_video_format_get_size()) + * + * Calculates the total number of bytes in the raw video format, for a buffer + * which may have a rowstride in bytes + * + * Since: ??? + * + * Returns: size (in bytes) of raw video format + */ +int +gst_video_format_get_size_strided (GstVideoFormat format, + int width, int height, int rowstride) +{ + if (!rowstride) + return gst_video_format_get_size (format, width, height); + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (width > 0 && height > 0, 0); + + switch (format) { + /* all packed formats have the same calculation, ie. rowstride * height + */ + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_v216: + return GST_ROUND_UP_4 (rowstride * height); + + /* these planar formats have 2x sub-sampling in the vertical direction, + * so U/V have half as many rows as Y: + */ + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + return GST_ROUND_UP_4 (2 * rowstride * height); + + /* these planar formats have no sub-sampling in the vertical direction, + * so each plane has 'height' number of rows + */ + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + return GST_ROUND_UP_4 (3 * rowstride * height); + default: + return 0; + } +} + +/** * gst_video_format_convert: * @format: a #GstVideoFormat * @width: the width of video diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h index 717c59a..3c39f85 100644 --- a/gst-libs/gst/video/video.h +++ b/gst-libs/gst/video/video.h @@ -33,7 +33,7 @@ G_BEGIN_DECLS * @GST_VIDEO_FORMAT_I420: planar 4:2:0 YUV * @GST_VIDEO_FORMAT_YV12: planar 4:2:0 YVU (like I420 but UV planes swapped) * @GST_VIDEO_FORMAT_YUY2: packed 4:2:2 YUV (Y0-U0-Y1-V0 Y2-U2-Y3-V2 Y4 ...) - * @GST_VIDEO_FORMAT_UYVY: packed 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...) + * @GST_VIDEO_FORMAT_UYVY: packed 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...) * @GST_VIDEO_FORMAT_AYUV: packed 4:4:4 YUV with alpha channel (A0-Y0-U0-V0 ...) * @GST_VIDEO_FORMAT_RGBx: sparse rgb packed into 32 bit, space last * @GST_VIDEO_FORMAT_BGRx: sparse reverse rgb packed into 32 bit, space last @@ -264,13 +264,13 @@ typedef enum { #define GST_VIDEO_CAPS_RGBx \ __GST_VIDEO_CAPS_MAKE_32 (1, 2, 3) - + #define GST_VIDEO_CAPS_xRGB \ __GST_VIDEO_CAPS_MAKE_32 (2, 3, 4) - + #define GST_VIDEO_CAPS_BGRx \ __GST_VIDEO_CAPS_MAKE_32 (3, 2, 1) - + #define GST_VIDEO_CAPS_xBGR \ __GST_VIDEO_CAPS_MAKE_32 (4, 3, 2) @@ -278,13 +278,13 @@ typedef enum { #define GST_VIDEO_CAPS_RGBA \ __GST_VIDEO_CAPS_MAKE_32A (1, 2, 3, 4) - + #define GST_VIDEO_CAPS_ARGB \ __GST_VIDEO_CAPS_MAKE_32A (2, 3, 4, 1) - + #define GST_VIDEO_CAPS_BGRA \ __GST_VIDEO_CAPS_MAKE_32A (3, 2, 1, 4) - + #define GST_VIDEO_CAPS_ABGR \ __GST_VIDEO_CAPS_MAKE_32A (4, 3, 2, 1) @@ -300,7 +300,7 @@ typedef enum { #define GST_VIDEO_CAPS_BGRx_HOST_ENDIAN \ GST_VIDEO_CAPS_xRGB #endif - + /* 15/16 bit */ #define GST_VIDEO_CAPS_RGB_16 \ @@ -470,6 +470,8 @@ gboolean gst_video_format_parse_caps (const GstCaps * caps, gboolean gst_video_format_parse_caps_interlaced (GstCaps * caps, gboolean * interlaced); +gboolean gst_video_format_parse_caps_strided (GstCaps * caps, GstVideoFormat * format, + int *width, int *height, int *rowstride); gboolean gst_video_parse_caps_pixel_aspect_ratio (GstCaps * caps, int * par_n, @@ -502,6 +504,10 @@ GstCaps * gst_video_format_new_caps_interlaced (GstVideoFormat format, GstCaps * gst_video_format_new_template_caps (GstVideoFormat format); +GstCaps * gst_video_format_new_caps_strided (GstVideoFormat format, + int width, int height, int rowstride, + int framerate_n, int framerate_d, int par_n, int par_d); + /* format properties */ GstVideoFormat gst_video_format_from_fourcc (guint32 fourcc) G_GNUC_CONST; @@ -544,6 +550,9 @@ int gst_video_format_get_size (GstVideoFormat format, int width, int height) G_GNUC_CONST; +int gst_video_format_get_size_strided (GstVideoFormat format, + int width, int height, int rowstride); + gboolean gst_video_get_size_from_caps (const GstCaps * caps, gint * size); gboolean gst_video_format_convert (GstVideoFormat format, @@ -603,7 +612,6 @@ GstBuffer * gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps, GstClockTime timeout, GError ** error); - G_END_DECLS #endif /* __GST_VIDEO_H__ */ -- 1.7.9.5 From 868974bf8f16b6635ab945950c456a231995e687 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 20 Nov 2009 18:43:12 -0600 Subject: [PATCH] Add NV12 support in stridetransform --- gst-libs/gst/video/video.c | 3 +++ gst/stride/gststridetransform.c | 12 ++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index 9211c4e..d1abc5f 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -2250,6 +2250,9 @@ gst_video_format_get_size_strided (GstVideoFormat format, case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y444: return GST_ROUND_UP_4 (3 * rowstride * height); + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + return GST_ROUND_UP_4 (rowstride) * GST_ROUND_UP_2 (height) * 3 / 2; default: return 0; } diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index ea52500..56207d0 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -2,7 +2,7 @@ * * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ * - * Description: V4L2 sink element + * Description: stride transform element * Created on: Jul 30, 2009 * Author: Rob Clark <rob@ti.com> * @@ -62,7 +62,7 @@ GST_ELEMENT_DETAILS ("Stride transform", /* TODO: add rgb formats too! */ #define SUPPORTED_CAPS \ - GST_VIDEO_CAPS_YUV_STRIDED ("{ I420, YV12, YUY2, UYVY }", "[ 0, max ]") + GST_VIDEO_CAPS_YUV_STRIDED ("{ I420, YV12, YUY2, UYVY, NV12 }", "[ 0, max ]") static GstStaticPadTemplate src_template = @@ -357,12 +357,10 @@ stridify (GstStrideTransform *self, guchar *strided, guchar *unstrided) 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); + stridemove (strided, unstrided, stride, width, (GST_ROUND_UP_2 (height) * 3) / 2); 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); @@ -403,12 +401,10 @@ unstridify (GstStrideTransform *self, guchar *unstrided, guchar *strided) 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); + stridemove (unstrided, strided, width, stride, (GST_ROUND_UP_2 (height) * 3) / 2); 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); -- 1.7.9.5 From 29a088acbdb95d93a647e0dac457790eae1ab65a Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 27 Nov 2009 11:13:47 -0600 Subject: [PATCH] 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.9.5 From fb06e3fce8803d801330c9792975e3b60b1e34a8 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 27 Nov 2009 11:14:58 -0600 Subject: [PATCH] fix to avoid parsing caps on every frame --- gst/stride/gststridetransform.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 03deeb1..143a9f7 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -197,11 +197,15 @@ gst_stride_transform_transform_size (GstBaseTransform *base, if (self->cached_caps[idx] != othercaps) { - if (!gst_stride_transform_get_unit_size (base, othercaps, - &(self->cached_size[idx]))) - { + guint sz; + if (!gst_stride_transform_get_unit_size (base, othercaps, &sz)) { return FALSE; } + if (self->cached_caps[idx]) { + gst_caps_unref (self->cached_caps[idx]); + } + self->cached_size[idx] = sz; + self->cached_caps[idx] = gst_caps_ref (othercaps); } *othersize = self->cached_size[idx]; -- 1.7.9.5 From a3233f4d26426951f97aadc81865d5711764d34b Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 27 Nov 2009 15:05:56 -0600 Subject: [PATCH] refactor stridetransform to make it easier to add new transforms (stride and/or colorspace) --- gst/stride/Makefile.am | 1 + gst/stride/convert.c | 267 +++++++++++++++++++++++++++++++++++ gst/stride/gststridetransform.c | 295 ++++++++------------------------------- gst/stride/gststridetransform.h | 18 ++- 4 files changed, 340 insertions(+), 241 deletions(-) create mode 100644 gst/stride/convert.c diff --git a/gst/stride/Makefile.am b/gst/stride/Makefile.am index 1adc197..0b61d55 100644 --- a/gst/stride/Makefile.am +++ b/gst/stride/Makefile.am @@ -2,6 +2,7 @@ plugin_LTLIBRARIES = libgststridetransform.la libgststridetransform_la_SOURCES = \ gststridetransform.c \ + convert.c \ plugin.c libgststridetransform_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) diff --git a/gst/stride/convert.c b/gst/stride/convert.c new file mode 100644 index 0000000..860f16c --- /dev/null +++ b/gst/stride/convert.c @@ -0,0 +1,267 @@ +/* GStreamer + * + * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ + * + * Description: stride transform conversion utilities + * Created on: Nov 27, 2009 + * Author: Rob Clark <rob@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <gst/video/video.h> + +#include "gststridetransform.h" + + +GST_DEBUG_CATEGORY_EXTERN (stridetransform_debug); +#define GST_CAT_DEFAULT stridetransform_debug + + +/* + * Conversion utilities: + */ + +static void +memmove_demux (guchar *new_buf, guchar *orig_buf, gint sz, gint pxstride) +{ + if (new_buf > orig_buf) { + /* copy backwards */ + new_buf += ((sz - 1) * pxstride); + orig_buf += sz - 1; + 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 + * 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), new_width); + } + } +} + +/* + * Conversion Functions: + */ + +/** convert 4:2:0 semiplanar to same 4:2:0 semiplanar */ +static GstFlowReturn +unstridify_420sp_420sp (GstStrideTransform *self, guchar *unstrided, guchar *strided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->in_rowstride; + + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + + stridemove (unstrided, strided, width, stride, + (GST_ROUND_UP_2 (height) * 3) / 2); + + return GST_FLOW_OK; +} +static GstFlowReturn +stridify_420sp_420sp (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + stridemove (strided, unstrided, stride, width, + (GST_ROUND_UP_2 (height) * 3) / 2); + + return GST_FLOW_OK; +} + +/** convert 4:2:0 planar to same 4:2:0 planar */ +static GstFlowReturn +unstridify_420p_420p (GstStrideTransform *self, guchar *unstrided, guchar *strided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->in_rowstride; + + 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 */ + /* XXX odd widths/heights/strides: */ + stridemove ( + unstrided + (int)(height*width*1.5), + strided + (int)(height*stride*1.5), + width/2, stride, height); /* move U/V */ + + return GST_FLOW_OK; +} +static GstFlowReturn +stridify_420p_420p (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + + /* XXX odd widths/heights/strides: */ + 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; +} + +/** convert 4:2:2 packed to same 4:2:2 packed */ +static GstFlowReturn +unstridify_422i_422i (GstStrideTransform *self, guchar *unstrided, guchar *strided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->in_rowstride; + + g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + + stridemove (unstrided, strided, width*2, stride, height); + + return GST_FLOW_OK; +} +static GstFlowReturn +stridify_422i_422i (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + + stridemove (strided, unstrided, stride, width*2, height); + + return GST_FLOW_OK; +} + +/** convert I420 unstrided to NV12 strided */ +static GstFlowReturn +stridify_i420_nv12 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + + /* 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; +} + +/* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ +Conversion stride_conversions[] = { + { { GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV12 }, stridify_420sp_420sp, unstridify_420sp_420sp }, + { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_I420 }, stridify_420p_420p, unstridify_420p_420p }, + { { GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YV12 }, stridify_420p_420p, unstridify_420p_420p }, + { { GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_YUY2 }, stridify_422i_422i, unstridify_422i_422i }, + { { GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY }, stridify_422i_422i, unstridify_422i_422i }, + { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_NV12 }, stridify_i420_nv12, NULL }, + /* add new entries before here */ + { { GST_VIDEO_FORMAT_UNKNOWN } } +}; + + diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 143a9f7..6ab0479 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -47,12 +47,17 @@ #endif #include <string.h> + #include <gst/video/video.h> #include "gst/gst-i18n-plugin.h" #include "gststridetransform.h" +/* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ +extern const Conversion stride_conversions[]; + + static const GstElementDetails stridetransform_details = GST_ELEMENT_DETAILS ("Stride transform", "Filter/Converter/Video", @@ -70,14 +75,14 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS (SUPPORTED_CAPS) - ); +); static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (SUPPORTED_CAPS) - ); +); GST_DEBUG_CATEGORY (stridetransform_debug); @@ -99,8 +104,6 @@ static gboolean gst_stride_transform_set_caps (GstBaseTransform *base, GstCaps *incaps, GstCaps *outcaps); static GstFlowReturn gst_stride_transform_transform (GstBaseTransform *base, GstBuffer *inbuf, GstBuffer *outbuf); -static GstFlowReturn gst_stride_transform_transform_ip (GstBaseTransform *base, - GstBuffer *buf); GST_BOILERPLATE (GstStrideTransform, gst_stride_transform, GstVideoFilter, GST_TYPE_VIDEO_FILTER); @@ -136,8 +139,6 @@ gst_stride_transform_class_init (GstStrideTransformClass *klass) GST_DEBUG_FUNCPTR (gst_stride_transform_transform_caps); basetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_stride_transform_set_caps); - basetransform_class->transform_ip = - GST_DEBUG_FUNCPTR (gst_stride_transform_transform_ip); basetransform_class->transform = GST_DEBUG_FUNCPTR (gst_stride_transform_transform); @@ -219,7 +220,7 @@ gst_stride_transform_transform_size (GstBaseTransform *base, * helper to add all fields, other than rowstride to @caps, copied from @s. */ static void -add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rowstride) +add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rowstride, GstPadDirection direction) { gint idx; GstStructure *new_s = gst_structure_new (name, NULL); @@ -232,38 +233,39 @@ add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rows while (idx >= 0) { const gchar *name = gst_structure_nth_field_name (s, idx); idx--; + + /* for format field, check the stride_conversions table to see what + * we can support: + */ 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')); + + /* XXX double check this: */ + gint to_format = (direction == GST_PAD_SINK) ? 1 : 0; + gint from_format = (direction == GST_PAD_SRC) ? 1 : 0; + + if (gst_structure_get_fourcc (s, "format", &fourcc)) { + GValue formats = {0}; + GValue fourccval = {0}; + gint i; + GstVideoFormat format = gst_video_format_from_fourcc (fourcc); + + g_value_init (&formats, GST_TYPE_LIST); + g_value_init (&fourccval, GST_TYPE_FOURCC); + + for (i=0; stride_conversions[i].format[0]!=GST_VIDEO_FORMAT_UNKNOWN; i++) { + if (stride_conversions[i].format[from_format] == format) { + gst_value_set_fourcc (&fourccval, gst_video_format_to_fourcc + (stride_conversions[i].format[to_format])); 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; + } } + + continue; } } + /* copy over all other non-rowstride fields: */ if (strcmp ("rowstride", name)) { const GValue *val = gst_structure_get_value (s, name); gst_structure_set_value (new_s, name, val); @@ -297,14 +299,14 @@ gst_stride_transform_transform_caps (GstBaseTransform *base, if (gst_structure_has_name (s, "video/x-raw-yuv") || gst_structure_has_name (s, "video/x-raw-yuv-strided")) { - add_all_fields (ret, "video/x-raw-yuv", s, FALSE); - add_all_fields (ret, "video/x-raw-yuv-strided", s, TRUE); + add_all_fields (ret, "video/x-raw-yuv", s, FALSE, direction); + add_all_fields (ret, "video/x-raw-yuv-strided", s, TRUE, direction); } else if (gst_structure_has_name (s, "video/x-raw-rgb") || gst_structure_has_name (s, "video/x-raw-rgb-strided")) { - add_all_fields (ret, "video/x-raw-rgb", s, FALSE); - add_all_fields (ret, "video/x-raw-rgb-strided", s, TRUE); + add_all_fields (ret, "video/x-raw-rgb", s, FALSE, direction); + add_all_fields (ret, "video/x-raw-rgb-strided", s, TRUE, direction); } @@ -324,211 +326,37 @@ gst_stride_transform_set_caps (GstBaseTransform *base, { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); gint width, height; + GstVideoFormat in_format, out_format; + gint i; LOG_CAPS (self, incaps); LOG_CAPS (self, outcaps); g_return_val_if_fail (gst_video_format_parse_caps_strided (incaps, - &self->in_format, &self->width, &self->height, &self->in_rowstride), FALSE); + &in_format, &self->width, &self->height, &self->in_rowstride), FALSE); g_return_val_if_fail (gst_video_format_parse_caps_strided (outcaps, - &self->out_format, &width, &height, &self->out_rowstride), FALSE); - - g_return_val_if_fail (self->width == width, FALSE); - g_return_val_if_fail (self->height == height, FALSE); - - return TRUE; -} - -/* ************************************************************************* */ - -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); - } - } -} + &out_format, &width, &height, &self->out_rowstride), FALSE); -/** - * 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), new_width); - } - } -} + self->conversion = NULL; - -/** - * 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; - - 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; + for (i=0; stride_conversions[i].format[0]!=GST_VIDEO_FORMAT_UNKNOWN; i++) { + if ((stride_conversions[i].format[0] == in_format) && + (stride_conversions[i].format[1] == out_format)) { + GST_DEBUG_OBJECT (self, "found stride_conversion: %d", i); + self->conversion = &stride_conversions[i]; + break; } } - 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); - return GST_FLOW_OK; - 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; - } -} - + g_return_val_if_fail (self->conversion, FALSE); + g_return_val_if_fail (self->conversion->unstridify || !self->in_rowstride, FALSE); + g_return_val_if_fail (self->conversion->stridify || !self->out_rowstride, FALSE); + g_return_val_if_fail (self->width == width, FALSE); + g_return_val_if_fail (self->height == height, FALSE); -/** - * 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->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); - return GST_FLOW_OK; - 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; - } + return TRUE; } - static GstFlowReturn gst_stride_transform_transform (GstBaseTransform *base, GstBuffer *inbuf, GstBuffer *outbuf) @@ -543,10 +371,10 @@ gst_stride_transform_transform (GstBaseTransform *base, GST_DEBUG_OBJECT (self, "not implemented"); // TODO return GST_FLOW_ERROR; } else if (self->in_rowstride) { - return unstridify (self, + return self->conversion->unstridify (self, GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); } else if (self->out_rowstride) { - return stridify (self, + return self->conversion->stridify (self, GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); } @@ -555,12 +383,3 @@ gst_stride_transform_transform (GstBaseTransform *base, return GST_FLOW_ERROR; } - -static GstFlowReturn -gst_stride_transform_transform_ip (GstBaseTransform *base, - GstBuffer *buf) -{ - /* transform function is safe to call with same buffer ptr: - */ - return gst_stride_transform_transform (base, buf, buf); -} diff --git a/gst/stride/gststridetransform.h b/gst/stride/gststridetransform.h index 0141571..bce2526 100644 --- a/gst/stride/gststridetransform.h +++ b/gst/stride/gststridetransform.h @@ -2,7 +2,7 @@ * * Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ * - * Description: V4L2 sink element + * Description: stride transform element * Created on: Jul 2, 2009 * Author: Rob Clark <rob@ti.com> * @@ -29,7 +29,6 @@ #include <gst/video/gstvideofilter.h> #include <gst/video/video.h> - G_BEGIN_DECLS #define GST_TYPE_STRIDE_TRANSFORM \ @@ -47,6 +46,19 @@ typedef struct _GstStrideTransform GstStrideTransform; typedef struct _GstStrideTransformClass GstStrideTransformClass; /** + * stride/colorspace conversion table (used internally) + */ +typedef struct { + + GstVideoFormat format[2]; /* in_format, out_format */ + + GstFlowReturn (*stridify) (GstStrideTransform *self, guchar *strided, guchar *unstrided); + GstFlowReturn (*unstridify) (GstStrideTransform *self, guchar *unstrided, guchar *strided); + +} Conversion; + + +/** * GstStrideTransform: * * Opaque datastructure. @@ -55,10 +67,10 @@ struct _GstStrideTransform { GstVideoFilter videofilter; /*< private >*/ - GstVideoFormat in_format, out_format; gint width, height; gint in_rowstride; gint out_rowstride; + const Conversion *conversion; /* for caching the tranform_size() results.. */ GstCaps *cached_caps[2]; -- 1.7.9.5 From 5953e78b54fc43028f8a17be2e5a623ff3248884 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Thu, 8 Apr 2010 00:30:25 -0500 Subject: [PATCH] add some neon --- configure.ac | 1 + gst/stride/Makefile.am | 1 + gst/stride/armv7.s | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ gst/stride/convert.c | 76 +++++++++++++++++-------------- 4 files changed, 162 insertions(+), 35 deletions(-) create mode 100644 gst/stride/armv7.s diff --git a/configure.ac b/configure.ac index f3dc2b3..0cbb91c 100644 --- a/configure.ac +++ b/configure.ac @@ -58,6 +58,7 @@ dnl AS_LIBTOOL_TAGS AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL +AM_PROG_AS dnl *** required versions of GStreamer stuff *** GST_REQ=0.10.36 diff --git a/gst/stride/Makefile.am b/gst/stride/Makefile.am index 0b61d55..3b466de 100644 --- a/gst/stride/Makefile.am +++ b/gst/stride/Makefile.am @@ -3,6 +3,7 @@ plugin_LTLIBRARIES = libgststridetransform.la libgststridetransform_la_SOURCES = \ gststridetransform.c \ convert.c \ + armv7.s \ plugin.c libgststridetransform_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) diff --git a/gst/stride/armv7.s b/gst/stride/armv7.s new file mode 100644 index 0000000..ed636f7 --- /dev/null +++ b/gst/stride/armv7.s @@ -0,0 +1,119 @@ +@ GStreamer +@ +@ Copyright (C) 2009 Texas Instruments, Inc - http://www.ti.com/ +@ +@ Description: NEON/VFP accelerated functions for armv7 architecture +@ Created on: Nov 27, 2009 +@ Author: Rob Clark <rob@ti.com> +@ +@ This library is free software; you can redistribute it and/or +@ modify it under the terms of the GNU Library General Public +@ License as published by the Free Software Foundation; either +@ version 2 of the License, or (at your option) any later version. +@ +@ This library is distributed in the hope that it will be useful, +@ but WITHOUT ANY WARRANTY; without even the implied warranty of +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +@ Library General Public License for more details. +@ +@ You should have received a copy of the GNU Library General Public +@ License along with this library; if not, write to the +@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, +@ Boston, MA 02111-1307, USA. + + .fpu neon + .text + + .align + .global stride_copy_zip2 + .type stride_copy_zip2, %function +@void +@stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz) +@{ +@@@@ note: r0-r3, q0-3, and q8-q15 do not need to be preserved +stride_copy_zip2: +@ interleave remaining >= 16 bytes: + pld [r1, #64] + pld [r2, #64] + cmp r3, #16 + blt stride_copy_zip2_2 +stride_copy_zip2_1: + vld1.8 {q8}, [r1]! + vld1.8 {q9}, [r2]! + + vzip.8 q8, q9 + + pld [r1, #64] + vst1.8 {q8,q9}, [r0]! + pld [r2, #64] + sub r3, r3, #16 + + cmp r3, #16 + bge stride_copy_zip2_1 +@ interleave remaining >= 8 bytes: +stride_copy_zip2_2: + cmp r3, #8 + blt stride_copy_zip2_3 + + vld1.8 {d16}, [r1]! + vld1.8 {d17}, [r2]! + + vzip.8 d16, d17 + + vst1.8 {d16,d17}, [r0]! + sub r3, r3, #8 + +@ interleave remaining < 8 bytes: +stride_copy_zip2_3: +@XXX + bx lr +@} + + .align + .global stride_copy + .type stride_copy, %function +@void +@stride_copy (guchar *new_buf, guchar *orig_buf, gint sz) +@{ +@@@@ note: r0-r3, q0-3, and q8-q15 do not need to be preserved +stride_copy: +@ copy remaining >= 64 bytes: + pld [r1, #64] + cmp r2, #64 + blt stride_copy_2 +stride_copy_1: + vld1.8 {q8-q9}, [r1]! + sub r2, r2, #64 + vld1.8 {q10-q11},[r1]! + vst1.8 {q8-q9}, [r0]! + pld [r1, #64] + cmp r2, #64 + vst1.8 {q10-q11},[r0]! + bge stride_copy_1 +@ copy remaining >= 32 bytes: +stride_copy_2: + cmp r2, #32 + blt stride_copy_3 + vld1.8 {q8-q9}, [r1]! + sub r2, r2, #32 + vst1.8 {q8-q9}, [r0]! +@ copy remaining >= 16 bytes: +stride_copy_3: + cmp r2, #16 + blt stride_copy_4 + vld1.8 {q8}, [r1]! + sub r2, r2, #16 + vst1.8 {q8}, [r0]! +@ copy remaining >= 8 bytes: +stride_copy_4: + cmp r2, #8 + blt stride_copy_5 + vld1.8 {d16}, [r1]! + sub r2, r2, #8 + vst1.8 {d16}, [r0]! +@ copy remaining < 8 bytes: +stride_copy_5: +@XXX + bx lr +@} + diff --git a/gst/stride/convert.c b/gst/stride/convert.c index 860f16c..a15063b 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -37,38 +37,43 @@ GST_DEBUG_CATEGORY_EXTERN (stridetransform_debug); #define GST_CAT_DEFAULT stridetransform_debug +/* note: some parts of code support in-place transform.. some do not.. I'm + * not sure if zip/interleave functions could really support in-place copy.. + * I need to think about this after having some sleep ;-) + */ + +#define WEAK __attribute__((weak)) + /* * Conversion utilities: */ -static void -memmove_demux (guchar *new_buf, guchar *orig_buf, gint sz, gint pxstride) +WEAK void +stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz) { - if (new_buf > orig_buf) { - /* copy backwards */ - new_buf += ((sz - 1) * pxstride); - orig_buf += sz - 1; - while(sz--) { - *new_buf = *orig_buf; - new_buf -= pxstride; - orig_buf--; - } - } else { - while(sz--) { - *new_buf = *orig_buf; - new_buf += pxstride; - orig_buf++; - } + while (sz--) { + *new_buf++ = *orig_buf1++; + *new_buf++ = *orig_buf2++; } } +WEAK void +stride_copy (guchar *new_buf, guchar *orig_buf, gint sz) +{ + memcpy (new_buf, orig_buf, sz); +} + + +/** + * move to strided buffer, interleaving two planes of identical dimensions + */ static void -stridemove_demux (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, gint height, gint pxstride) +stridemove_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, 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); + GST_DEBUG ("new_buf=%p, orig_buf1=%p, orig_buf2=%p, new_width=%d, orig_width=%d, height=%d", + new_buf, orig_buf1, orig_buf2, 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, @@ -76,11 +81,19 @@ stridemove_demux (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_w */ 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); + stride_copy_zip2 ( + new_buf+(new_width*row), + orig_buf1+(orig_width*row), + orig_buf2+(orig_width*row), + orig_width); } } else { for (row=0; row<height; row++) { - memmove_demux (new_buf+(new_width*row), orig_buf+(orig_width*row), new_width, pxstride); + stride_copy_zip2 ( + new_buf+(new_width*row), + orig_buf1+(orig_width*row), + orig_buf2+(orig_width*row), + new_width); } } } @@ -106,11 +119,11 @@ stridemove (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, */ 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); + stride_copy (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), new_width); + stride_copy (new_buf+(new_width*row), orig_buf+(orig_width*row), new_width); } } } @@ -234,19 +247,12 @@ stridify_i420_nv12 (GstStrideTransform *self, guchar *strided, guchar *unstrided g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); - /* 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 ( + /* XXX widths/heights/strides that are not multiple of four??: */ + stridemove_zip2 ( strided + (height*stride), unstrided + (height*width), - stride, width/2, height/2, 2); /* move U */ + unstrided + (int)(height*width*1.25), + stride, width/2, height/2); /* interleave U&V */ stridemove (strided, unstrided, stride, width, height); /* move Y */ return GST_FLOW_OK; -- 1.7.9.5 From 60b276fc8b01d69587f0c540ade1059475fbdd48 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Tue, 1 Dec 2009 22:42:43 -0600 Subject: [PATCH] add support to convert to YUY2/YUYV color format --- gst/stride/armv7.s | 63 ++++++++++++++++++++++++++++++++++++++++++ gst/stride/convert.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 133 insertions(+), 4 deletions(-) diff --git a/gst/stride/armv7.s b/gst/stride/armv7.s index ed636f7..2697a14 100644 --- a/gst/stride/armv7.s +++ b/gst/stride/armv7.s @@ -69,6 +69,69 @@ stride_copy_zip2_3: bx lr @} + + .align + .global stride_copy_zip3a + .type stride_copy_zip3a, %function +@void +@stride_copy_zip3a (guchar *new_buf, +@ guchar *orig_buf1, guchar *orig_buf2, guchar *orig_buf3, gint sz) +@{ +@@@@ note: r0-r3, q0-3, and q8-q15 do not need to be preserved +stride_copy_zip3a: + pld [r1, #64] + pld [r2, #64] + pld [r3, #64] + ldr ip, [sp] @ the sz arg +@ interleave remaining >= 32 bytes: + cmp ip, #32 + blt stride_copy_zip3a_2 +stride_copy_zip3a_1: + vld1.8 {q8}, [r1]! @ Y + vld1.8 {q10}, [r1]! @ Y + vld1.8 {q9}, [r2]! @ U + vld1.8 {q11}, [r3]! @ V + + pld [r1, #64] + pld [r2, #64] + pld [r3, #64] + + vzip.8 q9, q11 @ interleave U&V + vzip.8 q8, q9 @ interleave Y1UV1 + vzip.8 q10, q11 @ interleave Y2UV2 + + vst1.8 {q8,q9}, [r0]! + vst1.8 {q10,q11}, [r0]! + + sub ip, ip, #32 + + cmp ip, #32 + bge stride_copy_zip3a_1 +@ interleave remaining >= 16 bytes: +stride_copy_zip3a_2: + cmp ip, #16 + blt stride_copy_zip3a_3 + + vld1.8 {d16}, [r1]! @ Y + vld1.8 {d18}, [r1]! @ Y + vld1.8 {d17}, [r2]! @ U + vld1.8 {d19}, [r3]! @ V + + vzip.8 d17, d19 @ interleave U&V + vzip.8 d16, d17 @ interleave Y1UV1 + vzip.8 d18, d19 @ interleave Y2UV2 + + vst1.8 {d16,d17}, [r0]! + vst1.8 {d18,d19}, [r0]! + + sub ip, ip, #16 +@ copy remaining >= 8 bytes: +stride_copy_zip3a_3: +@XXX + bx lr +@} + + .align .global stride_copy .type stride_copy, %function diff --git a/gst/stride/convert.c b/gst/stride/convert.c index a15063b..0f59e78 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -58,6 +58,19 @@ stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz } WEAK void +stride_copy_zip3a (guchar *new_buf, + guchar *orig_buf1, guchar *orig_buf2, guchar *orig_buf3, gint sz) +{ + while (sz > 1) { + *new_buf++ = *orig_buf1++; + *new_buf++ = *orig_buf2++; + *new_buf++ = *orig_buf1++; + *new_buf++ = *orig_buf3++; + sz -= 2; + } +} + +WEAK void stride_copy (guchar *new_buf, guchar *orig_buf, gint sz) { memcpy (new_buf, orig_buf, sz); @@ -99,6 +112,36 @@ stridemove_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint new } /** + * move to strided buffer, interleaving three planes, where the first plane + * (orig_buf1) has 2x as many samples.. Ie. ABACABAC.. + */ +static void +stridemove_zip3a (guchar *new_buf, + guchar *orig_buf1, guchar *orig_buf2, guchar *orig_buf3, + guint new_width, gint orig_width, gint height) +{ + gint copy_width = (new_width < orig_width) ? new_width : orig_width; + + while (height > 0) { + + /* even row */ + stride_copy_zip3a (new_buf, orig_buf1, orig_buf2, orig_buf3, copy_width); + new_buf += new_width; + orig_buf1 += orig_width; + + /* odd row, recycles same U & V */ + stride_copy_zip3a (new_buf, orig_buf1, orig_buf2, orig_buf3, copy_width); + new_buf += new_width; + orig_buf1 += orig_width; + + orig_buf2 += orig_width/2; + orig_buf3 += orig_width/2; + + height -= 2; + } +} + +/** * 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 @@ -250,14 +293,36 @@ stridify_i420_nv12 (GstStrideTransform *self, guchar *strided, guchar *unstrided /* XXX widths/heights/strides that are not multiple of four??: */ stridemove_zip2 ( strided + (height*stride), - unstrided + (height*width), - unstrided + (int)(height*width*1.25), - stride, width/2, height/2); /* interleave U&V */ - stridemove (strided, unstrided, stride, width, height); /* move Y */ + unstrided + (height*width), /* U */ + unstrided + (int)(height*width*1.25), /* V */ + stride, width/2, height/2); + stridemove (strided, unstrided, stride, width, height); /* Y */ + + return GST_FLOW_OK; +} + +/** convert I420 unstrided to YUY2 strided */ +static GstFlowReturn +stridify_i420_yuy2 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + + /* XXX widths/heights/strides that are not multiple of four??: */ + stridemove_zip3a ( + strided, + unstrided, /* Y */ + unstrided + (height*width), /* U */ + unstrided + (int)(height*width*1.25), /* V */ + stride, width, height); return GST_FLOW_OK; } + /* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ Conversion stride_conversions[] = { { { GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV12 }, stridify_420sp_420sp, unstridify_420sp_420sp }, @@ -266,6 +331,7 @@ Conversion stride_conversions[] = { { { GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_YUY2 }, stridify_422i_422i, unstridify_422i_422i }, { { GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY }, stridify_422i_422i, unstridify_422i_422i }, { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_NV12 }, stridify_i420_nv12, NULL }, + { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YUY2 }, stridify_i420_yuy2, NULL }, /* add new entries before here */ { { GST_VIDEO_FORMAT_UNKNOWN } } }; -- 1.7.9.5 From 6cb0fdd410d257d04fbe824a37cfc34a88583fa9 Mon Sep 17 00:00:00 2001 From: "Castaneda Sheissa, Roberto" <rsheissa@ti.com> Date: Sun, 3 Jan 2010 13:40:30 -0600 Subject: [PATCH] Add support for RGB565 to stridetransform --- gst/stride/convert.c | 30 ++++++++++ gst/stride/gststridetransform.c | 120 ++++++++++++++++++++------------------- 2 files changed, 93 insertions(+), 57 deletions(-) diff --git a/gst/stride/convert.c b/gst/stride/convert.c index 0f59e78..fdb02ae 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -322,6 +322,35 @@ stridify_i420_yuy2 (GstStrideTransform *self, guchar *strided, guchar *unstrided return GST_FLOW_OK; } +/** convert RGB565 to RGB565 strided **/ +static GstFlowReturn +stridify_rgb565_rgb565 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; + + g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + + stridemove (strided, unstrided, stride, width*2, height); + + return GST_FLOW_OK; +} + +/** convert RGB565 strided to RGB565 **/ +static GstFlowReturn +unstridify_rgb565_rgb565 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +{ + gint width = self->width; + gint height = self->height; + gint stride = self->in_rowstride; + + g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + + stridemove (unstrided, strided, width*2, stride, height); + return GST_FLOW_OK; +} + /* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ Conversion stride_conversions[] = { @@ -332,6 +361,7 @@ Conversion stride_conversions[] = { { { GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY }, stridify_422i_422i, unstridify_422i_422i }, { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_NV12 }, stridify_i420_nv12, NULL }, { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YUY2 }, stridify_i420_yuy2, NULL }, + { { GST_VIDEO_FORMAT_RGB16, GST_VIDEO_FORMAT_RGB16 }, stridify_rgb565_rgb565, unstridify_rgb565_rgb565 }, /* add new entries before here */ { { GST_VIDEO_FORMAT_UNKNOWN } } }; diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 6ab0479..c35be73 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -66,46 +66,47 @@ GST_ELEMENT_DETAILS ("Stride transform", /* TODO: add rgb formats too! */ -#define SUPPORTED_CAPS \ - GST_VIDEO_CAPS_YUV_STRIDED ("{ I420, YV12, YUY2, UYVY, NV12 }", "[ 0, max ]") +#define YUV_SUPPORTED_CAPS \ + GST_VIDEO_CAPS_YUV_STRIDED ("{I420, YV12, YUY2, UYVY, NV12 }", "[ 0, max ]") +#define RGB_SUPPORTED_CAPS \ + GST_VIDEO_CAPS_RGB_16_STRIDED ("[ 0, max ]") -static GstStaticPadTemplate src_template = -GST_STATIC_PAD_TEMPLATE ("src", + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (SUPPORTED_CAPS) -); + GST_STATIC_CAPS (YUV_SUPPORTED_CAPS ";" RGB_SUPPORTED_CAPS) + ); -static GstStaticPadTemplate sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (SUPPORTED_CAPS) -); + GST_STATIC_CAPS (YUV_SUPPORTED_CAPS ";" RGB_SUPPORTED_CAPS) + ); GST_DEBUG_CATEGORY (stridetransform_debug); #define GST_CAT_DEFAULT stridetransform_debug /* type functions */ -static void gst_stride_transform_dispose (GObject *obj); +static void gst_stride_transform_dispose (GObject * obj); /* GstBaseTransform functions */ -static gboolean gst_stride_transform_get_unit_size (GstBaseTransform *base, - GstCaps *caps, guint *size); -static gboolean gst_stride_transform_transform_size (GstBaseTransform *base, +static gboolean gst_stride_transform_get_unit_size (GstBaseTransform * base, + GstCaps * caps, guint * size); +static gboolean gst_stride_transform_transform_size (GstBaseTransform * base, GstPadDirection direction, - GstCaps *caps, guint size, - GstCaps *othercaps, guint *othersize); -static GstCaps *gst_stride_transform_transform_caps (GstBaseTransform *base, - GstPadDirection direction, GstCaps *caps); -static gboolean gst_stride_transform_set_caps (GstBaseTransform *base, - GstCaps *incaps, GstCaps *outcaps); -static GstFlowReturn gst_stride_transform_transform (GstBaseTransform *base, - GstBuffer *inbuf, GstBuffer *outbuf); + GstCaps * caps, guint size, GstCaps * othercaps, guint * othersize); +static GstCaps *gst_stride_transform_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_stride_transform_set_caps (GstBaseTransform * base, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, + GstBuffer * inbuf, GstBuffer * outbuf); -GST_BOILERPLATE (GstStrideTransform, gst_stride_transform, GstVideoFilter, GST_TYPE_VIDEO_FILTER); +GST_BOILERPLATE (GstStrideTransform, gst_stride_transform, GstVideoFilter, + GST_TYPE_VIDEO_FILTER); static void @@ -113,7 +114,8 @@ gst_stride_transform_base_init (gpointer g_class) { GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - GST_DEBUG_CATEGORY_INIT (stridetransform_debug, "stride", 0, "stride transform element"); + GST_DEBUG_CATEGORY_INIT (stridetransform_debug, "stride", 0, + "stride transform element"); gst_element_class_set_details (gstelement_class, &stridetransform_details); @@ -124,7 +126,7 @@ gst_stride_transform_base_init (gpointer g_class) } static void -gst_stride_transform_class_init (GstStrideTransformClass *klass) +gst_stride_transform_class_init (GstStrideTransformClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS (klass); @@ -146,14 +148,15 @@ gst_stride_transform_class_init (GstStrideTransformClass *klass) } static void -gst_stride_transform_init (GstStrideTransform *self, GstStrideTransformClass *klass) +gst_stride_transform_init (GstStrideTransform * self, + GstStrideTransformClass * klass) { GST_DEBUG_OBJECT (self, "not implemented"); } static void -gst_stride_transform_dispose (GObject *object) +gst_stride_transform_dispose (GObject * object) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (object); GST_DEBUG_OBJECT (self, "not implemented"); @@ -164,15 +167,15 @@ gst_stride_transform_dispose (GObject *object) * figure out the required buffer size based on @caps */ static gboolean -gst_stride_transform_get_unit_size (GstBaseTransform *base, - GstCaps *caps, guint *size) +gst_stride_transform_get_unit_size (GstBaseTransform * base, + GstCaps * caps, guint * size) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); GstVideoFormat format; gint width, height, rowstride; - g_return_val_if_fail (gst_video_format_parse_caps_strided ( - caps, &format, &width, &height, &rowstride), FALSE); + g_return_val_if_fail (gst_video_format_parse_caps_strided (caps, &format, + &width, &height, &rowstride), FALSE); *size = gst_video_format_get_size_strided (format, width, height, rowstride); @@ -188,16 +191,14 @@ gst_stride_transform_get_unit_size (GstBaseTransform *base, * buffer size is a multiple of the unit size.. which doesn't hold true. */ static gboolean -gst_stride_transform_transform_size (GstBaseTransform *base, +gst_stride_transform_transform_size (GstBaseTransform * base, GstPadDirection direction, - GstCaps *caps, guint size, - GstCaps *othercaps, guint *othersize) + GstCaps * caps, guint size, GstCaps * othercaps, guint * othersize) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); guint idx = (direction == GST_PAD_SINK) ? 0 : 1; - if (self->cached_caps[idx] != othercaps) - { + if (self->cached_caps[idx] != othercaps) { guint sz; if (!gst_stride_transform_get_unit_size (base, othercaps, &sz)) { return FALSE; @@ -220,13 +221,15 @@ gst_stride_transform_transform_size (GstBaseTransform *base, * helper to add all fields, other than rowstride to @caps, copied from @s. */ static void -add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rowstride, GstPadDirection direction) +add_all_fields (GstCaps * caps, const gchar * name, GstStructure * s, + gboolean rowstride, GstPadDirection direction) { gint idx; GstStructure *new_s = gst_structure_new (name, NULL); if (rowstride) { - gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, + NULL); } idx = gst_structure_n_fields (s) - 1; @@ -245,15 +248,16 @@ add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rows gint from_format = (direction == GST_PAD_SRC) ? 1 : 0; if (gst_structure_get_fourcc (s, "format", &fourcc)) { - GValue formats = {0}; - GValue fourccval = {0}; + GValue formats = { 0 }; + GValue fourccval = { 0 }; gint i; GstVideoFormat format = gst_video_format_from_fourcc (fourcc); g_value_init (&formats, GST_TYPE_LIST); g_value_init (&fourccval, GST_TYPE_FOURCC); - for (i=0; stride_conversions[i].format[0]!=GST_VIDEO_FORMAT_UNKNOWN; i++) { + for (i = 0; stride_conversions[i].format[0] != GST_VIDEO_FORMAT_UNKNOWN; + i++) { if (stride_conversions[i].format[from_format] == format) { gst_value_set_fourcc (&fourccval, gst_video_format_to_fourcc (stride_conversions[i].format[to_format])); @@ -281,8 +285,8 @@ add_all_fields (GstCaps *caps, const gchar *name, GstStructure *s, gboolean rows * identical parameters */ static GstCaps * -gst_stride_transform_transform_caps (GstBaseTransform *base, - GstPadDirection direction, GstCaps *caps) +gst_stride_transform_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); GstCaps *ret; @@ -321,8 +325,8 @@ gst_stride_transform_transform_caps (GstBaseTransform *base, * plus the requested rowstride of the @incaps and @outcaps */ static gboolean -gst_stride_transform_set_caps (GstBaseTransform *base, - GstCaps *incaps, GstCaps *outcaps) +gst_stride_transform_set_caps (GstBaseTransform * base, + GstCaps * incaps, GstCaps * outcaps) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); gint width, height; @@ -333,13 +337,13 @@ gst_stride_transform_set_caps (GstBaseTransform *base, LOG_CAPS (self, outcaps); g_return_val_if_fail (gst_video_format_parse_caps_strided (incaps, - &in_format, &self->width, &self->height, &self->in_rowstride), FALSE); + &in_format, &self->width, &self->height, &self->in_rowstride), FALSE); g_return_val_if_fail (gst_video_format_parse_caps_strided (outcaps, - &out_format, &width, &height, &self->out_rowstride), FALSE); + &out_format, &width, &height, &self->out_rowstride), FALSE); self->conversion = NULL; - for (i=0; stride_conversions[i].format[0]!=GST_VIDEO_FORMAT_UNKNOWN; i++) { + for (i = 0; stride_conversions[i].format[0] != GST_VIDEO_FORMAT_UNKNOWN; i++) { if ((stride_conversions[i].format[0] == in_format) && (stride_conversions[i].format[1] == out_format)) { GST_DEBUG_OBJECT (self, "found stride_conversion: %d", i); @@ -349,26 +353,27 @@ gst_stride_transform_set_caps (GstBaseTransform *base, } g_return_val_if_fail (self->conversion, FALSE); - g_return_val_if_fail (self->conversion->unstridify || !self->in_rowstride, FALSE); - g_return_val_if_fail (self->conversion->stridify || !self->out_rowstride, FALSE); - g_return_val_if_fail (self->width == width, FALSE); + g_return_val_if_fail (self->conversion->unstridify + || !self->in_rowstride, FALSE); + g_return_val_if_fail (self->conversion->stridify + || !self->out_rowstride, FALSE); + g_return_val_if_fail (self->width == width, FALSE); g_return_val_if_fail (self->height == height, FALSE); return TRUE; } static GstFlowReturn -gst_stride_transform_transform (GstBaseTransform *base, - GstBuffer *inbuf, GstBuffer *outbuf) +gst_stride_transform_transform (GstBaseTransform * base, + GstBuffer * inbuf, GstBuffer * outbuf) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); GST_DEBUG_OBJECT (self, "inbuf=%p (size=%d), outbuf=%p (size=%d)", - inbuf, GST_BUFFER_SIZE (inbuf), - outbuf, GST_BUFFER_SIZE (outbuf)); + inbuf, GST_BUFFER_SIZE (inbuf), outbuf, GST_BUFFER_SIZE (outbuf)); if (self->in_rowstride && self->out_rowstride) { - GST_DEBUG_OBJECT (self, "not implemented"); // TODO + GST_DEBUG_OBJECT (self, "not implemented"); // TODO return GST_FLOW_ERROR; } else if (self->in_rowstride) { return self->conversion->unstridify (self, @@ -378,7 +383,8 @@ gst_stride_transform_transform (GstBaseTransform *base, GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); } - GST_DEBUG_OBJECT (self, "this shouldn't happen! in_rowstride=%d, out_rowstride=%d", + GST_DEBUG_OBJECT (self, + "this shouldn't happen! in_rowstride=%d, out_rowstride=%d", self->in_rowstride, self->out_rowstride); return GST_FLOW_ERROR; -- 1.7.9.5 From 711cb5b4353dd1f24cce3f1d5203fbe4116c28e6 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Thu, 8 Apr 2010 03:30:35 -0500 Subject: [PATCH] stridetransform: updates for new extra-anal compiler warning flags --- gst/stride/convert.c | 6 ++++++ gst/stride/gststridetransform.c | 13 ++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/gst/stride/convert.c b/gst/stride/convert.c index fdb02ae..ad9c0aa 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -48,6 +48,12 @@ GST_DEBUG_CATEGORY_EXTERN (stridetransform_debug); * Conversion utilities: */ +void stride_copy_zip2 (guchar * new_buf, guchar * orig_buf1, + guchar * orig_buf2, gint sz); +void stride_copy_zip3a (guchar * new_buf, guchar * orig_buf1, + guchar * orig_buf2, guchar * orig_buf3, gint sz); +void stride_copy (guchar * new_buf, guchar * orig_buf, gint sz); + WEAK void stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz) { diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index c35be73..de07c11 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -57,14 +57,6 @@ /* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ extern const Conversion stride_conversions[]; - -static const GstElementDetails stridetransform_details = -GST_ELEMENT_DETAILS ("Stride transform", - "Filter/Converter/Video", - "Convert between video buffers with and without stride, or with differing stride", - "Rob Clark <rob@ti.com>,"); - - /* TODO: add rgb formats too! */ #define YUV_SUPPORTED_CAPS \ GST_VIDEO_CAPS_YUV_STRIDED ("{I420, YV12, YUY2, UYVY, NV12 }", "[ 0, max ]") @@ -117,7 +109,10 @@ gst_stride_transform_base_init (gpointer g_class) GST_DEBUG_CATEGORY_INIT (stridetransform_debug, "stride", 0, "stride transform element"); - gst_element_class_set_details (gstelement_class, &stridetransform_details); + gst_element_class_set_details_simple (gstelement_class, + "Stride transform", "Filter/Converter/Video", + "Convert between video buffers with and without stride, or with differing stride", + "Rob Clark <rob@ti.com>,"); gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sink_template)); -- 1.7.9.5 From ef42a94ae72d947128aa3b562c913e55b08bf1db Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Sat, 30 Jan 2010 14:32:42 -0600 Subject: [PATCH] stridetransform: fix problem transforming caps with list of fourcc's previous logic assumed that the format field would contain just a single fourcc --- gst/stride/convert.c | 206 ++++++++++++++++++++------------------- gst/stride/gststridetransform.c | 78 ++++++++++----- 2 files changed, 159 insertions(+), 125 deletions(-) diff --git a/gst/stride/convert.c b/gst/stride/convert.c index ad9c0aa..17f9e2a 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -55,7 +55,8 @@ void stride_copy_zip3a (guchar * new_buf, guchar * orig_buf1, void stride_copy (guchar * new_buf, guchar * orig_buf, gint sz); WEAK void -stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz) +stride_copy_zip2 (guchar * new_buf, guchar * orig_buf1, guchar * orig_buf2, + gint sz) { while (sz--) { *new_buf++ = *orig_buf1++; @@ -64,8 +65,8 @@ stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz } WEAK void -stride_copy_zip3a (guchar *new_buf, - guchar *orig_buf1, guchar *orig_buf2, guchar *orig_buf3, gint sz) +stride_copy_zip3a (guchar * new_buf, + guchar * orig_buf1, guchar * orig_buf2, guchar * orig_buf3, gint sz) { while (sz > 1) { *new_buf++ = *orig_buf1++; @@ -77,7 +78,7 @@ stride_copy_zip3a (guchar *new_buf, } WEAK void -stride_copy (guchar *new_buf, guchar *orig_buf, gint sz) +stride_copy (guchar * new_buf, guchar * orig_buf, gint sz) { memcpy (new_buf, orig_buf, sz); } @@ -87,11 +88,13 @@ stride_copy (guchar *new_buf, guchar *orig_buf, gint sz) * move to strided buffer, interleaving two planes of identical dimensions */ static void -stridemove_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint new_width, gint orig_width, gint height) +stridemove_zip2 (guchar * new_buf, guchar * orig_buf1, guchar * orig_buf2, + gint new_width, gint orig_width, gint height) { int row; - GST_DEBUG ("new_buf=%p, orig_buf1=%p, orig_buf2=%p, new_width=%d, orig_width=%d, height=%d", + GST_DEBUG + ("new_buf=%p, orig_buf1=%p, orig_buf2=%p, new_width=%d, orig_width=%d, height=%d", new_buf, orig_buf1, orig_buf2, new_width, orig_width, height); /* if increasing the stride, work from bottom-up to avoid overwriting data @@ -99,20 +102,16 @@ stridemove_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint new * for the same reason. */ if (new_width > orig_width) { - for (row=height-1; row>=0; row--) { - stride_copy_zip2 ( - new_buf+(new_width*row), - orig_buf1+(orig_width*row), - orig_buf2+(orig_width*row), - orig_width); + for (row = height - 1; row >= 0; row--) { + stride_copy_zip2 (new_buf + (new_width * row), + orig_buf1 + (orig_width * row), + orig_buf2 + (orig_width * row), orig_width); } } else { - for (row=0; row<height; row++) { - stride_copy_zip2 ( - new_buf+(new_width*row), - orig_buf1+(orig_width*row), - orig_buf2+(orig_width*row), - new_width); + for (row = 0; row < height; row++) { + stride_copy_zip2 (new_buf + (new_width * row), + orig_buf1 + (orig_width * row), + orig_buf2 + (orig_width * row), new_width); } } } @@ -122,8 +121,8 @@ stridemove_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint new * (orig_buf1) has 2x as many samples.. Ie. ABACABAC.. */ static void -stridemove_zip3a (guchar *new_buf, - guchar *orig_buf1, guchar *orig_buf2, guchar *orig_buf3, +stridemove_zip3a (guchar * new_buf, + guchar * orig_buf1, guchar * orig_buf2, guchar * orig_buf3, guint new_width, gint orig_width, gint height) { gint copy_width = (new_width < orig_width) ? new_width : orig_width; @@ -140,8 +139,8 @@ stridemove_zip3a (guchar *new_buf, new_buf += new_width; orig_buf1 += orig_width; - orig_buf2 += orig_width/2; - orig_buf3 += orig_width/2; + orig_buf2 += orig_width / 2; + orig_buf3 += orig_width / 2; height -= 2; } @@ -155,7 +154,8 @@ stridemove_zip3a (guchar *new_buf, * enough. */ static void -stridemove (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, gint height) +stridemove (guchar * new_buf, guchar * orig_buf, gint new_width, + gint orig_width, gint height) { int row; @@ -167,12 +167,14 @@ stridemove (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, * for the same reason. */ if (new_width > orig_width) { - for (row=height-1; row>=0; row--) { - stride_copy (new_buf+(new_width*row), orig_buf+(orig_width*row), orig_width); + for (row = height - 1; row >= 0; row--) { + stride_copy (new_buf + (new_width * row), orig_buf + (orig_width * row), + orig_width); } } else { - for (row=0; row<height; row++) { - stride_copy (new_buf+(new_width*row), orig_buf+(orig_width*row), new_width); + for (row = 0; row < height; row++) { + stride_copy (new_buf + (new_width * row), orig_buf + (orig_width * row), + new_width); } } } @@ -183,9 +185,10 @@ stridemove (guchar *new_buf, guchar *orig_buf, gint new_width, gint orig_width, /** convert 4:2:0 semiplanar to same 4:2:0 semiplanar */ static GstFlowReturn -unstridify_420sp_420sp (GstStrideTransform *self, guchar *unstrided, guchar *strided) +unstridify_420sp_420sp (GstStrideTransform * self, guchar * unstrided, + guchar * strided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->in_rowstride; @@ -196,10 +199,12 @@ unstridify_420sp_420sp (GstStrideTransform *self, guchar *unstrided, guchar *str return GST_FLOW_OK; } + static GstFlowReturn -stridify_420sp_420sp (GstStrideTransform *self, guchar *strided, guchar *unstrided) +stridify_420sp_420sp (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->out_rowstride; @@ -214,115 +219,107 @@ stridify_420sp_420sp (GstStrideTransform *self, guchar *strided, guchar *unstrid /** convert 4:2:0 planar to same 4:2:0 planar */ static GstFlowReturn -unstridify_420p_420p (GstStrideTransform *self, guchar *unstrided, guchar *strided) +unstridify_420p_420p (GstStrideTransform * self, guchar * unstrided, + guchar * strided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->in_rowstride; 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, strided, width, stride, height); /* move Y */ + stridemove (unstrided + (height * width), strided + (height * stride), width / 2, stride, height); /* move V/U */ /* XXX odd widths/heights/strides: */ - stridemove ( - unstrided + (int)(height*width*1.5), - strided + (int)(height*stride*1.5), - width/2, stride, height); /* move U/V */ + stridemove (unstrided + (int) (height * width * 1.5), strided + (int) (height * stride * 1.5), width / 2, stride, height); /* move U/V */ return GST_FLOW_OK; } + static GstFlowReturn -stridify_420p_420p (GstStrideTransform *self, guchar *strided, guchar *unstrided) +stridify_420p_420p (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->out_rowstride; g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); /* XXX odd widths/heights/strides: */ - 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 */ + 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; } /** convert 4:2:2 packed to same 4:2:2 packed */ static GstFlowReturn -unstridify_422i_422i (GstStrideTransform *self, guchar *unstrided, guchar *strided) +unstridify_422i_422i (GstStrideTransform * self, guchar * unstrided, + guchar * strided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->in_rowstride; - g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - stridemove (unstrided, strided, width*2, stride, height); + stridemove (unstrided, strided, width * 2, stride, height); return GST_FLOW_OK; } + static GstFlowReturn -stridify_422i_422i (GstStrideTransform *self, guchar *strided, guchar *unstrided) +stridify_422i_422i (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->out_rowstride; - g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - stridemove (strided, unstrided, stride, width*2, height); + stridemove (strided, unstrided, stride, width * 2, height); return GST_FLOW_OK; } /** convert I420 unstrided to NV12 strided */ static GstFlowReturn -stridify_i420_nv12 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +stridify_i420_nv12 (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->out_rowstride; g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); /* XXX widths/heights/strides that are not multiple of four??: */ - stridemove_zip2 ( - strided + (height*stride), - unstrided + (height*width), /* U */ - unstrided + (int)(height*width*1.25), /* V */ - stride, width/2, height/2); - stridemove (strided, unstrided, stride, width, height); /* Y */ + stridemove_zip2 (strided + (height * stride), unstrided + (height * width), /* U */ + unstrided + (int) (height * width * 1.25), /* V */ + stride, width / 2, height / 2); + stridemove (strided, unstrided, stride, width, height); /* Y */ return GST_FLOW_OK; } /** convert I420 unstrided to YUY2 strided */ static GstFlowReturn -stridify_i420_yuy2 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +stridify_i420_yuy2 (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; + gint width = self->width; gint height = self->height; gint stride = self->out_rowstride; g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); /* XXX widths/heights/strides that are not multiple of four??: */ - stridemove_zip3a ( - strided, - unstrided, /* Y */ - unstrided + (height*width), /* U */ - unstrided + (int)(height*width*1.25), /* V */ + stridemove_zip3a (strided, unstrided, /* Y */ + unstrided + (height * width), /* U */ + unstrided + (int) (height * width * 1.25), /* V */ stride, width, height); return GST_FLOW_OK; @@ -330,46 +327,51 @@ stridify_i420_yuy2 (GstStrideTransform *self, guchar *strided, guchar *unstrided /** convert RGB565 to RGB565 strided **/ static GstFlowReturn -stridify_rgb565_rgb565 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +stridify_rgb565_rgb565 (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; + gint width = self->width; + gint height = self->height; + gint stride = self->out_rowstride; - g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - stridemove (strided, unstrided, stride, width*2, height); + stridemove (strided, unstrided, stride, width * 2, height); - return GST_FLOW_OK; + return GST_FLOW_OK; } /** convert RGB565 strided to RGB565 **/ static GstFlowReturn -unstridify_rgb565_rgb565 (GstStrideTransform *self, guchar *strided, guchar *unstrided) +unstridify_rgb565_rgb565 (GstStrideTransform * self, guchar * strided, + guchar * unstrided) { - gint width = self->width; - gint height = self->height; - gint stride = self->in_rowstride; + gint width = self->width; + gint height = self->height; + gint stride = self->in_rowstride; - g_return_val_if_fail (stride >= (width*2), GST_FLOW_ERROR); + g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - stridemove (unstrided, strided, width*2, stride, height); - return GST_FLOW_OK; + stridemove (unstrided, strided, width * 2, stride, height); + return GST_FLOW_OK; } +#define CONVERT(tofmt, fromfmt, stridify, unstridify) \ + { \ + { GST_VIDEO_FORMAT_##tofmt, GST_VIDEO_FORMAT_##fromfmt }, \ + stridify, unstridify \ + } /* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ -Conversion stride_conversions[] = { - { { GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_NV12 }, stridify_420sp_420sp, unstridify_420sp_420sp }, - { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_I420 }, stridify_420p_420p, unstridify_420p_420p }, - { { GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YV12 }, stridify_420p_420p, unstridify_420p_420p }, - { { GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_YUY2 }, stridify_422i_422i, unstridify_422i_422i }, - { { GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY }, stridify_422i_422i, unstridify_422i_422i }, - { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_NV12 }, stridify_i420_nv12, NULL }, - { { GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YUY2 }, stridify_i420_yuy2, NULL }, - { { GST_VIDEO_FORMAT_RGB16, GST_VIDEO_FORMAT_RGB16 }, stridify_rgb565_rgb565, unstridify_rgb565_rgb565 }, +const Conversion stride_conversions[] = { + CONVERT (NV12, NV12, stridify_420sp_420sp, unstridify_420sp_420sp), + CONVERT (I420, I420, stridify_420p_420p, unstridify_420p_420p), + CONVERT (YV12, YV12, stridify_420p_420p, unstridify_420p_420p), + CONVERT (YUY2, YUY2, stridify_422i_422i, unstridify_422i_422i), + CONVERT (UYVY, UYVY, stridify_422i_422i, unstridify_422i_422i), + CONVERT (I420, NV12, stridify_i420_nv12, NULL), + CONVERT (I420, YUY2, stridify_i420_yuy2, NULL), + CONVERT (RGB16, RGB16, stridify_rgb565_rgb565, unstridify_rgb565_rgb565), /* add new entries before here */ - { { GST_VIDEO_FORMAT_UNKNOWN } } + {{GST_VIDEO_FORMAT_UNKNOWN}} }; - - diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index de07c11..4469e7f 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -146,7 +146,9 @@ static void gst_stride_transform_init (GstStrideTransform * self, GstStrideTransformClass * klass) { - GST_DEBUG_OBJECT (self, "not implemented"); + GST_DEBUG_OBJECT (self, "ENTER"); + self->cached_caps[0] = NULL; + self->cached_caps[1] = NULL; } @@ -154,7 +156,7 @@ static void gst_stride_transform_dispose (GObject * object) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (object); - GST_DEBUG_OBJECT (self, "not implemented"); + GST_DEBUG_OBJECT (self, "ENTER"); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -210,7 +212,30 @@ gst_stride_transform_transform_size (GstBaseTransform * base, return TRUE; } +/** + * helper to check possible @fourcc conversions to the list @formats + */ +static void +add_all_fourcc_conversions (GValue * formats, guint32 fourcc, + GstPadDirection direction) +{ + gint to_format = (direction == GST_PAD_SINK) ? 1 : 0; + gint from_format = (direction == GST_PAD_SRC) ? 1 : 0; + GValue fourccval = { 0 }; + gint i; + GstVideoFormat format = gst_video_format_from_fourcc (fourcc); + g_value_init (&fourccval, GST_TYPE_FOURCC); + + for (i = 0; stride_conversions[i].format[0] != GST_VIDEO_FORMAT_UNKNOWN; i++) { + if (stride_conversions[i].format[from_format] == format) { + guint result_fourcc = + gst_video_format_to_fourcc (stride_conversions[i].format[to_format]); + gst_value_set_fourcc (&fourccval, result_fourcc); + gst_value_list_append_value (formats, &fourccval); + } + } +} /** * helper to add all fields, other than rowstride to @caps, copied from @s. @@ -230,43 +255,44 @@ add_all_fields (GstCaps * caps, const gchar * name, GstStructure * s, idx = gst_structure_n_fields (s) - 1; while (idx >= 0) { const gchar *name = gst_structure_nth_field_name (s, idx); + const GValue *val = gst_structure_get_value (s, name); + idx--; /* for format field, check the stride_conversions table to see what * we can support: */ if (!strcmp ("format", name)) { - guint fourcc; + GValue formats = { 0 }; - /* XXX double check this: */ - gint to_format = (direction == GST_PAD_SINK) ? 1 : 0; - gint from_format = (direction == GST_PAD_SRC) ? 1 : 0; + g_value_init (&formats, GST_TYPE_LIST); - if (gst_structure_get_fourcc (s, "format", &fourcc)) { - GValue formats = { 0 }; - GValue fourccval = { 0 }; + if (GST_VALUE_HOLDS_FOURCC (val)) { + add_all_fourcc_conversions (&formats, + gst_value_get_fourcc (val), direction); + } else if (GST_VALUE_HOLDS_LIST (val)) { gint i; - GstVideoFormat format = gst_video_format_from_fourcc (fourcc); - - g_value_init (&formats, GST_TYPE_LIST); - g_value_init (&fourccval, GST_TYPE_FOURCC); - - for (i = 0; stride_conversions[i].format[0] != GST_VIDEO_FORMAT_UNKNOWN; - i++) { - if (stride_conversions[i].format[from_format] == format) { - gst_value_set_fourcc (&fourccval, gst_video_format_to_fourcc - (stride_conversions[i].format[to_format])); - gst_value_list_append_value (&formats, &fourccval); + for (i = 0; i < gst_value_list_get_size (val); i++) { + const GValue *list_val = gst_value_list_get_value (val, i); + if (GST_VALUE_HOLDS_FOURCC (list_val)) { + add_all_fourcc_conversions (&formats, + gst_value_get_fourcc (list_val), direction); + } else { + GST_WARNING ("malformed caps!!"); + break; } } - - continue; + } else { + GST_WARNING ("malformed caps!!"); } + + gst_structure_set_value (new_s, "format", &formats); + + continue; } /* copy over all other non-rowstride fields: */ if (strcmp ("rowstride", name)) { - const GValue *val = gst_structure_get_value (s, name); gst_structure_set_value (new_s, name, val); } } @@ -347,6 +373,10 @@ gst_stride_transform_set_caps (GstBaseTransform * base, } } + GST_DEBUG_OBJECT (self, + "conversion[%d]=%p, in_rowstride=%d, out_rowstride=%d", + i, self->conversion, self->in_rowstride, self->out_rowstride); + g_return_val_if_fail (self->conversion, FALSE); g_return_val_if_fail (self->conversion->unstridify || !self->in_rowstride, FALSE); @@ -355,6 +385,8 @@ gst_stride_transform_set_caps (GstBaseTransform * base, g_return_val_if_fail (self->width == width, FALSE); g_return_val_if_fail (self->height == height, FALSE); + GST_DEBUG_OBJECT (self, "caps are ok"); + return TRUE; } -- 1.7.9.5 From 5fab0dcd753eea7590c6309f7df0f63238a32972 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Sat, 6 Feb 2010 22:10:16 -0600 Subject: [PATCH] modify playbin to use stridetransform --- gst/playback/gstplaysink.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index d02ec60..c7d61b8 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -1338,19 +1338,25 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async) head = prev = chain->queue; } - if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) { - GST_DEBUG_OBJECT (playsink, "creating videoconverter"); - chain->conv = - g_object_new (GST_TYPE_PLAY_SINK_VIDEO_CONVERT, "name", "vconv", NULL); - gst_bin_add (bin, chain->conv); - if (prev) { - if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink", - GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) - goto link_failed; + if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) { + GST_DEBUG_OBJECT (playsink, "creating stridetransform"); + chain->conv = gst_element_factory_make ("stridetransform", "vconv"); + if (chain->conv == NULL) { + post_missing_element_message (playsink, "stridetransform"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "stridetransform"), ("video rendering might fail")); } else { - head = chain->conv; + gst_bin_add (bin, chain->conv); + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->conv; + } + prev = chain->conv; } - prev = chain->conv; } if (prev) { -- 1.7.9.5 From 6a39280385cc61ac147ccc624d64fdce739e583c Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Thu, 19 Aug 2010 10:32:52 -0500 Subject: [PATCH] playbin: disable interlaced support Latest totem is enabling interlaced support, which causes similar issues to when native-video is not used.. for now, since none of the codecs support it, disable interlaced support. --- gst/playback/gstplaysink.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index c7d61b8..adf8a9e 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -2184,11 +2184,13 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) /* we have video and we are requested to show it */ need_video = TRUE; +#if 0 /* we only deinterlace if native video is not requested and * we have raw video */ if ((flags & GST_PLAY_FLAG_DEINTERLACE) && !(flags & GST_PLAY_FLAG_NATIVE_VIDEO) && playsink->video_pad_raw) need_deinterlace = TRUE; +#endif } if (playsink->audio_pad) { -- 1.7.9.5 From 08bd65ea875fbb6f5cf9b1268cbe8adf4e9577bd Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Mon, 23 Aug 2010 14:01:14 -0500 Subject: [PATCH] textoverlay: add stride support --- ext/pango/gsttextoverlay.c | 30 ++++++++++++++++++++++-------- ext/pango/gsttextoverlay.h | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/ext/pango/gsttextoverlay.c b/ext/pango/gsttextoverlay.c index a92659f..823b207 100644 --- a/ext/pango/gsttextoverlay.c +++ b/ext/pango/gsttextoverlay.c @@ -191,7 +191,9 @@ static GstStaticPadTemplate src_template_factory = "video/x-surface;" GST_VIDEO_CAPS_YUV ("{I420, YV12, AYUV, YUY2, UYVY, v308, v210," " v216, Y41B, Y42B, Y444, Y800, Y16, NV12, NV21, UYVP, A420," - " YUV9, IYU1}")) + " YUV9, IYU1}") ";" + GST_VIDEO_CAPS_YUV_STRIDED ("{AYUV, I420, UYVY, NV12, NV21}", + "[0, max]")) ); static GstStaticPadTemplate video_sink_template_factory = @@ -211,7 +213,9 @@ static GstStaticPadTemplate video_sink_template_factory = "video/x-surface;" GST_VIDEO_CAPS_YUV ("{I420, YV12, AYUV, YUY2, UYVY, v308, v210," " v216, Y41B, Y42B, Y444, Y800, Y16, NV12, NV21, UYVP, A420," - " YUV9, IYU1}")) + " YUV9, IYU1}") ";" + GST_VIDEO_CAPS_YUV_STRIDED ("{AYUV, I420, UYVY, NV12, NV21}", + "[0, max]")) ); static GstStaticPadTemplate text_sink_template_factory = @@ -787,12 +791,13 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps) overlay->width = 0; overlay->height = 0; + overlay->rowstride = 0; structure = gst_caps_get_structure (caps, 0); fps = gst_structure_get_value (structure, "framerate"); if (fps - && gst_video_format_parse_caps (caps, &overlay->format, &overlay->width, - &overlay->height)) { + && gst_video_format_parse_caps_strided (caps, &overlay->format, + &overlay->width, &overlay->height, &overlay->rowstride)) { ret = gst_pad_set_caps (overlay->srcpad, caps); } @@ -1446,14 +1451,21 @@ gst_text_overlay_render_pangocairo (GstTextOverlay * overlay, #define BOX_XPAD 6 #define BOX_YPAD 6 +static gint +gst_text_overlay_get_stride (GstTextOverlay * overlay, gint component) +{ + if (overlay->rowstride) + return overlay->rowstride; + return gst_video_format_get_row_stride (overlay->format, 0, overlay->width); +} + static inline void gst_text_overlay_shade_planar_Y (GstTextOverlay * overlay, guchar * dest, gint x0, gint x1, gint y0, gint y1) { gint i, j, dest_stride; - dest_stride = gst_video_format_get_row_stride (overlay->format, 0, - overlay->width); + dest_stride = gst_text_overlay_get_stride (overlay, 0); x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width); x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width); @@ -1520,7 +1532,9 @@ static inline void gst_text_overlay_shade_xRGB (GstTextOverlay * overlay, guchar * dest, gint x0, gint x1, gint y0, gint y1) { - gint i, j; + gint i, j, dest_stride; + + dest_stride = gst_text_overlay_get_stride (overlay, 0); x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width); x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width); @@ -1532,7 +1546,7 @@ gst_text_overlay_shade_xRGB (GstTextOverlay * overlay, guchar * dest, for (j = x0; j < x1; j++) { gint y, y_pos, k; - y_pos = (i * 4 * overlay->width) + j * 4; + y_pos = (i * dest_stride) + j * 4; for (k = 0; k < 4; k++) { y = dest[y_pos + k] + overlay->shading_value; dest[y_pos + k] = CLAMP (y, 0, 255); diff --git a/ext/pango/gsttextoverlay.h b/ext/pango/gsttextoverlay.h index d36e476..0895286 100644 --- a/ext/pango/gsttextoverlay.h +++ b/ext/pango/gsttextoverlay.h @@ -118,6 +118,7 @@ struct _GstTextOverlay { gint width; gint height; + gint rowstride; gint fps_n; gint fps_d; GstVideoFormat format; -- 1.7.9.5 From 378582c69be6c3e05b9f6f1ed06452db214ff42f Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Mon, 13 Sep 2010 19:04:47 -0500 Subject: [PATCH] video: more flexible video caps utility Add gst_video_format_new_caps_simple() to allow for more flexible video caps builder, which could be used for template caps and non-fixed caps. Include some changes from ea7446e5b5ad7e2ea15e23d9e7a6bf0746d7c8fa. --- gst-libs/gst/video/video.c | 146 ++++++++++++++++++++++++-------------------- gst-libs/gst/video/video.h | 2 + 2 files changed, 83 insertions(+), 65 deletions(-) diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index d1abc5f..fb0fa6b 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -602,24 +602,41 @@ gst_video_format_new_caps_interlaced (GstVideoFormat format, return res; } -static GstCaps * -gst_video_format_new_caps_raw_strided (GstVideoFormat format, int rowstride) +/** + * gst_video_format_new_caps_simple: + * @format: the #GstVideoFormat describing the raw video format + * @rowstride: 0 for unstrided, -1 for any stride (unfixed), or other + * for fixed stride + * @fieldname: first field to set + * @...: additional arguments + * + * Creates a new #GstCaps object based on the parameters provided. + * + * Since: ??? + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_caps_simple (GstVideoFormat format, int rowstride, + const char *fieldname, ...) { - GstCaps *caps = NULL; + va_list varargs; + GstStructure *s; g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); if (gst_video_format_is_yuv (format)) { - caps = gst_caps_new_simple (rowstride ? + s = gst_structure_new (rowstride ? "video/x-raw-yuv-strided" : "video/x-raw-yuv", - "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), NULL); + "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), + NULL); } else if (gst_video_format_is_rgb (format)) { int red_mask = 0; int blue_mask = 0; int green_mask = 0; - int alpha_mask; - int depth; - int bpp; + int alpha_mask = 0; + int depth = 0; + int bpp = 0; gboolean have_alpha; unsigned int mask = 0; @@ -723,12 +740,12 @@ gst_video_format_new_caps_raw_strided (GstVideoFormat format, int rowstride) g_assert_not_reached (); } - caps = gst_caps_new_simple (rowstride ? - "video/x-raw-rgb-strided" : "video/x-raw-rgb", - "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); + s = gst_structure_new (rowstride ? "video/x-raw-rgb-strided" : + "video/x-raw-rgb", "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, + NULL); if (bpp != 8) { - gst_caps_set_simple (caps, + gst_structure_set (s, "endianness", G_TYPE_INT, G_BIG_ENDIAN, "red_mask", G_TYPE_INT, red_mask, "green_mask", G_TYPE_INT, green_mask, @@ -736,9 +753,12 @@ gst_video_format_new_caps_raw_strided (GstVideoFormat format, int rowstride) } if (have_alpha) { + /* note: we are passing a bogus width/height to get_component_offset(), + * but those parameters are ignored for the packed formats so it is ok + */ alpha_mask = mask >> (8 * gst_video_format_get_component_offset (format, 3, 0, 0)); - gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL); + gst_structure_set (s, "alpha_mask", G_TYPE_INT, alpha_mask, NULL); } } else if (gst_video_format_is_gray (format)) { int bpp; @@ -764,23 +784,61 @@ gst_video_format_new_caps_raw_strided (GstVideoFormat format, int rowstride) } if (bpp <= 8) { - caps = gst_caps_new_simple ("video/x-raw-gray", - "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); + s = gst_structure_new (rowstride ? "video/x-raw-gray-strided" : + "video/x-raw-gray", "bpp", G_TYPE_INT, bpp, "depth", + G_TYPE_INT, depth, NULL); } else { - caps = gst_caps_new_simple ("video/x-raw-gray", - "bpp", G_TYPE_INT, bpp, - "depth", G_TYPE_INT, depth, - "endianness", G_TYPE_INT, endianness, NULL); + s = gst_structure_new (rowstride ? "video/x-raw-gray-strided" : + "video/x-raw-gray", "bpp", G_TYPE_INT, bpp, "depth", + G_TYPE_INT, depth, "endianness", G_TYPE_INT, endianness, NULL); } } else { return NULL; } - if (rowstride) { - gst_caps_set_simple (caps, "rowstride", G_TYPE_INT, rowstride, NULL); + if (rowstride > 0) { + gst_structure_set (s, "rowstride", G_TYPE_INT, rowstride, NULL); + } else if (rowstride < 0) { + gst_structure_set (s, "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); } - return caps; + va_start (varargs, fieldname); + gst_structure_set_valist (s, fieldname, varargs); + va_end (varargs); + + return gst_caps_new_full (s, NULL); +} + +/** + * gst_video_format_new_caps_strided: + * @format: the #GstVideoFormat describing the raw video format + * @width: width of video + * @height: height of video + * @rowstride: the rowstride (in bytes), or 0 if no rowstride + * @framerate_n: numerator of frame rate + * @framerate_d: denominator of frame rate + * @par_n: numerator of pixel aspect ratio + * @par_d: denominator of pixel aspect ratio + * + * Creates a new #GstCaps object based on the parameters provided. + * + * Since: ??? + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_caps_strided (GstVideoFormat format, + int width, int height, int rowstride, + int framerate_n, int framerate_d, int par_n, int par_d) +{ + g_return_val_if_fail (width > 0 && height > 0, NULL); + + return gst_video_format_new_caps_simple (format, rowstride, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, + NULL); } /** @@ -827,7 +885,7 @@ gst_video_format_new_template_caps (GstVideoFormat format) g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); - caps = gst_video_format_new_caps_raw_strided (format, 0); + caps = gst_video_format_new_caps_simple (format, 0, NULL); if (caps) { GValue value = { 0 }; GValue v = { 0 }; @@ -855,48 +913,6 @@ gst_video_format_new_template_caps (GstVideoFormat format) } /** - * gst_video_format_new_caps_strided: - * @format: the #GstVideoFormat describing the raw video format - * @width: width of video - * @height: height of video - * @rowstride: the rowstride (in bytes), or 0 if no rowstride - * @framerate_n: numerator of frame rate - * @framerate_d: denominator of frame rate - * @par_n: numerator of pixel aspect ratio - * @par_d: denominator of pixel aspect ratio - * - * Creates a new #GstCaps object based on the parameters provided. - * - * Since: ??? - * - * Returns: a new #GstCaps object, or NULL if there was an error - */ -GstCaps * -gst_video_format_new_caps_strided (GstVideoFormat format, - int width, int height, int rowstride, - int framerate_n, int framerate_d, int par_n, int par_d) -{ - GstCaps *caps; - GstStructure *structure; - - g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); - g_return_val_if_fail (width > 0 && height > 0, NULL); - - caps = gst_video_format_new_caps_raw_strided (format, rowstride); - if (caps) { - structure = gst_caps_get_structure (caps, 0); - - gst_structure_set (structure, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); - } - - return caps; -} - -/** * gst_video_format_from_fourcc: * @fourcc: a FOURCC value representing raw YUV video * diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h index 3c39f85..997824e 100644 --- a/gst-libs/gst/video/video.h +++ b/gst-libs/gst/video/video.h @@ -507,6 +507,8 @@ GstCaps * gst_video_format_new_template_caps (GstVideoFormat format); GstCaps * gst_video_format_new_caps_strided (GstVideoFormat format, int width, int height, int rowstride, int framerate_n, int framerate_d, int par_n, int par_d); +GstCaps * gst_video_format_new_caps_simple (GstVideoFormat format, + int rowstride, const char *fieldname, ...); /* format properties */ -- 1.7.9.5 From ce30cf7e36e9ba4b8c70ae737c7944ddeecf894e Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Mon, 13 Sep 2010 19:05:56 -0500 Subject: [PATCH] video: fix endianess issue for 16bit RGB formats --- gst-libs/gst/video/video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index fb0fa6b..c9b23b6 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -638,6 +638,7 @@ gst_video_format_new_caps_simple (GstVideoFormat format, int rowstride, int depth = 0; int bpp = 0; gboolean have_alpha; + int endianness = G_BIG_ENDIAN; unsigned int mask = 0; switch (format) { @@ -736,6 +737,7 @@ gst_video_format_new_caps_simple (GstVideoFormat format, int rowstride, default: g_assert_not_reached (); } + endianness = G_BYTE_ORDER; } else if (bpp != 8) { g_assert_not_reached (); } @@ -746,7 +748,7 @@ gst_video_format_new_caps_simple (GstVideoFormat format, int rowstride, if (bpp != 8) { gst_structure_set (s, - "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "endianness", G_TYPE_INT, endianness, "red_mask", G_TYPE_INT, red_mask, "green_mask", G_TYPE_INT, green_mask, "blue_mask", G_TYPE_INT, blue_mask, NULL); -- 1.7.9.5 From 647ac1bab7b06a5fc34a966b5a169e9c81e6d065 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Mon, 13 Sep 2010 19:10:36 -0500 Subject: [PATCH] stride: more flexible stride/color conversion Refactor stride transform element to address a number of limitations: 1) support converting buffers from one rowstride to another, in addition to just handling conversion from strided <-> unstrided. 2) refactor convert code to make it easier to add new formats 3) refactor caps handling code to build template caps based upon color formats listed in convert (stride_conversions table). 4) refactor caps parsing/building to correctly handle RGB formats 5) add support for crop.. currently we optimize by just only copying the uncropped part of the frame, but this is the first step to true handling of cropping, so that we can crop out padding for the benefit of sink elements that don't understand crop or stride. (The convert code handles it fine.. the caps parsing/building in gststridetransform.c would need to handle caps re-negotiation when the crop changes for this to be complete.) --- gst/stride/armv7.s | 8 +- gst/stride/convert.c | 400 ++++++++++++++++++++------------------- gst/stride/gststridetransform.c | 375 ++++++++++++++++++++++++------------ gst/stride/gststridetransform.h | 25 ++- 4 files changed, 490 insertions(+), 318 deletions(-) diff --git a/gst/stride/armv7.s b/gst/stride/armv7.s index 2697a14..5f4200d 100644 --- a/gst/stride/armv7.s +++ b/gst/stride/armv7.s @@ -28,7 +28,7 @@ .global stride_copy_zip2 .type stride_copy_zip2, %function @void -@stride_copy_zip2 (guchar *new_buf, guchar *orig_buf1, guchar *orig_buf2, gint sz) +@stride_copy_zip2 (guchar * out, guchar * in1, guchar * in2, gint sz) @{ @@@@ note: r0-r3, q0-3, and q8-q15 do not need to be preserved stride_copy_zip2: @@ -74,8 +74,8 @@ stride_copy_zip2_3: .global stride_copy_zip3a .type stride_copy_zip3a, %function @void -@stride_copy_zip3a (guchar *new_buf, -@ guchar *orig_buf1, guchar *orig_buf2, guchar *orig_buf3, gint sz) +@stride_copy_zip3a (guchar * out, +@ guchar * in1, guchar * in2, guchar * in3, gint sz) @{ @@@@ note: r0-r3, q0-3, and q8-q15 do not need to be preserved stride_copy_zip3a: @@ -136,7 +136,7 @@ stride_copy_zip3a_3: .global stride_copy .type stride_copy, %function @void -@stride_copy (guchar *new_buf, guchar *orig_buf, gint sz) +@stride_copy (guchar *out, guchar *in, gint sz) @{ @@@@ note: r0-r3, q0-3, and q8-q15 do not need to be preserved stride_copy: diff --git a/gst/stride/convert.c b/gst/stride/convert.c index 17f9e2a..5d392ac 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -55,32 +55,31 @@ void stride_copy_zip3a (guchar * new_buf, guchar * orig_buf1, void stride_copy (guchar * new_buf, guchar * orig_buf, gint sz); WEAK void -stride_copy_zip2 (guchar * new_buf, guchar * orig_buf1, guchar * orig_buf2, - gint sz) +stride_copy_zip2 (guchar * out, guchar * in1, guchar * in2, gint sz) { while (sz--) { - *new_buf++ = *orig_buf1++; - *new_buf++ = *orig_buf2++; + *out++ = *in1++; + *out++ = *in2++; } } WEAK void -stride_copy_zip3a (guchar * new_buf, - guchar * orig_buf1, guchar * orig_buf2, guchar * orig_buf3, gint sz) +stride_copy_zip3a (guchar * out, + guchar * in1, guchar * in2, guchar * in3, gint sz) { while (sz > 1) { - *new_buf++ = *orig_buf1++; - *new_buf++ = *orig_buf2++; - *new_buf++ = *orig_buf1++; - *new_buf++ = *orig_buf3++; + *out++ = *in1++; + *out++ = *in2++; + *out++ = *in1++; + *out++ = *in3++; sz -= 2; } } WEAK void -stride_copy (guchar * new_buf, guchar * orig_buf, gint sz) +stride_copy (guchar * out, guchar * in, gint sz) { - memcpy (new_buf, orig_buf, sz); + memcpy (out, in, sz); } @@ -88,31 +87,19 @@ stride_copy (guchar * new_buf, guchar * orig_buf, gint sz) * move to strided buffer, interleaving two planes of identical dimensions */ static void -stridemove_zip2 (guchar * new_buf, guchar * orig_buf1, guchar * orig_buf2, - gint new_width, gint orig_width, gint height) +stridemove_zip2 (guchar * out, guchar * in1, guchar * in2, + gint out_bpl, gint in_bpl, gint width, gint height) { int row; GST_DEBUG - ("new_buf=%p, orig_buf1=%p, orig_buf2=%p, new_width=%d, orig_width=%d, height=%d", - new_buf, orig_buf1, orig_buf2, 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--) { - stride_copy_zip2 (new_buf + (new_width * row), - orig_buf1 + (orig_width * row), - orig_buf2 + (orig_width * row), orig_width); - } - } else { - for (row = 0; row < height; row++) { - stride_copy_zip2 (new_buf + (new_width * row), - orig_buf1 + (orig_width * row), - orig_buf2 + (orig_width * row), new_width); - } + ("out=%p, in1=%p, in2=%p, out_bpl=%d, in_bpl=%d, width=%d, height=%d", + out, in1, in2, out_bpl, in_bpl, width, height); + + for (row = 0; row < height; row++) { + stride_copy_zip2 (out + (out_bpl * row), + in1 + (in_bpl * row), + in2 + (in_bpl * row), width); } } @@ -121,26 +108,28 @@ stridemove_zip2 (guchar * new_buf, guchar * orig_buf1, guchar * orig_buf2, * (orig_buf1) has 2x as many samples.. Ie. ABACABAC.. */ static void -stridemove_zip3a (guchar * new_buf, - guchar * orig_buf1, guchar * orig_buf2, guchar * orig_buf3, - guint new_width, gint orig_width, gint height) +stridemove_zip3a (guchar * out, + guchar * in1, guchar * in2, guchar * in3, + guint out_bpl, gint in_bpl, gint width, gint height) { - gint copy_width = (new_width < orig_width) ? new_width : orig_width; + GST_DEBUG + ("out=%p, in1=%p, in2=%p, in3=%p, out_bpl=%d, in_bpl=%d, width=%d, height=%d", + out, in1, in2, in3, out_bpl, in_bpl, width, height); while (height > 0) { /* even row */ - stride_copy_zip3a (new_buf, orig_buf1, orig_buf2, orig_buf3, copy_width); - new_buf += new_width; - orig_buf1 += orig_width; + stride_copy_zip3a (out, in1, in2, in3, width); + out += out_bpl; + in1 += in_bpl; /* odd row, recycles same U & V */ - stride_copy_zip3a (new_buf, orig_buf1, orig_buf2, orig_buf3, copy_width); - new_buf += new_width; - orig_buf1 += orig_width; + stride_copy_zip3a (out, in1, in2, in3, width); + out += out_bpl; + in1 += in_bpl; - orig_buf2 += orig_width / 2; - orig_buf3 += orig_width / 2; + in2 += in_bpl / 2; + in3 += in_bpl / 2; height -= 2; } @@ -154,28 +143,18 @@ stridemove_zip3a (guchar * new_buf, * enough. */ static void -stridemove (guchar * new_buf, guchar * orig_buf, gint new_width, - gint orig_width, gint height) +stridemove (guchar * out, guchar * in, gint out_bpl, gint in_bpl, + gint 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--) { - stride_copy (new_buf + (new_width * row), orig_buf + (orig_width * row), - orig_width); - } - } else { - for (row = 0; row < height; row++) { - stride_copy (new_buf + (new_width * row), orig_buf + (orig_width * row), - new_width); - } + GST_DEBUG ("out=%p, in=%p, out_bpl=%d, in_bpl=%d, width=%d, height=%d", + out, in, out_bpl, in_bpl, width, height); + + for (row = 0; row < height; row++) { + stride_copy (out, in, width); + out += out_bpl; + in += in_bpl; } } @@ -183,195 +162,232 @@ stridemove (guchar * new_buf, guchar * orig_buf, gint new_width, * Conversion Functions: */ -/** convert 4:2:0 semiplanar to same 4:2:0 semiplanar */ -static GstFlowReturn -unstridify_420sp_420sp (GstStrideTransform * self, guchar * unstrided, - guchar * strided) +/** + * helper to calculate offsets/sizes that are re-used for each frame (until + * caps or crop changes) + * @isx: input sub-sampling in x direction + * @osx: output sub-sampling in x direction + * @isy: input sub-sampling in y direction + * @isx: input sub-sampling in y direction + */ +static inline gboolean refresh_cache(GstStrideTransform * self, + gint nplanes, gint bpp, gint * isx, gint * osx, gint * isy, gint * osy) { - gint width = self->width; - gint height = self->height; - gint stride = self->in_rowstride; + gint in_off, out_off; + int i; - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + if (((self->crop_top + self->crop_height) > self->height) || + ((self->crop_left + self->crop_width) > self->width)) { + GST_ERROR_OBJECT (self, "invalid crop parameter"); + return GST_FLOW_ERROR; + } - stridemove (unstrided, strided, width, stride, - (GST_ROUND_UP_2 (height) * 3) / 2); + in_off = out_off = 0; - return GST_FLOW_OK; -} + for (i = 0; i < nplanes; i++) { + Cache * cache = &self->cache[i]; -static GstFlowReturn -stridify_420sp_420sp (GstStrideTransform * self, guchar * strided, - guchar * unstrided) -{ - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; + cache->in_bpl = self->in_rowstride ? + self->in_rowstride : bpp * self->width; - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + cache->out_bpl = self->out_rowstride ? + self->out_rowstride : bpp * self->width; - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); - stridemove (strided, unstrided, stride, width, - (GST_ROUND_UP_2 (height) * 3) / 2); + if ((cache->in_bpl < (self->width * bpp)) || + (cache->out_bpl < (self->width * bpp))) { + GST_ERROR_OBJECT (self, "invalid stride parameter"); + return GST_FLOW_ERROR; + } - return GST_FLOW_OK; -} + cache->width = self->crop_width ? + self->crop_width : self->width; -/** convert 4:2:0 planar to same 4:2:0 planar */ -static GstFlowReturn -unstridify_420p_420p (GstStrideTransform * self, guchar * unstrided, - guchar * strided) -{ - gint width = self->width; - gint height = self->height; - gint stride = self->in_rowstride; + cache->height = self->crop_height ? + self->crop_height : self->height; - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + if ((cache->width > self->width) || + (cache->height > self->height)) { + GST_ERROR_OBJECT (self, "invalid crop width/height parameter"); + return 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 */ - /* XXX odd widths/heights/strides: */ - stridemove (unstrided + (int) (height * width * 1.5), strided + (int) (height * stride * 1.5), width / 2, stride, height); /* move U/V */ + /* note: everything above here is same for each plane, so in theory we + * could only calculate on first plane, and copy on subsequent planes + */ + + /* adjust for sub-sampling and bytes per pixel (bpp): */ + cache->in_bpl /= *isx; + cache->out_bpl /= *osx; + cache->width *= bpp; + cache->width /= *isx; + cache->height /= *isy; + + /* calculate offset to beginning of data to copy/transform: */ + cache->in_off = in_off; + cache->in_off += (bpp * self->crop_left / *isx) + + (cache->in_bpl * self->crop_top / *isy); + + cache->out_off = out_off; + cache->out_off += (bpp * self->crop_left / *osx) + + (cache->out_bpl * self->crop_top / *osy); + + in_off += (self->height / *isy) * cache->in_bpl; + out_off += (self->height / *osy) * cache->out_bpl; + + osx++; + isx++; + osy++; + isy++; + } return GST_FLOW_OK; } -static GstFlowReturn -stridify_420p_420p (GstStrideTransform * self, guchar * strided, - guchar * unstrided) +/** perform simple convert between buffers of same format */ +static inline GstFlowReturn convert_n_n (GstStrideTransform *self, + guchar * out, guchar * in, gint nplanes) { - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; - - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + int i; - /* XXX odd widths/heights/strides: */ - 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 */ + for (i = 0; i < nplanes; i++) { + stridemove (out + self->cache[i].out_off, in + self->cache[i].in_off, + self->cache[i].out_bpl, self->cache[i].in_bpl, + self->cache[i].width, self->cache[i].height); + } return GST_FLOW_OK; } -/** convert 4:2:2 packed to same 4:2:2 packed */ +/** convert 4:2:0 semiplanar to same 4:2:0 semiplanar */ static GstFlowReturn -unstridify_422i_422i (GstStrideTransform * self, guchar * unstrided, - guchar * strided) +convert_420sp_420sp (GstStrideTransform * self, + guchar * out, guchar * in) { - gint width = self->width; - gint height = self->height; - gint stride = self->in_rowstride; - - g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - - stridemove (unstrided, strided, width * 2, stride, height); + if (G_UNLIKELY (self->needs_refresh)) { + gint sx[] = {1, 1}; + gint sy[] = {1, 2}; + if (refresh_cache (self, 2, 1, sx, sx, sy, sy)) + return GST_FLOW_ERROR; + self->needs_refresh = FALSE; + } - return GST_FLOW_OK; + return convert_n_n (self, out, in, 2); } +/** convert 4:2:0 planar to same 4:2:0 planar */ static GstFlowReturn -stridify_422i_422i (GstStrideTransform * self, guchar * strided, - guchar * unstrided) +convert_420p_420p (GstStrideTransform * self, + guchar * out, guchar * in) { - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; - - g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - - stridemove (strided, unstrided, stride, width * 2, height); + if (G_UNLIKELY (self->needs_refresh)) { + gint sx[] = {1, 2, 2}; + gint sy[] = {1, 2, 2}; + if (refresh_cache (self, 3, 1, sx, sx, sy, sy)) + return GST_FLOW_ERROR; + self->needs_refresh = FALSE; + } - return GST_FLOW_OK; + return convert_n_n (self, out, in, 3); } -/** convert I420 unstrided to NV12 strided */ +/** convert 4:2:2 packed to same 4:2:2 packed */ + static GstFlowReturn -stridify_i420_nv12 (GstStrideTransform * self, guchar * strided, - guchar * unstrided) +convert_422i_422i (GstStrideTransform * self, + guchar * out, guchar * in) { - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; - - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); - - /* XXX widths/heights/strides that are not multiple of four??: */ - stridemove_zip2 (strided + (height * stride), unstrided + (height * width), /* U */ - unstrided + (int) (height * width * 1.25), /* V */ - stride, width / 2, height / 2); - stridemove (strided, unstrided, stride, width, height); /* Y */ + if (G_UNLIKELY (self->needs_refresh)) { + gint sx[] = {1}; + gint sy[] = {1}; + if (refresh_cache (self, 1, 2, sx, sx, sy, sy)) + return GST_FLOW_ERROR; + self->needs_refresh = FALSE; + } - return GST_FLOW_OK; + return convert_n_n (self, out, in, 1); } -/** convert I420 unstrided to YUY2 strided */ +/** convert I420 unstrided to NV12 strided */ static GstFlowReturn -stridify_i420_yuy2 (GstStrideTransform * self, guchar * strided, - guchar * unstrided) +convert_i420_nv12 (GstStrideTransform * self, + guchar * out, guchar * in) { - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; + GstFlowReturn ret; + + if (G_UNLIKELY (self->needs_refresh)) { + gint isx[] = {1, 2, 2}; + gint osx[] = {1, 1, 1}; + gint sy[] = {1, 2, 2}; + if (refresh_cache (self, 3, 1, isx, osx, sy, sy)) + return GST_FLOW_ERROR; + self->needs_refresh = FALSE; + } - g_return_val_if_fail (stride >= width, GST_FLOW_ERROR); + ret = convert_n_n (self, out, in, 1); + if (ret != GST_FLOW_OK) + return ret; - /* XXX widths/heights/strides that are not multiple of four??: */ - stridemove_zip3a (strided, unstrided, /* Y */ - unstrided + (height * width), /* U */ - unstrided + (int) (height * width * 1.25), /* V */ - stride, width, height); + stridemove_zip2 (out + self->cache[1].out_off, + in + self->cache[1].in_off, /* U */ + in + self->cache[2].in_off, /* V */ + self->cache[2].out_bpl, + self->cache[1].in_bpl, + self->cache[1].width, + self->cache[1].height); return GST_FLOW_OK; } -/** convert RGB565 to RGB565 strided **/ +/** convert I420 unstrided to YUY2 strided */ static GstFlowReturn -stridify_rgb565_rgb565 (GstStrideTransform * self, guchar * strided, - guchar * unstrided) +convert_i420_yuy2 (GstStrideTransform * self, + guchar * out, guchar * in) { - gint width = self->width; - gint height = self->height; - gint stride = self->out_rowstride; - - g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); + if (G_UNLIKELY (self->needs_refresh)) { + gint sx[] = {1, 2, 2}; + gint sy[] = {1, 2, 2}; + if (refresh_cache (self, 3, 1, sx, sx, sy, sy)) + return GST_FLOW_ERROR; + self->needs_refresh = FALSE; + } - stridemove (strided, unstrided, stride, width * 2, height); + stridemove_zip3a (out, + in + self->cache[0].in_off, /* Y */ + in + self->cache[1].in_off, /* U */ + in + self->cache[2].in_off, /* V */ + self->cache[0].out_bpl, + self->cache[0].in_bpl, + self->cache[0].width, + self->cache[0].height); return GST_FLOW_OK; } -/** convert RGB565 strided to RGB565 **/ +/** convert 16bpp rgb formats */ static GstFlowReturn -unstridify_rgb565_rgb565 (GstStrideTransform * self, guchar * strided, - guchar * unstrided) +convert_rgb16_rgb16 (GstStrideTransform * self, + guchar * out, guchar * in) { - gint width = self->width; - gint height = self->height; - gint stride = self->in_rowstride; - - g_return_val_if_fail (stride >= (width * 2), GST_FLOW_ERROR); - - stridemove (unstrided, strided, width * 2, stride, height); - return GST_FLOW_OK; + /* format is same 2-bytes per pixel */ + return convert_422i_422i (self, out, in); } -#define CONVERT(tofmt, fromfmt, stridify, unstridify) \ +#define CONVERT(tofmt, fromfmt, convert) \ { \ { GST_VIDEO_FORMAT_##tofmt, GST_VIDEO_FORMAT_##fromfmt }, \ - stridify, unstridify \ + convert \ } /* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ const Conversion stride_conversions[] = { - CONVERT (NV12, NV12, stridify_420sp_420sp, unstridify_420sp_420sp), - CONVERT (I420, I420, stridify_420p_420p, unstridify_420p_420p), - CONVERT (YV12, YV12, stridify_420p_420p, unstridify_420p_420p), - CONVERT (YUY2, YUY2, stridify_422i_422i, unstridify_422i_422i), - CONVERT (UYVY, UYVY, stridify_422i_422i, unstridify_422i_422i), - CONVERT (I420, NV12, stridify_i420_nv12, NULL), - CONVERT (I420, YUY2, stridify_i420_yuy2, NULL), - CONVERT (RGB16, RGB16, stridify_rgb565_rgb565, unstridify_rgb565_rgb565), + CONVERT (NV12, NV12, convert_420sp_420sp), + CONVERT (I420, I420, convert_420p_420p), + CONVERT (YV12, YV12, convert_420p_420p), + CONVERT (YUY2, YUY2, convert_422i_422i), + CONVERT (UYVY, UYVY, convert_422i_422i), + CONVERT (I420, NV12, convert_i420_nv12), + CONVERT (I420, YUY2, convert_i420_yuy2), + CONVERT (RGB16, RGB16, convert_rgb16_rgb16), /* add new entries before here */ {{GST_VIDEO_FORMAT_UNKNOWN}} }; diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 4469e7f..7874ed4 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -57,27 +57,6 @@ /* last entry has GST_VIDEO_FORMAT_UNKNOWN for in/out formats */ extern const Conversion stride_conversions[]; -/* TODO: add rgb formats too! */ -#define YUV_SUPPORTED_CAPS \ - GST_VIDEO_CAPS_YUV_STRIDED ("{I420, YV12, YUY2, UYVY, NV12 }", "[ 0, max ]") - -#define RGB_SUPPORTED_CAPS \ - GST_VIDEO_CAPS_RGB_16_STRIDED ("[ 0, max ]") - - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (YUV_SUPPORTED_CAPS ";" RGB_SUPPORTED_CAPS) - ); - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (YUV_SUPPORTED_CAPS ";" RGB_SUPPORTED_CAPS) - ); - - GST_DEBUG_CATEGORY (stridetransform_debug); #define GST_CAT_DEFAULT stridetransform_debug @@ -85,6 +64,8 @@ GST_DEBUG_CATEGORY (stridetransform_debug); static void gst_stride_transform_dispose (GObject * obj); /* GstBaseTransform functions */ +static gboolean gst_stride_transform_event (GstBaseTransform * trans, + GstEvent * event); static gboolean gst_stride_transform_get_unit_size (GstBaseTransform * base, GstCaps * caps, guint * size); static gboolean gst_stride_transform_transform_size (GstBaseTransform * base, @@ -96,6 +77,7 @@ static gboolean gst_stride_transform_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps); static GstFlowReturn gst_stride_transform_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf); +static GstCaps * get_all_templ_caps (GstPadDirection direction); GST_BOILERPLATE (GstStrideTransform, gst_stride_transform, GstVideoFilter, GST_TYPE_VIDEO_FILTER); @@ -115,9 +97,11 @@ gst_stride_transform_base_init (gpointer g_class) "Rob Clark <rob@ti.com>,"); gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sink_template)); + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + get_all_templ_caps (GST_PAD_SINK))); gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&src_template)); + gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + get_all_templ_caps (GST_PAD_SRC))); } static void @@ -128,6 +112,8 @@ gst_stride_transform_class_init (GstStrideTransformClass * klass) gobject_class->dispose = gst_stride_transform_dispose; + basetransform_class->event = + GST_DEBUG_FUNCPTR (gst_stride_transform_event); basetransform_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_stride_transform_get_unit_size); basetransform_class->transform_size = @@ -160,6 +146,35 @@ gst_stride_transform_dispose (GObject * object) G_OBJECT_CLASS (parent_class)->dispose (object); } +static gboolean +gst_stride_transform_event (GstBaseTransform * trans, GstEvent * event) +{ + GstStrideTransform *self = GST_STRIDE_TRANSFORM (trans); + + GST_DEBUG_OBJECT (self, "event %" GST_PTR_FORMAT, event); + + switch (GST_EVENT_TYPE (event)) { + /* if we get a crop, we don't change output size (yet, although it + * would be nice to be able to figure out if the sink supported + * cropping and if it does not perform the crop ourselves.. which + * would involve adjusting output caps appropriately). For now + * we just treat it as an optimization and avoid copying the data + * that will be later cropped out by the sink. + */ + case GST_EVENT_CROP: + gst_event_parse_crop (event, &self->crop_top, &self->crop_left, + &self->crop_width, &self->crop_height); + self->needs_refresh = TRUE; + GST_DEBUG_OBJECT (self, "cropping at %d,%d %dx%d", self->crop_top, + self->crop_left, self->crop_width, self->crop_height); + default: + break; + } + + /* forward all events */ + return TRUE; +} + /** * figure out the required buffer size based on @caps */ @@ -212,95 +227,205 @@ gst_stride_transform_transform_size (GstBaseTransform * base, return TRUE; } +static inline GstCaps * +get_templ_caps (GstVideoFormat fmt, gboolean strided) +{ + return gst_video_format_new_caps_simple (fmt, + strided ? -1 : 0, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, + NULL); +} + /** - * helper to check possible @fourcc conversions to the list @formats + * Utility to get all possible template caps for given direction */ -static void -add_all_fourcc_conversions (GValue * formats, guint32 fourcc, - GstPadDirection direction) +static GstCaps * +get_all_templ_caps (GstPadDirection direction) { + int i; gint to_format = (direction == GST_PAD_SINK) ? 1 : 0; - gint from_format = (direction == GST_PAD_SRC) ? 1 : 0; - GValue fourccval = { 0 }; - gint i; - GstVideoFormat format = gst_video_format_from_fourcc (fourcc); - - g_value_init (&fourccval, GST_TYPE_FOURCC); + GstCaps *templ = gst_caps_new_empty (); - for (i = 0; stride_conversions[i].format[0] != GST_VIDEO_FORMAT_UNKNOWN; i++) { - if (stride_conversions[i].format[from_format] == format) { - guint result_fourcc = - gst_video_format_to_fourcc (stride_conversions[i].format[to_format]); - gst_value_set_fourcc (&fourccval, result_fourcc); - gst_value_list_append_value (formats, &fourccval); - } + for (i = 0; stride_conversions[i].format[0]; i++) { + const Conversion *c = &stride_conversions[i]; + gst_caps_append (templ, get_templ_caps (c->format[to_format], TRUE)); + gst_caps_append (templ, get_templ_caps (c->format[to_format], FALSE)); } + + gst_caps_do_simplify (templ); + + GST_DEBUG ("template %s caps: %"GST_PTR_FORMAT, + (direction == GST_PAD_SINK) ? "sink" : "src", templ); + + return templ; } -/** - * helper to add all fields, other than rowstride to @caps, copied from @s. - */ -static void -add_all_fields (GstCaps * caps, const gchar * name, GstStructure * s, - gboolean rowstride, GstPadDirection direction) +static inline gboolean +is_filtered_field (const gchar *name) { - gint idx; - GstStructure *new_s = gst_structure_new (name, NULL); + static const gchar * filtered_fields[] = { + "rowstride", "format", "bpp", "depth", "endianness", + "red_mask", "green_mask", "blue_mask" + }; + gint i; + for (i = 0; i < G_N_ELEMENTS (filtered_fields); i++) + if (!strcmp (filtered_fields[i], name)) + return TRUE; + return FALSE; +} - if (rowstride) { - gst_structure_set (new_s, "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, - NULL); - } +static inline GstCaps * +get_caps (GstVideoFormat fmt, gboolean strided, GstStructure *s) +{ + gint idx; + GstCaps *ret = + gst_video_format_new_caps_simple (fmt, strided ? -1 : 0, NULL); idx = gst_structure_n_fields (s) - 1; while (idx >= 0) { const gchar *name = gst_structure_nth_field_name (s, idx); - const GValue *val = gst_structure_get_value (s, name); idx--; - /* for format field, check the stride_conversions table to see what - * we can support: + /* filter out certain format specific fields.. copy everything else + * from the original struct */ - if (!strcmp ("format", name)) { - GValue formats = { 0 }; - - g_value_init (&formats, GST_TYPE_LIST); + if (!is_filtered_field (name)) { + const GValue *val = gst_structure_get_value (s, name); + gst_caps_set_value (ret, name, val); + } + } - if (GST_VALUE_HOLDS_FOURCC (val)) { - add_all_fourcc_conversions (&formats, - gst_value_get_fourcc (val), direction); - } else if (GST_VALUE_HOLDS_LIST (val)) { - gint i; - for (i = 0; i < gst_value_list_get_size (val); i++) { - const GValue *list_val = gst_value_list_get_value (val, i); - if (GST_VALUE_HOLDS_FOURCC (list_val)) { - add_all_fourcc_conversions (&formats, - gst_value_get_fourcc (list_val), direction); - } else { - GST_WARNING ("malformed caps!!"); - break; - } - } - } else { - GST_WARNING ("malformed caps!!"); - } + return ret; +} - gst_structure_set_value (new_s, "format", &formats); +/** + * Utility to get all possible caps that can be converted to/from (depending + * on 'direction') the specified 'fmt'. The rest of the fields are populated + * from 's' + */ +static GstCaps * +get_all_caps (GstPadDirection direction, GstVideoFormat fmt, GstStructure *s) +{ + GstCaps *ret = gst_caps_new_empty (); + gint to_format = (direction == GST_PAD_SINK) ? 1 : 0; + gint from_format = (direction == GST_PAD_SRC) ? 1 : 0; + gint i; - continue; + for (i = 0; stride_conversions[i].format[0]; i++) { + const Conversion *c = &stride_conversions[i]; + if (c->format[from_format] == fmt) { + gst_caps_append (ret, get_caps (c->format[to_format], TRUE, s)); + gst_caps_append (ret, get_caps (c->format[to_format], FALSE, s)); } + } + + return ret; +} - /* copy over all other non-rowstride fields: */ - if (strcmp ("rowstride", name)) { - gst_structure_set_value (new_s, name, val); +/** convert GValue holding fourcc to GstVideoFormat (for YUV) */ +static inline GstVideoFormat +fmt_from_val (const GValue *val) +{ + return gst_video_format_from_fourcc (gst_value_get_fourcc (val)); +} + +/** convert structure to GstVideoFormat (for RGB) */ +static inline GstVideoFormat +fmt_from_struct (const GstStructure *s) +{ + /* hmm.. this is not supporting any case where ranges/lists are used + * for any of the rgb related fields in the caps. But I'm not quite + * sure a sane way to handle that.. rgb caps suck + */ + gint depth, bpp, endianness; + gint red_mask, green_mask, blue_mask, alpha_mask; + gboolean have_alpha, ok = TRUE; + + ok &= gst_structure_get_int (s, "depth", &depth); + ok &= gst_structure_get_int (s, "bpp", &bpp); + ok &= gst_structure_get_int (s, "endianness", &endianness); + ok &= gst_structure_get_int (s, "red_mask", &red_mask); + ok &= gst_structure_get_int (s, "green_mask", &green_mask); + ok &= gst_structure_get_int (s, "blue_mask", &blue_mask); + have_alpha = gst_structure_get_int (s, "alpha_mask", &alpha_mask); + + if (!ok) + return GST_VIDEO_FORMAT_UNKNOWN; + + if (depth == 24 && bpp == 32 && endianness == G_BIG_ENDIAN) { + if (red_mask == 0xff000000 && green_mask == 0x00ff0000 && + blue_mask == 0x0000ff00) { + return GST_VIDEO_FORMAT_RGBx; + } + if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 && + blue_mask == 0xff000000) { + return GST_VIDEO_FORMAT_BGRx; + } + if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 && + blue_mask == 0x000000ff) { + return GST_VIDEO_FORMAT_xRGB; + } + if (red_mask == 0x000000ff && green_mask == 0x0000ff00 && + blue_mask == 0x00ff0000) { + return GST_VIDEO_FORMAT_xBGR; + } + } else if (depth == 32 && bpp == 32 && endianness == G_BIG_ENDIAN && + have_alpha) { + if (red_mask == 0xff000000 && green_mask == 0x00ff0000 && + blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) { + return GST_VIDEO_FORMAT_RGBA; + } + if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 && + blue_mask == 0xff000000 && alpha_mask == 0x000000ff) { + return GST_VIDEO_FORMAT_BGRA; + } + if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 && + blue_mask == 0x000000ff && alpha_mask == 0xff000000) { + return GST_VIDEO_FORMAT_ARGB; + } + if (red_mask == 0x000000ff && green_mask == 0x0000ff00 && + blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) { + return GST_VIDEO_FORMAT_ABGR; + } + } else if (depth == 24 && bpp == 24 && endianness == G_BIG_ENDIAN) { + if (red_mask == 0xff0000 && green_mask == 0x00ff00 && + blue_mask == 0x0000ff) { + return GST_VIDEO_FORMAT_RGB; + } + if (red_mask == 0x0000ff && green_mask == 0x00ff00 && + blue_mask == 0xff0000) { + return GST_VIDEO_FORMAT_BGR; + } + } else if ((depth == 15 || depth == 16) && bpp == 16 && + endianness == G_BYTE_ORDER) { + if (red_mask == GST_VIDEO_COMP1_MASK_16_INT + && green_mask == GST_VIDEO_COMP2_MASK_16_INT + && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) { + return GST_VIDEO_FORMAT_RGB16; + } + if (red_mask == GST_VIDEO_COMP3_MASK_16_INT + && green_mask == GST_VIDEO_COMP2_MASK_16_INT + && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) { + return GST_VIDEO_FORMAT_BGR16; + } + if (red_mask == GST_VIDEO_COMP1_MASK_15_INT + && green_mask == GST_VIDEO_COMP2_MASK_15_INT + && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) { + return GST_VIDEO_FORMAT_RGB15; + } + if (red_mask == GST_VIDEO_COMP3_MASK_15_INT + && green_mask == GST_VIDEO_COMP2_MASK_15_INT + && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) { + return GST_VIDEO_FORMAT_BGR15; } } - gst_caps_merge_structure (caps, new_s); + return GST_VIDEO_FORMAT_UNKNOWN; } - /** * we can transform @caps to strided or non-strided caps with otherwise * identical parameters @@ -310,31 +435,50 @@ gst_stride_transform_transform_caps (GstBaseTransform * base, GstPadDirection direction, GstCaps * caps) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); - GstCaps *ret; - GstStructure *s; - - g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL); - - GST_DEBUG_OBJECT (self, "direction=%d, caps=%p", direction, caps); - LOG_CAPS (self, caps); - - ret = gst_caps_new_empty (); - s = gst_caps_get_structure (caps, 0); - - if (gst_structure_has_name (s, "video/x-raw-yuv") || - gst_structure_has_name (s, "video/x-raw-yuv-strided")) { - - add_all_fields (ret, "video/x-raw-yuv", s, FALSE, direction); - add_all_fields (ret, "video/x-raw-yuv-strided", s, TRUE, direction); - - } else if (gst_structure_has_name (s, "video/x-raw-rgb") || - gst_structure_has_name (s, "video/x-raw-rgb-strided")) { - - add_all_fields (ret, "video/x-raw-rgb", s, FALSE, direction); - add_all_fields (ret, "video/x-raw-rgb-strided", s, TRUE, direction); + GstCaps *ret = gst_caps_new_empty (); + int i; + + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *s = gst_caps_get_structure (caps, i); + const char *name = gst_structure_get_name (s); + + /* this is a bit ugly.. ideally it would be easier to parse caps + * a bit more generically without having to care so much about + * difference between RGB and YUV.. but YUV can be specified as + * a list of format params, whereas RGB is a combination of many + * fields.. + */ + if (g_str_has_prefix (name, "video/x-raw-yuv")) { + const GValue *val = gst_structure_get_value (s, "format"); + if (GST_VALUE_HOLDS_FOURCC (val)) { + gst_caps_append (ret, + get_all_caps (direction, fmt_from_val (val), s)); + } else if (GST_VALUE_HOLDS_LIST (val)) { + gint j; + for (j = 0; j < gst_value_list_get_size (val); j++) { + const GValue *list_val = gst_value_list_get_value (val, j); + if (GST_VALUE_HOLDS_FOURCC (list_val)) { + gst_caps_append (ret, + get_all_caps (direction, fmt_from_val (list_val), s)); + } else { + GST_WARNING_OBJECT (self, + "malformed format in caps: %"GST_PTR_FORMAT, s); + break; + } + } + } else { + GST_WARNING_OBJECT (self, "malformed yuv caps: %"GST_PTR_FORMAT, s); + } + } else if (g_str_has_prefix (name, "video/x-raw-rgb")) { + gst_caps_append (ret, get_all_caps (direction, fmt_from_struct (s), s)); + } else { + GST_WARNING_OBJECT (self, "ignoring: %"GST_PTR_FORMAT, s); + } } + gst_caps_do_simplify (ret); + LOG_CAPS (self, ret); return ret; @@ -369,6 +513,7 @@ gst_stride_transform_set_caps (GstBaseTransform * base, (stride_conversions[i].format[1] == out_format)) { GST_DEBUG_OBJECT (self, "found stride_conversion: %d", i); self->conversion = &stride_conversions[i]; + self->needs_refresh = TRUE; break; } } @@ -378,10 +523,6 @@ gst_stride_transform_set_caps (GstBaseTransform * base, i, self->conversion, self->in_rowstride, self->out_rowstride); g_return_val_if_fail (self->conversion, FALSE); - g_return_val_if_fail (self->conversion->unstridify - || !self->in_rowstride, FALSE); - g_return_val_if_fail (self->conversion->stridify - || !self->out_rowstride, FALSE); g_return_val_if_fail (self->width == width, FALSE); g_return_val_if_fail (self->height == height, FALSE); @@ -399,20 +540,14 @@ gst_stride_transform_transform (GstBaseTransform * base, GST_DEBUG_OBJECT (self, "inbuf=%p (size=%d), outbuf=%p (size=%d)", inbuf, GST_BUFFER_SIZE (inbuf), outbuf, GST_BUFFER_SIZE (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 self->conversion->unstridify (self, - GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); - } else if (self->out_rowstride) { - return self->conversion->stridify (self, + if (self->conversion) { + return self->conversion->convert (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); + "this shouldn't happen! in_rowstride=%d, out_rowstride=%d, conversion=%p", + self->in_rowstride, self->out_rowstride, self->conversion); return GST_FLOW_ERROR; } diff --git a/gst/stride/gststridetransform.h b/gst/stride/gststridetransform.h index bce2526..34733cd 100644 --- a/gst/stride/gststridetransform.h +++ b/gst/stride/gststridetransform.h @@ -52,11 +52,18 @@ typedef struct { GstVideoFormat format[2]; /* in_format, out_format */ - GstFlowReturn (*stridify) (GstStrideTransform *self, guchar *strided, guchar *unstrided); - GstFlowReturn (*unstridify) (GstStrideTransform *self, guchar *unstrided, guchar *strided); + GstFlowReturn (*convert) (GstStrideTransform *self, guchar *out, guchar *in); } Conversion; +typedef struct { + gint in_bpl; /* bytes per line in input */ + gint out_bpl; /* bytes per line in output */ + gint in_off; + gint out_off; + gint width; + gint height; +} Cache; /** * GstStrideTransform: @@ -67,9 +74,23 @@ struct _GstStrideTransform { GstVideoFilter videofilter; /*< private >*/ + + /* values set from caps: */ gint width, height; gint in_rowstride; gint out_rowstride; + + /* values set from set from crop event: */ + gint crop_width, crop_height, crop_top, crop_left; + + /* cached values used for each conversion, indexed by plane in case of + * multi-planar formats. These won't have zero values meaning not-used + * (as long as !needs_refresh), but will be set to whatever byte width/ + * offset is appropriate for the format. + */ + Cache cache[3]; + gboolean needs_refresh; + const Conversion *conversion; /* for caching the tranform_size() results.. */ -- 1.7.9.5 From 6d6fd27cf2c81d44d168e47775443ba2812fd342 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Mon, 13 Sep 2010 19:16:02 -0500 Subject: [PATCH] stride: support for 32bit RGB formats --- gst/stride/convert.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/gst/stride/convert.c b/gst/stride/convert.c index 5d392ac..7f976a5 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -372,6 +372,22 @@ convert_rgb16_rgb16 (GstStrideTransform * self, return convert_422i_422i (self, out, in); } +/** convert 32bbp rgb formats */ +static GstFlowReturn +convert_rgb32_rgb32 (GstStrideTransform * self, + guchar * out, guchar * in) +{ + if (G_UNLIKELY (self->needs_refresh)) { + gint sx[] = {1}; + gint sy[] = {1}; + if (refresh_cache (self, 1, 4, sx, sx, sy, sy)) + return GST_FLOW_ERROR; + self->needs_refresh = FALSE; + } + + return convert_n_n (self, out, in, 1); +} + #define CONVERT(tofmt, fromfmt, convert) \ { \ { GST_VIDEO_FORMAT_##tofmt, GST_VIDEO_FORMAT_##fromfmt }, \ @@ -388,6 +404,14 @@ const Conversion stride_conversions[] = { CONVERT (I420, NV12, convert_i420_nv12), CONVERT (I420, YUY2, convert_i420_yuy2), CONVERT (RGB16, RGB16, convert_rgb16_rgb16), + CONVERT (RGBx, RGBx, convert_rgb32_rgb32), + CONVERT (BGRx, BGRx, convert_rgb32_rgb32), + CONVERT (xRGB, xRGB, convert_rgb32_rgb32), + CONVERT (xBGR, xBGR, convert_rgb32_rgb32), + CONVERT (RGBA, RGBA, convert_rgb32_rgb32), + CONVERT (BGRA, BGRA, convert_rgb32_rgb32), + CONVERT (ARGB, ARGB, convert_rgb32_rgb32), + CONVERT (ABGR, ABGR, convert_rgb32_rgb32), /* add new entries before here */ {{GST_VIDEO_FORMAT_UNKNOWN}} }; -- 1.7.9.5 From 9a189cf9eefd0030a276b7a8018496f28bc4b257 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Fri, 24 Dec 2010 20:55:43 -0600 Subject: [PATCH] ffmpegcolorspace: support for rowstride --- gst/ffmpegcolorspace/avcodec.h | 2 +- gst/ffmpegcolorspace/gstffmpegcodecmap.c | 75 ++++++++++++++++++++-------- gst/ffmpegcolorspace/gstffmpegcodecmap.h | 1 + gst/ffmpegcolorspace/gstffmpegcolorspace.c | 30 ++++++++--- gst/ffmpegcolorspace/gstffmpegcolorspace.h | 1 + gst/ffmpegcolorspace/imgconvert.c | 12 ++--- 6 files changed, 86 insertions(+), 35 deletions(-) diff --git a/gst/ffmpegcolorspace/avcodec.h b/gst/ffmpegcolorspace/avcodec.h index 6067aed..f350b3c 100644 --- a/gst/ffmpegcolorspace/avcodec.h +++ b/gst/ffmpegcolorspace/avcodec.h @@ -217,7 +217,7 @@ typedef struct AVPaletteControl { } AVPaletteControl; -int avpicture_get_size(int pix_fmt, int width, int height); +int avpicture_get_size(int pix_fmt, int width, int height, int stride); void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift); const char *avcodec_get_pix_fmt_name(int pix_fmt); diff --git a/gst/ffmpegcolorspace/gstffmpegcodecmap.c b/gst/ffmpegcolorspace/gstffmpegcodecmap.c index 97052cb..a9c3d64 100644 --- a/gst/ffmpegcolorspace/gstffmpegcodecmap.c +++ b/gst/ffmpegcolorspace/gstffmpegcodecmap.c @@ -619,7 +619,8 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps, if (!raw) return; - if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + if (gst_structure_has_name (structure, "video/x-raw-yuv") || + gst_structure_has_name (structure, "video/x-raw-yuv-strided")) { guint32 fourcc; if (gst_structure_get_fourcc (structure, "format", &fourcc)) { @@ -828,10 +829,10 @@ gst_ffmpegcsp_caps_with_codectype (enum CodecType type, int gst_ffmpegcsp_avpicture_fill (AVPicture * picture, uint8_t * ptr, enum PixelFormat pix_fmt, int width, int height, - int interlaced) + int stride, int interlaced) { int size, w2, h2, size2; - int stride, stride2; + int stride2; PixFmtInfo *pinfo; pinfo = get_pix_fmt_info (pix_fmt); @@ -847,11 +848,15 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, case PIX_FMT_YUVJ420P: case PIX_FMT_YUVJ422P: case PIX_FMT_YUVJ444P: - stride = GST_ROUND_UP_4 (width); h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); - size = stride * h2; w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); - stride2 = GST_ROUND_UP_4 (w2); + if (stride) { + stride2 = stride; + } else { + stride = GST_ROUND_UP_4 (width); + stride2 = GST_ROUND_UP_4 (w2); + } + size = stride * h2; h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); size2 = stride2 * h2; picture->data[0] = ptr; @@ -882,11 +887,15 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return 2 * size + 2 * size2; case PIX_FMT_YVU410P: case PIX_FMT_YVU420P: - stride = GST_ROUND_UP_4 (width); h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); - size = stride * h2; w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); - stride2 = GST_ROUND_UP_4 (w2); + if (stride) { + stride2 = stride; + } else { + stride = GST_ROUND_UP_4 (width); + stride2 = GST_ROUND_UP_4 (w2); + } + size = stride * h2; h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); size2 = stride2 * h2; picture->data[0] = ptr; @@ -898,11 +907,15 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return size + 2 * size2; case PIX_FMT_NV12: case PIX_FMT_NV21: - stride = GST_ROUND_UP_4 (width); h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); - size = stride * h2; w2 = 2 * DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); - stride2 = GST_ROUND_UP_4 (w2); + if (stride) { + stride2 = stride; + } else { + stride = GST_ROUND_UP_4 (width); + stride2 = GST_ROUND_UP_4 (w2); + } + size = stride * h2; h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); size2 = stride2 * h2; picture->data[0] = ptr; @@ -914,7 +927,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return size + size2; case PIX_FMT_RGB24: case PIX_FMT_BGR24: - stride = GST_ROUND_UP_4 (width * 3); + if (!stride) { + stride = GST_ROUND_UP_4 (width * 3); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -930,7 +945,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, case PIX_FMT_ABGR32: case PIX_FMT_xRGB32: case PIX_FMT_BGRx32: - stride = width * 4; + if (!stride) { + stride = width * 4; + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -942,7 +959,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, case PIX_FMT_YUV422: case PIX_FMT_UYVY422: case PIX_FMT_YVYU422: - stride = GST_ROUND_UP_4 (width * 2); + if (!stride) { + stride = GST_ROUND_UP_4 (width * 2); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -950,7 +969,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, picture->linesize[0] = stride; return size; case PIX_FMT_V308: - stride = GST_ROUND_UP_4 (width * 3); + if (!stride) { + stride = GST_ROUND_UP_4 (width * 3); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -958,8 +979,10 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, picture->linesize[0] = stride; return size; case PIX_FMT_UYVY411: - stride = - GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + GST_ROUND_UP_4 (width) / 2); + if (!stride) { + stride = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + + GST_ROUND_UP_4 (width) / 2); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -968,7 +991,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return size; case PIX_FMT_Y800: case PIX_FMT_GRAY8: - stride = GST_ROUND_UP_4 (width); + if (!stride) { + stride = GST_ROUND_UP_4 (width); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -978,7 +1003,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, case PIX_FMT_Y16: case PIX_FMT_GRAY16_L: case PIX_FMT_GRAY16_B: - stride = GST_ROUND_UP_4 (width * 2); + if (!stride) { + stride = GST_ROUND_UP_4 (width * 2); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -987,7 +1014,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return size; case PIX_FMT_MONOWHITE: case PIX_FMT_MONOBLACK: - stride = GST_ROUND_UP_4 ((width + 7) >> 3); + if (!stride) { + stride = GST_ROUND_UP_4 ((width + 7) >> 3); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = NULL; @@ -996,7 +1025,9 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return size; case PIX_FMT_PAL8: /* already forced to be with stride, so same result as other function */ - stride = GST_ROUND_UP_4 (width); + if (!stride) { + stride = GST_ROUND_UP_4 (width); + } size = stride * height; picture->data[0] = ptr; picture->data[1] = ptr + size; /* palette is stored here as 256 32 bit words */ diff --git a/gst/ffmpegcolorspace/gstffmpegcodecmap.h b/gst/ffmpegcolorspace/gstffmpegcodecmap.h index 077fe3f..3d08bb0 100644 --- a/gst/ffmpegcolorspace/gstffmpegcodecmap.h +++ b/gst/ffmpegcolorspace/gstffmpegcodecmap.h @@ -52,6 +52,7 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, enum PixelFormat pix_fmt, int width, int height, + int stride, int interlaced); #endif /* __GST_FFMPEG_CODECMAP_H__ */ diff --git a/gst/ffmpegcolorspace/gstffmpegcolorspace.c b/gst/ffmpegcolorspace/gstffmpegcolorspace.c index c8805b3..96e62f8 100644 --- a/gst/ffmpegcolorspace/gstffmpegcolorspace.c +++ b/gst/ffmpegcolorspace/gstffmpegcolorspace.c @@ -48,6 +48,10 @@ GST_DEBUG_CATEGORY (ffmpegcolorspace_performance); "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, A420} ;" \ + "video/x-raw-yuv-strided, width = "GST_VIDEO_SIZE_RANGE" , " \ + "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ + "rowstride="GST_VIDEO_SIZE_RANGE"," \ + "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, A420} ;" \ GST_VIDEO_CAPS_RGB";" \ GST_VIDEO_CAPS_BGR";" \ GST_VIDEO_CAPS_RGBx";" \ @@ -205,8 +209,8 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, { GstFFMpegCsp *space; GstStructure *structure; - gint in_height, in_width; - gint out_height, out_width; + gint in_height, in_width, in_stride = 0; + gint out_height, out_width, out_stride = 0; const GValue *in_framerate = NULL; const GValue *out_framerate = NULL; const GValue *in_par = NULL; @@ -225,6 +229,10 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, if (!res) goto no_width_height; + /* stride is optional: */ + if (gst_structure_has_name (structure, "video/x-raw-yuv-strided")) + gst_structure_get_int (structure, "rowstride", &in_stride); + /* and framerate */ in_framerate = gst_structure_get_value (structure, "framerate"); if (in_framerate == NULL || !GST_VALUE_HOLDS_FRACTION (in_framerate)) @@ -241,6 +249,10 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, if (!res) goto no_width_height; + /* stride is optional: */ + if (gst_structure_has_name (structure, "video/x-raw-yuv-strided")) + gst_structure_get_int (structure, "rowstride", &out_stride); + /* and framerate */ out_framerate = gst_structure_get_value (structure, "framerate"); if (out_framerate == NULL || !GST_VALUE_HOLDS_FRACTION (out_framerate)) @@ -263,6 +275,8 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, space->width = ctx->width = in_width; space->height = ctx->height = in_height; + space->in_stride = in_stride; + space->out_stride = out_stride; space->interlaced = FALSE; gst_structure_get_boolean (structure, "interlaced", &space->interlaced); @@ -401,7 +415,7 @@ gst_ffmpegcsp_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, GstStructure *structure = NULL; AVCodecContext *ctx = NULL; gboolean ret = TRUE; - gint width, height; + gint width, height, stride = 0; g_assert (size); @@ -409,6 +423,10 @@ gst_ffmpegcsp_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); + /* stride is optional: */ + if (gst_structure_has_name (structure, "video/x-raw-yuv-strided")) + gst_structure_get_int (structure, "rowstride", &stride); + ctx = avcodec_alloc_context (); g_assert (ctx != NULL); @@ -422,7 +440,7 @@ gst_ffmpegcsp_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, goto beach; } - *size = avpicture_get_size (ctx->pix_fmt, width, height); + *size = avpicture_get_size (ctx->pix_fmt, width, height, stride); /* ffmpeg frames have the palette after the frame data, whereas * GStreamer currently puts it into the caps as 'palette_data' field, @@ -460,7 +478,7 @@ gst_ffmpegcsp_transform (GstBaseTransform * btrans, GstBuffer * inbuf, /* fill from with source data */ gst_ffmpegcsp_avpicture_fill (&space->from_frame, GST_BUFFER_DATA (inbuf), space->from_pixfmt, space->width, space->height, - space->interlaced); + space->in_stride, space->interlaced); /* fill optional palette */ if (space->palette) @@ -469,7 +487,7 @@ gst_ffmpegcsp_transform (GstBaseTransform * btrans, GstBuffer * inbuf, /* fill target frame */ gst_ffmpegcsp_avpicture_fill (&space->to_frame, GST_BUFFER_DATA (outbuf), space->to_pixfmt, space->width, space->height, - space->interlaced); + space->out_stride, space->interlaced); /* and convert */ result = img_convert (&space->to_frame, space->to_pixfmt, diff --git a/gst/ffmpegcolorspace/gstffmpegcolorspace.h b/gst/ffmpegcolorspace/gstffmpegcolorspace.h index 198ab8a..bd5e01c 100644 --- a/gst/ffmpegcolorspace/gstffmpegcolorspace.h +++ b/gst/ffmpegcolorspace/gstffmpegcolorspace.h @@ -46,6 +46,7 @@ struct _GstFFMpegCsp { GstVideoFilter element; gint width, height; + gint in_stride, out_stride; gboolean interlaced; gfloat fps; enum PixelFormat from_pixfmt, to_pixfmt; diff --git a/gst/ffmpegcolorspace/imgconvert.c b/gst/ffmpegcolorspace/imgconvert.c index c670e25..084dbef 100644 --- a/gst/ffmpegcolorspace/imgconvert.c +++ b/gst/ffmpegcolorspace/imgconvert.c @@ -594,12 +594,12 @@ avpicture_layout (const AVPicture * src, int pix_fmt, int width, int height, #endif int -avpicture_get_size (int pix_fmt, int width, int height) +avpicture_get_size (int pix_fmt, int width, int height, int stride) { AVPicture dummy_pict; return gst_ffmpegcsp_avpicture_fill (&dummy_pict, NULL, pix_fmt, width, - height, FALSE); + height, stride, FALSE); } /** @@ -3518,16 +3518,16 @@ get_convert_table_entry (int src_pix_fmt, int dst_pix_fmt) static int avpicture_alloc (AVPicture * picture, int pix_fmt, int width, int height, - int interlaced) + int stride, int interlaced) { unsigned int size; void *ptr; - size = avpicture_get_size (pix_fmt, width, height); + size = avpicture_get_size (pix_fmt, width, height, stride); ptr = av_malloc (size); if (!ptr) goto fail; - gst_ffmpegcsp_avpicture_fill (picture, ptr, pix_fmt, width, height, + gst_ffmpegcsp_avpicture_fill (picture, ptr, pix_fmt, width, height, stride, interlaced); return 0; fail: @@ -3775,7 +3775,7 @@ no_chroma_filter: else int_pix_fmt = PIX_FMT_RGB24; } - if (avpicture_alloc (tmp, int_pix_fmt, dst_width, dst_height, + if (avpicture_alloc (tmp, int_pix_fmt, dst_width, dst_height, 0, dst->interlaced) < 0) return -1; ret = -1; -- 1.7.9.5 From f2f8b9b6add9a8e7ee20bc51ed4f777907528be5 Mon Sep 17 00:00:00 2001 From: Alessandro Decina <alessandro.decina@collabora.co.uk> Date: Thu, 30 Jun 2011 12:46:55 +0200 Subject: [PATCH] pbutils: fix compilation error in macro expansion Fix: "encoding-target.c: In function 'get_locale': encoding-target.c:421: error: used struct type value where scalar is required" Rename a local variable from 'loc' to 'locale' since GST_LOG declares a variable called loc internally. --- gst-libs/gst/pbutils/encoding-target.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gst-libs/gst/pbutils/encoding-target.c b/gst-libs/gst/pbutils/encoding-target.c index f3002b7..c5ea300 100644 --- a/gst-libs/gst/pbutils/encoding-target.c +++ b/gst-libs/gst/pbutils/encoding-target.c @@ -412,16 +412,16 @@ serialize_stream_profiles (GKeyFile * out, GstEncodingProfile * sprof, static gchar * get_locale (void) { - const char *loc = NULL; + const char *locale = NULL; gchar *ret; #ifdef ENABLE_NLS #if defined(LC_MESSAGES) - loc = setlocale (LC_MESSAGES, NULL); - GST_LOG ("LC_MESSAGES: %s", GST_STR_NULL (loc)); + locale = setlocale (LC_MESSAGES, NULL); + GST_LOG ("LC_MESSAGES: %s", GST_STR_NULL (locale)); #elif defined(LC_ALL) - loc = setlocale (LC_ALL, NULL); - GST_LOG ("LC_ALL: %s", GST_STR_NULL (loc)); + locale = setlocale (LC_ALL, NULL); + GST_LOG ("LC_ALL: %s", GST_STR_NULL (locale)); #else GST_LOG ("Neither LC_ALL nor LC_MESSAGES defined"); #endif @@ -429,11 +429,11 @@ get_locale (void) GST_LOG ("i18n disabled"); #endif - if (loc == NULL || g_ascii_strncasecmp (loc, "en", 2) == 0) + if (locale == NULL || g_ascii_strncasecmp (locale, "en", 2) == 0) return NULL; /* en_GB.UTF-8 => en */ - ret = g_ascii_strdown (loc, -1); + ret = g_ascii_strdown (locale, -1); ret = g_strcanon (ret, "abcdefghijklmnopqrstuvwxyz", '\0'); GST_LOG ("using locale: %s", ret); return ret; -- 1.7.9.5 From cc1dab49bde15ef6cf6038f58dfd00f5b079b127 Mon Sep 17 00:00:00 2001 From: Alessandro Decina <alessandro.decina@collabora.co.uk> Date: Wed, 6 Jul 2011 19:02:21 +0200 Subject: [PATCH] encodebin: set GST_ENC_FLAG_NO_VIDEO_CONVERTION on omap --- gst/encoding/gstencodebin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/encoding/gstencodebin.c b/gst/encoding/gstencodebin.c index 17610cb..20e4715 100644 --- a/gst/encoding/gstencodebin.c +++ b/gst/encoding/gstencodebin.c @@ -227,7 +227,7 @@ struct _StreamGroup #define DEFAULT_QUEUE_TIME_MAX GST_SECOND #define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND #define DEFAULT_AVOID_REENCODING FALSE -#define DEFAULT_FLAGS 0 +#define DEFAULT_FLAGS GST_ENC_FLAG_NO_VIDEO_CONVERSION #define DEFAULT_RAW_CAPS \ "video/x-raw-yuv; " \ -- 1.7.9.5 From 243950d443ad88df88580e03cc9151a16c422565 Mon Sep 17 00:00:00 2001 From: Alessandro Decina <alessandro.decina@collabora.co.uk> Date: Thu, 7 Jul 2011 16:11:48 +0200 Subject: [PATCH] encodebin: whitelist h264parse only when plugging parsers... ...and fix parsers post 24.14 --- gst/encoding/gstencodebin.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/encoding/gstencodebin.c b/gst/encoding/gstencodebin.c index 20e4715..7074df2 100644 --- a/gst/encoding/gstencodebin.c +++ b/gst/encoding/gstencodebin.c @@ -786,6 +786,7 @@ _get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof) format = gst_encoding_profile_get_format (sprof); + GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format); /* FIXME : requesting twice the parsers twice is a bit ugly, we should @@ -809,7 +810,8 @@ _get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof) break; } - if (parserfact) + if (parserfact + && !strcmp (((GstPluginFeature *) parserfact)->name, "h264parse")) parser = gst_element_factory_create (parserfact, NULL); gst_plugin_feature_list_free (parsers); -- 1.7.9.5 From 4bb4d524f494fb9e2f05d5e202ab86795eb6fcf0 Mon Sep 17 00:00:00 2001 From: Alessandro Decina <alessandro.decina@collabora.co.uk> Date: Thu, 18 Aug 2011 11:28:19 +0200 Subject: [PATCH] stridetransform: maintain caps order transform yuv to yuv;yuv-strided and yuv-strided to yuv-strided;yuv. Fixes some dynamic pipelines negotiating non-strided yuv for no good reason. --- gst/stride/gststridetransform.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 7874ed4..b272500 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -479,6 +479,32 @@ gst_stride_transform_transform_caps (GstBaseTransform * base, gst_caps_do_simplify (ret); + /* do_simplify sorts caps in a way that yuv always comes before yuv-strided. + * If we're converting from yuv-strided we want to favor yuv-strided though, + * so we reverse the result. + */ + if (!gst_caps_is_empty (caps)) { + GstCaps *tmp; + GstStructure *s; + const char *name; + + s = gst_caps_get_structure (caps, 0); + name = gst_structure_get_name (s); + + if (!strcmp (name, "video/x-raw-yuv-strided") || + !strcmp (name, "video/x-raw-rgb-strided")) { + tmp = gst_caps_new_empty (); + + for (int i = gst_caps_get_size (ret) - 1; i >= 0; i--) { + gst_caps_append_structure (tmp, + gst_structure_copy (gst_caps_get_structure (ret, i))); + } + + gst_caps_unref (ret); + ret = tmp; + } + } + LOG_CAPS (self, ret); return ret; -- 1.7.9.5 From 454bfe6913cf05af1f178ce8e8f771947c955295 Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Thu, 24 Nov 2011 16:08:40 -0600 Subject: [PATCH] appsink: add crop signal.. --- gst-libs/gst/app/gstappsink.c | 37 +++++++++++++++++++++++++++++++++++++ gst-libs/gst/app/gstappsink.h | 3 ++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/app/gstappsink.c b/gst-libs/gst/app/gstappsink.c index 9a891b6..6a4ef57 100644 --- a/gst-libs/gst/app/gstappsink.c +++ b/gst-libs/gst/app/gstappsink.c @@ -111,6 +111,7 @@ enum SIGNAL_NEW_PREROLL, SIGNAL_NEW_BUFFER, SIGNAL_NEW_BUFFER_LIST, + SIGNAL_CROP, /* actions */ SIGNAL_PULL_PREROLL, @@ -345,6 +346,35 @@ gst_app_sink_class_init (GstAppSinkClass * klass) g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstAppSink::crop: + * @appsink: the appsink element that emited the signal + * @top: coordinate of top row of pixels + * @left: coordinate of left column of pixels + * @width: width of visible picture (starting from %left) + * @height: height of visible picture (starting from %top) + * + * Signal new picture cropping (applicable for YUV/RGB buffers). Note + * that for gst 0.11, this information should come from the buffer as + * meta-data, to make it easier to synchronize cropping coordinates + * with buffers. For now, you can probably ignore that because for + * decoders cropping won't be changing on a per-frame basis. In case + * you do need to care about synchronizing with buffers, you probably + * need to count the new-buffer signals and keep a queue of cropping + * coordinates to match up with buffers when you pop them. Or just + * wait for 0.11. + * + * This signal is emited from the steaming thread and only when the + * "emit-signals" property is %TRUE. + * + * Note that this signal is only emited when the "emit-signals" property is + * set to %TRUE, which it is not by default for performance reasons. + */ + gst_app_sink_signals[SIGNAL_CROP] = + g_signal_new ("crop", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, crop), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 4, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); /** * GstAppSink::pull-preroll: @@ -692,6 +722,13 @@ gst_app_sink_event (GstBaseSink * sink, GstEvent * event) gst_app_sink_flush_unlocked (appsink); g_mutex_unlock (priv->mutex); break; + case GST_EVENT_CROP:{ + gint top, left, width, height; + gst_event_parse_crop (event, &top, &left, &width, &height); + g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_CROP], 0, top, left, + width, height); + break; + } default: break; } diff --git a/gst-libs/gst/app/gstappsink.h b/gst-libs/gst/app/gstappsink.h index 3e0bc41..660be7d 100644 --- a/gst-libs/gst/app/gstappsink.h +++ b/gst-libs/gst/app/gstappsink.h @@ -105,9 +105,10 @@ struct _GstAppSinkClass /* ABI added */ GstBufferList * (*new_buffer_list) (GstAppSink *sink); GstBufferList * (*pull_buffer_list) (GstAppSink *sink); + GstBufferList * (*crop) (GstAppSink *sink, gint top, gint left, gint width, gint height); /*< private >*/ - gpointer _gst_reserved[GST_PADDING - 2]; + gpointer _gst_reserved[GST_PADDING - 3]; }; GType gst_app_sink_get_type(void); -- 1.7.9.5 From f4118a8245a885924944c86a4126bac7e68df2cf Mon Sep 17 00:00:00 2001 From: Luciana Fujii Pontello <luciana@fujii.eti.br> Date: Fri, 23 Dec 2011 02:43:52 -0200 Subject: [PATCH] configure.ac: Check for glib 2.30 gst-plugins-base requires glib >= 2.30 because of g_cclosure_marshal_generic that was introduced in 2.30. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0cbb91c..aa854ce 100644 --- a/configure.ac +++ b/configure.ac @@ -263,7 +263,7 @@ AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)]) dnl *** checks for dependency libraries *** dnl GLib is required -AG_GST_GLIB_CHECK([2.24]) +AG_GST_GLIB_CHECK([2.30]) ORC_CHECK([0.4.11]) -- 1.7.9.5 From 24eb2b95845eaa14113abfb0518ff48d5c4bfce0 Mon Sep 17 00:00:00 2001 From: Alessandro Decina <alessandro.decina@collabora.co.uk> Date: Wed, 11 Jan 2012 16:27:09 +0100 Subject: [PATCH] decodebin2: raise the default queue size from 2MB to 5MB --- gst/playback/gstdecodebin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c index 8bcadde..762a417 100644 --- a/gst/playback/gstdecodebin2.c +++ b/gst/playback/gstdecodebin2.c @@ -234,7 +234,7 @@ enum /* whan playing, keep a max of 2MB of data but try to keep the number of buffers * as low as possible (try to aim for 5 buffers) */ -#define AUTO_PLAY_SIZE_BYTES 2 * 1024 * 1024 +#define AUTO_PLAY_SIZE_BYTES 5 * 1024 * 1024 #define AUTO_PLAY_SIZE_BUFFERS 5 #define AUTO_PLAY_SIZE_TIME 0 -- 1.7.9.5 From 0399993e327b8205a5ca33bf444179f3f38d32cc Mon Sep 17 00:00:00 2001 From: Luciana Fujii Pontello <luciana@fujii.eti.br> Date: Tue, 13 Mar 2012 00:59:59 -0300 Subject: [PATCH] decodebin2: Increase the default queue even more Increase even more the multiqueue size to avoid seeking and audio problems when the queue gets full. --- gst/playback/gstdecodebin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c index 762a417..12c8861 100644 --- a/gst/playback/gstdecodebin2.c +++ b/gst/playback/gstdecodebin2.c @@ -234,7 +234,7 @@ enum /* whan playing, keep a max of 2MB of data but try to keep the number of buffers * as low as possible (try to aim for 5 buffers) */ -#define AUTO_PLAY_SIZE_BYTES 5 * 1024 * 1024 +#define AUTO_PLAY_SIZE_BYTES 8 * 1024 * 1024 #define AUTO_PLAY_SIZE_BUFFERS 5 #define AUTO_PLAY_SIZE_TIME 0 -- 1.7.9.5 From c54f7c8651fbc7b560dd0cca6997d5ae677e4958 Mon Sep 17 00:00:00 2001 From: Alessandro Decina <alessandro.decina@collabora.com> Date: Thu, 22 Mar 2012 13:00:09 +0100 Subject: [PATCH] stridetransform: reset crop sizes on caps changes --- gst/stride/gststridetransform.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index b272500..d0fad88 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -533,6 +533,10 @@ gst_stride_transform_set_caps (GstBaseTransform * base, &out_format, &width, &height, &self->out_rowstride), FALSE); self->conversion = NULL; + self->crop_width = 0; + self->crop_height = 0; + self->crop_left = 0; + self->crop_top = 0; for (i = 0; stride_conversions[i].format[0] != GST_VIDEO_FORMAT_UNKNOWN; i++) { if ((stride_conversions[i].format[0] == in_format) && -- 1.7.9.5 From 6e521c70f8f193ff5f691b87dab81b39891611c3 Mon Sep 17 00:00:00 2001 From: Luciana Fujii Pontello <luciana.fujii@collabora.co.uk> Date: Wed, 28 Mar 2012 12:36:19 -0400 Subject: [PATCH] ximagesink: Handle crop event --- sys/ximage/ximagesink.c | 112 +++++++++++++++++++++++++++++++++++++++++++---- sys/ximage/ximagesink.h | 3 ++ 2 files changed, 107 insertions(+), 8 deletions(-) diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c index 2adcc73..a9363ee 100644 --- a/sys/ximage/ximagesink.c +++ b/sys/ximage/ximagesink.c @@ -106,6 +106,7 @@ /* Our interfaces */ #include <gst/interfaces/navigation.h> #include <gst/interfaces/xoverlay.h> +#include <gst/video/video.h> /* Object header */ #include "ximagesink.h" @@ -683,6 +684,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage) { GstVideoRectangle src, dst, result; gboolean draw_border = FALSE; + GstVideoRectangle *crop = &ximagesink->crop; g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE); @@ -723,10 +725,17 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage) } } - src.w = ximage->width; - src.h = ximage->height; - dst.w = ximagesink->xwindow->width; - dst.h = ximagesink->xwindow->height; + if (crop->x || crop->y || crop->w || crop->h) { + src.w = crop->w; + src.h = crop->h; + dst.w = ximagesink->xwindow->width; + dst.h = ximagesink->xwindow->height; + } else { + src.w = ximage->width; + src.h = ximage->height; + dst.w = ximagesink->xwindow->width; + dst.h = ximagesink->xwindow->height; + } gst_video_sink_center_rect (src, dst, &result, FALSE); @@ -744,8 +753,8 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage) ximage, 0, 0, result.x, result.y, result.w, result.h, ximagesink->xwindow->width, ximagesink->xwindow->height); XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win, - ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y, - result.w, result.h, FALSE); + ximagesink->xwindow->gc, ximage->ximage, crop->x, crop->y, + result.x, result.y, result.w, result.h, FALSE); } else #endif /* HAVE_XSHM */ { @@ -754,8 +763,8 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage) ximage, 0, 0, result.x, result.y, result.w, result.h, ximagesink->xwindow->width, ximagesink->xwindow->height); XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win, - ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y, - result.w, result.h); + ximagesink->xwindow->gc, ximage->ximage, crop->x, crop->y, + result.x, result.y, result.w, result.h); } XSync (ximagesink->xcontext->disp, FALSE); @@ -1258,6 +1267,51 @@ gst_ximagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext) gst_value_get_fraction_denominator (xcontext->par)); } +static gboolean +gst_ximagesink_configure_overlay (GstXImageSink * ximagesink, gint width, + gint height, gint video_par_n, gint video_par_d) +{ + guint calculated_par_n; + guint calculated_par_d; + + if (!gst_video_calculate_display_ratio (&calculated_par_n, &calculated_par_d, + width, height, video_par_n, video_par_d, 1, 1)) { + GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL), + ("Error calculating the output display ratio of the video.")); + return FALSE; + } + GST_DEBUG_OBJECT (ximagesink, + "video width/height: %dx%d, calculated display ratio: %d/%d", + width, height, calculated_par_n, calculated_par_d); + + /* now find a width x height that respects this display ratio. + * prefer those that have one of w/h the same as the incoming video + * using wd / hd = calculated_pad_n / calculated_par_d */ + + /* start with same height, because of interlaced video */ + /* check hd / calculated_par_d is an integer scale factor, and scale wd with the PAR */ + if (height % calculated_par_d == 0) { + GST_DEBUG_OBJECT (ximagesink, "keeping video height"); + GST_VIDEO_SINK_WIDTH (ximagesink) = (guint) + gst_util_uint64_scale_int (height, calculated_par_n, calculated_par_d); + GST_VIDEO_SINK_HEIGHT (ximagesink) = height; + } else if (width % calculated_par_n == 0) { + GST_DEBUG_OBJECT (ximagesink, "keeping video width"); + GST_VIDEO_SINK_WIDTH (ximagesink) = width; + GST_VIDEO_SINK_HEIGHT (ximagesink) = (guint) + gst_util_uint64_scale_int (width, calculated_par_d, calculated_par_n); + } else { + GST_DEBUG_OBJECT (ximagesink, "approximating while keeping video height"); + GST_VIDEO_SINK_WIDTH (ximagesink) = (guint) + gst_util_uint64_scale_int (height, calculated_par_n, calculated_par_d); + GST_VIDEO_SINK_HEIGHT (ximagesink) = height; + } + GST_DEBUG_OBJECT (ximagesink, "scaling to %dx%d", + GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink)); + + return TRUE; +} + /* This function gets the X Display and global info about it. Everything is stored in our object and will be cleaned when the object is disposed. Note here that caps for supported format are generated without any window or @@ -1758,6 +1812,38 @@ gst_ximagesink_event (GstBaseSink * sink, GstEvent * event) } break; } + case GST_EVENT_CROP:{ + gint left, top, width, height; + GstStructure *structure; + GstMessage *message; + GstVideoRectangle *c = &ximagesink->crop; + + gst_event_parse_crop (event, &top, &left, &width, &height); + + c->y = top; + c->x = left; + + if (width == -1) + width = GST_VIDEO_SINK_WIDTH (ximagesink); + if (height == -1) + height = GST_VIDEO_SINK_HEIGHT (ximagesink); + + c->w = width; + c->h = height; + + structure = gst_structure_new ("video-size-crop", "width", G_TYPE_INT, + width, "height", G_TYPE_INT, height, NULL); + message = + gst_message_new_application (GST_OBJECT (ximagesink), structure); + gst_bus_post (gst_element_get_bus (GST_ELEMENT (ximagesink)), message); + + if (!gst_ximagesink_configure_overlay (ximagesink, width, height, + gst_value_get_fraction_numerator (ximagesink->par), + gst_value_get_fraction_denominator (ximagesink->par))) + return FALSE; + + break; + } default: break; } @@ -2299,6 +2385,11 @@ gst_ximagesink_reset (GstXImageSink * ximagesink) gst_ximagesink_bufferpool_clear (ximagesink); + ximagesink->crop.x = 0; + ximagesink->crop.y = 0; + ximagesink->crop.w = 0; + ximagesink->crop.h = 0; + g_mutex_lock (ximagesink->flow_lock); if (ximagesink->xwindow) { gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow); @@ -2372,6 +2463,11 @@ gst_ximagesink_init (GstXImageSink * ximagesink) ximagesink->keep_aspect = FALSE; ximagesink->handle_events = TRUE; ximagesink->handle_expose = TRUE; + + ximagesink->crop.x = 0; + ximagesink->crop.y = 0; + ximagesink->crop.w = 0; + ximagesink->crop.h = 0; } static void diff --git a/sys/ximage/ximagesink.h b/sys/ximage/ximagesink.h index 83e973f..948cfa6 100644 --- a/sys/ximage/ximagesink.h +++ b/sys/ximage/ximagesink.h @@ -221,6 +221,9 @@ struct _GstXImageSink /* stream metadata */ gchar *media_title; + + /* Crop */ + GstVideoRectangle crop; }; struct _GstXImageSinkClass -- 1.7.9.5 From 8de95c9d2dcb8068dd4db1146412fe9d14dd59fc Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Tue, 12 Jun 2012 20:08:02 -0500 Subject: [PATCH] New dmabuf helper library Add gst-libs/gst/dmabuf which contains helpers to attach and retrieve dmabuf handles to/from buffers. --- configure.ac | 3 + gst-libs/gst/Makefile.am | 1 + gst-libs/gst/dmabuf/Makefile.am | 21 +++ gst-libs/gst/dmabuf/dmabuf.c | 163 ++++++++++++++++++++ gst-libs/gst/dmabuf/dmabuf.h | 101 ++++++++++++ pkgconfig/Makefile.am | 3 + pkgconfig/gstreamer-dmabuf-uninstalled.pc.in | 16 ++ pkgconfig/gstreamer-dmabuf.pc.in | 16 ++ pkgconfig/gstreamer-plugins-base-uninstalled.pc.in | 4 +- pkgconfig/gstreamer-plugins-base.pc.in | 2 +- 10 files changed, 327 insertions(+), 3 deletions(-) create mode 100644 gst-libs/gst/dmabuf/Makefile.am create mode 100644 gst-libs/gst/dmabuf/dmabuf.c create mode 100644 gst-libs/gst/dmabuf/dmabuf.h create mode 100644 pkgconfig/gstreamer-dmabuf-uninstalled.pc.in create mode 100644 pkgconfig/gstreamer-dmabuf.pc.in diff --git a/configure.ac b/configure.ac index aa854ce..068ccd8 100644 --- a/configure.ac +++ b/configure.ac @@ -980,6 +980,7 @@ gst-libs/gst/tag/Makefile gst-libs/gst/pbutils/Makefile gst-libs/gst/pbutils/gstpluginsbaseversion.h gst-libs/gst/video/Makefile +gst-libs/gst/dmabuf/Makefile tools/Makefile pkgconfig/Makefile pkgconfig/gstreamer-audio.pc @@ -988,6 +989,8 @@ pkgconfig/gstreamer-app.pc pkgconfig/gstreamer-app-uninstalled.pc pkgconfig/gstreamer-cdda.pc pkgconfig/gstreamer-cdda-uninstalled.pc +pkgconfig/gstreamer-dmabuf.pc +pkgconfig/gstreamer-dmabuf-uninstalled.pc pkgconfig/gstreamer-fft.pc pkgconfig/gstreamer-fft-uninstalled.pc pkgconfig/gstreamer-floatcast.pc diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index 0984251..b4de632 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -13,6 +13,7 @@ SUBDIRS = \ sdp \ rtsp \ video \ + dmabuf \ pbutils \ audio \ riff \ diff --git a/gst-libs/gst/dmabuf/Makefile.am b/gst-libs/gst/dmabuf/Makefile.am new file mode 100644 index 0000000..8993ca4 --- /dev/null +++ b/gst-libs/gst/dmabuf/Makefile.am @@ -0,0 +1,21 @@ +lib_LTLIBRARIES = libgstdmabuf-@GST_MAJORMINOR@.la + +libgstdmabuf_@GST_MAJORMINOR@_la_SOURCES = \ + dmabuf.c +libgstdmabuf_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/dmabuf +libgstdmabuf_@GST_MAJORMINOR@include_HEADERS = \ + dmabuf.h + +libgstdmabuf_@GST_MAJORMINOR@_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS)\ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) + +libgstdmabuf_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) \ + $(GST_LIBS) + +libgstdmabuf_@GST_MAJORMINOR@_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) \ + $(GST_ALL_LDFLAGS) \ + $(GST_LT_LDFLAGS) + diff --git a/gst-libs/gst/dmabuf/dmabuf.c b/gst-libs/gst/dmabuf/dmabuf.c new file mode 100644 index 0000000..57a3b99 --- /dev/null +++ b/gst-libs/gst/dmabuf/dmabuf.c @@ -0,0 +1,163 @@ +/* GStreamer dmabuf + * + * Copyright (c) 2012, Texas Instruments Incorporated + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstdmabuf + * @short_description: GStreamer dmabuf support + * + * Since: 0.10.? + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> + +#include "dmabuf.h" + +struct _GstDmaBuf +{ + GstMiniObject parent; + + int fd; +}; + +struct _GstDmaBufClass +{ + GstMiniObjectClass parent_class; +}; + +#define GST_DMA_BUF_QUARK gst_dma_buf_quark_get_type() +static GST_BOILERPLATE_QUARK (GstDmaBuf, gst_dma_buf_quark); + +#define DMA_BUF_QUARK dma_buf_quark_get_type() +static GST_BOILERPLATE_QUARK (DmaBuf, dma_buf_quark); + +/** + * gst_buffer_set_dma_buf: + * @buf: a #GstBuffer + * @dmabuf: (allow-none): a #GstDmaBuf, or NULL to clear a + * previously-set dmabuf + * + * Sets an dmabuf handle on a buffer. The buffer will obtain its own + * reference to the dmabuf handle, meaning this function does not take + * ownership of @dmabuf. + * + * Since: 0.10.? + */ +void +gst_buffer_set_dma_buf (GstBuffer * buf, GstDmaBuf * dmabuf) +{ + gst_buffer_set_qdata (buf, GST_DMA_BUF_QUARK, + gst_structure_id_new (GST_DMA_BUF_QUARK, + DMA_BUF_QUARK, GST_TYPE_DMA_BUF, dmabuf, NULL)); +} + +/** + * gst_buffer_get_dma_buf: + * @buf: a #GstBuffer + * + * Get the dmabuf handle that has previously been attached to a buffer + * with gst_buffer_set_dma_buf(), usually by another element + * upstream. + * + * Returns: (transfer none): the #GstDmaBuf attached to + * this buffer, or NULL. Does not return a reference to the dmabuf handle, + * caller must obtain her own ref via gst_dma_buf_ref() + * if needed. + * + * Since: 0.10.? + */ +GstDmaBuf * +gst_buffer_get_dma_buf (GstBuffer * buf) +{ + const GstStructure *s; + const GValue *val; + + s = gst_buffer_get_qdata (buf, GST_DMA_BUF_QUARK); + if (s == NULL) + return NULL; + + val = gst_structure_id_get_value (s, DMA_BUF_QUARK); + if (val == NULL) + return NULL; + + return GST_DMA_BUF (gst_value_get_mini_object (val)); +} + +static void +gst_dma_buf_finalize (GstMiniObject * mini_obj) +{ + GstDmaBuf *dmabuf = (GstDmaBuf *) mini_obj; + close (dmabuf->fd); + + /* not chaining up to GstMiniObject's finalize for now, we know it's empty */ +} + +static void +gst_dma_buf_class_init (GstDmaBufClass * klass) +{ + GST_MINI_OBJECT_CLASS (klass)->finalize = gst_dma_buf_finalize; +} + +GST_BOILERPLATE_MINI_OBJECT (GstDmaBuf, gst_dma_buf); + +/** + * gst_dma_buf_new: + * @fd: (transfer full) the dmabuf fd + * + * Creates a new dmabuf handle object, which takes ownership of the + * specified dmabuf file descriptor. When the dmabuf handle object + * is finalized, the dmabuf fd is closed. + * + * Returns: (transfer full): a new #GstDmaBuf. Unref with + * gst_dma_buf_unref() when no longer needed. + * + * Since: 0.10.? + */ +GstDmaBuf * +gst_dma_buf_new (int fd) +{ + GstDmaBuf *dmabuf; + + dmabuf = (GstDmaBuf *) gst_mini_object_new (GST_TYPE_DMA_BUF); + + dmabuf->fd = fd; + + return dmabuf; +} + +/** + * gst_dma_buf_get_fd: + * + * Returns: a the dmabuf file descriptor object; if the caller wants + * to hold on to the handle after the reference on the corresponding + * gst buffer is lost, she should probably dup() the fd. (Although + * it is probably better to hang on to the ref to the GstBuffer and + * let that hold the ref to the dmabuf fd). + * + * Since: 0.10.? + */ +int +gst_dma_buf_get_fd (GstDmaBuf * dmabuf) +{ + return dmabuf->fd; +} diff --git a/gst-libs/gst/dmabuf/dmabuf.h b/gst-libs/gst/dmabuf/dmabuf.h new file mode 100644 index 0000000..e78463f --- /dev/null +++ b/gst-libs/gst/dmabuf/dmabuf.h @@ -0,0 +1,101 @@ +/* GStreamer dmabuf + * + * Copyright (c) 2012, Texas Instruments Incorporated + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_DMA_BUF_H__ +#define __GST_DMA_BUF_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS + +/** + * GstDmaBuf: + * + * A handle to a dma-buf suitable for sharing across devices. + * + * Since: 0.10.? + */ +#define GST_TYPE_DMA_BUF \ + (gst_dma_buf_get_type ()) +#define GST_DMA_BUF(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DMA_BUF, GstDmaBuf)) +#define GST_IS_DMA_BUF(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DMA_BUF)) + +typedef struct _GstDmaBuf GstDmaBuf; +typedef struct _GstDmaBufClass GstDmaBufClass; + +/** + * gst_dma_buf_ref: + * @dmabuf: a a #GstDmaBuf. + * + * Increases the refcount by one. + * + * Returns: (transfer full): @dmabuf + * + * Since: 0.10.? + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstDmaBuf * +gst_dma_buf_ref (GstDmaBuf * dmabuf); +#endif + +static inline GstDmaBuf * +gst_dma_buf_ref (GstDmaBuf * dmabuf) +{ + return (GstDmaBuf *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (dmabuf)); +} + +/** + * gst_dma_buf_unref: + * @dmabuf: (transfer full): a #GstDmaBuf. + * + * Decreases the refcount. If the refcount reaches 0, the dmabuf will be + * freed and closed. + * + * Since: 0.10.? + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC void +gst_dma_buf_unref (GstDmaBuf * dmabuf); +#endif + +static inline void +gst_dma_buf_unref (GstDmaBuf * dmabuf) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (dmabuf)); +} + +GType gst_dma_buf_get_type (void); + +GstDmaBuf * gst_dma_buf_new (int fd); + +int gst_dma_buf_get_fd (GstDmaBuf * buf); + +/* attach/retrieve dmabuf from buffers */ + +void gst_buffer_set_dma_buf (GstBuffer * buf, + GstDmaBuf * dmabuf); + +GstDmaBuf * gst_buffer_get_dma_buf (GstBuffer * buf); + +G_END_DECLS + +#endif /* __GST_DMA_BUF_H__ */ diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index 8fb2529..50506fe 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am @@ -3,6 +3,7 @@ pcverfiles = \ gstreamer-audio-@GST_MAJORMINOR@.pc \ gstreamer-app-@GST_MAJORMINOR@.pc \ gstreamer-cdda-@GST_MAJORMINOR@.pc \ + gstreamer-dmabuf-@GST_MAJORMINOR@.pc \ gstreamer-fft-@GST_MAJORMINOR@.pc \ gstreamer-floatcast-@GST_MAJORMINOR@.pc \ gstreamer-interfaces-@GST_MAJORMINOR@.pc \ @@ -19,6 +20,7 @@ pcverfiles_uninstalled = \ gstreamer-audio-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-app-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-cdda-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-dmabuf-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-fft-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-floatcast-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-interfaces-@GST_MAJORMINOR@-uninstalled.pc \ @@ -52,6 +54,7 @@ pcinfiles = \ gstreamer-audio.pc.in gstreamer-audio-uninstalled.pc.in \ gstreamer-app.pc.in gstreamer-app-uninstalled.pc.in \ gstreamer-cdda.pc.in gstreamer-cdda-uninstalled.pc.in \ + gstreamer-dmabuf.pc.in gstreamer-dmabuf-uninstalled.pc.in \ gstreamer-fft.pc.in gstreamer-fft-uninstalled.pc.in \ gstreamer-floatcast.pc.in gstreamer-floatcast-uninstalled.pc.in \ gstreamer-interfaces.pc.in gstreamer-interfaces-uninstalled.pc.in \ diff --git a/pkgconfig/gstreamer-dmabuf-uninstalled.pc.in b/pkgconfig/gstreamer-dmabuf-uninstalled.pc.in new file mode 100644 index 0000000..4d7f167 --- /dev/null +++ b/pkgconfig/gstreamer-dmabuf-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/video +typelibdir=@abs_top_builddir@/gst-libs/gst/video + +Name: GStreamer DMA-BUF Library, Uninstalled +Description: Video base classes and helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/dmabuf/libgstdmabuf-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/pkgconfig/gstreamer-dmabuf.pc.in b/pkgconfig/gstreamer-dmabuf.pc.in new file mode 100644 index 0000000..4849538 --- /dev/null +++ b/pkgconfig/gstreamer-dmabuf.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer DMA-BUF Library +Description: Video base classes and helper functions +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstdmabuf-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in b/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in index 8a9bea2..b9efabe 100644 --- a/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in +++ b/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in @@ -10,7 +10,7 @@ Name: GStreamer Base Plugins Libraries, Uninstalled Description: Streaming media framework, base plugins libraries, uninstalled Version: @VERSION@ Requires: gstreamer-@GST_MAJORMINOR@ -Libs: -L@abs_top_builddir@/gst-libs/gst/audio -L@abs_top_builddir@/gst-libs/gst/cdda -L@abs_top_builddir@/gst-libs/gst/fft -L@abs_top_builddir@/gst-libs/gst/floatcast -L@abs_top_builddir@/gst-libs/gst/interfaces -L@abs_top_builddir@/gst-libs/gst/netbuffer -L@abs_top_builddir@/gst-libs/gst/riff -L@abs_top_builddir@/gst-libs/gst/rtp -L@abs_top_builddir@/gst-libs/gst/rtsp -L@abs_top_builddir@/gst-libs/gst/sdp -L@abs_top_builddir@/gst-libs/gst/tag -L@abs_top_builddir@/gst-libs/gst/pbutils -L@abs_top_builddir@/gst-libs/gst/video -L@abs_top_builddir@/gst-libs/gst/app +Libs: -L@abs_top_builddir@/gst-libs/gst/audio -L@abs_top_builddir@/gst-libs/gst/cdda -L@abs_top_builddir@/gst-libs/gst/dmabuf -L@abs_top_builddir@/gst-libs/gst/fft -L@abs_top_builddir@/gst-libs/gst/floatcast -L@abs_top_builddir@/gst-libs/gst/interfaces -L@abs_top_builddir@/gst-libs/gst/netbuffer -L@abs_top_builddir@/gst-libs/gst/riff -L@abs_top_builddir@/gst-libs/gst/rtp -L@abs_top_builddir@/gst-libs/gst/rtsp -L@abs_top_builddir@/gst-libs/gst/sdp -L@abs_top_builddir@/gst-libs/gst/tag -L@abs_top_builddir@/gst-libs/gst/pbutils -L@abs_top_builddir@/gst-libs/gst/video -L@abs_top_builddir@/gst-libs/gst/app Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs -libraries=app audio cdda fft floatcast interfaces netbuffer riff rtp rtsp sdp tag pbutils video +libraries=app audio cdda fft dmabuf floatcast interfaces netbuffer riff rtp rtsp sdp tag pbutils video diff --git a/pkgconfig/gstreamer-plugins-base.pc.in b/pkgconfig/gstreamer-plugins-base.pc.in index 4bc6088..70e6d86 100644 --- a/pkgconfig/gstreamer-plugins-base.pc.in +++ b/pkgconfig/gstreamer-plugins-base.pc.in @@ -11,4 +11,4 @@ Version: @VERSION@ Libs: -L${libdir} Cflags: -I${includedir} -libraries=audio cdda fft floatcast interfaces netbuffer riff rtp tag pbutils video +libraries=audio cdda dmabuf fft floatcast interfaces netbuffer riff rtp tag pbutils video -- 1.7.9.5 From 66561ca66f29c011cc8e0e3478bf466f2a149c9f Mon Sep 17 00:00:00 2001 From: Rob Clark <rob@ti.com> Date: Tue, 12 Jun 2012 18:48:57 -0500 Subject: [PATCH] video: add qdata based crop interface Add a qdata based crop interface that can be used to attach and retrieve cropping info from buffers --- gst-libs/gst/video/Makefile.am | 6 +- gst-libs/gst/video/video-crop.c | 171 +++++++++++++++++++++++++++++++++++++++ gst-libs/gst/video/video-crop.h | 104 ++++++++++++++++++++++++ 3 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 gst-libs/gst/video/video-crop.c create mode 100644 gst-libs/gst/video/video-crop.h diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am index 7306995..f8d3f1c 100644 --- a/gst-libs/gst/video/Makefile.am +++ b/gst-libs/gst/video/Makefile.am @@ -20,13 +20,15 @@ CLEANFILES = $(BUILT_SOURCES) # video-blend.h should be disted but not installed into the includedir libgstvideo_@GST_MAJORMINOR@_la_SOURCES = \ video.c gstvideosink.c gstvideofilter.c convertframe.c \ - video-blend.c video-blend.h video-overlay-composition.c + video-blend.c video-blend.h video-overlay-composition.c \ + video-crop.c nodist_libgstvideo_@GST_MAJORMINOR@_la_SOURCES = \ $(built_sources) $(built_headers) \ $(ORC_NODIST_SOURCES) libgstvideo_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/video libgstvideo_@GST_MAJORMINOR@include_HEADERS = \ - video.h gstvideosink.h gstvideofilter.h video-overlay-composition.h + video.h gstvideosink.h gstvideofilter.h video-overlay-composition.h \ + video-crop.h nodist_libgstvideo_@GST_MAJORMINOR@include_HEADERS = $(built_headers) libgstvideo_@GST_MAJORMINOR@_la_CFLAGS = \ diff --git a/gst-libs/gst/video/video-crop.c b/gst-libs/gst/video/video-crop.c new file mode 100644 index 0000000..be9055e --- /dev/null +++ b/gst-libs/gst/video/video-crop.c @@ -0,0 +1,171 @@ +/* GStreamer video crop + * + * Copyright (c) 2012, Texas Instruments Incorporated + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstvideocrop + * @short_description: GStreamer video cropping support + * + * Since: 0.10.? + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> + +#include "video-crop.h" + +struct _GstVideoCrop +{ + GstMiniObject parent; + + gint top, left, width, height; +}; + +struct _GstVideoCropClass +{ + GstMiniObjectClass parent_class; +}; + +#define GST_VIDEO_CROP_QUARK gst_video_crop_quark_get_type() +static GST_BOILERPLATE_QUARK (GstVideoCrop, gst_video_crop_quark); + +#define VIDEO_CROP_QUARK video_crop_quark_get_type() +static GST_BOILERPLATE_QUARK (VideoCrop, video_crop_quark); + +/** + * gst_buffer_set_video_crop: + * @buf: a #GstBuffer + * @crop: (allow-none): a #GstVideoCrop, or NULL to clear a + * previously-set crop + * + * Sets an video crop on a buffer. The buffer will obtain its own + * reference to the crop, meaning this function does not take ownership + * of @crop. + * + * Since: 0.10.? + */ +void +gst_buffer_set_video_crop (GstBuffer * buf, GstVideoCrop * crop) +{ + gst_buffer_set_qdata (buf, GST_VIDEO_CROP_QUARK, + gst_structure_id_new (GST_VIDEO_CROP_QUARK, + VIDEO_CROP_QUARK, GST_TYPE_VIDEO_CROP, crop, NULL)); +} + +/** + * gst_buffer_get_video_crop: + * @buf: a #GstBuffer + * + * Get the video crop that has previously been attached to a buffer + * with gst_buffer_set_video_crop(), usually by another element + * upstream. + * + * Returns: (transfer none): the #GstVideoCrop attached to + * this buffer, or NULL. Does not return a reference to the crop, + * caller must obtain her own ref via gst_video_crop_ref() + * if needed. + * + * Since: 0.10.? + */ +GstVideoCrop * +gst_buffer_get_video_crop (GstBuffer * buf) +{ + const GstStructure *s; + const GValue *val; + + s = gst_buffer_get_qdata (buf, GST_VIDEO_CROP_QUARK); + if (s == NULL) + return NULL; + + val = gst_structure_id_get_value (s, VIDEO_CROP_QUARK); + if (val == NULL) + return NULL; + + return GST_VIDEO_CROP (gst_value_get_mini_object (val)); +} + +static void +gst_video_crop_finalize (GstMiniObject * mini_obj) +{ + /* not chaining up to GstMiniObject's finalize for now, we know it's empty */ +} + +static void +gst_video_crop_class_init (GstVideoCropClass * klass) +{ + GST_MINI_OBJECT_CLASS (klass)->finalize = gst_video_crop_finalize; +} + +GST_BOILERPLATE_MINI_OBJECT (GstVideoCrop, gst_video_crop); + +/** + * gst_video_crop_new: + * @top: top coordinate of cropping region + * @left: left coordinate of cropping region + * @width: width of cropping region + * @height: height of cropping region + * + * Creates a new crop object. + * + * Returns: (transfer full): a new #GstVideoCrop. Unref with + * gst_video_crop_unref() when no longer needed. + * + * Since: 0.10.? + */ +GstVideoCrop * +gst_video_crop_new (guint top, guint left, guint width, guint height) +{ + GstVideoCrop *crop; + + crop = (GstVideoCrop *) gst_mini_object_new (GST_TYPE_VIDEO_CROP); + + crop->top = top; + crop->left = left; + crop->width = width; + crop->height = height; + + return crop; +} + +guint +gst_video_crop_top (GstVideoCrop * crop) +{ + return crop->top; +} + +guint +gst_video_crop_left (GstVideoCrop * crop) +{ + return crop->left; +} + +guint +gst_video_crop_width (GstVideoCrop * crop) +{ + return crop->width; +} + +guint +gst_video_crop_height (GstVideoCrop * crop) +{ + return crop->height; +} diff --git a/gst-libs/gst/video/video-crop.h b/gst-libs/gst/video/video-crop.h new file mode 100644 index 0000000..bfc7cfe --- /dev/null +++ b/gst-libs/gst/video/video-crop.h @@ -0,0 +1,104 @@ +/* GStreamer video-crop + * + * Copyright (c) 2012, Texas Instruments Incorporated + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_VIDEO_CROP_H__ +#define __GST_VIDEO_CROP_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS + +/** + * GstVideoCrop: + * + * Crop coordinates for a video buffer. + * + * Since: 0.10.? + */ +#define GST_TYPE_VIDEO_CROP \ + (gst_video_crop_get_type ()) +#define GST_VIDEO_CROP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_CROP, GstVideoCrop)) +#define GST_IS_VIDEO_CROP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_CROP)) + +typedef struct _GstVideoCrop GstVideoCrop; +typedef struct _GstVideoCropClass GstVideoCropClass; + +/** + * gst_video_crop_ref: + * @crop: a a #GstVideoCrop. + * + * Increases the refcount by one. + * + * Returns: (transfer full): @crop + * + * Since: 0.10.? + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC GstVideoCrop * +gst_video_crop_ref (GstVideoCrop * crop); +#endif + +static inline GstVideoCrop * +gst_video_crop_ref (GstVideoCrop * crop) +{ + return (GstVideoCrop *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (crop)); +} + +/** + * gst_video_crop_unref: + * @crop: (transfer full): a #GstVideoCrop. + * + * Decreases the refcount. If the refcount reaches 0, the crop will be + * freed. + * + * Since: 0.10.? + */ +#ifdef _FOOL_GTK_DOC_ +G_INLINE_FUNC void +gst_video_crop_unref (GstVideoCrop * crop); +#endif + +static inline void +gst_video_crop_unref (GstVideoCrop * crop) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (crop)); +} + +GType gst_video_crop_get_type (void); + +GstVideoCrop * gst_video_crop_new (guint top, guint left, guint width, guint height); + +guint gst_video_crop_top (GstVideoCrop * crop); +guint gst_video_crop_left (GstVideoCrop * crop); +guint gst_video_crop_width (GstVideoCrop * crop); +guint gst_video_crop_height (GstVideoCrop * crop); + +/* attach/retrieve crop from buffers */ + +void gst_buffer_set_video_crop (GstBuffer * buf, + GstVideoCrop * crop); + +GstVideoCrop * gst_buffer_get_video_crop (GstBuffer * buf); + +G_END_DECLS + +#endif /* __GST_VIDEO_CROP_H__ */ -- 1.7.9.5 From e722241fe664a326c8fe2a50b848c37ac44cdaa7 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Fri, 29 Jun 2012 16:31:29 +0000 Subject: [PATCH] ffmpegcolorspace: ensure we don't lose any crop setting --- gst/ffmpegcolorspace/gstffmpegcolorspace.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/ffmpegcolorspace/gstffmpegcolorspace.c b/gst/ffmpegcolorspace/gstffmpegcolorspace.c index 96e62f8..0521632 100644 --- a/gst/ffmpegcolorspace/gstffmpegcolorspace.c +++ b/gst/ffmpegcolorspace/gstffmpegcolorspace.c @@ -475,6 +475,9 @@ gst_ffmpegcsp_transform (GstBaseTransform * btrans, GstBuffer * inbuf, space->to_pixfmt == PIX_FMT_NB)) goto unknown_format; + /* Ensure any crop setting is preserved */ + gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_QDATA); + /* fill from with source data */ gst_ffmpegcsp_avpicture_fill (&space->from_frame, GST_BUFFER_DATA (inbuf), space->from_pixfmt, space->width, space->height, -- 1.7.9.5 From 9c2b1f36e88011e42df2b0b61ea6d84af95bacde Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Wed, 20 Jun 2012 09:30:34 +0000 Subject: [PATCH] stridetransform: fix caps leaks --- gst/stride/gststridetransform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index d0fad88..7b9b189 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -143,6 +143,8 @@ gst_stride_transform_dispose (GObject * object) { GstStrideTransform *self = GST_STRIDE_TRANSFORM (object); GST_DEBUG_OBJECT (self, "ENTER"); + gst_caps_replace (&self->cached_caps[0], NULL); + gst_caps_replace (&self->cached_caps[1], NULL); G_OBJECT_CLASS (parent_class)->dispose (object); } -- 1.7.9.5 From 73e7712c1f139959024e0ff61077b690d43bc9c0 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Wed, 20 Jun 2012 09:30:47 +0000 Subject: [PATCH] stridetransform: fix wrong stride with non multiple of 4 widths Also do not execute code with side effects in asserts-like code. --- gst/stride/gststridetransform.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 7b9b189..0ff5814 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -525,14 +525,24 @@ gst_stride_transform_set_caps (GstBaseTransform * base, gint width, height; GstVideoFormat in_format, out_format; gint i; + gboolean ok; LOG_CAPS (self, incaps); LOG_CAPS (self, outcaps); - g_return_val_if_fail (gst_video_format_parse_caps_strided (incaps, - &in_format, &self->width, &self->height, &self->in_rowstride), FALSE); - g_return_val_if_fail (gst_video_format_parse_caps_strided (outcaps, - &out_format, &width, &height, &self->out_rowstride), FALSE); + ok = gst_video_format_parse_caps_strided (incaps, + &in_format, &self->width, &self->height, &self->in_rowstride); + g_return_val_if_fail (ok, FALSE); + ok = gst_video_format_parse_caps_strided (outcaps, + &out_format, &width, &height, &self->out_rowstride); + g_return_val_if_fail (ok, FALSE); + + /* Ensure we round up to match what GStreamer expects when no stride + is given */ + if (self->in_rowstride == 0) + self->in_rowstride = GST_ROUND_UP_4 (self->width); + if (self->out_rowstride == 0) + self->out_rowstride = GST_ROUND_UP_4 (width); self->conversion = NULL; self->crop_width = 0; -- 1.7.9.5 From adf99c63124823900d7337d021d8912ca978c42a Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Thu, 21 Jun 2012 15:17:53 +0000 Subject: [PATCH] stridetransform: move semantic code out of assert-like call --- gst/stride/gststridetransform.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/stride/gststridetransform.c b/gst/stride/gststridetransform.c index 0ff5814..a29177c 100644 --- a/gst/stride/gststridetransform.c +++ b/gst/stride/gststridetransform.c @@ -187,9 +187,11 @@ gst_stride_transform_get_unit_size (GstBaseTransform * base, GstStrideTransform *self = GST_STRIDE_TRANSFORM (base); GstVideoFormat format; gint width, height, rowstride; + gboolean ok; - g_return_val_if_fail (gst_video_format_parse_caps_strided (caps, &format, - &width, &height, &rowstride), FALSE); + ok = gst_video_format_parse_caps_strided (caps, &format, + &width, &height, &rowstride); + g_return_val_if_fail (ok, FALSE); *size = gst_video_format_get_size_strided (format, width, height, rowstride); -- 1.7.9.5 From 73749c30bec869fa1dcd777a31233a253b876540 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Wed, 1 Aug 2012 16:55:19 +0000 Subject: [PATCH] stridetransform: log relevant values when size check fails --- gst/stride/convert.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/stride/convert.c b/gst/stride/convert.c index 7f976a5..1b39f2e 100644 --- a/gst/stride/convert.c +++ b/gst/stride/convert.c @@ -195,7 +195,9 @@ static inline gboolean refresh_cache(GstStrideTransform * self, if ((cache->in_bpl < (self->width * bpp)) || (cache->out_bpl < (self->width * bpp))) { - GST_ERROR_OBJECT (self, "invalid stride parameter"); + GST_ERROR_OBJECT (self, + "invalid stride parameter (in_bpl %d, out_bpl %d, width %d, bpp %d", + cache->in_bpl, cache->out_bpl, self->width, bpp); return GST_FLOW_ERROR; } -- 1.7.9.5 From fad32193a79b394c8e7e630b0aa739462a424fa4 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Thu, 20 Sep 2012 17:09:43 +0100 Subject: [PATCH] typefind: give less weight to H.263 streams when few blocks are found This avoids mistaking at least one H.264 stream for H.263. --- gst/typefind/gsttypefindfunctions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index 27823b6..c8bd86e 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -2377,7 +2377,7 @@ h263_video_type_find (GstTypeFind * tf, gpointer unused) data_scan_ctx_advance (tf, &c, 1); } - if (good > 0 && bad == 0) + if (good > 1 && bad == 0) gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H263_VIDEO_CAPS); else if (good > 2 * bad) gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H263_VIDEO_CAPS); -- 1.7.9.5 From e4a9ff80fd8330bebecb38047af0904c06abaa96 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti <ricardo.salveti@linaro.org> Date: Thu, 4 Oct 2012 16:31:47 +0100 Subject: [PATCH] stridetransform: fix makefile for non ARM targets --- gst/stride/Makefile.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gst/stride/Makefile.am b/gst/stride/Makefile.am index 3b466de..566eeb2 100644 --- a/gst/stride/Makefile.am +++ b/gst/stride/Makefile.am @@ -1,10 +1,18 @@ plugin_LTLIBRARIES = libgststridetransform.la +ARM_FILES=armv7.s + +if HAVE_CPU_ARM +ARCH_FILES = $(ARM_FILES) +else +ARCH_FILES = +endif + libgststridetransform_la_SOURCES = \ gststridetransform.c \ convert.c \ - armv7.s \ - plugin.c + plugin.c \ + $(ARCH_FILES) libgststridetransform_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) libgststridetransform_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -- 1.7.9.5 From b31404f105d1d5ebfca02ffb71f5227367787333 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Wed, 10 Oct 2012 16:16:54 +0100 Subject: [PATCH] textoverlay: heed crop event values when placing subtitles Since we can receive data at a larger resolution that what will be visible, we need to use the cropped values to decide where to draw subtitles. --- ext/pango/gsttextoverlay.c | 37 +++++++++++++++++++++++++++++++++++++ ext/pango/gsttextoverlay.h | 5 +++++ 2 files changed, 42 insertions(+) diff --git a/ext/pango/gsttextoverlay.c b/ext/pango/gsttextoverlay.c index 823b207..4dc9895 100644 --- a/ext/pango/gsttextoverlay.c +++ b/ext/pango/gsttextoverlay.c @@ -699,6 +699,11 @@ gst_text_overlay_init (GstTextOverlay * overlay, GstTextOverlayClass * klass) overlay->fps_n = 0; overlay->fps_d = 1; + overlay->crop_top = 0; + overlay->crop_left = 0; + overlay->crop_width = 0; + overlay->crop_height = 0; + overlay->text_buffer = NULL; overlay->text_linked = FALSE; overlay->cond = g_cond_new (); @@ -798,6 +803,17 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps) if (fps && gst_video_format_parse_caps_strided (caps, &overlay->format, &overlay->width, &overlay->height, &overlay->rowstride)) { + + /* If we got a crop event, use these values instead of the ones from + the caps, which are uncropped. + FIXME: We get the crop event before caps are set. I am suspicious + of whether this is actually correct, and the following would not + be needed if events were received after caps are set. */ + if (overlay->crop_width > 0) + overlay->width = overlay->crop_width; + if (overlay->crop_height > 0) + overlay->height = overlay->crop_height; + ret = gst_pad_set_caps (overlay->srcpad, caps); } @@ -1217,6 +1233,7 @@ gst_text_overlay_get_pos (GstTextOverlay * overlay, gint * xpos, gint * ypos) *xpos = 0; } *xpos += overlay->deltax; + *xpos += overlay->crop_left; if (overlay->use_vertical_render) valign = GST_TEXT_OVERLAY_VALIGN_TOP; @@ -1245,6 +1262,7 @@ gst_text_overlay_get_pos (GstTextOverlay * overlay, gint * xpos, gint * ypos) break; } *ypos += overlay->deltay; + *ypos += overlay->crop_top; } static inline void @@ -1865,6 +1883,25 @@ gst_text_overlay_video_event (GstPad * pad, GstEvent * event) ret = gst_pad_event_default (pad, event); break; } + case GST_EVENT_CROP: + { + gint top, left, width, height; + GST_OBJECT_LOCK (overlay); + gst_event_parse_crop (event, &top, &left, &width, &height); + GST_INFO_OBJECT (overlay, "Crop: %d %d %d %d", top, left, width, height); + if (width < 0) + width = overlay->width - left; + if (height < 0) + height = overlay->height - top; + overlay->crop_top = top; + overlay->crop_left = left; + overlay->crop_width = width; + overlay->crop_height = height; + overlay->width = width; + overlay->height = width; + GST_OBJECT_UNLOCK (overlay); + break; + } case GST_EVENT_EOS: GST_OBJECT_LOCK (overlay); GST_INFO_OBJECT (overlay, "video EOS"); diff --git a/ext/pango/gsttextoverlay.h b/ext/pango/gsttextoverlay.h index 0895286..554f667 100644 --- a/ext/pango/gsttextoverlay.h +++ b/ext/pango/gsttextoverlay.h @@ -128,6 +128,11 @@ struct _GstTextOverlay { GstTextOverlayWrapMode wrap_mode; GstTextOverlayLineAlign line_align; + gint crop_top; + gint crop_left; + gint crop_width; + gint crop_height; + gint xpad; gint ypad; gint deltax; -- 1.7.9.5 From b603b2e4d5fcc780e925f553f481baca87e317e9 Mon Sep 17 00:00:00 2001 From: Thibault Saunier <thibault.saunier@collabora.com> Date: Thu, 18 Oct 2012 15:47:03 -0300 Subject: [PATCH] xvimagesink: Handle the cropping event and attached on buffer struct --- sys/xvimage/xvimagesink.c | 63 ++++++++++++++++++++++++++++++++++++++++++--- sys/xvimage/xvimagesink.h | 5 ++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index 8a7913b..21a2ef3 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -787,8 +787,10 @@ static gboolean gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstXvImageBuffer * xvimage) { + GstVideoCrop *crop; GstVideoRectangle result; gboolean draw_border = FALSE; + gint disp_x, disp_y, disp_width, disp_height; /* We take the flow_lock. If expose is in there we don't want to run concurrently from the data flow thread */ @@ -852,6 +854,19 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, xvimagesink->redraw_border = FALSE; } + crop = xvimagesink->crop_rect; + if (crop == NULL) { + disp_x = xvimagesink->disp_x; + disp_y = xvimagesink->disp_y; + disp_width = xvimagesink->disp_width; + disp_height = xvimagesink->disp_height; + } else { + disp_x = xvimagesink->disp_x + gst_video_crop_left (crop); + disp_y = xvimagesink->disp_y + gst_video_crop_top (crop); + disp_width = gst_video_crop_width (crop); + disp_height = gst_video_crop_height (crop); + } + /* We scale to the window's geometry */ #ifdef HAVE_XSHM if (xvimagesink->xcontext->use_xshm) { @@ -865,8 +880,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, xvimagesink->xcontext->xv_port_id, xvimagesink->xwindow->win, xvimagesink->xwindow->gc, xvimage->xvimage, - xvimagesink->disp_x, xvimagesink->disp_y, - xvimagesink->disp_width, xvimagesink->disp_height, + disp_x, disp_y, disp_width, disp_height, result.x, result.y, result.w, result.h, FALSE); } else #endif /* HAVE_XSHM */ @@ -875,8 +889,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, xvimagesink->xcontext->xv_port_id, xvimagesink->xwindow->win, xvimagesink->xwindow->gc, xvimage->xvimage, - xvimagesink->disp_x, xvimagesink->disp_y, - xvimagesink->disp_width, xvimagesink->disp_height, + disp_x, disp_y, disp_width, disp_height, result.x, result.y, result.w, result.h); } @@ -2375,6 +2388,14 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) xvimagesink = GST_XVIMAGESINK (vsink); + if (gst_buffer_get_video_crop (buf)) { + if (xvimagesink->crop_rect) + gst_video_crop_unref (xvimagesink->crop_rect); + + xvimagesink->crop_rect = + gst_video_crop_ref (gst_buffer_get_video_crop (buf)); + } + /* If this buffer has been allocated using our buffer management we simply put the ximage which is in the PRIVATE pointer */ if (GST_IS_XVIMAGE_BUFFER (buf)) { @@ -2456,6 +2477,33 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event) } break; } + case GST_EVENT_CROP:{ + GstStructure *structure; + GstMessage *message; + gint left, top, width, height; + + gst_event_parse_crop (event, &top, &left, &width, &height); + GST_DEBUG_OBJECT (sink, "Got crop event: %d %d %d %d", top, left, width, + height); + if (width < 0) { + width = GST_VIDEO_SINK_WIDTH (xvimagesink) - left; + } + if (height < 0) { + height = GST_VIDEO_SINK_HEIGHT (xvimagesink) - top; + } + + if (xvimagesink->crop_rect) + gst_video_crop_unref (xvimagesink->crop_rect); + xvimagesink->crop_rect = gst_video_crop_new (top, left, width, height); + + structure = gst_structure_new ("video-size-crop", "width", G_TYPE_INT, + width, "height", G_TYPE_INT, height, NULL); + message = gst_message_new_application (GST_OBJECT (xvimagesink), + structure); + gst_bus_post (gst_element_get_bus (GST_ELEMENT (xvimagesink)), message); + + break; + } default: break; } @@ -3451,6 +3499,11 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink) xvimagesink->have_render_rect = FALSE; gst_xvimagesink_xcontext_clear (xvimagesink); + + if (xvimagesink->crop_rect) { + gst_video_crop_unref (xvimagesink->crop_rect); + xvimagesink->crop_rect = NULL; + } } /* Finalize is called only once, dispose can be called multiple times. @@ -3533,6 +3586,8 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink, */ xvimagesink->colorkey = (8 << 16) | (8 << 8) | 16; xvimagesink->draw_borders = TRUE; + + xvimagesink->crop_rect = NULL; } static void diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h index f3d0a99..fdbe4f9 100644 --- a/sys/xvimage/xvimagesink.h +++ b/sys/xvimage/xvimagesink.h @@ -42,6 +42,8 @@ #include <math.h> #include <stdlib.h> +#include <gst/video/video-crop.h> + G_BEGIN_DECLS #define GST_TYPE_XVIMAGESINK \ @@ -269,6 +271,9 @@ struct _GstXvImageSink { /* size of incoming video, used as the size for XvImage */ guint video_width, video_height; + /* Size to be croped */ + GstVideoCrop *crop_rect; + /* display sizes, used for clipping the image */ gint disp_x, disp_y; gint disp_width, disp_height; -- 1.7.9.5 From 021686dda22e30ccdf073deac80d9e9250f54de6 Mon Sep 17 00:00:00 2001 From: Thibault Saunier <thibault.saunier@collabora.com> Date: Fri, 19 Oct 2012 17:39:22 -0300 Subject: [PATCH] playsink: Add a colorspace converter In case the user sets a sink that doesn't handle NV12, it is needed. --- gst/playback/gstplaysink.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index adf8a9e..94847d4 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -479,14 +479,11 @@ gst_play_sink_class_init (GstPlaySinkClass * klass) gst_element_class_add_static_pad_template (gstelement_klass, &audiorawtemplate); - gst_element_class_add_static_pad_template (gstelement_klass, - &audiotemplate); + gst_element_class_add_static_pad_template (gstelement_klass, &audiotemplate); gst_element_class_add_static_pad_template (gstelement_klass, &videorawtemplate); - gst_element_class_add_static_pad_template (gstelement_klass, - &videotemplate); - gst_element_class_add_static_pad_template (gstelement_klass, - &texttemplate); + gst_element_class_add_static_pad_template (gstelement_klass, &videotemplate); + gst_element_class_add_static_pad_template (gstelement_klass, &texttemplate); gst_element_class_set_details_simple (gstelement_klass, "Player Sink", "Generic/Bin/Sink", "Convenience sink for multiple streams", @@ -1340,7 +1337,9 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async) if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) { GST_DEBUG_OBJECT (playsink, "creating stridetransform"); - chain->conv = gst_element_factory_make ("stridetransform", "vconv"); + chain->conv = + gst_parse_bin_from_description ("ffmpegcolorspace ! stridetransform", + TRUE, NULL); if (chain->conv == NULL) { post_missing_element_message (playsink, "stridetransform"); GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, @@ -3050,14 +3049,14 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink) if (pad == playsink->audio_pad) { raw = is_raw_pad (pad); - reconfigure = (!!playsink->audio_pad_raw != !!raw) + reconfigure = (! !playsink->audio_pad_raw != ! !raw) && playsink->audiochain; GST_DEBUG_OBJECT (pad, "Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, reconfigure, caps); } else if (pad == playsink->video_pad) { raw = is_raw_pad (pad); - reconfigure = (!!playsink->video_pad_raw != !!raw) + reconfigure = (! !playsink->video_pad_raw != ! !raw) && playsink->videochain; GST_DEBUG_OBJECT (pad, "Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, -- 1.7.9.5 From 5eac2e936544f7a2d6e4f20a14204fdbebb2abfc Mon Sep 17 00:00:00 2001 From: "Oleksij Rempel (Alexey Fisher)" <bug-track@fisher-privat.net> Date: Mon, 5 Mar 2012 11:09:12 +0100 Subject: [PATCH] xvimagesink: don't use deprecated XKeycodeToKeysym https://bugzilla.gnome.org/show_bug.cgi?id=671299 Signed-off-by: Oleksij Rempel (Alexey Fisher) <bug-track@fisher-privat.net> --- sys/xvimage/xvimagesink.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index 21a2ef3..b210358 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -129,6 +129,9 @@ #include "gst/glib-compat-private.h" +/* for XkbKeycodeToKeysym */ +#include <X11/XKBlib.h> + GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink); #define GST_CAT_DEFAULT gst_debug_xvimagesink GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); @@ -1243,6 +1246,7 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask, &e)) { KeySym keysym; + const char *key_str = NULL; /* We lock only for the X function call */ g_mutex_unlock (xvimagesink->x_lock); @@ -1269,24 +1273,20 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) case KeyRelease: /* Key pressed/released over our window. We send upstream events for interactivity/navigation */ - GST_DEBUG ("xvimagesink key %d pressed over window at %d,%d", - e.xkey.keycode, e.xkey.x, e.xkey.y); g_mutex_lock (xvimagesink->x_lock); - keysym = XKeycodeToKeysym (xvimagesink->xcontext->disp, - e.xkey.keycode, 0); - g_mutex_unlock (xvimagesink->x_lock); + keysym = XkbKeycodeToKeysym (xvimagesink->xcontext->disp, + e.xkey.keycode, 0, 0); if (keysym != NoSymbol) { - char *key_str = NULL; - - g_mutex_lock (xvimagesink->x_lock); key_str = XKeysymToString (keysym); - g_mutex_unlock (xvimagesink->x_lock); - gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), - e.type == KeyPress ? "key-press" : "key-release", key_str); } else { - gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), - e.type == KeyPress ? "key-press" : "key-release", "unknown"); + key_str = "unknown"; } + g_mutex_unlock (xvimagesink->x_lock); + GST_DEBUG_OBJECT (xvimagesink, + "key %d pressed over window at %d,%d (%s)", + e.xkey.keycode, e.xkey.x, e.xkey.y, key_str); + gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), + e.type == KeyPress ? "key-press" : "key-release", key_str); break; default: GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type); -- 1.7.9.5 From 278832696be574e2f3406a44c76e396386031a87 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> Date: Thu, 6 Sep 2012 15:03:49 +0200 Subject: [PATCH] streamsynchronizer: do not leak EOS events --- gst/playback/gststreamsynchronizer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/playback/gststreamsynchronizer.c b/gst/playback/gststreamsynchronizer.c index 8b80a6b..a5377eb 100644 --- a/gst/playback/gststreamsynchronizer.c +++ b/gst/playback/gststreamsynchronizer.c @@ -539,6 +539,7 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event) } } gst_object_unref (srcpad); + gst_event_unref (event); goto done; break; } -- 1.7.9.5 From 44188a1cb290f1272df3e13bc42c440bdd1423c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian.droege@collabora.co.uk> Date: Fri, 27 Jul 2012 12:58:40 +0200 Subject: [PATCH] streamsynchronizer: Unblock streams on FLUSH_START events --- gst/playback/gststreamsynchronizer.c | 39 +++++++++++++++++++++++++--------- gst/playback/gststreamsynchronizer.h | 1 - 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/gst/playback/gststreamsynchronizer.c b/gst/playback/gststreamsynchronizer.c index a5377eb..f22ab4b 100644 --- a/gst/playback/gststreamsynchronizer.c +++ b/gst/playback/gststreamsynchronizer.c @@ -77,6 +77,8 @@ typedef struct gboolean seen_data; gint64 running_time_diff; + + GCond *stream_finish_cond; } GstStream; /* Must be called with lock! */ @@ -344,7 +346,10 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event) GST_DEBUG_OBJECT (self, "New group start time: %" GST_TIME_FORMAT, GST_TIME_ARGS (self->group_start_time)); - g_cond_broadcast (self->stream_finish_cond); + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + g_cond_broadcast (ostream->stream_finish_cond); + } } } GST_STREAM_SYNCHRONIZER_UNLOCK (self); @@ -367,7 +372,7 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event) if (stream) { if (stream->wait) { GST_DEBUG_OBJECT (pad, "Stream %d is waiting", stream->stream_number); - g_cond_wait (self->stream_finish_cond, self->lock); + g_cond_wait (stream->stream_finish_cond, self->lock); stream = gst_pad_get_element_private (pad); if (stream) stream->wait = FALSE; @@ -454,6 +459,18 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event) GST_STREAM_SYNCHRONIZER_UNLOCK (self); break; } + case GST_EVENT_FLUSH_START:{ + GstStream *stream; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream) { + GST_DEBUG_OBJECT (pad, "Flushing streams"); + g_cond_broadcast (stream->stream_finish_cond); + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + break; + } case GST_EVENT_FLUSH_STOP:{ GstStream *stream; @@ -726,6 +743,7 @@ gst_stream_synchronizer_request_new_pad (GstElement * element, stream = g_slice_new0 (GstStream); stream->transform = self; stream->stream_number = self->current_stream_number; + stream->stream_finish_cond = g_cond_new (); tmp = g_strdup_printf ("sink_%d", self->current_stream_number); stream->sinkpad = gst_pad_new_from_static_template (&sinktemplate, tmp); @@ -828,6 +846,7 @@ gst_stream_synchronizer_release_stream (GstStreamSynchronizer * self, self->group_start_time = MAX (self->group_start_time, stop_running_time); } + g_cond_free (stream->stream_finish_cond); g_slice_free (GstStream, stream); /* NOTE: In theory we have to check here if all streams @@ -879,13 +898,19 @@ gst_stream_synchronizer_change_state (GstElement * element, case GST_STATE_CHANGE_PAUSED_TO_PLAYING: GST_DEBUG_OBJECT (self, "State change PAUSED->PLAYING"); break; - case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_PAUSED_TO_READY:{ + GList *l; + GST_DEBUG_OBJECT (self, "State change READY->NULL"); GST_STREAM_SYNCHRONIZER_LOCK (self); - g_cond_broadcast (self->stream_finish_cond); + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + g_cond_broadcast (ostream->stream_finish_cond); + } self->shutdown = TRUE; GST_STREAM_SYNCHRONIZER_UNLOCK (self); + } default: break; } @@ -950,11 +975,6 @@ gst_stream_synchronizer_finalize (GObject * object) self->lock = NULL; } - if (self->stream_finish_cond) { - g_cond_free (self->stream_finish_cond); - self->stream_finish_cond = NULL; - } - G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -964,7 +984,6 @@ gst_stream_synchronizer_init (GstStreamSynchronizer * self, GstStreamSynchronizerClass * klass) { self->lock = g_mutex_new (); - self->stream_finish_cond = g_cond_new (); } static void diff --git a/gst/playback/gststreamsynchronizer.h b/gst/playback/gststreamsynchronizer.h index e2379ae..32b6c69 100644 --- a/gst/playback/gststreamsynchronizer.h +++ b/gst/playback/gststreamsynchronizer.h @@ -46,7 +46,6 @@ struct _GstStreamSynchronizer /* < private > */ GMutex *lock; - GCond *stream_finish_cond; gboolean shutdown; GList *streams; -- 1.7.9.5 From cef29f4da5e46ef695ee12fb9838de8c76bbd7f5 Mon Sep 17 00:00:00 2001 From: Edward Hervey <edward.hervey@collabora.co.uk> Date: Tue, 11 Sep 2012 16:27:24 +0200 Subject: [PATCH] streamsynchronizer: Don't wait on non-time streams streams with non-TIME segments will not have timestamps ... ... and therefore will never unblock the other streams. Fixes blocking issue when using playbin suburi feature --- gst/playback/gststreamsynchronizer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/playback/gststreamsynchronizer.c b/gst/playback/gststreamsynchronizer.c index f22ab4b..64dbdf8 100644 --- a/gst/playback/gststreamsynchronizer.c +++ b/gst/playback/gststreamsynchronizer.c @@ -455,6 +455,9 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event) GST_WARNING_OBJECT (pad, "Non-TIME segment: %s", gst_format_get_name (format)); gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); + /* Since this stream is not time-based, we mark it so that + * other streams don't wait forever on it */ + stream->wait = TRUE; } GST_STREAM_SYNCHRONIZER_UNLOCK (self); break; -- 1.7.9.5 From e757feeec0d866c18429a81e78fedf63ac3b6886 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Wed, 14 Nov 2012 10:52:47 +0000 Subject: [PATCH] decodebin2: Increase the default queue even more than more for some sad wmv sample that wedges on seeking otherwise. --- gst/playback/gstdecodebin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c index 12c8861..4f1e027 100644 --- a/gst/playback/gstdecodebin2.c +++ b/gst/playback/gstdecodebin2.c @@ -234,7 +234,7 @@ enum /* whan playing, keep a max of 2MB of data but try to keep the number of buffers * as low as possible (try to aim for 5 buffers) */ -#define AUTO_PLAY_SIZE_BYTES 8 * 1024 * 1024 +#define AUTO_PLAY_SIZE_BYTES 12 * 1024 * 1024 #define AUTO_PLAY_SIZE_BUFFERS 5 #define AUTO_PLAY_SIZE_TIME 0 -- 1.7.9.5 From 5be0fb0fe0348cba8687cb43cc4aefb92a2e8385 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Fri, 23 Nov 2012 13:33:17 +0000 Subject: [PATCH] xvimagesink: fix display of cropped buffers from ducati I suspect this is needed to work around some bug in the lower layers (X or drivers), but do not know X enough to tell. --- sys/xvimage/xvimagesink.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index b210358..b1a6b1d 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -861,14 +861,12 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, if (crop == NULL) { disp_x = xvimagesink->disp_x; disp_y = xvimagesink->disp_y; - disp_width = xvimagesink->disp_width; - disp_height = xvimagesink->disp_height; } else { disp_x = xvimagesink->disp_x + gst_video_crop_left (crop); disp_y = xvimagesink->disp_y + gst_video_crop_top (crop); - disp_width = gst_video_crop_width (crop); - disp_height = gst_video_crop_height (crop); } + disp_width = xvimagesink->disp_width; + disp_height = xvimagesink->disp_height; /* We scale to the window's geometry */ #ifdef HAVE_XSHM @@ -884,7 +882,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, xvimagesink->xwindow->win, xvimagesink->xwindow->gc, xvimage->xvimage, disp_x, disp_y, disp_width, disp_height, - result.x, result.y, result.w, result.h, FALSE); + 0, 0, disp_width, disp_height, FALSE); } else #endif /* HAVE_XSHM */ { @@ -892,8 +890,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, xvimagesink->xcontext->xv_port_id, xvimagesink->xwindow->win, xvimagesink->xwindow->gc, xvimage->xvimage, - disp_x, disp_y, disp_width, disp_height, - result.x, result.y, result.w, result.h); + disp_x, disp_y, disp_width, disp_height, 0, 0, disp_width, disp_height); } XSync (xvimagesink->xcontext->disp, FALSE); @@ -2492,10 +2489,19 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event) height = GST_VIDEO_SINK_HEIGHT (xvimagesink) - top; } + g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (xvimagesink->x_lock); + if (xvimagesink->crop_rect) gst_video_crop_unref (xvimagesink->crop_rect); xvimagesink->crop_rect = gst_video_crop_new (top, left, width, height); + XResizeWindow (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, + width, height); + + g_mutex_unlock (xvimagesink->x_lock); + g_mutex_unlock (xvimagesink->flow_lock); + structure = gst_structure_new ("video-size-crop", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); message = gst_message_new_application (GST_OBJECT (xvimagesink), -- 1.7.9.5 From c779786a365a040d775fb26082fa573099f42dd1 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: Wed, 5 Dec 2012 15:22:01 +0000 Subject: [PATCH] playsink: remove obsolete stridetransform This should not be needed anymore now that -strided caps are obsolete. This also fixes an issue where at least some of the ARM versions of copying routines are not copying all the necessary bytes when the number of bytes to copy is not a multiple of 8, leaving a band of corrupted data on the right of some frames. --- gst/playback/gstplaysink.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 94847d4..a82a387 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -1336,15 +1336,13 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async) } if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) { - GST_DEBUG_OBJECT (playsink, "creating stridetransform"); - chain->conv = - gst_parse_bin_from_description ("ffmpegcolorspace ! stridetransform", - TRUE, NULL); + GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace"); + chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); if (chain->conv == NULL) { - post_missing_element_message (playsink, "stridetransform"); + post_missing_element_message (playsink, "ffmpegcolorspace"); GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), - "stridetransform"), ("video rendering might fail")); + "ffmpegcolorspace"), ("video rendering might fail")); } else { gst_bin_add (bin, chain->conv); if (prev) { -- 1.7.9.5 From 32c51e661bea963e34fbfef2ce9f78934f8e9cd5 Mon Sep 17 00:00:00 2001 From: Olivier Naudan <o-naudan@ti.com> Date: Wed, 30 May 2012 13:13:04 +0200 Subject: [PATCH] Disable unit tests, to avoid issue when building with qemu --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 1901bcf..2016ec1 100644 --- a/configure.ac +++ b/configure.ac @@ -273,6 +273,7 @@ AG_GST_CHECK_GST_BASE($GST_MAJORMINOR, [$GST_REQ], yes) AG_GST_CHECK_GST_GDP($GST_MAJORMINOR, [$GST_REQ], yes) AG_GST_CHECK_GST_CONTROLLER($GST_MAJORMINOR, [$GST_REQ], yes) AG_GST_CHECK_GST_CHECK($GST_MAJORMINOR, [$GST_REQ], no) +HAVE_GST_CHECK=no AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes") dnl Check for documentation xrefs -- 1.7.9.5