3 * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * 2006 Edgard Lima <edgard.lima@indt.org.br>
5 * 2009 Texas Instruments, Inc - http://www.ti.com/
7 * gstv4l2bufferpool.c V4L2 buffer pool class
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
33 #include "gst/video/video.h"
34 #include "gst/video/gstmetavideo.h"
36 #include <gstv4l2bufferpool.h>
38 #include "gstv4l2src.h"
39 #include "gstv4l2sink.h"
40 #include "v4l2_calls.h"
41 #include "gst/gst-i18n-plugin.h"
43 /* videodev2.h is not versioned and we can't easily check for the presence
44 * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
45 * was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */
46 #ifndef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
47 #define V4L2_FIELD_INTERLACED_TB 8
48 #define V4L2_FIELD_INTERLACED_BT 9
52 GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
53 #define GST_CAT_DEFAULT v4l2_debug
59 gst_meta_v4l2_get_info (void)
61 static const GstMetaInfo *meta_info = NULL;
63 if (meta_info == NULL) {
65 gst_meta_register ("GstMetaV4l2", "GstMetaV4l2",
66 sizeof (GstMetaV4l2), (GstMetaInitFunction) NULL,
67 (GstMetaFreeFunction) NULL, (GstMetaCopyFunction) NULL,
68 (GstMetaTransformFunction) NULL);
76 #define gst_v4l2_buffer_pool_parent_class parent_class
77 G_DEFINE_TYPE (GstV4l2BufferPool, gst_v4l2_buffer_pool, GST_TYPE_BUFFER_POOL);
80 gst_v4l2_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
82 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
87 meta = GST_META_V4L2_GET (buffer);
88 g_assert (meta != NULL);
92 index = meta->vbuffer.index;
93 GST_LOG_OBJECT (pool, "finalizing buffer %p %d", buffer, index);
94 pool->buffers[index] = NULL;
97 "buffer %p (data %p, len %u) freed, unmapping",
98 buffer, meta->mem, meta->vbuffer.length);
99 v4l2_munmap (meta->mem, meta->vbuffer.length);
101 gst_buffer_unref (buffer);
105 gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
106 GstBufferPoolParams * params)
108 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
118 newbuf = gst_buffer_new ();
119 meta = GST_META_V4L2_ADD (newbuf);
123 GST_LOG_OBJECT (pool, "creating buffer %u, %p", index, newbuf, pool);
125 meta->vbuffer.index = index;
126 meta->vbuffer.type = obj->type;
127 meta->vbuffer.memory = V4L2_MEMORY_MMAP;
129 if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &meta->vbuffer) < 0)
130 goto querybuf_failed;
132 GST_LOG_OBJECT (pool, " index: %u", meta->vbuffer.index);
133 GST_LOG_OBJECT (pool, " type: %d", meta->vbuffer.type);
134 GST_LOG_OBJECT (pool, " bytesused: %u", meta->vbuffer.bytesused);
135 GST_LOG_OBJECT (pool, " flags: %08x", meta->vbuffer.flags);
136 GST_LOG_OBJECT (pool, " field: %d", meta->vbuffer.field);
137 GST_LOG_OBJECT (pool, " memory: %d", meta->vbuffer.memory);
138 if (meta->vbuffer.memory == V4L2_MEMORY_MMAP)
139 GST_LOG_OBJECT (pool, " MMAP offset: %u", meta->vbuffer.m.offset);
140 GST_LOG_OBJECT (pool, " length: %u", meta->vbuffer.length);
141 GST_LOG_OBJECT (pool, " input: %u", meta->vbuffer.input);
143 meta->mem = v4l2_mmap (0, meta->vbuffer.length,
144 PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
145 meta->vbuffer.m.offset);
146 if (meta->mem == MAP_FAILED)
149 gst_buffer_take_memory (newbuf, -1,
150 gst_memory_new_wrapped (0,
151 meta->mem, NULL, meta->vbuffer.length, 0, meta->vbuffer.length));
153 /* add metadata to raw video buffers */
155 gsize offset[GST_VIDEO_MAX_PLANES];
156 gint stride[GST_VIDEO_MAX_PLANES];
159 stride[0] = obj->bytesperline;
161 GST_DEBUG_OBJECT (pool, "adding video meta");
162 gst_buffer_add_meta_video_full (newbuf, info->flags,
163 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
164 GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
177 gint errnosave = errno;
179 GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
180 gst_buffer_unref (newbuf);
182 return GST_FLOW_ERROR;
186 gint errnosave = errno;
188 GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
189 gst_buffer_unref (newbuf);
191 return GST_FLOW_ERROR;
196 gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
198 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
200 guint size, min_buffers, max_buffers;
203 GST_DEBUG_OBJECT (pool, "set config");
205 /* parse the config and keep around */
206 if (!gst_buffer_pool_config_get (config, &caps, &size, &min_buffers,
207 &max_buffers, &prefix, &align))
210 GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
212 pool->min_buffers = min_buffers;
213 pool->max_buffers = max_buffers;
219 GST_WARNING_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
225 gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
227 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
228 GstV4l2Object *obj = pool->obj;
230 struct v4l2_requestbuffers breq;
233 num_buffers = pool->max_buffers;
235 /* first, lets request buffers, and see how many we can get: */
236 GST_DEBUG_OBJECT (pool, "starting, requesting %d MMAP buffers", num_buffers);
238 memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
239 breq.type = obj->type;
240 breq.count = num_buffers;
241 breq.memory = V4L2_MEMORY_MMAP;
243 if (v4l2_ioctl (pool->video_fd, VIDIOC_REQBUFS, &breq) < 0)
246 GST_LOG_OBJECT (pool, " count: %u", breq.count);
247 GST_LOG_OBJECT (pool, " type: %d", breq.type);
248 GST_LOG_OBJECT (pool, " memory: %d", breq.memory);
250 if (breq.count < GST_V4L2_MIN_BUFFERS)
253 if (num_buffers != breq.count) {
254 GST_WARNING_OBJECT (pool, "using %u buffers instead", breq.count);
255 num_buffers = breq.count;
259 pool->requeuebuf = (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? TRUE : FALSE);
260 pool->buffer_count = num_buffers;
261 pool->buffers = g_new0 (GstBuffer *, num_buffers);
264 /* now, map the buffers: */
265 for (n = 0; n < num_buffers; n++) {
268 if (gst_v4l2_buffer_pool_alloc_buffer (bpool, &buffer, NULL) != GST_FLOW_OK)
269 goto buffer_new_failed;
271 if (pool->requeuebuf)
272 gst_v4l2_buffer_pool_qbuf (bpool, buffer);
279 GST_ERROR_OBJECT (pool,
280 "error requesting %d buffers: %s", num_buffers, g_strerror (errno));
285 GST_ERROR_OBJECT (pool,
286 "we received %d from device '%s', we want at least %d",
287 breq.count, obj->videodev, GST_V4L2_MIN_BUFFERS);
292 GST_ERROR_OBJECT (pool, "failed to create a buffer");
298 gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
300 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
303 GST_DEBUG_OBJECT (pool, "stopping pool");
305 /* free the buffers: */
306 for (n = 0; n < pool->buffer_count; n++)
307 gst_v4l2_buffer_pool_free_buffer (bpool, pool->buffers[n]);
313 gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
314 GstBufferPoolParams * params)
316 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
318 struct v4l2_buffer vbuffer;
319 GstV4l2Object *obj = pool->obj;
321 if (GST_BUFFER_POOL_IS_FLUSHING (bpool))
324 memset (&vbuffer, 0x00, sizeof (vbuffer));
325 vbuffer.type = obj->type;
326 vbuffer.memory = V4L2_MEMORY_MMAP;
328 if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &vbuffer) < 0)
331 /* get our GstBuffer with that index from the pool, if the buffer was
332 * outstanding we have a serious problem.
334 outbuf = pool->buffers[vbuffer.index];
338 /* mark the buffer outstanding */
339 pool->buffers[vbuffer.index] = NULL;
341 GST_LOG_OBJECT (pool,
342 "dequeued frame %d (ix=%d), flags %08x, pool-ct=%d, buffer=%p",
343 vbuffer.sequence, vbuffer.index, vbuffer.flags, pool->num_live_buffers,
346 pool->num_live_buffers++;
347 GST_DEBUG_OBJECT (pool, "num_live_buffers++: %d", pool->num_live_buffers);
349 /* set top/bottom field first if v4l2_buffer has the information */
350 if (vbuffer.field == V4L2_FIELD_INTERLACED_TB)
351 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF);
352 if (vbuffer.field == V4L2_FIELD_INTERLACED_BT)
353 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_TFF);
355 /* this can change at every frame, esp. with jpeg */
356 gst_buffer_resize (outbuf, 0, vbuffer.bytesused);
365 return GST_FLOW_WRONG_STATE;
369 GST_WARNING_OBJECT (pool,
370 "problem grabbing frame %d (ix=%d), pool-ct=%d, buf.flags=%d",
371 vbuffer.sequence, vbuffer.index,
372 GST_MINI_OBJECT_REFCOUNT (pool), vbuffer.flags);
376 GST_WARNING_OBJECT (pool,
377 "Non-blocking I/O has been selected using O_NONBLOCK and"
378 " no buffer was in the outgoing queue. device %s", obj->videodev);
381 GST_ERROR_OBJECT (pool,
382 "The buffer type is not supported, or the index is out of bounds, "
383 "or no buffers have been allocated yet, or the userptr "
384 "or length are invalid. device %s", obj->videodev);
387 GST_ERROR_OBJECT (pool,
388 "insufficient memory to enqueue a user pointer buffer");
391 GST_INFO_OBJECT (pool,
392 "VIDIOC_DQBUF failed due to an internal error."
393 " Can also indicate temporary problems like signal loss."
394 " Note the driver might dequeue an (empty) buffer despite"
395 " returning an error, or even stop capturing."
396 " device %s", obj->videodev);
397 /* have we de-queued a buffer ? */
398 if (!(vbuffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
399 GST_DEBUG_OBJECT (pool, "reenqueing buffer");
400 /* FIXME ... should we do something here? */
404 GST_WARNING_OBJECT (pool,
405 "could not sync on a buffer on device %s", obj->videodev);
408 GST_WARNING_OBJECT (pool,
409 "Grabbing frame got interrupted on %s unexpectedly. %d: %s.",
410 obj->videodev, errno, g_strerror (errno));
413 return GST_FLOW_ERROR;
417 GST_ERROR_OBJECT (pool, "No free buffers found in the pool at index %d.",
419 return GST_FLOW_ERROR;
424 gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
426 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
428 GST_DEBUG_OBJECT (pool, "release");
430 if (pool->requeuebuf)
431 gst_v4l2_buffer_pool_qbuf (bpool, buffer);
435 gst_v4l2_buffer_pool_finalize (GObject * object)
437 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
439 if (pool->video_fd >= 0)
440 v4l2_close (pool->video_fd);
443 g_free (pool->buffers);
444 pool->buffers = NULL;
447 G_OBJECT_CLASS (parent_class)->finalize (object);
451 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
456 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
458 GObjectClass *object_class = G_OBJECT_CLASS (klass);
459 GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
461 object_class->finalize = gst_v4l2_buffer_pool_finalize;
463 bufferpool_class->start = gst_v4l2_buffer_pool_start;
464 bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
465 bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
466 bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
467 bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
468 bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
469 bufferpool_class->free_buffer = gst_v4l2_buffer_pool_free_buffer;
473 * gst_v4l2_buffer_pool_new:
474 * @obj: the v4l2 object owning the pool
475 * @num_buffers: the requested number of buffers in the pool
476 * @requeuebuf: if %TRUE, and if the pool is still in the running state, a
477 * buffer with no remaining references is immediately passed back to v4l2
478 * (VIDIOC_QBUF), otherwise it is returned to the pool of available buffers
479 * (which can be accessed via gst_v4l2_buffer_pool_get().
481 * Construct a new buffer pool.
483 * Returns: the new pool, use gst_v4l2_buffer_pool_destroy() to free resources
486 gst_v4l2_buffer_pool_new (GstV4l2Object * obj)
488 GstV4l2BufferPool *pool;
490 pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, NULL);
492 pool->video_fd = v4l2_dup (obj->video_fd);
493 if (pool->video_fd < 0)
498 return GST_BUFFER_POOL_CAST (pool);
503 gint errnosave = errno;
504 gst_object_unref (pool);
511 * gst_v4l2_buffer_pool_qbuf:
513 * @buf: the buffer to queue
515 * Queue a buffer to the driver
517 * Returns: %TRUE for success
520 gst_v4l2_buffer_pool_qbuf (GstBufferPool * bpool, GstBuffer * buf)
522 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
526 meta = GST_META_V4L2_GET (buf);
527 g_assert (meta != NULL);
529 index = meta->vbuffer.index;
531 GST_LOG_OBJECT (pool, "enqueue pool buffer %d", index);
533 if (pool->buffers[index] != NULL)
536 if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &meta->vbuffer) < 0)
539 pool->buffers[index] = buf;
541 pool->num_live_buffers--;
542 GST_DEBUG_OBJECT (pool, "num_live_buffers--: %d", pool->num_live_buffers);
549 GST_WARNING_OBJECT (pool, "the buffer was already queued");
554 GST_WARNING_OBJECT (pool, "could not queue a buffer");
560 * gst_v4l2_buffer_pool_available_buffers:
563 * Check the number of buffers available to the driver, ie. buffers that
564 * have been QBUF'd but not yet DQBUF'd.
566 * Returns: the number of buffers available.
569 gst_v4l2_buffer_pool_available_buffers (GstBufferPool * bpool)
571 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
573 return pool->buffer_count - pool->num_live_buffers;