v4l2src: Try to avoid TRY_FMT when camera is streaming
Some camera firmware crash is TRY_FMT is called during streaming. As a
side effect. This try and detect that the same format as currently
running is about to be tried, and skip renegotiation.
https://bugzilla.gnome.org/show_bug.cgi?id=796789
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index ee6ebdb..11c81ff 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -4020,6 +4020,46 @@
}
gboolean
+gst_v4l2_object_caps_is_subset (GstV4l2Object * v4l2object, GstCaps * caps)
+{
+ GstStructure *config;
+ GstCaps *oldcaps;
+ gboolean ret;
+
+ if (!v4l2object->pool)
+ return FALSE;
+
+ config = gst_buffer_pool_get_config (v4l2object->pool);
+ gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
+
+ ret = oldcaps && gst_caps_is_subset (oldcaps, caps);
+
+ gst_structure_free (config);
+
+ return ret;
+}
+
+GstCaps *
+gst_v4l2_object_get_current_caps (GstV4l2Object * v4l2object)
+{
+ GstStructure *config;
+ GstCaps *oldcaps;
+
+ if (!v4l2object->pool)
+ return NULL;
+
+ config = gst_buffer_pool_get_config (v4l2object->pool);
+ gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
+
+ if (oldcaps)
+ gst_caps_ref (oldcaps);
+
+ gst_structure_free (config);
+
+ return oldcaps;
+}
+
+gboolean
gst_v4l2_object_unlock (GstV4l2Object * v4l2object)
{
gboolean ret = TRUE;
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 9097a48..7871eaf 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -278,7 +278,9 @@
gboolean gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error);
gboolean gst_v4l2_object_try_format (GstV4l2Object * v4l2object, GstCaps * caps, GstV4l2Error * error);
-gboolean gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps);
+gboolean gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps);
+gboolean gst_v4l2_object_caps_is_subset (GstV4l2Object * v4l2object, GstCaps * caps);
+GstCaps * gst_v4l2_object_get_current_caps (GstV4l2Object * v4l2object);
gboolean gst_v4l2_object_unlock (GstV4l2Object * v4l2object);
gboolean gst_v4l2_object_unlock_stop (GstV4l2Object * v4l2object);
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index aba4496..88c813f 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -447,6 +447,14 @@
fcaps = gst_caps_copy_nth (caps, i);
if (GST_V4L2_IS_ACTIVE (obj)) {
+ /* try hard to avoid TRY_FMT since some UVC camera just crash when this
+ * is called at run-time. */
+ if (gst_v4l2_object_caps_is_subset (obj, fcaps)) {
+ gst_caps_unref (fcaps);
+ fcaps = gst_v4l2_object_get_current_caps (obj);
+ break;
+ }
+
/* Just check if the format is acceptable, once we know
* no buffers should be outstanding we try S_FMT.
*