From 66ca1b2280a918d3bd7c7ce09ec22d485be34666 Mon Sep 17 00:00:00 2001 From: Edgard Lima Date: Thu, 15 Nov 2007 12:22:10 +0000 Subject: Always copy buffers by default (handle safer with bugged drivers) and added a property to make it possible to use mma... Original commit message from CVS: Always copy buffers by default (handle safer with bugged drivers) and added a property to make it possible to use mmap effectively (no copy if possible) when application wants to. Fixes: #480557. --- sys/v4l2/gstv4l2src.c | 17 ++++++++++++++++- sys/v4l2/gstv4l2src.h | 3 +++ sys/v4l2/v4l2src_calls.c | 31 +++++++++++-------------------- 3 files changed, 30 insertions(+), 21 deletions(-) (limited to 'sys') diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 9fce1846..e8fd9c2d 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -68,11 +68,14 @@ GST_ELEMENT_DETAILS ("Video (video4linux2/raw) Source", GST_DEBUG_CATEGORY (v4l2src_debug); #define GST_CAT_DEFAULT v4l2src_debug +#define DEFAULT_PROP_ALWAYS_COPY TRUE + enum { PROP_0, V4L2_STD_OBJECT_PROPS, - PROP_QUEUE_SIZE + PROP_QUEUE_SIZE, + PROP_ALWAYS_COPY }; static const guint32 gst_v4l2_formats[] = { @@ -289,6 +292,10 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass) "Number of buffers to be enqueud in the driver", GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY, + g_param_spec_boolean ("always-copy", "Always Copy", + "If the buffer will or not be used directly from mmap", + DEFAULT_PROP_ALWAYS_COPY, G_PARAM_READWRITE)); basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps); basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps); @@ -310,6 +317,8 @@ gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass) /* number of buffers requested */ v4l2src->num_buffers = GST_V4L2_MIN_BUFFERS; + v4l2src->always_copy = DEFAULT_PROP_ALWAYS_COPY; + v4l2src->formats = NULL; v4l2src->is_capturing = FALSE; @@ -356,6 +365,9 @@ gst_v4l2src_set_property (GObject * object, case PROP_QUEUE_SIZE: v4l2src->num_buffers = g_value_get_uint (value); break; + case PROP_ALWAYS_COPY: + v4l2src->always_copy = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -376,6 +388,9 @@ gst_v4l2src_get_property (GObject * object, case PROP_QUEUE_SIZE: g_value_set_uint (value, v4l2src->num_buffers); break; + case PROP_ALWAYS_COPY: + g_value_set_boolean (value, v4l2src->always_copy); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h index f4677458..ae7aa74e 100644 --- a/sys/v4l2/gstv4l2src.h +++ b/sys/v4l2/gstv4l2src.h @@ -101,6 +101,9 @@ struct _GstV4l2Src gboolean use_mmap; guint32 frame_byte_size; + /* if the buffer will be or not used from directly mmap */ + gboolean always_copy; + /* True if we want to stop */ gboolean quit; gboolean is_capturing; diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index 0b03c999..e2a07ea9 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -954,26 +954,16 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf) } } - do { + g_mutex_lock (v4l2src->pool->lock); - g_mutex_lock (v4l2src->pool->lock); + index = buffer.index; - index = buffer.index; - - /* get our GstBuffer with that index from the pool, if the buffer was - * outstanding we have a serious problem. */ - pool_buffer = GST_BUFFER (v4l2src->pool->buffers[index]); - - if (pool_buffer == NULL) { - g_mutex_unlock (v4l2src->pool->lock); - g_usleep (20000); /* wait 20 miliseconds */ - /* FIXME: we need a exit condition here */ - } else { - break; - } - - } while (TRUE); + /* get our GstBuffer with that index from the pool, if the buffer was + * outstanding we have a serious problem. */ + pool_buffer = GST_BUFFER (v4l2src->pool->buffers[index]); + if (pool_buffer == NULL) + goto no_buffer; GST_LOG_OBJECT (v4l2src, "grabbed buffer %p at index %d", pool_buffer, index); @@ -982,7 +972,8 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf) v4l2src->pool->num_live_buffers++; /* if we are handing out the last buffer in the pool, we need to make a * copy and bring the buffer back in the pool. */ - need_copy = v4l2src->pool->num_live_buffers == v4l2src->pool->buffer_count; + need_copy = v4l2src->always_copy + || (v4l2src->pool->num_live_buffers == v4l2src->pool->buffer_count); g_mutex_unlock (v4l2src->pool->lock); @@ -1020,6 +1011,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf) if (G_UNLIKELY (need_copy)) { *buf = gst_buffer_copy (pool_buffer); + GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); /* this will requeue */ gst_buffer_unref (pool_buffer); } else { @@ -1059,7 +1051,7 @@ too_many_trials: NUM_TRIALS, v4l2src->v4l2object->videodev, g_strerror (errno))); return GST_FLOW_ERROR; } -#if 0 +no_buffer: { GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED, (_("Failed trying to get video frames from device '%s'."), @@ -1068,7 +1060,6 @@ too_many_trials: g_mutex_unlock (v4l2src->pool->lock); return GST_FLOW_ERROR; } -#endif /* qbuf_failed: { -- cgit