v4l2src: Try to avoid TRY_FMT when camera is streaming
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 11 Jul 2018 16:21:44 +0000 (12:21 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 11 Jul 2018 23:05:00 +0000 (19:05 -0400)
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

sys/v4l2/gstv4l2object.c
sys/v4l2/gstv4l2object.h
sys/v4l2/gstv4l2src.c

index ee6ebdb..11c81ff 100644 (file)
@@ -4020,6 +4020,46 @@ gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps)
 }
 
 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;
index 9097a48..7871eaf 100644 (file)
@@ -278,7 +278,9 @@ gint         gst_v4l2_object_extrapolate_stride (const GstVideoFormatInfo * finf
 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);
index aba4496..88c813f 100644 (file)
@@ -447,6 +447,14 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
     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.
        *