[gstreamer1-plugins-good] Fix v4l2-src not working with some v4l2 devices (bgo#735660)
Hans de Goede
jwrdegoede at fedoraproject.org
Fri Aug 29 10:56:55 UTC 2014
commit 67202adc8db460dc331c5440741c8c8c91b7578e
Author: Hans de Goede <hdegoede at redhat.com>
Date: Fri Aug 29 12:56:53 2014 +0200
Fix v4l2-src not working with some v4l2 devices (bgo#735660)
...arest_size-Always-reinit-all-struct-field.patch | 56 ++++++++++
...arest_size-Fix-Unsupported-field-type-err.patch | 107 ++++++++++++++++++++
...-all-drivers-support-requesting-0-buffers.patch | 68 +++++++++++++
gstreamer1-plugins-good.spec | 12 ++-
4 files changed, 242 insertions(+), 1 deletions(-)
---
diff --git a/0001-v4l2-get_nearest_size-Always-reinit-all-struct-field.patch b/0001-v4l2-get_nearest_size-Always-reinit-all-struct-field.patch
new file mode 100644
index 0000000..fd859a4
--- /dev/null
+++ b/0001-v4l2-get_nearest_size-Always-reinit-all-struct-field.patch
@@ -0,0 +1,56 @@
+From b3b38ba864ac7eff3cd225ed05c697b67509b263 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede at redhat.com>
+Date: Fri, 29 Aug 2014 10:57:20 +0200
+Subject: [PATCH 1/3] v4l2: get_nearest_size: Always reinit all struct fields
+ on retry
+
+They may have been modified by the ioctl even if it failed. This also makes
+the S_FMT fallback path try progressive first, making it consistent with the
+preferred TRY_FMT path.
+
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+---
+ sys/v4l2/gstv4l2object.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
+index 3b22b1a..881a52d 100644
+--- a/sys/v4l2/gstv4l2object.c
++++ b/sys/v4l2/gstv4l2object.c
+@@ -2171,6 +2171,8 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with interlaced video */
++ memset (&fmt, 0, sizeof (fmt));
++ fmt.type = v4l2object->type;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+@@ -2192,16 +2194,22 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ GST_LOG_OBJECT (v4l2object->element,
+ "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
+
++ memset (&fmt, 0, sizeof (fmt));
++ fmt.type = v4l2object->type;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
++ fmt.fmt.pix.pixelformat = pixelformat;
++ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+- /* try again with progressive video */
++ /* try again with interlaced video */
++ memset (&fmt, 0, sizeof (fmt));
++ fmt.type = v4l2object->type;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+- fmt.fmt.pix.field = V4L2_FIELD_NONE;
++ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ }
+
+--
+2.1.0
+
diff --git a/0002-v4l2-get_nearest_size-Fix-Unsupported-field-type-err.patch b/0002-v4l2-get_nearest_size-Fix-Unsupported-field-type-err.patch
new file mode 100644
index 0000000..7c62aa3
--- /dev/null
+++ b/0002-v4l2-get_nearest_size-Fix-Unsupported-field-type-err.patch
@@ -0,0 +1,107 @@
+From 92c026bfd32634018c155e458a4df9f6bf8152d3 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede at redhat.com>
+Date: Fri, 29 Aug 2014 12:01:27 +0200
+Subject: [PATCH 2/3] v4l2: get_nearest_size: Fix "Unsupported field type"
+ errors
+
+Most V4L2 ioctls like try_fmt will adjust input fields to match what the
+hardware can do rather then returning -EINVAL. As is docmented here:
+http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-g-fmt.html
+
+EINVAL is only returned if the buffer type field is invalid or not supported.
+
+So upon requesting V4L2_FIELD_NONE devices which can only do interlaced
+mode will change the field value to e.g. V4L2_FIELD_BOTTOM as only returning
+half the lines is the closest they can do to progressive modes.
+
+In essence this means that we've failed to get a (usable) progessive mode
+and should fall back to interlaced mode.
+
+This commit adds a check for having gotten a usable field value after the first
+try_fmt, to force fallback to interlaced mode even if the try_fmt succeeded,
+thereby fixing get_nearest_size failing on these devices.
+
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+---
+ sys/v4l2/gstv4l2object.c | 44 +++++++++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 17 deletions(-)
+
+diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
+index 881a52d..ef77e71 100644
+--- a/sys/v4l2/gstv4l2object.c
++++ b/sys/v4l2/gstv4l2object.c
+@@ -2141,6 +2141,24 @@ default_frame_sizes:
+ }
+
+ static gboolean
++gst_v4l2_object_get_interlace (int field, gboolean * interlaced)
++{
++ switch (field) {
++ case V4L2_FIELD_ANY:
++ case V4L2_FIELD_NONE:
++ *interlaced = FALSE;
++ return TRUE;
++ case V4L2_FIELD_INTERLACED:
++ case V4L2_FIELD_INTERLACED_TB:
++ case V4L2_FIELD_INTERLACED_BT:
++ *interlaced = TRUE;
++ return TRUE;
++ default:
++ return FALSE;
++ }
++}
++
++static gboolean
+ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
+ {
+@@ -2169,7 +2187,8 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+- if (r < 0 && errno == EINVAL) {
++ if ((r < 0 && errno == EINVAL) ||
++ !gst_v4l2_object_get_interlace (fmt.fmt.pix.field, interlaced)) {
+ /* try again with interlaced video */
+ memset (&fmt, 0, sizeof (fmt));
+ fmt.type = v4l2object->type;
+@@ -2202,7 +2221,8 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+- if (r < 0 && errno == EINVAL) {
++ if ((r < 0 && errno == EINVAL) ||
++ !gst_v4l2_object_get_interlace (fmt.fmt.pix.field, interlaced)) {
+ /* try again with interlaced video */
+ memset (&fmt, 0, sizeof (fmt));
+ fmt.type = v4l2object->type;
+@@ -2223,21 +2243,11 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+
+- switch (fmt.fmt.pix.field) {
+- case V4L2_FIELD_ANY:
+- case V4L2_FIELD_NONE:
+- *interlaced = FALSE;
+- break;
+- case V4L2_FIELD_INTERLACED:
+- case V4L2_FIELD_INTERLACED_TB:
+- case V4L2_FIELD_INTERLACED_BT:
+- *interlaced = TRUE;
+- break;
+- default:
+- GST_WARNING_OBJECT (v4l2object->element,
+- "Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
+- GST_FOURCC_ARGS (pixelformat), *width, *height);
+- goto error;
++ if (!gst_v4l2_object_get_interlace (fmt.fmt.pix.field, interlaced)) {
++ GST_WARNING_OBJECT (v4l2object->element,
++ "Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u: %u",
++ GST_FOURCC_ARGS (pixelformat), *width, *height, fmt.fmt.pix.field);
++ goto error;
+ }
+
+ ret = TRUE;
+--
+2.1.0
+
diff --git a/0003-v4l2-Not-all-drivers-support-requesting-0-buffers.patch b/0003-v4l2-Not-all-drivers-support-requesting-0-buffers.patch
new file mode 100644
index 0000000..8b588c4
--- /dev/null
+++ b/0003-v4l2-Not-all-drivers-support-requesting-0-buffers.patch
@@ -0,0 +1,68 @@
+From 2f3ea418c9b99486fb8ff72b9c35ef892ffcae1c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede at redhat.com>
+Date: Fri, 29 Aug 2014 12:10:01 +0200
+Subject: [PATCH 3/3] v4l2: Not all drivers support requesting 0 buffers
+
+Not all drivers support requesting 0 buffers, specifically any driver using
+the videobuf framework (rather then the new videobuf2 framework) for buffer
+management will not support this.
+
+This commits changes the code to probe available buffer types to request
+atleast one buffer, and to free it again on success, to fix the new gst v4l2
+from not working on these devices.
+
+Also turn being unable to free buffers through requesting 0 buffers from an
+error into a warning for the same reason.
+
+Note these devices do support changing the number of buffers and/or the fmt
+after requesting buffers as long as there is no streaming going on, and the
+buffers will eventually be free-ed when the fd is closed.
+
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+---
+ sys/v4l2/gstv4l2allocator.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
+index 68ce902..cbc6a6a 100644
+--- a/sys/v4l2/gstv4l2allocator.c
++++ b/sys/v4l2/gstv4l2allocator.c
+@@ -475,14 +475,20 @@ gst_v4l2_allocator_probe (GstV4l2Allocator * allocator, guint32 memory,
+ guint32 breq_flag, guint32 bcreate_flag)
+ {
+ struct v4l2_requestbuffers breq = { 0 };
++ struct v4l2_create_buffers bcreate = { 0 };
+ guint32 flags = 0;
+
+ breq.type = allocator->type;
+- breq.count = 0;
++ breq.count = 1;
+ breq.memory = memory;
+
+ if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) == 0) {
+- struct v4l2_create_buffers bcreate = { 0 };
++ /* Free the buffers, ignore the result not all drivers support this */
++ memset (&breq, 0, sizeof (breq));
++ breq.type = allocator->type;
++ breq.count = 0;
++ breq.memory = memory;
++ v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq);
+
+ flags |= breq_flag;
+
+@@ -779,9 +785,10 @@ done:
+
+ reqbufs_failed:
+ {
+- GST_ERROR_OBJECT (allocator,
++ GST_WARNING_OBJECT (allocator,
+ "error releasing buffers buffers: %s", g_strerror (errno));
+- ret = GST_V4L2_ERROR;
++ /* Not all drivers support freeing buffers by requesting 0 buffers, so
++ we don't set ret to an error here. */
+ goto done;
+ }
+ }
+--
+2.1.0
+
diff --git a/gstreamer1-plugins-good.spec b/gstreamer1-plugins-good.spec
index ff2098c..8345bcc 100644
--- a/gstreamer1-plugins-good.spec
+++ b/gstreamer1-plugins-good.spec
@@ -9,12 +9,16 @@
Name: gstreamer1-plugins-good
Version: 1.4.1
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: GStreamer plugins with good code and licensing
License: LGPLv2+
URL: http://gstreamer.freedesktop.org/
Source0: http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-%{version}.tar.xz
+# https://bugzilla.gnome.org/show_bug.cgi?id=735660
+Patch1: 0001-v4l2-get_nearest_size-Always-reinit-all-struct-field.patch
+Patch2: 0002-v4l2-get_nearest_size-Fix-Unsupported-field-type-err.patch
+Patch3: 0003-v4l2-Not-all-drivers-support-requesting-0-buffers.patch
BuildRequires: gstreamer1-devel >= %{version}
BuildRequires: gstreamer1-plugins-base-devel >= %{version}
@@ -84,6 +88,9 @@ to be installed.
%prep
%setup -q -n gst-plugins-good-%{version}
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
%build
%configure \
@@ -202,6 +209,9 @@ find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
%changelog
+* Fri Aug 29 2014 Hans de Goede <hdegoede at redhat.com> - 1.4.1-2
+- Fix v4l2-src not working with some v4l2 devices (bgo#735660)
+
* Fri Aug 29 2014 Wim Taymans <wtaymans at redhat.com> - 1.4.1-1
- Update to 1.4.1.
More information about the scm-commits
mailing list