v4l: remove caps argument, it's not needed
[platform/upstream/gstreamer.git] / sys / v4l2 / gstv4l2bufferpool.c
1 /* GStreamer
2  *
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/
6  *
7  * gstv4l2bufferpool.c V4L2 buffer pool class
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include <sys/mman.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "gst/video/video.h"
34
35 #include <gstv4l2bufferpool.h>
36 #include "gstv4l2src.h"
37 #include "gstv4l2sink.h"
38 #include "v4l2_calls.h"
39 #include "gst/gst-i18n-plugin.h"
40
41 /* videodev2.h is not versioned and we can't easily check for the presence
42  * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
43  * was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */
44 #ifndef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
45 #define V4L2_FIELD_INTERLACED_TB 8
46 #define V4L2_FIELD_INTERLACED_BT 9
47 #endif
48
49
50 GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
51 #define GST_CAT_DEFAULT v4l2_debug
52
53 /*
54  * GstV4l2Buffer:
55  */
56 const GstMetaInfo *
57 gst_meta_v4l2_get_info (void)
58 {
59   static const GstMetaInfo *meta_info = NULL;
60
61   if (meta_info == NULL) {
62     meta_info =
63         gst_meta_register ("GstMetaV4l2", "GstMetaV4l2",
64         sizeof (GstMetaV4l2), (GstMetaInitFunction) NULL,
65         (GstMetaFreeFunction) NULL, (GstMetaCopyFunction) NULL,
66         (GstMetaTransformFunction) NULL);
67   }
68   return meta_info;
69 }
70
71 static void
72 gst_v4l2_buffer_dispose (GstBuffer * buffer)
73 {
74   GstV4l2BufferPool *pool;
75   gboolean resuscitated = FALSE;
76   gint index;
77   GstMetaV4l2 *meta;
78
79   meta = GST_META_V4L2_GET (buffer);
80   g_assert (meta != NULL);
81
82   pool = meta->pool;
83   index = meta->vbuffer.index;
84
85   GST_LOG_OBJECT (pool->v4l2elem, "finalizing buffer %p %d", buffer, index);
86
87   GST_V4L2_BUFFER_POOL_LOCK (pool);
88   if (pool->running) {
89     if (pool->requeuebuf) {
90       if (!gst_v4l2_buffer_pool_qbuf (pool, buffer)) {
91         GST_WARNING ("could not requeue buffer %p %d", buffer, index);
92       } else {
93         resuscitated = TRUE;
94       }
95     } else {
96       resuscitated = TRUE;
97       /* XXX double check this... I think it is ok to not synchronize this
98        * w.r.t. destruction of the pool, since the buffer is still live and
99        * the buffer holds a ref to the pool..
100        */
101       g_async_queue_push (pool->avail_buffers, buffer);
102     }
103   } else {
104     GST_LOG_OBJECT (pool->v4l2elem, "the pool is shutting down");
105   }
106
107   if (resuscitated) {
108     GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
109     gst_buffer_ref (buffer);
110     pool->buffers[index] = buffer;
111   }
112
113   GST_V4L2_BUFFER_POOL_UNLOCK (pool);
114
115   if (!resuscitated) {
116     GST_LOG_OBJECT (pool->v4l2elem,
117         "buffer %p (data %p, len %u) not recovered, unmapping",
118         buffer, meta->mem, meta->vbuffer.length);
119     v4l2_munmap (meta->mem, meta->vbuffer.length);
120
121     g_object_unref (pool);
122   }
123 }
124
125 static GstBuffer *
126 gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index)
127 {
128   GstBuffer *ret;
129   GstMetaV4l2 *meta;
130
131   ret = gst_buffer_new ();
132   GST_MINI_OBJECT_CAST (ret)->dispose =
133       (GstMiniObjectDisposeFunction) gst_v4l2_buffer_dispose;
134
135   meta = GST_META_V4L2_ADD (ret);
136
137   GST_LOG_OBJECT (pool->v4l2elem, "creating buffer %u, %p in pool %p", index,
138       ret, pool);
139
140   meta->pool = (GstV4l2BufferPool *) g_object_ref (pool);
141
142   meta->vbuffer.index = index;
143   meta->vbuffer.type = pool->type;
144   meta->vbuffer.memory = V4L2_MEMORY_MMAP;
145
146   if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &meta->vbuffer) < 0)
147     goto querybuf_failed;
148
149   GST_LOG_OBJECT (pool->v4l2elem, "  index:     %u", meta->vbuffer.index);
150   GST_LOG_OBJECT (pool->v4l2elem, "  type:      %d", meta->vbuffer.type);
151   GST_LOG_OBJECT (pool->v4l2elem, "  bytesused: %u", meta->vbuffer.bytesused);
152   GST_LOG_OBJECT (pool->v4l2elem, "  flags:     %08x", meta->vbuffer.flags);
153   GST_LOG_OBJECT (pool->v4l2elem, "  field:     %d", meta->vbuffer.field);
154   GST_LOG_OBJECT (pool->v4l2elem, "  memory:    %d", meta->vbuffer.memory);
155   if (meta->vbuffer.memory == V4L2_MEMORY_MMAP)
156     GST_LOG_OBJECT (pool->v4l2elem, "  MMAP offset:  %u",
157         meta->vbuffer.m.offset);
158   GST_LOG_OBJECT (pool->v4l2elem, "  length:    %u", meta->vbuffer.length);
159   GST_LOG_OBJECT (pool->v4l2elem, "  input:     %u", meta->vbuffer.input);
160
161   meta->mem = v4l2_mmap (0, meta->vbuffer.length,
162       PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
163       meta->vbuffer.m.offset);
164   if (meta->mem == MAP_FAILED)
165     goto mmap_failed;
166
167   gst_buffer_take_memory (ret, -1,
168       gst_memory_new_wrapped (0,
169           meta->mem, NULL, meta->vbuffer.length, 0, meta->vbuffer.length));
170
171   return ret;
172
173   /* ERRORS */
174 querybuf_failed:
175   {
176     gint errnosave = errno;
177
178     GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
179     gst_buffer_unref (ret);
180     errno = errnosave;
181     return NULL;
182   }
183 mmap_failed:
184   {
185     gint errnosave = errno;
186
187     GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
188     gst_buffer_unref (ret);
189     errno = errnosave;
190     return NULL;
191   }
192 }
193
194 /*
195  * GstV4l2BufferPool:
196  */
197 #define gst_v4l2_buffer_pool_parent_class parent_class
198 G_DEFINE_TYPE (GstV4l2BufferPool, gst_v4l2_buffer_pool, G_TYPE_OBJECT);
199
200 static void
201 gst_v4l2_buffer_pool_finalize (GObject * object)
202 {
203   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
204
205   g_mutex_free (pool->lock);
206   pool->lock = NULL;
207
208   g_async_queue_unref (pool->avail_buffers);
209   pool->avail_buffers = NULL;
210
211   if (pool->video_fd >= 0)
212     v4l2_close (pool->video_fd);
213
214   if (pool->buffers) {
215     g_free (pool->buffers);
216     pool->buffers = NULL;
217   }
218
219   G_OBJECT_CLASS (parent_class)->finalize (object);
220 }
221
222 static void
223 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
224 {
225   pool->lock = g_mutex_new ();
226   pool->running = FALSE;
227   pool->num_live_buffers = 0;
228 }
229
230 static void
231 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
232 {
233   GObjectClass *object_class = G_OBJECT_CLASS (klass);
234
235   object_class->finalize = gst_v4l2_buffer_pool_finalize;
236 }
237
238 /* this is somewhat of a hack.. but better to keep the hack in
239  * one place than copy/pasting it around..
240  */
241 static GstV4l2Object *
242 get_v4l2_object (GstElement * v4l2elem)
243 {
244   GstV4l2Object *v4l2object = NULL;
245   if (GST_IS_V4L2SRC (v4l2elem)) {
246     v4l2object = (GST_V4L2SRC (v4l2elem))->v4l2object;
247   } else if (GST_IS_V4L2SINK (v4l2elem)) {
248     v4l2object = (GST_V4L2SINK (v4l2elem))->v4l2object;
249   } else {
250     GST_ERROR_OBJECT (v4l2elem, "unknown v4l2 element");
251   }
252   return v4l2object;
253 }
254
255 /**
256  * gst_v4l2_buffer_pool_new:
257  * @v4l2elem:  the v4l2 element (src or sink) that owns this pool
258  * @fd:   the video device file descriptor
259  * @num_buffers:  the requested number of buffers in the pool
260  * @requeuebuf: if %TRUE, and if the pool is still in the running state, a
261  *  buffer with no remaining references is immediately passed back to v4l2
262  *  (VIDIOC_QBUF), otherwise it is returned to the pool of available buffers
263  *  (which can be accessed via gst_v4l2_buffer_pool_get().
264  *
265  * Construct a new buffer pool.
266  *
267  * Returns: the new pool, use gst_v4l2_buffer_pool_destroy() to free resources
268  */
269 GstV4l2BufferPool *
270 gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
271     gboolean requeuebuf, enum v4l2_buf_type type)
272 {
273   GstV4l2BufferPool *pool;
274   gint n;
275   struct v4l2_requestbuffers breq;
276
277   pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, NULL);
278
279   pool->video_fd = v4l2_dup (fd);
280   if (pool->video_fd < 0)
281     goto dup_failed;
282
283   /* first, lets request buffers, and see how many we can get: */
284   GST_DEBUG_OBJECT (v4l2elem, "STREAMING, requesting %d MMAP buffers",
285       num_buffers);
286
287   memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
288   breq.type = type;
289   breq.count = num_buffers;
290   breq.memory = V4L2_MEMORY_MMAP;
291
292   if (v4l2_ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
293     goto reqbufs_failed;
294
295   GST_LOG_OBJECT (v4l2elem, " count:  %u", breq.count);
296   GST_LOG_OBJECT (v4l2elem, " type:   %d", breq.type);
297   GST_LOG_OBJECT (v4l2elem, " memory: %d", breq.memory);
298
299   if (breq.count < GST_V4L2_MIN_BUFFERS)
300     goto no_buffers;
301
302   if (num_buffers != breq.count) {
303     GST_WARNING_OBJECT (v4l2elem, "using %u buffers instead", breq.count);
304     num_buffers = breq.count;
305   }
306
307   pool->v4l2elem = v4l2elem;
308   pool->requeuebuf = requeuebuf;
309   pool->type = type;
310   pool->buffer_count = num_buffers;
311   pool->buffers = g_new0 (GstBuffer *, num_buffers);
312   pool->avail_buffers = g_async_queue_new ();
313
314   /* now, map the buffers: */
315   for (n = 0; n < num_buffers; n++) {
316     pool->buffers[n] = gst_v4l2_buffer_new (pool, n);
317     if (!pool->buffers[n])
318       goto buffer_new_failed;
319     pool->num_live_buffers++;
320     g_async_queue_push (pool->avail_buffers, pool->buffers[n]);
321   }
322
323   return pool;
324
325   /* ERRORS */
326 dup_failed:
327   {
328     gint errnosave = errno;
329
330     g_object_unref (pool);
331
332     errno = errnosave;
333
334     return NULL;
335   }
336 reqbufs_failed:
337   {
338     GstV4l2Object *v4l2object = get_v4l2_object (v4l2elem);
339     GST_ELEMENT_ERROR (v4l2elem, RESOURCE, READ,
340         (_("Could not get buffers from device '%s'."),
341             v4l2object->videodev),
342         ("error requesting %d buffers: %s", num_buffers, g_strerror (errno)));
343     return NULL;
344   }
345 no_buffers:
346   {
347     GstV4l2Object *v4l2object = get_v4l2_object (v4l2elem);
348     GST_ELEMENT_ERROR (v4l2elem, RESOURCE, READ,
349         (_("Could not get enough buffers from device '%s'."),
350             v4l2object->videodev),
351         ("we received %d from device '%s', we want at least %d",
352             breq.count, v4l2object->videodev, GST_V4L2_MIN_BUFFERS));
353     return NULL;
354   }
355 buffer_new_failed:
356   {
357     gint errnosave = errno;
358
359     gst_v4l2_buffer_pool_destroy (pool);
360
361     errno = errnosave;
362
363     return NULL;
364   }
365 }
366
367 /**
368  * gst_v4l2_buffer_pool_destroy:
369  * @pool: the pool
370  *
371  * Free all resources in the pool and the pool itself.
372  */
373 void
374 gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool)
375 {
376   gint n;
377
378   GST_V4L2_BUFFER_POOL_LOCK (pool);
379   pool->running = FALSE;
380   GST_V4L2_BUFFER_POOL_UNLOCK (pool);
381
382   GST_DEBUG_OBJECT (pool->v4l2elem, "destroy pool");
383
384   /* after this point, no more buffers will be queued or dequeued; no buffer
385    * from pool->buffers that is NULL will be set to a buffer, and no buffer that
386    * is not NULL will be pushed out. */
387
388   /* miniobjects have no dispose, so they can't break ref-cycles, as buffers ref
389    * the pool, we need to unref the buffer to properly finalize te pool */
390   for (n = 0; n < pool->buffer_count; n++) {
391     GstBuffer *buf;
392
393     GST_V4L2_BUFFER_POOL_LOCK (pool);
394     buf = pool->buffers[n];
395     GST_V4L2_BUFFER_POOL_UNLOCK (pool);
396
397     if (buf)
398       /* we own the ref if the buffer is in pool->buffers; drop it. */
399       gst_buffer_unref (buf);
400   }
401
402   g_object_unref (pool);
403 }
404
405 /**
406  * gst_v4l2_buffer_pool_get:
407  * @pool:   the "this" object
408  * @blocking:  should this call suspend until there is a buffer available
409  *    in the buffer pool?
410  *
411  * Get an available buffer in the pool
412  */
413 GstBuffer *
414 gst_v4l2_buffer_pool_get (GstV4l2BufferPool * pool, gboolean blocking)
415 {
416   GstBuffer *buf;
417
418   if (blocking) {
419     buf = g_async_queue_pop (pool->avail_buffers);
420   } else {
421     buf = g_async_queue_try_pop (pool->avail_buffers);
422   }
423
424   if (buf) {
425     GstMetaV4l2 *meta = GST_META_V4L2_GET (buf);
426
427     GST_V4L2_BUFFER_POOL_LOCK (pool);
428     gst_buffer_resize (buf, 0, meta->vbuffer.length);
429     GST_BUFFER_FLAG_UNSET (buf, 0xffffffff);
430     GST_V4L2_BUFFER_POOL_UNLOCK (pool);
431   }
432
433   pool->running = TRUE;
434
435   return buf;
436 }
437
438
439 /**
440  * gst_v4l2_buffer_pool_qbuf:
441  * @pool: the pool
442  * @buf: the buffer to queue
443  *
444  * Queue a buffer to the driver
445  *
446  * Returns: %TRUE for success
447  */
448 gboolean
449 gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf)
450 {
451   GstMetaV4l2 *meta;
452
453   meta = GST_META_V4L2_GET (buf);
454
455   GST_LOG_OBJECT (pool->v4l2elem, "enqueue pool buffer %d",
456       meta->vbuffer.index);
457
458   if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &meta->vbuffer) < 0)
459     goto queue_failed;
460
461   pool->num_live_buffers--;
462   GST_DEBUG_OBJECT (pool->v4l2elem, "num_live_buffers--: %d",
463       pool->num_live_buffers);
464
465   return TRUE;
466
467   /* ERRORS */
468 queue_failed:
469   {
470     GST_WARNING_OBJECT (pool->v4l2elem, "could not queue a buffer");
471     return FALSE;
472   }
473 }
474
475 /**
476  * gst_v4l2_buffer_pool_dqbuf:
477  * @pool: the pool
478  *
479  * Dequeue a buffer from the driver.  Some generic error handling is done in
480  * this function, but any error handling specific to v4l2src (capture) or
481  * v4l2sink (output) can be done outside this function by checking 'errno'
482  *
483  * Returns: a buffer
484  */
485 GstBuffer *
486 gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
487 {
488   GstV4l2Object *v4l2object = get_v4l2_object (pool->v4l2elem);
489   GstBuffer *pool_buffer;
490   struct v4l2_buffer buffer;
491
492   memset (&buffer, 0x00, sizeof (buffer));
493   buffer.type = pool->type;
494   buffer.memory = V4L2_MEMORY_MMAP;
495
496   if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) < 0)
497     goto error;
498
499   GST_V4L2_BUFFER_POOL_LOCK (pool);
500
501   /* get our GstBuffer with that index from the pool, if the buffer was
502    * outstanding we have a serious problem.
503    */
504   pool_buffer = pool->buffers[buffer.index];
505
506   if (pool_buffer == NULL)
507     goto no_buffers;
508
509   GST_LOG_OBJECT (pool->v4l2elem,
510       "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d, buffer=%p",
511       buffer.sequence, buffer.index, buffer.flags, pool->num_live_buffers,
512       pool_buffer);
513
514   pool->num_live_buffers++;
515   GST_DEBUG_OBJECT (pool->v4l2elem, "num_live_buffers++: %d",
516       pool->num_live_buffers);
517
518   /* set top/bottom field first if v4l2_buffer has the information */
519   if (buffer.field == V4L2_FIELD_INTERLACED_TB)
520     GST_BUFFER_FLAG_SET (pool_buffer, GST_VIDEO_BUFFER_TFF);
521   if (buffer.field == V4L2_FIELD_INTERLACED_BT)
522     GST_BUFFER_FLAG_UNSET (pool_buffer, GST_VIDEO_BUFFER_TFF);
523
524   /* this can change at every frame, esp. with jpeg */
525   gst_buffer_resize (pool_buffer, 0, buffer.bytesused);
526
527   GST_V4L2_BUFFER_POOL_UNLOCK (pool);
528
529   return pool_buffer;
530
531   /* ERRORS */
532 error:
533   {
534     GST_WARNING_OBJECT (pool->v4l2elem,
535         "problem grabbing frame %d (ix=%d), pool-ct=%d, buf.flags=%d",
536         buffer.sequence, buffer.index,
537         GST_MINI_OBJECT_REFCOUNT (pool), buffer.flags);
538
539     switch (errno) {
540       case EAGAIN:
541         GST_WARNING_OBJECT (pool->v4l2elem,
542             "Non-blocking I/O has been selected using O_NONBLOCK and"
543             " no buffer was in the outgoing queue. device %s",
544             v4l2object->videodev);
545         break;
546       case EINVAL:
547         GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
548             (_("Failed trying to get video frames from device '%s'."),
549                 v4l2object->videodev),
550             (_("The buffer type is not supported, or the index is out of bounds," " or no buffers have been allocated yet, or the userptr" " or length are invalid. device %s"), v4l2object->videodev));
551         break;
552       case ENOMEM:
553         GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
554             (_("Failed trying to get video frames from device '%s'. Not enough memory."), v4l2object->videodev), (_("insufficient memory to enqueue a user pointer buffer. device %s."), v4l2object->videodev));
555         break;
556       case EIO:
557         GST_INFO_OBJECT (pool->v4l2elem,
558             "VIDIOC_DQBUF failed due to an internal error."
559             " Can also indicate temporary problems like signal loss."
560             " Note the driver might dequeue an (empty) buffer despite"
561             " returning an error, or even stop capturing."
562             " device %s", v4l2object->videodev);
563         /* have we de-queued a buffer ? */
564         if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
565           GST_DEBUG_OBJECT (pool->v4l2elem, "reenqueing buffer");
566           /* FIXME ... should we do something here? */
567         }
568         break;
569       case EINTR:
570         GST_WARNING_OBJECT (pool->v4l2elem,
571             "could not sync on a buffer on device %s", v4l2object->videodev);
572         break;
573       default:
574         GST_WARNING_OBJECT (pool->v4l2elem,
575             "Grabbing frame got interrupted on %s unexpectedly. %d: %s.",
576             v4l2object->videodev, errno, g_strerror (errno));
577         break;
578     }
579     return NULL;
580   }
581 no_buffers:
582   {
583     GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
584         (_("Failed trying to get video frames from device '%s'."),
585             v4l2object->videodev),
586         (_("No free buffers found in the pool at index %d."), buffer.index));
587     GST_V4L2_BUFFER_POOL_UNLOCK (pool);
588     return NULL;
589   }
590 }
591
592 /**
593  * gst_v4l2_buffer_pool_available_buffers:
594  * @pool: the pool
595  *
596  * Check the number of buffers available to the driver, ie. buffers that
597  * have been QBUF'd but not yet DQBUF'd.
598  *
599  * Returns: the number of buffers available.
600  */
601 gint
602 gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool * pool)
603 {
604   return pool->buffer_count - pool->num_live_buffers;
605 }