summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2013-05-02 09:41:01 +0200
committerMichael Olbrich <m.olbrich@pengutronix.de>2013-09-13 16:29:46 +0200
commitc3c7164ffe0251869840b7d5771415696e416cc7 (patch)
tree52dfb78a06adf60948887274ed9ce4d280d11c31
parentbbc92d25bc2c0af33e8f1b7877505475145bbf9e (diff)
downloadgst-plugins-good-c3c7164ffe0251869840b7d5771415696e416cc7.tar.gz
gst-plugins-good-c3c7164ffe0251869840b7d5771415696e416cc7.tar.xz
v4l2: try to allocate new buffers with VIDIOC_CREATE_BUFS if needed
If max_buffers is 0 then an arbitrary number of buffers (currently 4) is allocated. If this is not enough v4l2src starts copying buffers. With this patch VIDIOC_CREATE_BUFS is used to allocate a new buffer. If this fails v4l2src falls back to copying buffers. https://bugzilla.gnome.org/show_bug.cgi?id=699447
-rw-r--r--sys/v4l2/gstv4l2bufferpool.c52
-rw-r--r--sys/v4l2/gstv4l2bufferpool.h1
2 files changed, 53 insertions, 0 deletions
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 0019c4819..fcf6a7f5c 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -159,6 +159,28 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
case GST_V4L2_IO_MMAP:
case GST_V4L2_IO_DMABUF:
{
+#ifdef VIDIOC_CREATE_BUFS
+ if (pool->num_allocated == pool->num_buffers) {
+ struct v4l2_create_buffers create_bufs;
+
+ memset (&create_bufs, 0, sizeof (struct v4l2_create_buffers));
+ create_bufs.count = 1;
+ create_bufs.memory = V4L2_MEMORY_MMAP;
+ create_bufs.format.type = obj->type;
+
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_G_FMT, &create_bufs.format) < 0)
+ goto g_fmt_failed;
+
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_CREATE_BUFS, &create_bufs) < 0)
+ goto create_bufs_failed;
+
+ GST_LOG_OBJECT (pool, "created buffer with index: %u",
+ create_bufs.index);
+ pool->num_buffers++;
+ pool->buffers = g_renew (GstBuffer *, pool->buffers, pool->num_buffers);
+ pool->buffers[pool->num_buffers - 1] = NULL;
+ }
+#endif
newbuf = gst_buffer_new ();
meta = GST_V4L2_META_ADD (newbuf);
@@ -252,6 +274,24 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
return GST_FLOW_OK;
/* ERRORS */
+#ifdef VIDIOC_CREATE_BUFS
+g_fmt_failed:
+ {
+ gint errnosave = errno;
+
+ GST_WARNING ("Failed G_FMT: %s", g_strerror (errnosave));
+ errno = errnosave;
+ return GST_FLOW_ERROR;
+ }
+create_bufs_failed:
+ {
+ gint errnosave = errno;
+
+ GST_WARNING ("Failed CREATE_BUFS: %s", g_strerror (errnosave));
+ errno = errnosave;
+ return GST_FLOW_ERROR;
+ }
+#endif
querybuf_failed:
{
gint errnosave = errno;
@@ -795,6 +835,17 @@ gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
/* start copying buffers when we are running low on buffers */
if (pool->num_queued < pool->copy_threshold) {
GstBuffer *copy;
+#ifdef VIDIOC_CREATE_BUFS
+ if (pool->can_alloc) {
+ if (GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
+ &copy, params) == GST_FLOW_OK) {
+ gst_v4l2_buffer_pool_release_buffer (bpool, copy);
+ break;
+ } else {
+ pool->can_alloc = FALSE;
+ }
+ }
+#endif
/* copy the memory */
copy = gst_buffer_copy (*buffer);
@@ -991,6 +1042,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, NULL);
pool->video_fd = fd;
pool->obj = obj;
+ pool->can_alloc = TRUE;
s = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
gst_buffer_pool_config_set_params (s, caps, obj->sizeimage, 2, 0);
diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h
index a9b022e9a..64e185227 100644
--- a/sys/v4l2/gstv4l2bufferpool.h
+++ b/sys/v4l2/gstv4l2bufferpool.h
@@ -55,6 +55,7 @@ struct _GstV4l2BufferPool
GstAllocationParams params;
guint size;
gboolean add_videometa;
+ gboolean can_alloc; /* if extra buffers can be allocated */
guint num_buffers; /* number of buffers we use */
guint num_allocated; /* number of buffers allocated by the driver */