From 67202adc8db460dc331c5440741c8c8c91b7578e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Aug 29 2014 10:56:53 +0000 Subject: Fix v4l2-src not working with some v4l2 devices (bgo#735660) --- 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 - 1.4.1-2 +- Fix v4l2-src not working with some v4l2 devices (bgo#735660) + * Fri Aug 29 2014 Wim Taymans - 1.4.1-1 - Update to 1.4.1.