diff options
Diffstat (limited to 'common/recipes-multimedia/gstreamer/gst-plugins-good')
31 files changed, 2413 insertions, 0 deletions
diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0001-sys-v4l2-gstv4l2-fix-the-depth-value-for-RGB32.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0001-sys-v4l2-gstv4l2-fix-the-depth-value-for-RGB32.patch new file mode 100644 index 0000000..b6bf9c1 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0001-sys-v4l2-gstv4l2-fix-the-depth-value-for-RGB32.patch @@ -0,0 +1,65 @@ +From f2ceec7fb2e1b7a182eb737216fe3214a743247d Mon Sep 17 00:00:00 2001 +From: Katsuya Matsubara <matsu@igel.co.jp> +Date: Wed, 14 Mar 2012 21:19:31 +0900 +Subject: [PATCH 01/31] sys/v4l2/gstv4l2: fix the depth value for RGB32 + +The 'depth' value for RGB32 must be 24 rather than 32. +This changes conversion code between color format +representaion in caps and V4L2 definition. +--- + sys/v4l2/gstv4l2object.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c +index 81d1cb7..2c1bde4 100644 +--- a/sys/v4l2/gstv4l2object.c ++++ b/sys/v4l2/gstv4l2object.c +@@ -1208,14 +1208,16 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + b_mask = 0xff0000; + break; + case V4L2_PIX_FMT_RGB32: +- bpp = depth = 32; ++ bpp = 32; ++ depth = 24; + endianness = G_BIG_ENDIAN; + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; + break; + case V4L2_PIX_FMT_BGR32: +- bpp = depth = 32; ++ bpp = 32; ++ depth = 24; + endianness = G_BIG_ENDIAN; + r_mask = 0x000000ff; + g_mask = 0x0000ff00; +@@ -1480,9 +1482,10 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + #endif + } + } else if (!strcmp (mimetype, "video/x-raw-rgb")) { +- gint depth, endianness, r_mask; ++ gint bpp, depth, endianness, r_mask; + + gst_structure_get_int (structure, "depth", &depth); ++ gst_structure_get_int (structure, "bpp", &bpp); + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get_int (structure, "red_mask", &r_mask); + +@@ -1499,10 +1502,10 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X; + break; + case 24: +- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; +- break; +- case 32: +- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; ++ if (bpp == 24) ++ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; ++ else if (bpp == 32) ++ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; + break; + } + } else if (strcmp (mimetype, "video/x-dv") == 0) { +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0002-Revert-sys-v4l2-gstv4l2-fix-the-depth-value-for-RGB3.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0002-Revert-sys-v4l2-gstv4l2-fix-the-depth-value-for-RGB3.patch new file mode 100644 index 0000000..d53ca83 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0002-Revert-sys-v4l2-gstv4l2-fix-the-depth-value-for-RGB3.patch @@ -0,0 +1,64 @@ +From 187c290bc57a65fe6f669a6026bdb36b4c89a2a9 Mon Sep 17 00:00:00 2001 +From: Katsuya Matsubara <matsu@igel.co.jp> +Date: Thu, 15 Mar 2012 14:53:39 +0900 +Subject: [PATCH 02/31] Revert "sys/v4l2/gstv4l2: fix the depth value for + RGB32" + +This reverts commit f2ceec7fb2e1b7a182eb737216fe3214a743247d. +--- + sys/v4l2/gstv4l2object.c | 17 +++++++---------- + 1 file changed, 7 insertions(+), 10 deletions(-) + +diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c +index 2c1bde4..81d1cb7 100644 +--- a/sys/v4l2/gstv4l2object.c ++++ b/sys/v4l2/gstv4l2object.c +@@ -1208,16 +1208,14 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + b_mask = 0xff0000; + break; + case V4L2_PIX_FMT_RGB32: +- bpp = 32; +- depth = 24; ++ bpp = depth = 32; + endianness = G_BIG_ENDIAN; + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; + break; + case V4L2_PIX_FMT_BGR32: +- bpp = 32; +- depth = 24; ++ bpp = depth = 32; + endianness = G_BIG_ENDIAN; + r_mask = 0x000000ff; + g_mask = 0x0000ff00; +@@ -1482,10 +1480,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + #endif + } + } else if (!strcmp (mimetype, "video/x-raw-rgb")) { +- gint bpp, depth, endianness, r_mask; ++ gint depth, endianness, r_mask; + + gst_structure_get_int (structure, "depth", &depth); +- gst_structure_get_int (structure, "bpp", &bpp); + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get_int (structure, "red_mask", &r_mask); + +@@ -1502,10 +1499,10 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X; + break; + case 24: +- if (bpp == 24) +- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; +- else if (bpp == 32) +- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; ++ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; ++ break; ++ case 32: ++ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; + break; + } + } else if (strcmp (mimetype, "video/x-dv") == 0) { +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0003-sys-v4l2-gstv4l2-register-uiomux-memory-regions-via-.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0003-sys-v4l2-gstv4l2-register-uiomux-memory-regions-via-.patch new file mode 100644 index 0000000..cd22317 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0003-sys-v4l2-gstv4l2-register-uiomux-memory-regions-via-.patch @@ -0,0 +1,262 @@ +From c3fe71c65f87b32351e58969becb30102d3ddb05 Mon Sep 17 00:00:00 2001 +From: Katsuya Matsubara <matsu@igel.co.jp> +Date: Fri, 6 Apr 2012 16:51:08 +0900 +Subject: [PATCH 03/31] sys/v4l2/gstv4l2: register uiomux memory regions via + USERPTR + +This patch enables to register uiomux memory regions via USERPTR +for capture buffers. This may reduce memory-copy overhead with +sharing the buffer between source and sink element. +--- + configure.ac | 8 ++++++ + sys/v4l2/Makefile.am | 2 ++ + sys/v4l2/gstv4l2bufferpool.c | 55 ++++++++++++++++++++++++++++++++++++++++++ + sys/v4l2/gstv4l2bufferpool.h | 8 ++++++ + sys/v4l2/gstv4l2src.c | 15 ++++++++---- + 5 files changed, 83 insertions(+), 5 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 8a43fda..5bfddfe 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -572,6 +572,14 @@ return 0; + AC_DEFINE(GST_V4L2_MISSING_BUFDECL, 1, [struct v4l2_buffer missing]) + fi + ++ dnl check for libuiomux ++ PKG_CHECK_MODULES(UIOMUX, uiomux >= 1.6.2, HAVE_UIOMUX="yes", [ ++ HAVE_UIOMUX="no" ++ ]) ++ if test $HAVE_UIOMUX = "yes"; then ++ AC_DEFINE(HAVE_UIOMUX, 1, [Define if we have libuiomux]) ++ fi ++ + dnl check for XOverlay libraries + AG_GST_CHECK_XV + fi +diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am +index a7a99de..c4b55d2 100644 +--- a/sys/v4l2/Makefile.am ++++ b/sys/v4l2/Makefile.am +@@ -28,6 +28,7 @@ libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CONTROLLER_CFLAGS) \ + $(GST_CFLAGS) \ ++ $(UIOMUX_CFLAGS) \ + $(X_CFLAGS) \ + $(LIBV4L2_CFLAGS) \ + $(GUDEV_CFLAGS) +@@ -42,6 +43,7 @@ libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ + -lgstvideo-$(GST_MAJORMINOR) \ + -lgstinterfaces-$(GST_MAJORMINOR) \ + $(GST_LIBS) \ ++ $(UIOMUX_LIBS) \ + $(xv_libs) \ + $(LIBV4L2_LIBS) \ + $(GUDEV_LIBS) +diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c +index b81c6a4..a2800aa 100644 +--- a/sys/v4l2/gstv4l2bufferpool.c ++++ b/sys/v4l2/gstv4l2bufferpool.c +@@ -108,7 +108,12 @@ gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer) + "buffer %p (data %p, len %u) not recovered, unmapping", + buffer, GST_BUFFER_DATA (buffer), buffer->vbuffer.length); + gst_mini_object_unref (GST_MINI_OBJECT (pool)); ++#if defined(HAVE_UIOMUX) ++ uiomux_free (pool->uiomux, pool->uiores, (void *) GST_BUFFER_DATA (buffer), ++ buffer->vbuffer.length); ++#else + v4l2_munmap ((void *) GST_BUFFER_DATA (buffer), buffer->vbuffer.length); ++#endif + + GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT + (buffer)); +@@ -166,7 +171,11 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps) + + ret->vbuffer.index = index; + ret->vbuffer.type = pool->type; ++#if defined(HAVE_UIOMUX) ++ ret->vbuffer.memory = V4L2_MEMORY_USERPTR; ++#else + ret->vbuffer.memory = V4L2_MEMORY_MMAP; ++#endif + + if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &ret->vbuffer) < 0) + goto querybuf_failed; +@@ -183,12 +192,21 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps) + GST_LOG_OBJECT (pool->v4l2elem, " length: %u", ret->vbuffer.length); + GST_LOG_OBJECT (pool->v4l2elem, " input: %u", ret->vbuffer.input); + ++#if defined(HAVE_UIOMUX) ++ data = uiomux_malloc (pool->uiomux, pool->uiores, ret->vbuffer.length, 32); ++ if (data == NULL) ++ goto malloc_failed; ++ ++ memset (data, 0, ret->vbuffer.length); ++ ret->vbuffer.m.userptr = (unsigned long) data; ++#else + data = (guint8 *) v4l2_mmap (0, ret->vbuffer.length, + PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd, + ret->vbuffer.m.offset); + + if (data == MAP_FAILED) + goto mmap_failed; ++#endif + + GST_BUFFER_DATA (ret) = data; + GST_BUFFER_SIZE (ret) = ret->vbuffer.length; +@@ -209,6 +227,17 @@ querybuf_failed: + errno = errnosave; + return NULL; + } ++#if defined(HAVE_UIOMUX) ++malloc_failed: ++ { ++ gint errnosave = errno; ++ ++ GST_WARNING ("Failed uiomux_malloc: %s", g_strerror (errnosave)); ++ gst_buffer_unref (GST_BUFFER (ret)); ++ errno = errnosave; ++ return NULL; ++ } ++#else + mmap_failed: + { + gint errnosave = errno; +@@ -218,6 +247,7 @@ mmap_failed: + errno = errnosave; + return NULL; + } ++#endif /* defined(HAVE_UIOMUX) */ + } + + +@@ -335,6 +365,9 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers, + GstV4l2BufferPool *pool; + gint n; + struct v4l2_requestbuffers breq; ++#if defined(HAVE_UIOMUX) ++ const char *blocks[2] = { "VIO", NULL }; ++#endif + + pool = (GstV4l2BufferPool *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER_POOL); + +@@ -342,6 +375,12 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers, + if (pool->video_fd < 0) + goto dup_failed; + ++#if defined(HAVE_UIOMUX) ++ pool->uiores = 1 << 0; ++ pool->uiomux = uiomux_open_named (blocks); ++ if (pool->uiomux == NULL) ++ goto uiomux_failed; ++#endif + + /* first, lets request buffers, and see how many we can get: */ + GST_DEBUG_OBJECT (v4l2elem, "STREAMING, requesting %d MMAP buffers", +@@ -350,7 +389,11 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers, + memset (&breq, 0, sizeof (struct v4l2_requestbuffers)); + breq.type = type; + breq.count = num_buffers; ++#if defined(HAVE_UIOMUX) ++ breq.memory = V4L2_MEMORY_USERPTR; ++#else + breq.memory = V4L2_MEMORY_MMAP; ++#endif + + if (v4l2_ioctl (fd, VIDIOC_REQBUFS, &breq) < 0) + goto reqbufs_failed; +@@ -396,6 +439,14 @@ dup_failed: + + return NULL; + } ++#if defined(HAVE_UIOMUX) ++uiomux_failed: ++ { ++ GST_ELEMENT_ERROR (v4l2elem, RESOURCE, READ, ++ (_("Failed uiomux_open")), (NULL)); ++ return NULL; ++ } ++#endif /* defined(HAVE_UIOMUX) */ + reqbufs_failed: + { + GstV4l2Object *v4l2object = get_v4l2_object (v4l2elem); +@@ -540,7 +591,11 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool) + + memset (&buffer, 0x00, sizeof (buffer)); + buffer.type = pool->type; ++#if defined(HAVE_UIOMUX) ++ buffer.memory = V4L2_MEMORY_USERPTR; ++#else + buffer.memory = V4L2_MEMORY_MMAP; ++#endif + + + if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) >= 0) { +diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h +index caad9ac..6fb3067 100644 +--- a/sys/v4l2/gstv4l2bufferpool.h ++++ b/sys/v4l2/gstv4l2bufferpool.h +@@ -27,6 +27,9 @@ + + #include <gst/gst.h> + #include "v4l2_calls.h" ++#if defined(HAVE_UIOMUX) ++#include "uiomux/uiomux.h" ++#endif + + GST_DEBUG_CATEGORY_EXTERN (v4l2buffer_debug); + +@@ -53,6 +56,11 @@ struct _GstV4l2BufferPool + { + GstMiniObject parent; + ++#if defined(HAVE_UIOMUX) ++ UIOMux *uiomux; /* uiomux handle */ ++ uiomux_resource_t uiores; /* uiomux resource flag */ ++#endif /* defined(HAVE_UIOMUX) */ ++ + GstElement *v4l2elem; /* the v4l2 src/sink that owns us.. maybe we should be owned by v4l2object? */ + gboolean requeuebuf; /* if true, unusued buffers are automatically re-QBUF'd */ + enum v4l2_buf_type type; /* V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT */ +diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c +index f8ae09c..d3f9a3c 100644 +--- a/sys/v4l2/gstv4l2src.c ++++ b/sys/v4l2/gstv4l2src.c +@@ -63,8 +63,13 @@ + GST_DEBUG_CATEGORY (v4l2src_debug); + #define GST_CAT_DEFAULT v4l2src_debug + ++#if defined(HAVE_UIOMUX) ++#define PROP_DEF_QUEUE_SIZE 4 ++#define PROP_DEF_ALWAYS_COPY FALSE ++#else + #define PROP_DEF_QUEUE_SIZE 2 + #define PROP_DEF_ALWAYS_COPY TRUE ++#endif + #define PROP_DEF_DECIMATE 1 + + #define DEFAULT_PROP_DEVICE "/dev/video0" +@@ -96,14 +101,14 @@ gst_v4l2src_iface_supported (GstImplementsInterface * iface, GType iface_type) + + #ifdef HAVE_XVIDEO + if (!(iface_type == GST_TYPE_TUNER || +- iface_type == GST_TYPE_X_OVERLAY || +- iface_type == GST_TYPE_COLOR_BALANCE || +- iface_type == GST_TYPE_VIDEO_ORIENTATION)) ++ iface_type == GST_TYPE_X_OVERLAY || ++ iface_type == GST_TYPE_COLOR_BALANCE || ++ iface_type == GST_TYPE_VIDEO_ORIENTATION)) + return FALSE; + #else + if (!(iface_type == GST_TYPE_TUNER || +- iface_type == GST_TYPE_COLOR_BALANCE || +- iface_type == GST_TYPE_VIDEO_ORIENTATION)) ++ iface_type == GST_TYPE_COLOR_BALANCE || ++ iface_type == GST_TYPE_VIDEO_ORIENTATION)) + return FALSE; + #endif + +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0004-sys-v4l2-gstv4l2-release-corresponding-uiomux-handle.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0004-sys-v4l2-gstv4l2-release-corresponding-uiomux-handle.patch new file mode 100644 index 0000000..c1b06b5 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0004-sys-v4l2-gstv4l2-release-corresponding-uiomux-handle.patch @@ -0,0 +1,31 @@ +From c856d711cc54856dac5410aac6bf35330e5f8394 Mon Sep 17 00:00:00 2001 +From: Katsuya Matsubara <matsu@igel.co.jp> +Date: Mon, 7 May 2012 10:11:38 +0900 +Subject: [PATCH 04/31] sys/v4l2/gstv4l2: release corresponding uiomux handle + whenever a buffer pool destroyed + +This change could avoid memory leaks and unnecessary file descriptor +consumption. +--- + sys/v4l2/gstv4l2bufferpool.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c +index a2800aa..90ce3b3 100644 +--- a/sys/v4l2/gstv4l2bufferpool.c ++++ b/sys/v4l2/gstv4l2bufferpool.c +@@ -513,6 +513,11 @@ gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool) + gst_buffer_unref (buf); + } + ++#if defined(HAVE_UIOMUX) ++ if (pool->uiomux) ++ uiomux_close (pool->uiomux); ++#endif ++ + gst_mini_object_unref (GST_MINI_OBJECT (pool)); + } + +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0005-videocrop-correct-coding-style-with-gst-indent.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0005-videocrop-correct-coding-style-with-gst-indent.patch new file mode 100644 index 0000000..d512ba6 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0005-videocrop-correct-coding-style-with-gst-indent.patch @@ -0,0 +1,104 @@ +From 1cce809f580828df792e35ae76a7a38685eec377 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Tue, 8 May 2012 17:04:13 +0900 +Subject: [PATCH 05/31] videocrop: correct coding style with gst-indent + +--- + gst/videocrop/gstvideocrop.c | 7 +++---- + gst/videocrop/gstvideocrop.h | 25 +++++++++++-------------- + 2 files changed, 14 insertions(+), 18 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 04b6e61..1f09f8d 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -147,8 +147,7 @@ gst_video_crop_base_init (gpointer g_class) + "Crops video into a user-defined region", + "Tim-Philipp Müller <tim centricular net>"); + +- gst_element_class_add_static_pad_template (element_class, +- &sink_template); ++ gst_element_class_add_static_pad_template (element_class, &sink_template); + gst_element_class_add_static_pad_template (element_class, &src_template); + } + +@@ -639,8 +638,8 @@ gst_video_crop_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GST_LOG_OBJECT (crop, "incaps = %" GST_PTR_FORMAT ", outcaps = %" + GST_PTR_FORMAT, incaps, outcaps); + +- if ((crop->crop_left | crop->crop_right | crop->crop_top | crop-> +- crop_bottom) == 0) { ++ if ((crop->crop_left | crop->crop_right | crop-> ++ crop_top | crop->crop_bottom) == 0) { + GST_LOG_OBJECT (crop, "we are using passthrough"); + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (crop), TRUE); + } else { +diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h +index 477f21b..f05649d 100644 +--- a/gst/videocrop/gstvideocrop.h ++++ b/gst/videocrop/gstvideocrop.h +@@ -23,7 +23,6 @@ + #include <gst/base/gstbasetransform.h> + + G_BEGIN_DECLS +- + #define GST_TYPE_VIDEO_CROP \ + (gst_video_crop_get_type()) + #define GST_VIDEO_CROP(obj) \ +@@ -34,27 +33,27 @@ G_BEGIN_DECLS + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_CROP)) + #define GST_IS_VIDEO_CROP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_CROP)) +- +-typedef enum { +- VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE = 0, /* RGBx, AYUV */ +- VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX, /* UYVY, YVYU */ +- VIDEO_CROP_PIXEL_FORMAT_PLANAR /* I420, YV12 */ ++ typedef enum ++{ ++ VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE = 0, /* RGBx, AYUV */ ++ VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX, /* UYVY, YVYU */ ++ VIDEO_CROP_PIXEL_FORMAT_PLANAR /* I420, YV12 */ + } VideoCropPixelFormat; + + typedef struct _GstVideoCropImageDetails GstVideoCropImageDetails; + struct _GstVideoCropImageDetails + { +- /*< private >*/ +- VideoCropPixelFormat packing; ++ /*< private > */ ++ VideoCropPixelFormat packing; + + guint width; + guint height; + guint size; + + /* for packed RGB and YUV */ +- guint stride; +- guint bytes_per_pixel; +- guint8 macro_y_off; /* for YUY2, YVYU, UYVY, Y offset within macropixel in bytes */ ++ guint stride; ++ guint bytes_per_pixel; ++ guint8 macro_y_off; /* for YUY2, YVYU, UYVY, Y offset within macropixel in bytes */ + + /* for planar YUV */ + guint y_stride, y_off; +@@ -69,7 +68,7 @@ struct _GstVideoCrop + { + GstBaseTransform basetransform; + +- /*< private >*/ ++ /*< private > */ + gint crop_left; + gint crop_right; + gint crop_top; +@@ -87,6 +86,4 @@ struct _GstVideoCropClass + GType gst_video_crop_get_type (void); + + G_END_DECLS +- + #endif /* __GST_VIDEO_CROP_H__ */ +- +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0006-videocrop-send-a-query-whether-the-rowstride-capabil.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0006-videocrop-send-a-query-whether-the-rowstride-capabil.patch new file mode 100644 index 0000000..7058544 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0006-videocrop-send-a-query-whether-the-rowstride-capabil.patch @@ -0,0 +1,105 @@ +From 39bb299bd638b78fdf8c4054bcc90f9f915d7ff8 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 10 May 2012 10:46:20 +0900 +Subject: [PATCH 06/31] videocrop: send a query whether the rowstride + capability is supported + +This patch sends a query which asks downstream plugins whether +can handle the rowstride capability. +gst_video_crop_start() can be invoked when the pad is enabled. +The query is issued by gst_video_crop_start() once at initialization. + +This patch is preliminary for the zero-copy cropping. +--- + gst/videocrop/gstvideocrop.c | 38 ++++++++++++++++++++++++++++++++++++++ + gst/videocrop/gstvideocrop.h | 4 ++++ + 2 files changed, 42 insertions(+) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 1f09f8d..b0c3a68 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -136,6 +136,7 @@ static gboolean gst_video_crop_set_caps (GstBaseTransform * trans, + GstCaps * in_caps, GstCaps * outcaps); + static gboolean gst_video_crop_src_event (GstBaseTransform * trans, + GstEvent * event); ++static gboolean gst_video_crop_start (GstBaseTransform * trans); + + static void + gst_video_crop_base_init (gpointer g_class) +@@ -228,6 +229,7 @@ gst_video_crop_class_init (GstVideoCropClass * klass) + basetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_crop_set_caps); + basetransform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size); ++ basetransform_class->start = GST_DEBUG_FUNCPTR (gst_video_crop_start); + + basetransform_class->passthrough_on_same_caps = FALSE; + basetransform_class->src_event = GST_DEBUG_FUNCPTR (gst_video_crop_src_event); +@@ -240,6 +242,10 @@ gst_video_crop_init (GstVideoCrop * vcrop, GstVideoCropClass * klass) + vcrop->crop_left = 0; + vcrop->crop_top = 0; + vcrop->crop_bottom = 0; ++ ++ /* register query type for rowstride */ ++ vcrop->query_type_stride = gst_query_type_register ("stride-supported", ++ "whether dealing with rowstride as a capability or not"); + } + + static gboolean +@@ -669,6 +675,38 @@ cropping_too_much: + } + } + ++static gboolean ++gst_video_crop_query_stride_supported (GstVideoCrop * vcrop) ++{ ++ gboolean result = FALSE; ++ GstPad *peer = gst_pad_get_peer (GST_BASE_TRANSFORM (vcrop)->srcpad); ++ GstStructure *structure; ++ GstQuery *query; ++ ++ structure = gst_structure_empty_new ("GstQueryStrideSupported"); ++ gst_structure_set (structure, "stride-supported", G_TYPE_BOOLEAN, FALSE, ++ NULL); ++ ++ query = gst_query_new_application (vcrop->query_type_stride, structure); ++ if (gst_pad_query (peer, query)) ++ gst_structure_get_boolean (structure, "stride-supported", &result); ++ ++ gst_query_unref (query); ++ gst_object_unref (peer); ++ ++ return result; ++} ++ ++static gboolean ++gst_video_crop_start (GstBaseTransform * trans) ++{ ++ GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); ++ ++ vcrop->stride_supported = gst_video_crop_query_stride_supported (vcrop); ++ ++ return TRUE; ++} ++ + static void + gst_video_crop_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h +index f05649d..5cfe03e 100644 +--- a/gst/videocrop/gstvideocrop.h ++++ b/gst/videocrop/gstvideocrop.h +@@ -76,6 +76,10 @@ struct _GstVideoCrop + + GstVideoCropImageDetails in; /* details of input image */ + GstVideoCropImageDetails out; /* details of output image */ ++ ++ /* query for rowstride */ ++ GstQueryType query_type_stride; ++ gboolean stride_supported; + }; + + struct _GstVideoCropClass +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0007-videocrop-set-rowstride-capability.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0007-videocrop-set-rowstride-capability.patch new file mode 100644 index 0000000..1eef8de --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0007-videocrop-set-rowstride-capability.patch @@ -0,0 +1,59 @@ +From 0d5b9694fc670d489d02018d1e2d83394f299ad5 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 10 May 2012 11:20:18 +0900 +Subject: [PATCH 07/31] videocrop: set rowstride capability + +This patch sets the rowstride capability if downstream plugins +can handle it. + +This patch is preliminary for the zero-copy cropping. +--- + gst/videocrop/gstvideocrop.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index b0c3a68..ae7ddaf 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -585,22 +585,22 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + other_caps = gst_caps_new_empty (); + + for (i = 0; i < gst_caps_get_size (caps); ++i) { +- const GValue *v; ++ const GValue *in_width, *in_height; + GstStructure *structure, *new_structure; + GValue w_val = { 0, }, h_val = { + 0,}; + + structure = gst_caps_get_structure (caps, i); + +- v = gst_structure_get_value (structure, "width"); +- if (!gst_video_crop_transform_dimension_value (v, dx, &w_val)) { ++ in_width = gst_structure_get_value (structure, "width"); ++ if (!gst_video_crop_transform_dimension_value (in_width, dx, &w_val)) { + GST_WARNING_OBJECT (vcrop, "could not tranform width value with dx=%d" + ", caps structure=%" GST_PTR_FORMAT, dx, structure); + continue; + } + +- v = gst_structure_get_value (structure, "height"); +- if (!gst_video_crop_transform_dimension_value (v, dy, &h_val)) { ++ in_height = gst_structure_get_value (structure, "height"); ++ if (!gst_video_crop_transform_dimension_value (in_height, dy, &h_val)) { + g_value_unset (&w_val); + GST_WARNING_OBJECT (vcrop, "could not tranform height value with dy=%d" + ", caps structure=%" GST_PTR_FORMAT, dy, structure); +@@ -610,6 +610,10 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + new_structure = gst_structure_copy (structure); + gst_structure_set_value (new_structure, "width", &w_val); + gst_structure_set_value (new_structure, "height", &h_val); ++ ++ /* set rowstride when creating output caps */ ++ if (vcrop->stride_supported && (direction == GST_PAD_SINK)) ++ gst_structure_set_value (new_structure, "rowstride", in_width); + g_value_unset (&w_val); + g_value_unset (&h_val); + GST_LOG_OBJECT (vcrop, "transformed structure %2d: %" GST_PTR_FORMAT +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0008-videocrop-kick-off-the-zero-copy-cropping.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0008-videocrop-kick-off-the-zero-copy-cropping.patch new file mode 100644 index 0000000..1e4734e --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0008-videocrop-kick-off-the-zero-copy-cropping.patch @@ -0,0 +1,100 @@ +From 78f532d7cc31fc7e2980998af97b1260c45ec5e5 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 10 May 2012 14:55:22 +0900 +Subject: [PATCH 08/31] videocrop: kick off the zero-copy cropping + +This patch enables zero-copy buffer cropping by creating a subbuffer +from an input buffer. + +Instead of creating a new buffer, the subbuffer is specified as an +offset into the input buffer along with an appropriate buffer size. + +The cropping functionality of gst_video_crop_transform() (which uses memory +copying) is bypassed when a subbuffer is defined. +--- + gst/videocrop/gstvideocrop.c | 48 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index ae7ddaf..cfd548e 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -137,6 +137,8 @@ static gboolean gst_video_crop_set_caps (GstBaseTransform * trans, + static gboolean gst_video_crop_src_event (GstBaseTransform * trans, + GstEvent * event); + static gboolean gst_video_crop_start (GstBaseTransform * trans); ++static GstFlowReturn gst_video_crop_prepare_output_buffer (GstBaseTransform * ++ trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf); + + static void + gst_video_crop_base_init (gpointer g_class) +@@ -230,6 +232,8 @@ gst_video_crop_class_init (GstVideoCropClass * klass) + basetransform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size); + basetransform_class->start = GST_DEBUG_FUNCPTR (gst_video_crop_start); ++ basetransform_class->prepare_output_buffer = ++ GST_DEBUG_FUNCPTR (gst_video_crop_prepare_output_buffer); + + basetransform_class->passthrough_on_same_caps = FALSE; + basetransform_class->src_event = GST_DEBUG_FUNCPTR (gst_video_crop_src_event); +@@ -484,6 +488,13 @@ gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf, + { + GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); + ++ if (vcrop->stride_supported && ++ ((vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) || ++ (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX))) { ++ GST_LOG_OBJECT (vcrop, "passthrough because of zero-copy cropping"); ++ return GST_FLOW_OK; ++ } ++ + switch (vcrop->in.packing) { + case VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE: + gst_video_crop_transform_packed_simple (vcrop, inbuf, outbuf); +@@ -711,6 +722,43 @@ gst_video_crop_start (GstBaseTransform * trans) + return TRUE; + } + ++static GstFlowReturn ++gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, ++ GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) ++{ ++ GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); ++ guint sub_offset, sub_size; ++ ++ if (!vcrop->stride_supported) { ++ GST_LOG_OBJECT ++ (vcrop, ++ "creating subbuffer isn't needed because downstream plugins don't support rowstride"); ++ return GST_FLOW_OK; ++ } ++ ++ if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) { ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ (vcrop->crop_left * vcrop->in.bytes_per_pixel); ++ } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) { ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel); ++ } else { ++ GST_LOG_OBJECT (vcrop, ++ "can't do zero-copy cropping except for packed format"); ++ return GST_FLOW_OK; ++ } ++ ++ sub_size = vcrop->out.height * vcrop->out.stride; ++ *buf = gst_buffer_create_sub (input, sub_offset, sub_size); ++ if (*buf == NULL) { ++ GST_ERROR_OBJECT (vcrop, "failed to create subbuffer"); ++ return GST_FLOW_ERROR; ++ } ++ gst_buffer_set_caps (*buf, caps); ++ ++ return GST_FLOW_OK; ++} ++ + static void + gst_video_crop_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0009-avidemux-set-frame-start-code-to-VC-1-advanced-profi.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0009-avidemux-set-frame-start-code-to-VC-1-advanced-profi.patch new file mode 100644 index 0000000..180fac3 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0009-avidemux-set-frame-start-code-to-VC-1-advanced-profi.patch @@ -0,0 +1,90 @@ +From a3dc6aa0c57e1fa00efdf0e68d3a4b8645519b9d Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Wed, 18 Jul 2012 19:30:34 +0900 +Subject: [PATCH 09/31] avidemux: set frame start code to VC-1 advanced + profile stream + +VC-1 advanced profile constrains the bitstream format to pair +the frame data with the frame start code. +This patch pulls frame data from previous plugin with extra field +for containing a start code and inserts the start code before the +frame data if the stream doesn't has the start code. +--- + gst/avi/gstavidemux.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 48 insertions(+), 3 deletions(-) + +diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c +index b6c065f..385aa30 100644 +--- a/gst/avi/gstavidemux.c ++++ b/gst/avi/gstavidemux.c +@@ -4689,6 +4689,10 @@ gst_avi_demux_loop_data (GstAviDemux * avi) + guint64 out_offset, out_offset_end; + gboolean keyframe; + GstAviIndexEntry *entry; ++ guint8 *data; ++ GstStructure *structure; ++ guint32 fourcc; ++ gboolean need_st_code; + + do { + stream_num = gst_avi_demux_find_next (avi, avi->segment.rate); +@@ -4740,12 +4744,53 @@ gst_avi_demux_loop_data (GstAviDemux * avi) + G_GUINT64_FORMAT " (0x%" G_GINT64_MODIFIER "x), kf %d", size, + stream_num, offset, offset, keyframe); + ++ structure = gst_caps_get_structure (GST_PAD_CAPS (stream->pad), 0); ++ if (gst_structure_get_fourcc (structure, "format", &fourcc)) { ++ /* set start code for VC-1 advanced profile if fourcc is 'WVC1' */ ++ if (fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1')) ++ need_st_code = TRUE; ++ else ++ need_st_code = FALSE; ++ } else ++ need_st_code = FALSE; ++ + /* FIXME, check large chunks and cut them up */ + + /* pull in the data */ +- ret = gst_pad_pull_range (avi->sinkpad, offset, size, &buf); +- if (ret != GST_FLOW_OK) +- goto pull_failed; ++ if (need_st_code) { ++ if (offset < 4) ++ /* This branch isn't passed through because offset is definitely ++ more than 4 owing to container's header presented before ++ frame data. */ ++ goto pull_failed; ++ ++ ret = gst_pad_pull_range (avi->sinkpad, offset - 4, size + 4, &buf); ++ if (ret != GST_FLOW_OK) ++ goto pull_failed; ++ ++ data = GST_BUFFER_DATA (buf); ++ /* check if this stream has a start code */ ++ if (data[4] == 0x00 && data[5] == 0x00 && data[6] == 0x01 && ++ data[7] == 0x0d) { ++ GstBuffer *sub_buf; ++ ++ sub_buf = gst_buffer_create_sub (buf, 4, size); ++ if (sub_buf == NULL) ++ goto pull_failed; ++ ++ gst_buffer_unref (buf); ++ buf = sub_buf; ++ } else { ++ data[0] = 0x00; ++ data[1] = 0x00; ++ data[2] = 0x01; ++ data[3] = 0x0d; ++ } ++ } else { ++ ret = gst_pad_pull_range (avi->sinkpad, offset, size, &buf); ++ if (ret != GST_FLOW_OK) ++ goto pull_failed; ++ } + + /* check for short buffers, this is EOS as well */ + if (GST_BUFFER_SIZE (buf) < size) +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0010-videocrop-add-gst_video_crop_get_image_details_from_.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0010-videocrop-add-gst_video_crop_get_image_details_from_.patch new file mode 100644 index 0000000..5d64ac8 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0010-videocrop-add-gst_video_crop_get_image_details_from_.patch @@ -0,0 +1,55 @@ +From 9f24d6c70d56c454a06b6fe41116d046dcc3c9f6 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Tue, 25 Sep 2012 15:51:24 +0900 +Subject: [PATCH 10/31] videocrop: add + gst_video_crop_get_image_details_from_structure + function + +Add an function to allow retrieval of image details from structures instead of +only from caps. +--- + gst/videocrop/gstvideocrop.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index cfd548e..80c6d3d 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -253,13 +253,11 @@ gst_video_crop_init (GstVideoCrop * vcrop, GstVideoCropClass * klass) + } + + static gboolean +-gst_video_crop_get_image_details_from_caps (GstVideoCrop * vcrop, +- GstVideoCropImageDetails * details, GstCaps * caps) ++gst_video_crop_get_image_details_from_structure (GstVideoCrop * vcrop, ++ GstVideoCropImageDetails * details, GstStructure * structure) + { +- GstStructure *structure; + gint width, height; + +- structure = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int (structure, "width", &width) || + !gst_structure_get_int (structure, "height", &height)) { + goto incomplete_format; +@@ -356,6 +354,18 @@ incomplete_format: + } + + static gboolean ++gst_video_crop_get_image_details_from_caps (GstVideoCrop * vcrop, ++ GstVideoCropImageDetails * details, GstCaps * caps) ++{ ++ GstStructure *structure; ++ ++ structure = gst_caps_get_structure (caps, 0); ++ ++ return gst_video_crop_get_image_details_from_structure (vcrop, details, ++ structure); ++} ++ ++static gboolean + gst_video_crop_get_unit_size (GstBaseTransform * trans, GstCaps * caps, + guint * size) + { +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0011-videocrop-change-the-unit-of-rowstride-to-byte.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0011-videocrop-change-the-unit-of-rowstride-to-byte.patch new file mode 100644 index 0000000..89c2025 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0011-videocrop-change-the-unit-of-rowstride-to-byte.patch @@ -0,0 +1,36 @@ +From 88b1d76187a840987ef548bd9c3023ebfd97ea5a Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Wed, 26 Sep 2012 10:34:31 +0900 +Subject: [PATCH 11/31] videocrop: change the unit of rowstride to byte + +Set rowstride units to bytes in order to align with other plugins. +--- + gst/videocrop/gstvideocrop.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 80c6d3d..6af348a 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -633,8 +633,16 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + gst_structure_set_value (new_structure, "height", &h_val); + + /* set rowstride when creating output caps */ +- if (vcrop->stride_supported && (direction == GST_PAD_SINK)) +- gst_structure_set_value (new_structure, "rowstride", in_width); ++ if (vcrop->stride_supported && (direction == GST_PAD_SINK)) { ++ GstVideoCropImageDetails img_details = { 0, }; ++ GValue stride = { 0, }; ++ ++ gst_video_crop_get_image_details_from_structure (vcrop, &img_details, ++ structure); ++ g_value_init (&stride, G_TYPE_INT); ++ g_value_set_int (&stride, (gint) img_details.stride); ++ gst_structure_set_value (new_structure, "rowstride", &stride); ++ } + g_value_unset (&w_val); + g_value_unset (&h_val); + GST_LOG_OBJECT (vcrop, "transformed structure %2d: %" GST_PTR_FORMAT +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0012-videocrop-add-tests-to-determine-if-width-and-height.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0012-videocrop-add-tests-to-determine-if-width-and-height.patch new file mode 100644 index 0000000..5712fdf --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0012-videocrop-add-tests-to-determine-if-width-and-height.patch @@ -0,0 +1,39 @@ +From 93c3d86c39fceb5a9dd6b390627da5090ee171dd Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 10:33:03 +0900 +Subject: [PATCH 12/31] videocrop: add tests to determine if width and height + caps hold range value before getting image details + +This check is necessary because gst_video_crop_get_image_details_from_structure() +can't be performed when caps contain range value. +--- + gst/videocrop/gstvideocrop.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 6af348a..059b11a 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -637,11 +637,14 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + GstVideoCropImageDetails img_details = { 0, }; + GValue stride = { 0, }; + +- gst_video_crop_get_image_details_from_structure (vcrop, &img_details, +- structure); +- g_value_init (&stride, G_TYPE_INT); +- g_value_set_int (&stride, (gint) img_details.stride); +- gst_structure_set_value (new_structure, "rowstride", &stride); ++ if (!GST_VALUE_HOLDS_INT_RANGE (&w_val) && ++ !GST_VALUE_HOLDS_INT_RANGE (&h_val) && ++ gst_video_crop_get_image_details_from_structure (vcrop, &img_details, ++ structure)) { ++ g_value_init (&stride, G_TYPE_INT); ++ g_value_set_int (&stride, (gint) img_details.stride); ++ gst_structure_set_value (new_structure, "rowstride", &stride); ++ } + } + g_value_unset (&w_val); + g_value_unset (&h_val); +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0013-videocrop-replace-the-processing-to-set-gint-value-t.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0013-videocrop-replace-the-processing-to-set-gint-value-t.patch new file mode 100644 index 0000000..bb0121b --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0013-videocrop-replace-the-processing-to-set-gint-value-t.patch @@ -0,0 +1,35 @@ +From 5cb7845d61eadad90c1a0a2bc5078ec4c4b3dc98 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 10:57:10 +0900 +Subject: [PATCH 13/31] videocrop: replace the processing to set gint value to + structure with gst_structure_set + +--- + gst/videocrop/gstvideocrop.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 059b11a..9c5df28 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -635,15 +635,13 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + /* set rowstride when creating output caps */ + if (vcrop->stride_supported && (direction == GST_PAD_SINK)) { + GstVideoCropImageDetails img_details = { 0, }; +- GValue stride = { 0, }; + + if (!GST_VALUE_HOLDS_INT_RANGE (&w_val) && + !GST_VALUE_HOLDS_INT_RANGE (&h_val) && + gst_video_crop_get_image_details_from_structure (vcrop, &img_details, + structure)) { +- g_value_init (&stride, G_TYPE_INT); +- g_value_set_int (&stride, (gint) img_details.stride); +- gst_structure_set_value (new_structure, "rowstride", &stride); ++ gst_structure_set (new_structure, "rowstride", G_TYPE_INT, ++ (gint) img_details.stride, NULL); + } + } + g_value_unset (&w_val); +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0014-videocrop-don-t-set-rowstride-only-when-the-color-sp.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0014-videocrop-don-t-set-rowstride-only-when-the-color-sp.patch new file mode 100644 index 0000000..3ae31e1 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0014-videocrop-don-t-set-rowstride-only-when-the-color-sp.patch @@ -0,0 +1,66 @@ +From 61154856964b78b3c601e687d6f081e666f94958 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 11:08:56 +0900 +Subject: [PATCH 14/31] videocrop: don't set rowstride only when the color + space is the planar + +videocrop wouldn't support zero-copy cropping in the planar format. +Therefore, rowstride shouldn't set only when the color space is the planar. +--- + gst/videocrop/gstvideocrop.c | 30 ++++++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 8 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 9c5df28..f2d2949 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -610,6 +610,8 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + GstStructure *structure, *new_structure; + GValue w_val = { 0, }, h_val = { + 0,}; ++ GstVideoCropImageDetails img_details = { 0, }; ++ guint rowstride; + + structure = gst_caps_get_structure (caps, i); + +@@ -633,17 +635,29 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + gst_structure_set_value (new_structure, "height", &h_val); + + /* set rowstride when creating output caps */ +- if (vcrop->stride_supported && (direction == GST_PAD_SINK)) { +- GstVideoCropImageDetails img_details = { 0, }; +- +- if (!GST_VALUE_HOLDS_INT_RANGE (&w_val) && +- !GST_VALUE_HOLDS_INT_RANGE (&h_val) && +- gst_video_crop_get_image_details_from_structure (vcrop, &img_details, ++ if (!GST_VALUE_HOLDS_INT_RANGE (&w_val) && ++ !GST_VALUE_HOLDS_INT_RANGE (&h_val)) { ++ if (!gst_video_crop_get_image_details_from_structure (vcrop, &img_details, + structure)) { +- gst_structure_set (new_structure, "rowstride", G_TYPE_INT, +- (gint) img_details.stride, NULL); ++ GST_ERROR_OBJECT (vcrop, "couldn't get image details from structure"); ++ goto add_structure; + } ++ } else { ++ GST_LOG_OBJECT (vcrop, "go through setting rowstride"); ++ goto add_structure; + } ++ ++ if (img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE || ++ img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) ++ rowstride = img_details.stride; ++ else ++ rowstride = 0; ++ ++ if (vcrop->stride_supported && (direction == GST_PAD_SINK) && rowstride) ++ gst_structure_set (new_structure, "rowstride", G_TYPE_INT, ++ (gint) rowstride, NULL); ++ ++ add_structure: + g_value_unset (&w_val); + g_value_unset (&h_val); + GST_LOG_OBJECT (vcrop, "transformed structure %2d: %" GST_PTR_FORMAT +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0015-videocrop-fix-wrong-subbuffer-size.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0015-videocrop-fix-wrong-subbuffer-size.patch new file mode 100644 index 0000000..0682416 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0015-videocrop-fix-wrong-subbuffer-size.patch @@ -0,0 +1,27 @@ +From 2b7594421cbde82ee1e67e625514321f9517ea76 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 12:02:54 +0900 +Subject: [PATCH 15/31] videocrop: fix wrong subbuffer size + +It wasn't just subbuffer size but in a unit of stride. +This patch corrects it. +--- + gst/videocrop/gstvideocrop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index f2d2949..0743719 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -781,7 +781,7 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + return GST_FLOW_OK; + } + +- sub_size = vcrop->out.height * vcrop->out.stride; ++ sub_size = vcrop->in.size - sub_offset; + *buf = gst_buffer_create_sub (input, sub_offset, sub_size); + if (*buf == NULL) { + GST_ERROR_OBJECT (vcrop, "failed to create subbuffer"); +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0016-videocrop-support-getting-NV12-image-details.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0016-videocrop-support-getting-NV12-image-details.patch new file mode 100644 index 0000000..e5a1bed --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0016-videocrop-support-getting-NV12-image-details.patch @@ -0,0 +1,84 @@ +From 47cf0121df5c54d665ccbf9a721cddf547fbbce3 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 11:29:44 +0900 +Subject: [PATCH 16/31] videocrop: support getting NV12 image details + +This patch adds a new pixel format definition that is NV12 format. +The color format type of NV12 is classified into VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR. +When rowstride or chroma_byte_offset is contained in caps, image +details reflects these value. + +This is preliminary for NV12 zero-copy cropping. +--- + gst/videocrop/gstvideocrop.c | 21 +++++++++++++++++++++ + gst/videocrop/gstvideocrop.h | 8 ++++++-- + 2 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 0743719..b6336da 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -328,6 +328,27 @@ gst_video_crop_get_image_details_from_structure (GstVideoCrop * vcrop, + details->v_stride * (GST_ROUND_UP_2 (height) / 2); + break; + } ++ case GST_MAKE_FOURCC ('N', 'V', '1', '2'): ++ { ++ gint stride, chroma_byte_offset; ++ ++ details->packing = VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR; ++ ++ if (gst_structure_get_int (structure, "rowstride", &stride)) ++ details->stride = stride; ++ else ++ details->stride = GST_ROUND_UP_2 (width); ++ ++ details->y_off = 0; ++ if (gst_structure_get_int (structure, "chroma_byte_offset", ++ &chroma_byte_offset)) ++ details->uv_off = chroma_byte_offset; ++ else ++ details->uv_off = details->stride * GST_ROUND_UP_2 (height); ++ ++ details->size = details->uv_off * 3 / 2; ++ } ++ break; + default: + goto unknown_format; + } +diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h +index 5cfe03e..2e5d5e6 100644 +--- a/gst/videocrop/gstvideocrop.h ++++ b/gst/videocrop/gstvideocrop.h +@@ -37,7 +37,8 @@ G_BEGIN_DECLS + { + VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE = 0, /* RGBx, AYUV */ + VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX, /* UYVY, YVYU */ +- VIDEO_CROP_PIXEL_FORMAT_PLANAR /* I420, YV12 */ ++ VIDEO_CROP_PIXEL_FORMAT_PLANAR, /* I420, YV12 */ ++ VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR /* NV12 */ + } VideoCropPixelFormat; + + typedef struct _GstVideoCropImageDetails GstVideoCropImageDetails; +@@ -51,7 +52,7 @@ struct _GstVideoCropImageDetails + guint size; + + /* for packed RGB and YUV */ +- guint stride; ++ guint stride; /* common use in semi-planar */ + guint bytes_per_pixel; + guint8 macro_y_off; /* for YUY2, YVYU, UYVY, Y offset within macropixel in bytes */ + +@@ -59,6 +60,9 @@ struct _GstVideoCropImageDetails + guint y_stride, y_off; + guint u_stride, u_off; + guint v_stride, v_off; ++ ++ /* for semi-planar YUV */ ++ guint uv_off; + }; + + typedef struct _GstVideoCrop GstVideoCrop; +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0017-videocrop-add-NV12-format-caps-template.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0017-videocrop-add-NV12-format-caps-template.patch new file mode 100644 index 0000000..11bf99e --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0017-videocrop-add-NV12-format-caps-template.patch @@ -0,0 +1,25 @@ +From d2d5af3b3912ff588c613803f366984eca82c53f Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 12:11:38 +0900 +Subject: [PATCH 17/31] videocrop: add NV12 format caps template + +This is preliminary for NV12 zero-copy cropping. +--- + gst/videocrop/gstvideocrop.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index b6336da..df02302 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -102,6 +102,7 @@ enum + GST_VIDEO_CAPS_YUV ("Y800") ";" \ + GST_VIDEO_CAPS_YUV ("I420") ";" \ + GST_VIDEO_CAPS_YUV ("YV12") ";" \ ++ GST_VIDEO_CAPS_YUV ("NV12") ";" \ + GST_VIDEO_CAPS_RGB_16 ";" \ + GST_VIDEO_CAPS_RGB_15 ";" \ + GST_VIDEO_CAPS_GRAY +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0018-videocrop-kick-off-NV12-zero-copy-cropping.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0018-videocrop-kick-off-NV12-zero-copy-cropping.patch new file mode 100644 index 0000000..4e391db --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0018-videocrop-kick-off-NV12-zero-copy-cropping.patch @@ -0,0 +1,105 @@ +From 795110fd2b53f1197e94c61078153b3433a1d296 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 13:45:06 +0900 +Subject: [PATCH 18/31] videocrop: kick off NV12 zero-copy cropping + +This patch allows videocrop plugin to do zero-copy cropping by +adjusting the buffer offsets that are rowstride and chroma_byte_offset. +First of all, the function of cropping with memcpy is passed through +when the semi planar is set. Then, chroma_byte_offset is adjusted +to compensate for the extra offset due to creating the subbuffer, +which is caused by offsetting the buffer address based on Y plane. +--- + gst/videocrop/gstvideocrop.c | 37 ++++++++++++++++++++++++++++++++----- + 1 file changed, 32 insertions(+), 5 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index df02302..6b1da8a 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -522,7 +522,8 @@ gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf, + + if (vcrop->stride_supported && + ((vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) || +- (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX))) { ++ (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) || ++ (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR))) { + GST_LOG_OBJECT (vcrop, "passthrough because of zero-copy cropping"); + return GST_FLOW_OK; + } +@@ -634,6 +635,7 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + 0,}; + GstVideoCropImageDetails img_details = { 0, }; + guint rowstride; ++ gint chroma_byte_offset, delta_chroma_offs; + + structure = gst_caps_get_structure (caps, i); + +@@ -656,7 +658,7 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + gst_structure_set_value (new_structure, "width", &w_val); + gst_structure_set_value (new_structure, "height", &h_val); + +- /* set rowstride when creating output caps */ ++ /* set rowstride and adjust chroma_byte_offset when creating output caps */ + if (!GST_VALUE_HOLDS_INT_RANGE (&w_val) && + !GST_VALUE_HOLDS_INT_RANGE (&h_val)) { + if (!gst_video_crop_get_image_details_from_structure (vcrop, &img_details, +@@ -665,20 +667,42 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + goto add_structure; + } + } else { +- GST_LOG_OBJECT (vcrop, "go through setting rowstride"); ++ GST_LOG_OBJECT (vcrop, ++ "go through setting rowstride and adjusting chroma_byte_offset"); + goto add_structure; + } + + if (img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE || +- img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) ++ img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) { + rowstride = img_details.stride; +- else ++ delta_chroma_offs = 0; ++ } else if (img_details.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { ++ guint ratio_y_c; ++ ++ rowstride = img_details.stride; ++ /* Y plane / UV plane */ ++ ratio_y_c = img_details.uv_off / (img_details.size - img_details.uv_off); ++ delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c; ++ } else { + rowstride = 0; ++ delta_chroma_offs = 0; ++ } + + if (vcrop->stride_supported && (direction == GST_PAD_SINK) && rowstride) + gst_structure_set (new_structure, "rowstride", G_TYPE_INT, + (gint) rowstride, NULL); + ++ if (vcrop->stride_supported && ++ gst_structure_get_int (structure, "chroma_byte_offset", ++ &chroma_byte_offset) && delta_chroma_offs) { ++ /* Adjust chroma_byte_offset because it would exceed the proper value ++ by delta_chroma_offs. It is due to offsetting the buffer address that ++ indicates Y plane with subbuffer for zero-copy cropping. */ ++ chroma_byte_offset -= delta_chroma_offs; ++ gst_structure_set (new_structure, "chroma_byte_offset", G_TYPE_INT, ++ chroma_byte_offset, NULL); ++ } ++ + add_structure: + g_value_unset (&w_val); + g_value_unset (&h_val); +@@ -797,6 +821,9 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) { + sub_offset = (vcrop->crop_top * vcrop->in.stride) + + (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel); ++ } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ ROUND_DOWN_2 (vcrop->crop_left); + } else { + GST_LOG_OBJECT (vcrop, + "can't do zero-copy cropping except for packed format"); +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0019-videocrop-send-a-query-by-the-first-invorker-of-quer.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0019-videocrop-send-a-query-by-the-first-invorker-of-quer.patch new file mode 100644 index 0000000..217ebd0 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0019-videocrop-send-a-query-by-the-first-invorker-of-quer.patch @@ -0,0 +1,123 @@ +From 554ffc759f9a87c4eac81fab91a2ac29e296c33c Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 4 Oct 2012 17:22:01 +0900 +Subject: [PATCH 19/31] videocrop: send a query by the first invorker of + query_stride_supported + +The query_stride_supported() might be failed because start() method +can be called before the pipeline is constructed. To resolve this issue, +this patch has the first invoker of query_stride_supported() send +the query to downstream plugins. The result of query is cached +at the first invoking. +--- + gst/videocrop/gstvideocrop.c | 30 +++++++++++++----------------- + gst/videocrop/gstvideocrop.h | 1 - + 2 files changed, 13 insertions(+), 18 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 6b1da8a..da30c1b 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -137,9 +137,9 @@ static gboolean gst_video_crop_set_caps (GstBaseTransform * trans, + GstCaps * in_caps, GstCaps * outcaps); + static gboolean gst_video_crop_src_event (GstBaseTransform * trans, + GstEvent * event); +-static gboolean gst_video_crop_start (GstBaseTransform * trans); + static GstFlowReturn gst_video_crop_prepare_output_buffer (GstBaseTransform * + trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf); ++static gboolean gst_video_crop_query_stride_supported (GstVideoCrop * vcrop); + + static void + gst_video_crop_base_init (gpointer g_class) +@@ -232,7 +232,6 @@ gst_video_crop_class_init (GstVideoCropClass * klass) + basetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_crop_set_caps); + basetransform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size); +- basetransform_class->start = GST_DEBUG_FUNCPTR (gst_video_crop_start); + basetransform_class->prepare_output_buffer = + GST_DEBUG_FUNCPTR (gst_video_crop_prepare_output_buffer); + +@@ -520,7 +519,7 @@ gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf, + { + GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); + +- if (vcrop->stride_supported && ++ if (gst_video_crop_query_stride_supported (vcrop) && + ((vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) || + (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) || + (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR))) { +@@ -688,11 +687,12 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + delta_chroma_offs = 0; + } + +- if (vcrop->stride_supported && (direction == GST_PAD_SINK) && rowstride) ++ if (gst_video_crop_query_stride_supported (vcrop) && ++ (direction == GST_PAD_SINK) && rowstride) + gst_structure_set (new_structure, "rowstride", G_TYPE_INT, + (gint) rowstride, NULL); + +- if (vcrop->stride_supported && ++ if (gst_video_crop_query_stride_supported (vcrop) && + gst_structure_get_int (structure, "chroma_byte_offset", + &chroma_byte_offset) && delta_chroma_offs) { + /* Adjust chroma_byte_offset because it would exceed the proper value +@@ -772,10 +772,14 @@ cropping_too_much: + static gboolean + gst_video_crop_query_stride_supported (GstVideoCrop * vcrop) + { +- gboolean result = FALSE; ++ static gboolean result = FALSE; + GstPad *peer = gst_pad_get_peer (GST_BASE_TRANSFORM (vcrop)->srcpad); + GstStructure *structure; + GstQuery *query; ++ static gboolean is_query_done = FALSE; ++ ++ if (is_query_done) ++ return result; + + structure = gst_structure_empty_new ("GstQueryStrideSupported"); + gst_structure_set (structure, "stride-supported", G_TYPE_BOOLEAN, FALSE, +@@ -788,17 +792,9 @@ gst_video_crop_query_stride_supported (GstVideoCrop * vcrop) + gst_query_unref (query); + gst_object_unref (peer); + +- return result; +-} +- +-static gboolean +-gst_video_crop_start (GstBaseTransform * trans) +-{ +- GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); +- +- vcrop->stride_supported = gst_video_crop_query_stride_supported (vcrop); ++ is_query_done = TRUE; + +- return TRUE; ++ return result; + } + + static GstFlowReturn +@@ -808,7 +804,7 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); + guint sub_offset, sub_size; + +- if (!vcrop->stride_supported) { ++ if (!gst_video_crop_query_stride_supported (vcrop)) { + GST_LOG_OBJECT + (vcrop, + "creating subbuffer isn't needed because downstream plugins don't support rowstride"); +diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h +index 2e5d5e6..1534b3d 100644 +--- a/gst/videocrop/gstvideocrop.h ++++ b/gst/videocrop/gstvideocrop.h +@@ -83,7 +83,6 @@ struct _GstVideoCrop + + /* query for rowstride */ + GstQueryType query_type_stride; +- gboolean stride_supported; + }; + + struct _GstVideoCropClass +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0020-videocrop-set-tile-boundary-offset-in-caps-for-T-L-a.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0020-videocrop-set-tile-boundary-offset-in-caps-for-T-L-a.patch new file mode 100644 index 0000000..1970394 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0020-videocrop-set-tile-boundary-offset-in-caps-for-T-L-a.patch @@ -0,0 +1,44 @@ +From efde8be8052d31a13629160c55f59e3be661a48c Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Fri, 12 Oct 2012 18:33:29 +0900 +Subject: [PATCH 20/31] videocrop: set tile boundary offset in caps for T/L + addressing + +This change is necessary for cropping the image data that is stored +as tiles in memory. Thease capabilities notify downstream plugins of +the offset to the previous tile boundary. +--- + gst/videocrop/gstvideocrop.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index da30c1b..dbebcfa 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -677,11 +677,23 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + delta_chroma_offs = 0; + } else if (img_details.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { + guint ratio_y_c; ++ GstStructure *structure; ++ gint tile_height; + + rowstride = img_details.stride; + /* Y plane / UV plane */ + ratio_y_c = img_details.uv_off / (img_details.size - img_details.uv_off); + delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c; ++ ++ /* set tile boudary for T/L addressing */ ++ structure = gst_caps_get_structure (caps, 0); ++ if (gst_structure_get_int (structure, "tile-height", &tile_height)) { ++ gst_structure_set (new_structure, "tile_boundary_y_offset", ++ G_TYPE_INT, vcrop->crop_top % tile_height, NULL); ++ ++ gst_structure_set (new_structure, "tile_boundary_c_offset", ++ G_TYPE_INT, vcrop->crop_top / ratio_y_c % tile_height, NULL); ++ } + } else { + rowstride = 0; + delta_chroma_offs = 0; +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0021-videocrop-support-cropping-interlaced-images.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0021-videocrop-support-cropping-interlaced-images.patch new file mode 100644 index 0000000..7d66fe4 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0021-videocrop-support-cropping-interlaced-images.patch @@ -0,0 +1,99 @@ +From b2975883315542cc9beead18a6bfe3bf1dab06b7 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Tue, 16 Oct 2012 16:42:17 +0900 +Subject: [PATCH 21/31] videocrop: support cropping interlaced images + +This patch supports it by adjusting the subbuffer offset and +chroma_byte_offset in caps. +--- + gst/videocrop/gstvideocrop.c | 43 ++++++++++++++++++++++++++++++++++++------ + gst/videocrop/gstvideocrop.h | 2 ++ + 2 files changed, 39 insertions(+), 6 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index dbebcfa..4d2a027 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -679,20 +679,44 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + guint ratio_y_c; + GstStructure *structure; + gint tile_height; ++ gboolean interlaced; ++ const gchar *layout; ++ ++ structure = gst_caps_get_structure (caps, 0); ++ if (gst_structure_get_boolean (structure, "interlaced", &interlaced) && ++ (interlaced == TRUE) && ++ ((layout = ++ gst_structure_get_string (structure, "field-layout")) != NULL) ++ && (strcmp (layout, "sequential") == 0)) ++ vcrop->interlaced = TRUE; ++ else ++ vcrop->interlaced = FALSE; + + rowstride = img_details.stride; + /* Y plane / UV plane */ + ratio_y_c = img_details.uv_off / (img_details.size - img_details.uv_off); +- delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c; ++ if (vcrop->interlaced) ++ delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c / 2; ++ else ++ delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c; + + /* set tile boudary for T/L addressing */ +- structure = gst_caps_get_structure (caps, 0); + if (gst_structure_get_int (structure, "tile-height", &tile_height)) { ++ gint tile_y_offs, tile_c_offs; ++ ++ if (vcrop->interlaced) { ++ tile_y_offs = vcrop->crop_top / 2 % tile_height; ++ tile_c_offs = vcrop->crop_top / ratio_y_c / 2 % tile_height; ++ } else { ++ tile_y_offs = vcrop->crop_top % tile_height; ++ tile_c_offs = vcrop->crop_top / ratio_y_c % tile_height; ++ } ++ + gst_structure_set (new_structure, "tile_boundary_y_offset", +- G_TYPE_INT, vcrop->crop_top % tile_height, NULL); ++ G_TYPE_INT, tile_y_offs, NULL); + + gst_structure_set (new_structure, "tile_boundary_c_offset", +- G_TYPE_INT, vcrop->crop_top / ratio_y_c % tile_height, NULL); ++ G_TYPE_INT, tile_c_offs, NULL); + } + } else { + rowstride = 0; +@@ -830,8 +854,15 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + sub_offset = (vcrop->crop_top * vcrop->in.stride) + + (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel); + } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- ROUND_DOWN_2 (vcrop->crop_left); ++ GstStructure *structure; ++ ++ structure = gst_caps_get_structure (caps, 0); ++ if (vcrop->interlaced) ++ sub_offset = (vcrop->crop_top / 2 * vcrop->in.stride) + ++ ROUND_DOWN_2 (vcrop->crop_left); ++ else ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ ROUND_DOWN_2 (vcrop->crop_left); + } else { + GST_LOG_OBJECT (vcrop, + "can't do zero-copy cropping except for packed format"); +diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h +index 1534b3d..a72cacb 100644 +--- a/gst/videocrop/gstvideocrop.h ++++ b/gst/videocrop/gstvideocrop.h +@@ -83,6 +83,8 @@ struct _GstVideoCrop + + /* query for rowstride */ + GstQueryType query_type_stride; ++ ++ gboolean interlaced; + }; + + struct _GstVideoCropClass +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0022-videocrop-move-output-buffer-size-calculation-to-tra.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0022-videocrop-move-output-buffer-size-calculation-to-tra.patch new file mode 100644 index 0000000..1c62e0d --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0022-videocrop-move-output-buffer-size-calculation-to-tra.patch @@ -0,0 +1,178 @@ +From e22281e0458c48f1d38b7a2abf20121378a811f8 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 18 Oct 2012 18:27:03 +0900 +Subject: [PATCH 22/31] videocrop: move output buffer size calculation to + transform_size() + +transform_size() is the optional method that can be overridden to +calculate buffer sizes. The default implementation uses get_unit_size(), +but when performing zero-copy cropping, transform_size() should be used +because the buffer size calculation is different from the default. +The buffer size calculation should be performed using the tranform_size() +override, rather than being inlined in prepare_output_buffer(). +--- + gst/videocrop/gstvideocrop.c | 120 +++++++++++++++++++++++++++++++++--------- + 1 file changed, 95 insertions(+), 25 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 4d2a027..4887137 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -140,6 +140,9 @@ static gboolean gst_video_crop_src_event (GstBaseTransform * trans, + static GstFlowReturn gst_video_crop_prepare_output_buffer (GstBaseTransform * + trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf); + static gboolean gst_video_crop_query_stride_supported (GstVideoCrop * vcrop); ++static gboolean gst_videocrop_transform_size (GstBaseTransform * trans, ++ GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps, ++ guint * othersize); + + static void + gst_video_crop_base_init (gpointer g_class) +@@ -234,6 +237,8 @@ gst_video_crop_class_init (GstVideoCropClass * klass) + GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size); + basetransform_class->prepare_output_buffer = + GST_DEBUG_FUNCPTR (gst_video_crop_prepare_output_buffer); ++ basetransform_class->transform_size = ++ GST_DEBUG_FUNCPTR (gst_videocrop_transform_size); + + basetransform_class->passthrough_on_same_caps = FALSE; + basetransform_class->src_event = GST_DEBUG_FUNCPTR (gst_video_crop_src_event); +@@ -838,7 +843,6 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) + { + GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); +- guint sub_offset, sub_size; + + if (!gst_video_crop_query_stride_supported (vcrop)) { + GST_LOG_OBJECT +@@ -847,30 +851,7 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + return GST_FLOW_OK; + } + +- if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) { +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- (vcrop->crop_left * vcrop->in.bytes_per_pixel); +- } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) { +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel); +- } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { +- GstStructure *structure; +- +- structure = gst_caps_get_structure (caps, 0); +- if (vcrop->interlaced) +- sub_offset = (vcrop->crop_top / 2 * vcrop->in.stride) + +- ROUND_DOWN_2 (vcrop->crop_left); +- else +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- ROUND_DOWN_2 (vcrop->crop_left); +- } else { +- GST_LOG_OBJECT (vcrop, +- "can't do zero-copy cropping except for packed format"); +- return GST_FLOW_OK; +- } +- +- sub_size = vcrop->in.size - sub_offset; +- *buf = gst_buffer_create_sub (input, sub_offset, sub_size); ++ *buf = gst_buffer_create_sub (input, vcrop->in.size - size, size); + if (*buf == NULL) { + GST_ERROR_OBJECT (vcrop, "failed to create subbuffer"); + return GST_FLOW_ERROR; +@@ -880,6 +861,95 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans, + return GST_FLOW_OK; + } + ++static gboolean ++gst_videocrop_transform_size (GstBaseTransform * trans, ++ GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps, ++ guint * othersize) ++{ ++ GstVideoCrop *vcrop = GST_VIDEO_CROP (trans); ++ guint inunitsize; ++ ++ if (!gst_video_crop_query_stride_supported (vcrop) || ++ direction == GST_PAD_SRC) { ++ guint outunitsize, units; ++ ++ if (!gst_video_crop_get_unit_size (trans, caps, &inunitsize)) ++ goto no_in_size; ++ ++ GST_DEBUG_OBJECT (vcrop, "input size %d, input unit size %d", size, ++ inunitsize); ++ ++ /* input size must be a multiple of the unit_size of the input caps */ ++ if (inunitsize == 0 || (size % inunitsize != 0)) ++ goto no_multiple; ++ ++ /* get the amount of units */ ++ units = size / inunitsize; ++ ++ /* now get the unit size of the output */ ++ if (!gst_video_crop_get_unit_size (trans, othercaps, &outunitsize)) ++ goto no_out_size; ++ ++ /* the output size is the unit_size times the amount of units on the ++ * input */ ++ *othersize = units * outunitsize; ++ } else { ++ guint sub_offset; ++ ++ /* Calculate a subbufer size for zero-copy cropping. The subbuffer is ++ created in prepare_output_buffer (). */ ++ if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) { ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ (vcrop->crop_left * vcrop->in.bytes_per_pixel); ++ } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) { ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel); ++ } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { ++ GstStructure *structure; ++ ++ structure = gst_caps_get_structure (caps, 0); ++ if (vcrop->interlaced) ++ sub_offset = (vcrop->crop_top / 2 * vcrop->in.stride) + ++ ROUND_DOWN_2 (vcrop->crop_left); ++ else ++ sub_offset = (vcrop->crop_top * vcrop->in.stride) + ++ ROUND_DOWN_2 (vcrop->crop_left); ++ } else { ++ GST_LOG_OBJECT (vcrop, ++ "can't do zero-copy cropping except for packed format"); ++ return FALSE; ++ } ++ ++ *othersize = vcrop->in.size - sub_offset; ++ } ++ ++ GST_DEBUG_OBJECT (vcrop, "transformed size to %d", *othersize); ++ ++ return TRUE; ++ ++ /* ERRORS */ ++no_in_size: ++ { ++ GST_DEBUG_OBJECT (vcrop, "could not get in_size"); ++ g_warning ("%s: could not get in_size", GST_ELEMENT_NAME (trans)); ++ return FALSE; ++ } ++no_multiple: ++ { ++ GST_DEBUG_OBJECT (vcrop, "Size %u is not a multiple of unit size %u", size, ++ inunitsize); ++ g_warning ("%s: size %u is not a multiple of unit size %u", ++ GST_ELEMENT_NAME (trans), size, inunitsize); ++ return FALSE; ++ } ++no_out_size: ++ { ++ GST_DEBUG_OBJECT (vcrop, "could not get out_size"); ++ g_warning ("%s: could not get out_size", GST_ELEMENT_NAME (trans)); ++ return FALSE; ++ } ++} ++ + static void + gst_video_crop_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0023-videocrop-skip-the-transforming-caps-process-when-th.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0023-videocrop-skip-the-transforming-caps-process-when-th.patch new file mode 100644 index 0000000..5c33ec6 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0023-videocrop-skip-the-transforming-caps-process-when-th.patch @@ -0,0 +1,32 @@ +From d13fa761751f252c89032248fbf3b363d4f1827c Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Thu, 29 Nov 2012 14:06:33 +0900 +Subject: [PATCH 23/31] videocrop: skip the transforming caps process when the + passthrough mode is set + +When the passthrough mode is set, the basetransform class tries to accommodate +a difference between input and output caps. This behavior causes +the reallocation of the output buffers, and discarding the physical buffers +used for zero-copy processing. +To avoid this problem, the transforming caps process shouldn't be performed. +--- + gst/videocrop/gstvideocrop.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 4887137..caeb0b1 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -614,6 +614,9 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + + vcrop = GST_VIDEO_CROP (trans); + ++ if (gst_base_transform_is_passthrough (trans)) ++ return gst_caps_ref (caps); ++ + GST_OBJECT_LOCK (vcrop); + + GST_LOG_OBJECT (vcrop, "l=%d,r=%d,b=%d,t=%d", +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0024-v4l2src-fix-RGB32-colorspace-deinitions.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0024-v4l2src-fix-RGB32-colorspace-deinitions.patch new file mode 100644 index 0000000..e141df9 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0024-v4l2src-fix-RGB32-colorspace-deinitions.patch @@ -0,0 +1,69 @@ +From e7782d58ed397e0f66cbb62b5c59f3adea8227c4 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Mon, 16 Apr 2012 11:05:07 +0900 +Subject: [PATCH 24/31] v4l2src: fix RGB32 colorspace deinitions + +This patch makes RGB32 colorspace definitions used in the caps negotiation +suitable for actual v4l2 driver's output format. +--- + sys/v4l2/gstv4l2object.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c +index 81d1cb7..0678305 100644 +--- a/sys/v4l2/gstv4l2object.c ++++ b/sys/v4l2/gstv4l2object.c +@@ -1208,14 +1208,16 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + b_mask = 0xff0000; + break; + case V4L2_PIX_FMT_RGB32: +- bpp = depth = 32; ++ bpp = 32; ++ depth = 24; + endianness = G_BIG_ENDIAN; +- r_mask = 0xff000000; +- g_mask = 0x00ff0000; +- b_mask = 0x0000ff00; ++ r_mask = 0x00ff0000; ++ g_mask = 0x0000ff00; ++ b_mask = 0x000000ff; + break; + case V4L2_PIX_FMT_BGR32: +- bpp = depth = 32; ++ bpp = 32; ++ depth = 24; + endianness = G_BIG_ENDIAN; + r_mask = 0x000000ff; + g_mask = 0x0000ff00; +@@ -1480,9 +1482,10 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + #endif + } + } else if (!strcmp (mimetype, "video/x-raw-rgb")) { +- gint depth, endianness, r_mask; ++ gint depth, bpp, endianness, r_mask; + + gst_structure_get_int (structure, "depth", &depth); ++ gst_structure_get_int (structure, "bpp", &bpp); + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get_int (structure, "red_mask", &r_mask); + +@@ -1499,10 +1502,13 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X; + break; + case 24: +- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; +- break; + case 32: +- fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; ++ if (bpp == 24) ++ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; ++ else if (bpp == 32) ++ fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; ++ else ++ GST_ERROR_OBJECT (v4l2object, "Invalid value bpp = %d", bpp); + break; + } + } else if (strcmp (mimetype, "video/x-dv") == 0) { +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0025-sys-v4l2-gstv4l2-skip-set-caps-processing-if-the-par.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0025-sys-v4l2-gstv4l2-skip-set-caps-processing-if-the-par.patch new file mode 100644 index 0000000..53e7acd --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0025-sys-v4l2-gstv4l2-skip-set-caps-processing-if-the-par.patch @@ -0,0 +1,86 @@ +From 91b8fe5f2e81eb1c5fcdd2f27e5d40ce64a4433f Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Wed, 16 May 2012 15:41:40 +0900 +Subject: [PATCH 25/31] sys/v4l2/gstv4l2: skip set caps processing if the + parameters are unchanged + +v4l2src re-creates the buffer pool in set_caps() when the buffers +already have been allocated. If always-copy is set to false, +the buffer dequeued from V4L2 driver can be passed to next plugin +without copying. Therefore, set_caps() could free the buffer which +is in use. + +set_caps() may be invoked by core libraries even if there is no change +to the caps value. This behavior could free the buffer which is in use +by another plugin. This patch skips the set_caps() processing if the caps +parameters are unchanged. +--- + sys/v4l2/gstv4l2src.c | 36 ++++++++++++++++++++++++++++-------- + 1 file changed, 28 insertions(+), 8 deletions(-) + +diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c +index d3f9a3c..3f9c6ba 100644 +--- a/sys/v4l2/gstv4l2src.c ++++ b/sys/v4l2/gstv4l2src.c +@@ -628,6 +628,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + struct v4l2_fmtdesc *format; + guint fps_n, fps_d; + guint size; ++ struct v4l2_format prev_format; + + v4l2src = GST_V4L2SRC (src); + +@@ -635,8 +636,35 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) + return FALSE; + ++ /* we want our own v4l2 type of fourcc codes */ ++ if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, &w, ++ &h, &interlaced, &fps_n, &fps_d, &size)) { ++ GST_INFO_OBJECT (v4l2src, ++ "can't get capture format from caps %" GST_PTR_FORMAT, caps); ++ return FALSE; ++ } ++ + /* make sure we stop capturing and dealloc buffers */ + if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) { ++ memset (&prev_format, 0x00, sizeof (struct v4l2_format)); ++ prev_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ if (v4l2_ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_FMT, ++ &prev_format) < 0) { ++ GST_ERROR_OBJECT (v4l2src, "Call to G_FMT failed: (%s)", ++ g_strerror (errno)); ++ return FALSE; ++ } ++ ++ if (prev_format.fmt.pix.width == w && ++ prev_format.fmt.pix.height == h && ++ prev_format.fmt.pix.pixelformat == format->pixelformat && ++ (v4l2src->fps_n == 0 || v4l2src->fps_n == fps_n) && ++ (v4l2src->fps_d == 0 || v4l2src->fps_d == fps_d) && ++ v4l2src->frame_byte_size == size) { ++ GST_LOG_OBJECT (v4l2src, "skip set caps because of no need to change"); ++ return TRUE; ++ } ++ + /* both will throw an element-error on failure */ + if (!gst_v4l2src_capture_stop (v4l2src)) + return FALSE; +@@ -644,14 +672,6 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + return FALSE; + } + +- /* we want our own v4l2 type of fourcc codes */ +- if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, &w, +- &h, &interlaced, &fps_n, &fps_d, &size)) { +- GST_INFO_OBJECT (v4l2src, +- "can't get capture format from caps %" GST_PTR_FORMAT, caps); +- return FALSE; +- } +- + GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, " + "format %s", w, h, fps_n, fps_d, format->description); + +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0026-sys-v4l2-gstv4l2-return-an-error-from-set_caps-if-tr.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0026-sys-v4l2-gstv4l2-return-an-error-from-set_caps-if-tr.patch new file mode 100644 index 0000000..e73f3a7 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0026-sys-v4l2-gstv4l2-return-an-error-from-set_caps-if-tr.patch @@ -0,0 +1,66 @@ +From 2cda1fcdf8147fdddbca0f2f2d584bda9cc9d283 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Wed, 23 May 2012 16:24:16 +0900 +Subject: [PATCH 26/31] sys/v4l2/gstv4l2: return an error from set_caps() if + trying to re-create in-use buffers + +Whether the caps can be changed depends on the always-copy option. + +If the caps of a buffer are changed, the buffer must be +re-created because the buffer size may change. If always-copy is +set to false, a buffer which is in use could be freed so that it +can be re-created. + +For this reason, if always-copy is set to false, changing the caps is +not supported and this patch returns an error. +--- + sys/v4l2/gstv4l2src.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c +index 3f9c6ba..3109429 100644 +--- a/sys/v4l2/gstv4l2src.c ++++ b/sys/v4l2/gstv4l2src.c +@@ -646,6 +646,8 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + + /* make sure we stop capturing and dealloc buffers */ + if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) { ++ gboolean caps_changed = FALSE; ++ + memset (&prev_format, 0x00, sizeof (struct v4l2_format)); + prev_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (v4l2_ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_FMT, +@@ -655,14 +657,24 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + return FALSE; + } + +- if (prev_format.fmt.pix.width == w && +- prev_format.fmt.pix.height == h && +- prev_format.fmt.pix.pixelformat == format->pixelformat && +- (v4l2src->fps_n == 0 || v4l2src->fps_n == fps_n) && +- (v4l2src->fps_d == 0 || v4l2src->fps_d == fps_d) && +- v4l2src->frame_byte_size == size) { ++ if (prev_format.fmt.pix.width != w || ++ prev_format.fmt.pix.height != h || ++ prev_format.fmt.pix.pixelformat != format->pixelformat || ++ (v4l2src->fps_n != 0 && v4l2src->fps_n != fps_n) || ++ (v4l2src->fps_d != 0 && v4l2src->fps_d != fps_d) || ++ v4l2src->frame_byte_size != size) { ++ caps_changed = TRUE; ++ } ++ ++ if (!caps_changed) { + GST_LOG_OBJECT (v4l2src, "skip set caps because of no need to change"); + return TRUE; ++ } else if (!v4l2src->always_copy && caps_changed) { ++ GST_ERROR_OBJECT (v4l2src, ++ "can't change caps if v4l2src->always_copy is FALSE"); ++ return FALSE; ++ } else { ++ GST_LOG_OBJECT (v4l2src, "run set caps"); + } + + /* both will throw an element-error on failure */ +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0027-videocrop-add-a-new-function-to-determine-if-source-.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0027-videocrop-add-a-new-function-to-determine-if-source-.patch new file mode 100644 index 0000000..cc41aaa --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0027-videocrop-add-a-new-function-to-determine-if-source-.patch @@ -0,0 +1,67 @@ +From a4185ee69f456d244f3bc5d1dc56800d112a3067 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Mon, 29 Oct 2012 11:52:32 +0900 +Subject: [PATCH 27/31] videocrop: add a new function to determine if source + images are interlaced + +This patch groups the processing to determine if source images are +interlaced to gst_video_crop_is_interlaced(). +--- + gst/videocrop/gstvideocrop.c | 32 ++++++++++++++++++++++---------- + 1 file changed, 22 insertions(+), 10 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index caeb0b1..d02948d 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -604,6 +604,26 @@ gst_video_crop_transform_dimension_value (const GValue * src_val, + return ret; + } + ++static gboolean ++gst_video_crop_is_interlaced (GstCaps * caps) ++{ ++ gboolean interlaced; ++ const gchar *layout; ++ GstStructure *structure; ++ gboolean result; ++ ++ structure = gst_caps_get_structure (caps, 0); ++ if (gst_structure_get_boolean (structure, "interlaced", &interlaced) && ++ (interlaced == TRUE) && ++ ((layout = gst_structure_get_string (structure, "field-layout")) != NULL) ++ && (strcmp (layout, "sequential") == 0)) ++ result = TRUE; ++ else ++ result = FALSE; ++ ++ return result; ++} ++ + static GstCaps * + gst_video_crop_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +@@ -687,18 +707,10 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + guint ratio_y_c; + GstStructure *structure; + gint tile_height; +- gboolean interlaced; +- const gchar *layout; + + structure = gst_caps_get_structure (caps, 0); +- if (gst_structure_get_boolean (structure, "interlaced", &interlaced) && +- (interlaced == TRUE) && +- ((layout = +- gst_structure_get_string (structure, "field-layout")) != NULL) +- && (strcmp (layout, "sequential") == 0)) +- vcrop->interlaced = TRUE; +- else +- vcrop->interlaced = FALSE; ++ ++ vcrop->interlaced = gst_video_crop_is_interlaced (caps); + + rowstride = img_details.stride; + /* Y plane / UV plane */ +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0028-videocrop-set-result-of-determing-if-source-images-a.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0028-videocrop-set-result-of-determing-if-source-images-a.patch new file mode 100644 index 0000000..d5c39b2 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0028-videocrop-set-result-of-determing-if-source-images-a.patch @@ -0,0 +1,35 @@ +From d9e4f81f59fea3a0b4342e7c6b3312384d479827 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Mon, 29 Oct 2012 14:53:32 +0900 +Subject: [PATCH 28/31] videocrop: set result of determing if source images + are interlaced at the head of transform_caps + +--- + gst/videocrop/gstvideocrop.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index d02948d..93d6512 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -642,6 +642,8 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + GST_LOG_OBJECT (vcrop, "l=%d,r=%d,b=%d,t=%d", + vcrop->crop_left, vcrop->crop_right, vcrop->crop_bottom, vcrop->crop_top); + ++ vcrop->interlaced = gst_video_crop_is_interlaced (caps); ++ + if (direction == GST_PAD_SRC) { + dx = vcrop->crop_left + vcrop->crop_right; + dy = vcrop->crop_top + vcrop->crop_bottom; +@@ -710,8 +712,6 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + + structure = gst_caps_get_structure (caps, 0); + +- vcrop->interlaced = gst_video_crop_is_interlaced (caps); +- + rowstride = img_details.stride; + /* Y plane / UV plane */ + ratio_y_c = img_details.uv_off / (img_details.size - img_details.uv_off); +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0029-videocrop-round-down-cropping-parameters-when-the-co.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0029-videocrop-round-down-cropping-parameters-when-the-co.patch new file mode 100644 index 0000000..7d1b8ee --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0029-videocrop-round-down-cropping-parameters-when-the-co.patch @@ -0,0 +1,193 @@ +From 077d4c596e51be368eb495b4aa3e8020acf11d56 Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Mon, 29 Oct 2012 14:25:22 +0900 +Subject: [PATCH 29/31] videocrop: round down cropping parameters when the + color format is NV12 + +When the color format is NV12, there are restrictions as the following. +This change properly rounds down cropping parameters according to the +restrictions. + +* Top: even number or multiple of 4 when a interlaced image is received. +* Left: even number +* Right: even number +--- + gst/videocrop/gstvideocrop.c | 86 +++++++++++++++++++++++++++++++++--------- + gst/videocrop/gstvideocrop.h | 9 +++++ + 2 files changed, 77 insertions(+), 18 deletions(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 93d6512..8fcc80e 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -624,6 +624,40 @@ gst_video_crop_is_interlaced (GstCaps * caps) + return result; + } + ++static gboolean ++gst_video_crop_round_down_crop_properties (GstVideoCrop * vcrop, GstCaps * caps, ++ GstVideoCropRectangle * vcrop_rect) ++{ ++ GstStructure *structure; ++ guint32 format = 0; ++ gboolean round_down_done; ++ ++ g_return_val_if_fail (vcrop_rect != NULL, FALSE); ++ ++ structure = gst_caps_get_structure (caps, 0); ++ if (!gst_structure_get_fourcc (structure, "format", &format)) { ++ GST_WARNING_OBJECT (vcrop, "failed to get fourcc"); ++ return FALSE; ++ } ++ ++ if (vcrop->interlaced && format == GST_MAKE_FOURCC ('N', 'V', '1', '2')) { ++ vcrop_rect->top = GST_ROUND_DOWN_4 (vcrop_rect->top); ++ vcrop_rect->left = GST_ROUND_DOWN_2 (vcrop_rect->left); ++ vcrop_rect->right = GST_ROUND_DOWN_2 (vcrop_rect->right); ++ round_down_done = TRUE; ++ } else if (!vcrop->interlaced && ++ format == GST_MAKE_FOURCC ('N', 'V', '1', '2')) { ++ vcrop_rect->top = GST_ROUND_DOWN_2 (vcrop_rect->top); ++ vcrop_rect->left = GST_ROUND_DOWN_2 (vcrop_rect->left); ++ vcrop_rect->right = GST_ROUND_DOWN_2 (vcrop_rect->right); ++ round_down_done = TRUE; ++ } else { ++ round_down_done = FALSE; ++ } ++ ++ return round_down_done; ++} ++ + static GstCaps * + gst_video_crop_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +@@ -631,6 +665,7 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + GstVideoCrop *vcrop; + GstCaps *other_caps; + gint dy, dx, i; ++ GstVideoCropRectangle rounded_rect; + + vcrop = GST_VIDEO_CROP (trans); + +@@ -644,12 +679,21 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + + vcrop->interlaced = gst_video_crop_is_interlaced (caps); + ++ rounded_rect.top = vcrop->crop_top; ++ rounded_rect.bottom = vcrop->crop_bottom; ++ rounded_rect.left = vcrop->crop_left; ++ rounded_rect.right = vcrop->crop_right; ++ if (gst_video_crop_round_down_crop_properties (vcrop, caps, &rounded_rect)) ++ GST_LOG_OBJECT (vcrop, "round down l=%d,r=%d,b=%d,t=%d", ++ rounded_rect.left, rounded_rect.right, rounded_rect.bottom, ++ rounded_rect.top); ++ + if (direction == GST_PAD_SRC) { +- dx = vcrop->crop_left + vcrop->crop_right; +- dy = vcrop->crop_top + vcrop->crop_bottom; ++ dx = rounded_rect.left + rounded_rect.right; ++ dy = rounded_rect.top + rounded_rect.bottom; + } else { +- dx = 0 - (vcrop->crop_left + vcrop->crop_right); +- dy = 0 - (vcrop->crop_top + vcrop->crop_bottom); ++ dx = 0 - (rounded_rect.left + rounded_rect.right); ++ dy = 0 - (rounded_rect.top + rounded_rect.bottom); + } + GST_OBJECT_UNLOCK (vcrop); + +@@ -716,20 +760,20 @@ gst_video_crop_transform_caps (GstBaseTransform * trans, + /* Y plane / UV plane */ + ratio_y_c = img_details.uv_off / (img_details.size - img_details.uv_off); + if (vcrop->interlaced) +- delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c / 2; ++ delta_chroma_offs = rowstride * rounded_rect.top / ratio_y_c / 2; + else +- delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c; ++ delta_chroma_offs = rowstride * rounded_rect.top / ratio_y_c; + + /* set tile boudary for T/L addressing */ + if (gst_structure_get_int (structure, "tile-height", &tile_height)) { + gint tile_y_offs, tile_c_offs; + + if (vcrop->interlaced) { +- tile_y_offs = vcrop->crop_top / 2 % tile_height; +- tile_c_offs = vcrop->crop_top / ratio_y_c / 2 % tile_height; ++ tile_y_offs = rounded_rect.top / 2 % tile_height; ++ tile_c_offs = rounded_rect.top / ratio_y_c / 2 % tile_height; + } else { +- tile_y_offs = vcrop->crop_top % tile_height; +- tile_c_offs = vcrop->crop_top / ratio_y_c % tile_height; ++ tile_y_offs = rounded_rect.top % tile_height; ++ tile_c_offs = rounded_rect.top / ratio_y_c % tile_height; + } + + gst_structure_set (new_structure, "tile_boundary_y_offset", +@@ -910,25 +954,31 @@ gst_videocrop_transform_size (GstBaseTransform * trans, + *othersize = units * outunitsize; + } else { + guint sub_offset; ++ GstVideoCropRectangle rounded_rect; ++ ++ rounded_rect.top = vcrop->crop_top; ++ rounded_rect.bottom = vcrop->crop_bottom; ++ rounded_rect.left = vcrop->crop_left; ++ rounded_rect.right = vcrop->crop_right; ++ gst_video_crop_round_down_crop_properties (vcrop, caps, &rounded_rect); + + /* Calculate a subbufer size for zero-copy cropping. The subbuffer is + created in prepare_output_buffer (). */ + if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) { +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- (vcrop->crop_left * vcrop->in.bytes_per_pixel); ++ sub_offset = (rounded_rect.top * vcrop->in.stride) + ++ (rounded_rect.left * vcrop->in.bytes_per_pixel); + } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) { +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel); ++ sub_offset = (rounded_rect.top * vcrop->in.stride) + ++ (ROUND_DOWN_2 (rounded_rect.left) * vcrop->in.bytes_per_pixel); + } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) { + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + if (vcrop->interlaced) +- sub_offset = (vcrop->crop_top / 2 * vcrop->in.stride) + +- ROUND_DOWN_2 (vcrop->crop_left); ++ sub_offset = (rounded_rect.top / 2 * vcrop->in.stride) + ++ rounded_rect.left; + else +- sub_offset = (vcrop->crop_top * vcrop->in.stride) + +- ROUND_DOWN_2 (vcrop->crop_left); ++ sub_offset = (rounded_rect.top * vcrop->in.stride) + rounded_rect.left; + } else { + GST_LOG_OBJECT (vcrop, + "can't do zero-copy cropping except for packed format"); +diff --git a/gst/videocrop/gstvideocrop.h b/gst/videocrop/gstvideocrop.h +index a72cacb..4885c37 100644 +--- a/gst/videocrop/gstvideocrop.h ++++ b/gst/videocrop/gstvideocrop.h +@@ -67,6 +67,7 @@ struct _GstVideoCropImageDetails + + typedef struct _GstVideoCrop GstVideoCrop; + typedef struct _GstVideoCropClass GstVideoCropClass; ++typedef struct _GstVideoCropRectangle GstVideoCropRectangle; + + struct _GstVideoCrop + { +@@ -94,5 +95,13 @@ struct _GstVideoCropClass + + GType gst_video_crop_get_type (void); + ++struct _GstVideoCropRectangle ++{ ++ gint left; ++ gint right; ++ gint top; ++ gint bottom; ++}; ++ + G_END_DECLS + #endif /* __GST_VIDEO_CROP_H__ */ +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0030-videocrop-hold-a-lock-to-prevent-from-accessing-crop.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0030-videocrop-hold-a-lock-to-prevent-from-accessing-crop.patch new file mode 100644 index 0000000..5114174 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0030-videocrop-hold-a-lock-to-prevent-from-accessing-crop.patch @@ -0,0 +1,30 @@ +From 34b6056ac873388ce008817819cefe930ee9901f Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Wed, 31 Oct 2012 12:33:58 +0900 +Subject: [PATCH 30/31] videocrop: hold a lock to prevent from accessing + cropping params on performing set_property + +--- + gst/videocrop/gstvideocrop.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 8fcc80e..2114dae 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -956,10 +956,12 @@ gst_videocrop_transform_size (GstBaseTransform * trans, + guint sub_offset; + GstVideoCropRectangle rounded_rect; + ++ GST_OBJECT_LOCK (vcrop); + rounded_rect.top = vcrop->crop_top; + rounded_rect.bottom = vcrop->crop_bottom; + rounded_rect.left = vcrop->crop_left; + rounded_rect.right = vcrop->crop_right; ++ GST_OBJECT_UNLOCK (vcrop); + gst_video_crop_round_down_crop_properties (vcrop, caps, &rounded_rect); + + /* Calculate a subbufer size for zero-copy cropping. The subbuffer is +-- +1.7.9.5 + diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-good/0031-videocrop-fix-a-memory-leak-caused-by-invoking-gst_p.patch b/common/recipes-multimedia/gstreamer/gst-plugins-good/0031-videocrop-fix-a-memory-leak-caused-by-invoking-gst_p.patch new file mode 100644 index 0000000..248f8f7 --- /dev/null +++ b/common/recipes-multimedia/gstreamer/gst-plugins-good/0031-videocrop-fix-a-memory-leak-caused-by-invoking-gst_p.patch @@ -0,0 +1,39 @@ +From d152c33c21eba3b9df2918fb8187ff5f839f766f Mon Sep 17 00:00:00 2001 +From: Kazunori Kobayashi <kkobayas@igel.co.jp> +Date: Tue, 22 Jan 2013 18:40:28 +0900 +Subject: [PATCH 31/31] videocrop: fix a memory leak caused by invoking + gst_pad_get_peer() + +Once is_query_done is set to TRUE, the function exits without decreasing +the reference count of a GstPad instance. +To fix the issue, this patch moves the call to gst_pad_get_peer() (which +increases the GstPad refence count) to after is_query_done is tested. +--- + gst/videocrop/gstvideocrop.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c +index 2114dae..49edc6e 100644 +--- a/gst/videocrop/gstvideocrop.c ++++ b/gst/videocrop/gstvideocrop.c +@@ -873,7 +873,7 @@ static gboolean + gst_video_crop_query_stride_supported (GstVideoCrop * vcrop) + { + static gboolean result = FALSE; +- GstPad *peer = gst_pad_get_peer (GST_BASE_TRANSFORM (vcrop)->srcpad); ++ GstPad *peer; + GstStructure *structure; + GstQuery *query; + static gboolean is_query_done = FALSE; +@@ -881,6 +881,8 @@ gst_video_crop_query_stride_supported (GstVideoCrop * vcrop) + if (is_query_done) + return result; + ++ peer = gst_pad_get_peer (GST_BASE_TRANSFORM (vcrop)->srcpad); ++ + structure = gst_structure_empty_new ("GstQueryStrideSupported"); + gst_structure_set (structure, "stride-supported", G_TYPE_BOOLEAN, FALSE, + NULL); +-- +1.7.9.5 + |