From add1cbdbd81e02caecc56a04d3d1c69b7be7a13d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 4 Aug 2011 12:50:01 +0100 Subject: [PATCH] v4l2: activate the pool in fallback When nobody is using our pool, activate it ourselves. Avoid leaking the buffer array. Set default pool configuration with caps. Don't keep current_caps, core does that for us now. --- sys/v4l2/gstv4l2bufferpool.c | 50 ++++++++++++++++++++++++++++++------ sys/v4l2/gstv4l2bufferpool.h | 9 ++++--- sys/v4l2/gstv4l2object.c | 2 +- sys/v4l2/gstv4l2object.h | 2 +- sys/v4l2/gstv4l2sink.c | 28 +++++--------------- sys/v4l2/gstv4l2sink.h | 1 - sys/v4l2/gstv4l2src.c | 6 +++-- 7 files changed, 59 insertions(+), 39 deletions(-) diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 3a5dc4026e..ea2159bbda 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -339,6 +339,9 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool) GST_DEBUG_OBJECT (pool, "starting, requesting %d MMAP buffers", max_buffers); + if (max_buffers == 0) + max_buffers = 4; + memset (&breq, 0, sizeof (struct v4l2_requestbuffers)); breq.type = obj->type; breq.count = max_buffers; @@ -456,6 +459,9 @@ gst_v4l2_buffer_pool_stop (GstBufferPool * bpool) if (pool->buffers[n]) gst_v4l2_buffer_pool_free_buffer (bpool, pool->buffers[n]); } + g_free (pool->buffers); + pool->buffers = NULL; + return ret; /* ERRORS */ @@ -813,10 +819,7 @@ gst_v4l2_buffer_pool_finalize (GObject * object) if (pool->video_fd >= 0) v4l2_close (pool->video_fd); - if (pool->buffers) { - g_free (pool->buffers); - pool->buffers = NULL; - } + g_free (pool->buffers); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -851,8 +854,8 @@ gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass) * * Returns: the new pool, use gst_object_unref() to free resources */ -GstV4l2BufferPool * -gst_v4l2_buffer_pool_new (GstV4l2Object * obj) +GstBufferPool * +gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps) { GstV4l2BufferPool *pool; gint fd; @@ -865,7 +868,10 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj) pool->video_fd = fd; pool->obj = obj; - return pool; + gst_buffer_pool_config_set (GST_BUFFER_POOL_CAST (pool)->config, caps, + obj->sizeimage, 2, 0, 0, 0); + + return GST_BUFFER_POOL (pool); /* ERRORS */ dup_failed: @@ -1007,14 +1013,31 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer * buf) if (buf->pool == bpool) { /* nothing, we can queue directly */ to_queue = buf; + GST_LOG_OBJECT (pool, "processing buffer from our pool"); } else { + GST_LOG_OBJECT (pool, "alloc buffer from our pool"); + if (!gst_buffer_pool_is_active (bpool)) { + GstStructure *config; + + /* this pool was not activated, configure and activate */ + GST_DEBUG_OBJECT (pool, "activating pool"); + + config = gst_buffer_pool_get_config (bpool); + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_META_VIDEO); + gst_buffer_pool_set_config (bpool, config); + + if (!gst_buffer_pool_set_active (bpool, TRUE)) + goto activate_failed; + } + /* this can block if all buffers are outstanding which would be * strange because we would expect the upstream element to have * allocated them and returned to us.. */ ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool, &to_queue, NULL); if (ret != GST_FLOW_OK) - goto done; + goto acquire_failed; /* copy into it and queue */ if (!gst_v4l2_object_copy (obj, to_queue, buf)) @@ -1058,6 +1081,17 @@ done: return ret; /* ERRORS */ +activate_failed: + { + GST_ERROR_OBJECT (obj->element, "failed to activate pool"); + return GST_FLOW_ERROR; + } +acquire_failed: + { + GST_WARNING_OBJECT (obj->element, "failed to acquire a buffer: %s", + gst_flow_get_name (ret)); + return ret; + } copy_failed: { GST_ERROR_OBJECT (obj->element, "failed to copy data"); diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h index 6a2e63d152..17e04e3bd4 100644 --- a/sys/v4l2/gstv4l2bufferpool.h +++ b/sys/v4l2/gstv4l2bufferpool.h @@ -39,9 +39,10 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2buffer_debug); G_BEGIN_DECLS -#define GST_TYPE_V4L2_BUFFER_POOL (gst_v4l2_buffer_pool_get_type()) -#define GST_IS_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER_POOL)) -#define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool)) +#define GST_TYPE_V4L2_BUFFER_POOL (gst_v4l2_buffer_pool_get_type()) +#define GST_IS_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER_POOL)) +#define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool)) +#define GST_V4L2_BUFFER_POOL_CAST(obj) ((GstV4l2BufferPool*)(obj)) struct _GstV4l2BufferPool { @@ -84,7 +85,7 @@ const GstMetaInfo * gst_meta_v4l2_get_info (void); GType gst_v4l2_buffer_pool_get_type (void); -GstV4l2BufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object *obj); +GstBufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object *obj, GstCaps *caps); GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer * buf); diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index e0fa836dd2..bcfbb54fae 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -2124,7 +2124,7 @@ gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps) /* Map the buffers */ GST_LOG_OBJECT (v4l2object->element, "initiating buffer pool"); - if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object))) + if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object, caps))) goto buffer_pool_new_failed; GST_V4L2_SET_ACTIVE (v4l2object); diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index 8c0e70bd8e..aae6a8db4c 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -126,7 +126,7 @@ struct _GstV4l2Object { /* optional pool */ gboolean always_copy; - GstV4l2BufferPool *pool; + GstBufferPool *pool; /* the video device's capabilities */ struct v4l2_capability vcap; diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c index 2df5f4a9eb..f2d9909c93 100644 --- a/sys/v4l2/gstv4l2sink.c +++ b/sys/v4l2/gstv4l2sink.c @@ -236,7 +236,6 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink) g_object_set (v4l2sink, "device", "/dev/video1", NULL); v4l2sink->probed_caps = NULL; - v4l2sink->current_caps = NULL; v4l2sink->overlay_fields_set = 0; v4l2sink->crop_fields_set = 0; @@ -252,10 +251,6 @@ gst_v4l2sink_dispose (GObject * object) gst_caps_unref (v4l2sink->probed_caps); } - if (v4l2sink->current_caps) { - gst_caps_unref (v4l2sink->current_caps); - } - G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -584,16 +579,6 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) return FALSE; } - if (v4l2sink->current_caps) { - GST_DEBUG_OBJECT (v4l2sink, "already have caps set.. are they equal?"); - LOG_CAPS (v4l2sink, v4l2sink->current_caps); - if (gst_caps_is_equal (v4l2sink->current_caps, caps)) { - GST_DEBUG_OBJECT (v4l2sink, "yes they are!"); - return TRUE; - } - GST_DEBUG_OBJECT (v4l2sink, "no they aren't!"); - } - if (!gst_v4l2_object_stop (obj)) goto stop_failed; @@ -618,8 +603,6 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) GST_VIDEO_SINK_WIDTH (v4l2sink) = v4l2sink->video_width; GST_VIDEO_SINK_HEIGHT (v4l2sink) = v4l2sink->video_height; - v4l2sink->current_caps = gst_caps_ref (caps); - return TRUE; /* ERRORS */ @@ -642,9 +625,8 @@ gst_v4l2sink_setup_allocation (GstBaseSink * bsink, GstQuery * query) GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); GstV4l2Object *obj = v4l2sink->v4l2object; GstBufferPool *pool; - GstStructure *config; + gsize size = 0; GstCaps *caps; - guint size = 0; gboolean need_pool; gst_query_parse_allocation (query, &caps, &need_pool); @@ -652,11 +634,12 @@ gst_v4l2sink_setup_allocation (GstBaseSink * bsink, GstQuery * query) if (caps == NULL) goto no_caps; - if ((pool = GST_BUFFER_POOL_CAST (obj->pool))) + if ((pool = obj->pool)) gst_object_ref (pool); if (pool != NULL) { const GstCaps *pcaps; + GstStructure *config; /* we had a pool, check caps */ config = gst_buffer_pool_get_config (pool); @@ -670,7 +653,7 @@ gst_v4l2sink_setup_allocation (GstBaseSink * bsink, GstQuery * query) } } /* we need at least 2 buffers to operate */ - gst_query_set_allocation_params (query, size, 2, 0, 0, 15, pool); + gst_query_set_allocation_params (query, size, 2, 0, 0, 0, pool); /* we also support various metadata */ gst_query_add_allocation_meta (query, GST_META_API_VIDEO); @@ -708,7 +691,8 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) if (G_UNLIKELY (obj->pool == NULL)) goto not_negotiated; - ret = gst_v4l2_buffer_pool_process (obj->pool, buf); + ret = + gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool), buf); return ret; diff --git a/sys/v4l2/gstv4l2sink.h b/sys/v4l2/gstv4l2sink.h index 05061cd04c..b461e2c922 100644 --- a/sys/v4l2/gstv4l2sink.h +++ b/sys/v4l2/gstv4l2sink.h @@ -55,7 +55,6 @@ struct _GstV4l2Sink { /*< private >*/ GstV4l2Object * v4l2object; GstCaps *probed_caps; /* all supported caps of underlying v4l2 device */ - GstCaps *current_caps; /* the current negotiated caps */ gint video_width, video_height; /* original (unscaled) video w/h */ diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index a9df8ef8b0..eed82d11f3 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -633,7 +633,8 @@ gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query) min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n); /* max latency is total duration of the frame buffer */ - max_latency = obj->pool->max_buffers * min_latency; + max_latency = + GST_V4L2_BUFFER_POOL_CAST (obj->pool)->max_buffers * min_latency; GST_DEBUG_OBJECT (bsrc, "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, @@ -759,7 +760,8 @@ gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf) } #endif - ret = gst_v4l2_buffer_pool_process (obj->pool, buf); + ret = + gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool), buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto error;