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);
79 static void gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool,
83 gst_v4l2_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
85 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
90 meta = GST_META_V4L2_GET (buffer);
91 g_assert (meta != NULL);
95 index = meta->vbuffer.index;
96 GST_LOG_OBJECT (pool, "finalizing buffer %p %d", buffer, index);
97 pool->buffers[index] = NULL;
100 "buffer %p (data %p, len %u) freed, unmapping",
101 buffer, meta->mem, meta->vbuffer.length);
102 v4l2_munmap (meta->mem, meta->vbuffer.length);
104 gst_buffer_unref (buffer);
108 gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
109 GstBufferPoolParams * params)
111 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
121 newbuf = gst_buffer_new ();
122 meta = GST_META_V4L2_ADD (newbuf);
126 GST_LOG_OBJECT (pool, "creating buffer %u, %p", index, newbuf, pool);
128 meta->vbuffer.index = index;
129 meta->vbuffer.type = obj->type;
130 meta->vbuffer.memory = V4L2_MEMORY_MMAP;
132 if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &meta->vbuffer) < 0)
133 goto querybuf_failed;
135 GST_LOG_OBJECT (pool, " index: %u", meta->vbuffer.index);
136 GST_LOG_OBJECT (pool, " type: %d", meta->vbuffer.type);
137 GST_LOG_OBJECT (pool, " bytesused: %u", meta->vbuffer.bytesused);
138 GST_LOG_OBJECT (pool, " flags: %08x", meta->vbuffer.flags);
139 GST_LOG_OBJECT (pool, " field: %d", meta->vbuffer.field);
140 GST_LOG_OBJECT (pool, " memory: %d", meta->vbuffer.memory);
141 if (meta->vbuffer.memory == V4L2_MEMORY_MMAP)
142 GST_LOG_OBJECT (pool, " MMAP offset: %u", meta->vbuffer.m.offset);
143 GST_LOG_OBJECT (pool, " length: %u", meta->vbuffer.length);
144 GST_LOG_OBJECT (pool, " input: %u", meta->vbuffer.input);
146 meta->mem = v4l2_mmap (0, meta->vbuffer.length,
147 PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
148 meta->vbuffer.m.offset);
149 if (meta->mem == MAP_FAILED)
152 gst_buffer_take_memory (newbuf, -1,
153 gst_memory_new_wrapped (0,
154 meta->mem, NULL, meta->vbuffer.length, 0, meta->vbuffer.length));
156 /* add metadata to raw video buffers */
158 gsize offset[GST_VIDEO_MAX_PLANES];
159 gint stride[GST_VIDEO_MAX_PLANES];
162 stride[0] = obj->bytesperline;
164 GST_DEBUG_OBJECT (pool, "adding video meta");
165 gst_buffer_add_meta_video_full (newbuf, info->flags,
166 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
167 GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
180 gint errnosave = errno;
182 GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
183 gst_buffer_unref (newbuf);
185 return GST_FLOW_ERROR;
189 gint errnosave = errno;
191 GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
192 gst_buffer_unref (newbuf);
194 return GST_FLOW_ERROR;
199 gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
201 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
203 guint size, min_buffers, max_buffers;
206 GST_DEBUG_OBJECT (pool, "set config");
208 /* parse the config and keep around */
209 if (!gst_buffer_pool_config_get (config, &caps, &size, &min_buffers,
210 &max_buffers, &prefix, &align))
213 GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
215 pool->min_buffers = min_buffers;
216 pool->max_buffers = max_buffers;
222 GST_WARNING_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
228 gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
230 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
231 GstV4l2Object *obj = pool->obj;
233 struct v4l2_requestbuffers breq;
236 num_buffers = pool->max_buffers;
238 /* first, lets request buffers, and see how many we can get: */
239 GST_DEBUG_OBJECT (pool, "starting, requesting %d MMAP buffers", num_buffers);
241 memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
242 breq.type = obj->type;
243 breq.count = num_buffers;
244 breq.memory = V4L2_MEMORY_MMAP;
246 if (v4l2_ioctl (pool->video_fd, VIDIOC_REQBUFS, &breq) < 0)
249 GST_LOG_OBJECT (pool, " count: %u", breq.count);
250 GST_LOG_OBJECT (pool, " type: %d", breq.type);
251 GST_LOG_OBJECT (pool, " memory: %d", breq.memory);
253 if (breq.count < GST_V4L2_MIN_BUFFERS)
256 if (num_buffers != breq.count) {
257 GST_WARNING_OBJECT (pool, "using %u buffers instead", breq.count);
258 num_buffers = breq.count;
262 pool->requeuebuf = (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? TRUE : FALSE);
263 pool->num_buffers = num_buffers;
264 pool->buffers = g_new0 (GstBuffer *, num_buffers);
267 /* now, map the buffers: */
268 for (n = 0; n < num_buffers; n++) {
271 if (gst_v4l2_buffer_pool_alloc_buffer (bpool, &buffer, NULL) != GST_FLOW_OK)
272 goto buffer_new_failed;
274 gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
281 GST_ERROR_OBJECT (pool,
282 "error requesting %d buffers: %s", num_buffers, g_strerror (errno));
287 GST_ERROR_OBJECT (pool,
288 "we received %d from device '%s', we want at least %d",
289 breq.count, obj->videodev, GST_V4L2_MIN_BUFFERS);
294 GST_ERROR_OBJECT (pool, "failed to create a buffer");
300 gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
302 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
305 GST_DEBUG_OBJECT (pool, "stopping pool");
307 /* free the buffers: */
308 for (n = 0; n < pool->num_buffers; n++) {
309 if (pool->buffers[n])
310 gst_v4l2_buffer_pool_free_buffer (bpool, pool->buffers[n]);
312 /* also free the buffers in the queue */
313 return GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
317 gst_v4l2_buffer_pool_dqbuf (GstBufferPool * bpool, GstBuffer ** buffer)
319 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
321 struct v4l2_buffer vbuffer;
322 GstV4l2Object *obj = pool->obj;
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), used %d, flags %08x, pool-queued=%d, buffer=%p",
343 vbuffer.sequence, vbuffer.index, vbuffer.bytesused, vbuffer.flags,
344 pool->num_queued, outbuf);
347 GST_DEBUG_OBJECT (pool, "num_queued: %d", pool->num_queued);
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 if (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
357 gst_buffer_resize (outbuf, 0, vbuffer.bytesused);
359 gst_buffer_resize (outbuf, 0, vbuffer.length);
368 GST_WARNING_OBJECT (pool,
369 "problem dequeuing frame %d (ix=%d), pool-ct=%d, buf.flags=%d",
370 vbuffer.sequence, vbuffer.index,
371 GST_MINI_OBJECT_REFCOUNT (pool), vbuffer.flags);
375 GST_WARNING_OBJECT (pool,
376 "Non-blocking I/O has been selected using O_NONBLOCK and"
377 " no buffer was in the outgoing queue. device %s", obj->videodev);
380 GST_ERROR_OBJECT (pool,
381 "The buffer type is not supported, or the index is out of bounds, "
382 "or no buffers have been allocated yet, or the userptr "
383 "or length are invalid. device %s", obj->videodev);
386 GST_ERROR_OBJECT (pool,
387 "insufficient memory to enqueue a user pointer buffer");
390 GST_INFO_OBJECT (pool,
391 "VIDIOC_DQBUF failed due to an internal error."
392 " Can also indicate temporary problems like signal loss."
393 " Note the driver might dequeue an (empty) buffer despite"
394 " returning an error, or even stop capturing."
395 " device %s", obj->videodev);
396 /* have we de-queued a buffer ? */
397 if (!(vbuffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
398 GST_DEBUG_OBJECT (pool, "reenqueing buffer");
399 /* FIXME ... should we do something here? */
403 GST_WARNING_OBJECT (pool,
404 "could not sync on a buffer on device %s", obj->videodev);
407 GST_WARNING_OBJECT (pool,
408 "Grabbing frame got interrupted on %s unexpectedly. %d: %s.",
409 obj->videodev, errno, g_strerror (errno));
412 return GST_FLOW_ERROR;
416 GST_ERROR_OBJECT (pool, "No free buffers found in the pool at index %d.",
418 return GST_FLOW_ERROR;
423 gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
424 GstBufferPoolParams * params)
426 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
429 GST_DEBUG_OBJECT (pool, "acquire");
431 if (GST_BUFFER_POOL_IS_FLUSHING (bpool))
434 if (pool->requeuebuf)
435 ret = gst_v4l2_buffer_pool_dqbuf (bpool, buffer);
437 if (pool->num_queued == pool->num_buffers) {
438 ret = gst_v4l2_buffer_pool_dqbuf (bpool, buffer);
441 GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool, buffer,
451 GST_DEBUG_OBJECT (bpool, "We are flushing");
452 return GST_FLOW_WRONG_STATE;
457 gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
459 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
461 GST_DEBUG_OBJECT (pool, "release");
463 if (pool->requeuebuf)
464 gst_v4l2_buffer_pool_qbuf (bpool, buffer);
466 GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool, buffer);
470 gst_v4l2_buffer_pool_finalize (GObject * object)
472 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
474 if (pool->video_fd >= 0)
475 v4l2_close (pool->video_fd);
478 g_free (pool->buffers);
479 pool->buffers = NULL;
482 G_OBJECT_CLASS (parent_class)->finalize (object);
486 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
491 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
493 GObjectClass *object_class = G_OBJECT_CLASS (klass);
494 GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
496 object_class->finalize = gst_v4l2_buffer_pool_finalize;
498 bufferpool_class->start = gst_v4l2_buffer_pool_start;
499 bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
500 bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
501 bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
502 bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
503 bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
504 bufferpool_class->free_buffer = gst_v4l2_buffer_pool_free_buffer;
508 * gst_v4l2_buffer_pool_new:
509 * @obj: the v4l2 object owning the pool
510 * @num_buffers: the requested number of buffers in the pool
511 * @requeuebuf: if %TRUE, and if the pool is still in the running state, a
512 * buffer with no remaining references is immediately passed back to v4l2
513 * (VIDIOC_QBUF), otherwise it is returned to the pool of available buffers
514 * (which can be accessed via gst_v4l2_buffer_pool_get().
516 * Construct a new buffer pool.
518 * Returns: the new pool, use gst_v4l2_buffer_pool_destroy() to free resources
521 gst_v4l2_buffer_pool_new (GstV4l2Object * obj)
523 GstV4l2BufferPool *pool;
525 pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, NULL);
527 pool->video_fd = v4l2_dup (obj->video_fd);
528 if (pool->video_fd < 0)
533 return GST_BUFFER_POOL_CAST (pool);
538 gint errnosave = errno;
539 gst_object_unref (pool);
546 * gst_v4l2_buffer_pool_qbuf:
548 * @buf: the buffer to queue
550 * Queue a buffer to the driver
552 * Returns: %TRUE for success
555 gst_v4l2_buffer_pool_qbuf (GstBufferPool * bpool, GstBuffer * buf)
557 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
561 meta = GST_META_V4L2_GET (buf);
562 g_assert (meta != NULL);
564 index = meta->vbuffer.index;
566 GST_LOG_OBJECT (pool, "enqueue pool buffer %d", index);
568 if (pool->buffers[index] != NULL)
571 if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &meta->vbuffer) < 0)
574 pool->buffers[index] = buf;
577 GST_DEBUG_OBJECT (pool, "num_queued: %d", pool->num_queued);
584 GST_WARNING_OBJECT (pool, "the buffer was already queued");
589 GST_WARNING_OBJECT (pool, "could not queue a buffer");
595 * gst_v4l2_buffer_pool_available_buffers:
598 * Check the number of buffers available to the driver, ie. buffers that
599 * have been QBUF'd but not yet DQBUF'd.
601 * Returns: the number of buffers available.
604 gst_v4l2_buffer_pool_available_buffers (GstBufferPool * bpool)
606 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
608 return pool->num_queued;