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.
This commit is contained in:
Edgard Lima 2007-11-15 12:22:10 +00:00
parent 62d8456eb7
commit 66ca1b2280
4 changed files with 41 additions and 21 deletions

View file

@ -1,3 +1,14 @@
2007-11-15 Edgard Lima <edgard.lima@indt.org.br>
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_set_property),
(gst_v4l2src_get_property):
* sys/v4l2/gstv4l2src.h:
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_grab_frame):
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.
2007-11-14 Tim-Philipp Müller <tim at centricular dot net> 2007-11-14 Tim-Philipp Müller <tim at centricular dot net>
* gst/id3demux/id3tags.c: * gst/id3demux/id3tags.c:

View file

@ -68,11 +68,14 @@ GST_ELEMENT_DETAILS ("Video (video4linux2/raw) Source",
GST_DEBUG_CATEGORY (v4l2src_debug); GST_DEBUG_CATEGORY (v4l2src_debug);
#define GST_CAT_DEFAULT v4l2src_debug #define GST_CAT_DEFAULT v4l2src_debug
#define DEFAULT_PROP_ALWAYS_COPY TRUE
enum enum
{ {
PROP_0, PROP_0,
V4L2_STD_OBJECT_PROPS, V4L2_STD_OBJECT_PROPS,
PROP_QUEUE_SIZE PROP_QUEUE_SIZE,
PROP_ALWAYS_COPY
}; };
static const guint32 gst_v4l2_formats[] = { 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", "Number of buffers to be enqueud in the driver",
GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS, GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS,
G_PARAM_READWRITE)); 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->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_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 */ /* number of buffers requested */
v4l2src->num_buffers = GST_V4L2_MIN_BUFFERS; v4l2src->num_buffers = GST_V4L2_MIN_BUFFERS;
v4l2src->always_copy = DEFAULT_PROP_ALWAYS_COPY;
v4l2src->formats = NULL; v4l2src->formats = NULL;
v4l2src->is_capturing = FALSE; v4l2src->is_capturing = FALSE;
@ -356,6 +365,9 @@ gst_v4l2src_set_property (GObject * object,
case PROP_QUEUE_SIZE: case PROP_QUEUE_SIZE:
v4l2src->num_buffers = g_value_get_uint (value); v4l2src->num_buffers = g_value_get_uint (value);
break; break;
case PROP_ALWAYS_COPY:
v4l2src->always_copy = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -376,6 +388,9 @@ gst_v4l2src_get_property (GObject * object,
case PROP_QUEUE_SIZE: case PROP_QUEUE_SIZE:
g_value_set_uint (value, v4l2src->num_buffers); g_value_set_uint (value, v4l2src->num_buffers);
break; break;
case PROP_ALWAYS_COPY:
g_value_set_boolean (value, v4l2src->always_copy);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;

View file

@ -101,6 +101,9 @@ struct _GstV4l2Src
gboolean use_mmap; gboolean use_mmap;
guint32 frame_byte_size; guint32 frame_byte_size;
/* if the buffer will be or not used from directly mmap */
gboolean always_copy;
/* True if we want to stop */ /* True if we want to stop */
gboolean quit; gboolean quit;
gboolean is_capturing; gboolean is_capturing;

View file

@ -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. */
/* get our GstBuffer with that index from the pool, if the buffer was pool_buffer = GST_BUFFER (v4l2src->pool->buffers[index]);
* 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);
if (pool_buffer == NULL)
goto no_buffer;
GST_LOG_OBJECT (v4l2src, "grabbed buffer %p at index %d", pool_buffer, index); 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++; v4l2src->pool->num_live_buffers++;
/* if we are handing out the last buffer in the pool, we need to make a /* 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. */ * 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); g_mutex_unlock (v4l2src->pool->lock);
@ -1020,6 +1011,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
if (G_UNLIKELY (need_copy)) { if (G_UNLIKELY (need_copy)) {
*buf = gst_buffer_copy (pool_buffer); *buf = gst_buffer_copy (pool_buffer);
GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
/* this will requeue */ /* this will requeue */
gst_buffer_unref (pool_buffer); gst_buffer_unref (pool_buffer);
} else { } else {
@ -1059,7 +1051,7 @@ too_many_trials:
NUM_TRIALS, v4l2src->v4l2object->videodev, g_strerror (errno))); NUM_TRIALS, v4l2src->v4l2object->videodev, g_strerror (errno)));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
#if 0 no_buffer:
{ {
GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED, GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
(_("Failed trying to get video frames from device '%s'."), (_("Failed trying to get video frames from device '%s'."),
@ -1068,7 +1060,6 @@ too_many_trials:
g_mutex_unlock (v4l2src->pool->lock); g_mutex_unlock (v4l2src->pool->lock);
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
#endif
/* /*
qbuf_failed: qbuf_failed:
{ {