From b12b8b0b220e5856695f40a3079293a73b52fb65 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Wed, 11 Jul 2018 12:21:44 -0400 Subject: [PATCH] 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 --- sys/v4l2/gstv4l2object.c | 40 ++++++++++++++++++++++++++++++++++++++++ sys/v4l2/gstv4l2object.h | 4 +++- sys/v4l2/gstv4l2src.c | 8 ++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) 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 @@ 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; 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 @@ 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); 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 @@ 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. * -- 2.7.4