summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiagoss@osg.samsung.com>2015-03-13 18:48:03 +0000
committerThiago Santos <thiagoss@osg.samsung.com>2015-03-13 18:48:03 +0000
commit0a945e7099159950f5ff14b13f7545dc53d2a57c (patch)
treeb6d81863ae0ad6a28a86dde760d3f92e0d377b1b
parent6cfa6c0da84f98a2efd5349340abe8afb2ae85fc (diff)
v4l2src: delay renegotiation until it is likely buffers were reclaimed
Allow renegotiation to happen when buffers have returned after an allocation query. As the allocation query is serialized, all buffers from the pool should have returned and we can stop it to create a new one for the new format https://bugzilla.gnome.org/show_bug.cgi?id=682770
-rw-r--r--sys/v4l2/gstv4l2src.c74
-rw-r--r--sys/v4l2/gstv4l2src.h2
2 files changed, 55 insertions, 21 deletions
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index 877561276..28a2d0fda 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -290,20 +290,11 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
static gboolean
gst_v4l2src_negotiate (GstBaseSrc * basesrc)
{
- GstV4l2Src *v4l2src;
- GstV4l2Object *obj;
GstCaps *thiscaps;
GstCaps *caps = NULL;
GstCaps *peercaps = NULL;
gboolean result = FALSE;
- v4l2src = GST_V4L2SRC (basesrc);
- obj = v4l2src->v4l2object;
-
- /* We don't allow renegotiation, just return TRUE in that case */
- if (GST_V4L2_IS_ACTIVE (obj))
- return TRUE;
-
/* first see what is possible on our source pad */
thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
@@ -432,6 +423,23 @@ gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter)
}
static gboolean
+gst_v4l2src_set_format (GstV4l2Src * v4l2src, GstCaps * caps)
+{
+ GstV4l2Object *obj;
+
+ obj = v4l2src->v4l2object;
+
+ g_signal_emit (v4l2src, gst_v4l2_signals[SIGNAL_PRE_SET_FORMAT], 0,
+ v4l2src->v4l2object->video_fd, caps);
+
+ if (!gst_v4l2_object_set_format (obj, caps))
+ /* error already posted */
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
{
GstV4l2Src *v4l2src;
@@ -444,16 +452,24 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
if (gst_v4l2_object_caps_equal (obj, caps))
return TRUE;
- /* make sure we stop capturing and dealloc buffers */
- if (!gst_v4l2_object_stop (obj))
- return FALSE;
-
- g_signal_emit (v4l2src, gst_v4l2_signals[SIGNAL_PRE_SET_FORMAT], 0,
- v4l2src->v4l2object->video_fd, caps);
+ if (GST_V4L2_IS_ACTIVE (obj)) {
+ /* Just check if the format is acceptable, once we know
+ * no buffers should be outstanding we try S_FMT.
+ *
+ * Basesrc will do an allocation query that
+ * should indirectly reclaim buffers, after that we can
+ * set the format and then configure our pool */
+ if (gst_v4l2_object_try_format (obj, caps))
+ v4l2src->pending_set_fmt = TRUE;
+ else
+ return FALSE;
+ } else {
+ /* make sure we stop capturing and dealloc buffers */
+ if (!gst_v4l2_object_stop (obj))
+ return FALSE;
- if (!gst_v4l2_object_set_format (obj, caps))
- /* error already posted */
- return FALSE;
+ return gst_v4l2src_set_format (v4l2src, caps);
+ }
return TRUE;
}
@@ -462,10 +478,23 @@ static gboolean
gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
{
GstV4l2Src *src = GST_V4L2SRC (bsrc);
- gboolean ret = FALSE;
+ gboolean ret = TRUE;
+
+ if (src->pending_set_fmt) {
+ GstCaps *caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc));
- if (gst_v4l2_object_decide_allocation (src->v4l2object, query))
- ret = GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
+ if (!gst_v4l2_object_stop (src->v4l2object))
+ return FALSE;
+ ret = gst_v4l2src_set_format (src, caps);
+ gst_caps_unref (caps);
+ src->pending_set_fmt = FALSE;
+ }
+
+ if (ret) {
+ ret = gst_v4l2_object_decide_allocation (src->v4l2object, query);
+ if (ret)
+ ret = GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
+ }
if (ret) {
if (!gst_buffer_pool_set_active (src->v4l2object->pool, TRUE))
@@ -597,6 +626,9 @@ gst_v4l2src_stop (GstBaseSrc * src)
if (!gst_v4l2_object_stop (obj))
return FALSE;
}
+
+ v4l2src->pending_set_fmt = FALSE;
+
return TRUE;
}
diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h
index 2d9055340..79dec17e0 100644
--- a/sys/v4l2/gstv4l2src.h
+++ b/sys/v4l2/gstv4l2src.h
@@ -61,6 +61,8 @@ struct _GstV4l2Src
GstClockTime ctrl_time;
+ gboolean pending_set_fmt;
+
/* Timestamp sanity check */
GstClockTime last_timestamp;
gboolean has_bad_timestamp;