v4l2bufferpool: fix typo in flags
[platform/upstream/gst-plugins-good.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., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #ifndef _GNU_SOURCE
30 # define _GNU_SOURCE            /* O_CLOEXEC */
31 #endif
32 #include <fcntl.h>
33
34 #include <sys/mman.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include "gst/video/video.h"
39 #include "gst/video/gstvideometa.h"
40 #include "gst/video/gstvideopool.h"
41 #include "gst/allocators/gstdmabuf.h"
42
43 #include <gstv4l2bufferpool.h>
44
45 #include "v4l2_calls.h"
46 #include "gst/gst-i18n-plugin.h"
47 #include <gst/glib-compat-private.h>
48
49 GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
50 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
51 #define GST_CAT_DEFAULT v4l2_debug
52
53 #define GST_V4L2_IMPORT_QUARK gst_v4l2_buffer_pool_import_quark ()
54
55
56 /*
57  * GstV4l2BufferPool:
58  */
59 #define gst_v4l2_buffer_pool_parent_class parent_class
60 G_DEFINE_TYPE (GstV4l2BufferPool, gst_v4l2_buffer_pool, GST_TYPE_BUFFER_POOL);
61
62 enum _GstV4l2BufferPoolAcquireFlags
63 {
64   GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT =
65       GST_BUFFER_POOL_ACQUIRE_FLAG_LAST,
66   GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_LAST
67 };
68
69 static void gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool,
70     GstBuffer * buffer);
71
72 static gboolean
73 gst_v4l2_is_buffer_valid (GstBuffer * buffer, GstV4l2MemoryGroup ** group)
74 {
75   GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
76   gboolean valid = FALSE;
77
78   if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))
79     goto done;
80
81   if (gst_is_dmabuf_memory (mem))
82     mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
83         GST_V4L2_MEMORY_QUARK);
84
85   if (mem && gst_is_v4l2_memory (mem)) {
86     GstV4l2Memory *vmem = (GstV4l2Memory *) mem;
87     valid = TRUE;
88     if (group)
89       *group = vmem->group;
90   }
91
92 done:
93   return valid;
94 }
95
96 static GstFlowReturn
97 gst_v4l2_buffer_pool_copy_buffer (GstV4l2BufferPool * pool, GstBuffer * dest,
98     GstBuffer * src)
99 {
100   const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
101
102   GST_LOG_OBJECT (pool, "copying buffer");
103
104   if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
105           finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
106     GstVideoFrame src_frame, dest_frame;
107
108     GST_DEBUG_OBJECT (pool, "copy video frame");
109
110     /* we have raw video, use videoframe copy to get strides right */
111     if (!gst_video_frame_map (&src_frame, &pool->caps_info, src, GST_MAP_READ))
112       goto invalid_buffer;
113
114     if (!gst_video_frame_map (&dest_frame, &pool->caps_info, dest,
115             GST_MAP_WRITE)) {
116       gst_video_frame_unmap (&src_frame);
117       goto invalid_buffer;
118     }
119
120     gst_video_frame_copy (&dest_frame, &src_frame);
121
122     gst_video_frame_unmap (&src_frame);
123     gst_video_frame_unmap (&dest_frame);
124   } else {
125     GstMapInfo map;
126
127     GST_DEBUG_OBJECT (pool, "copy raw bytes");
128
129     if (!gst_buffer_map (src, &map, GST_MAP_READ))
130       goto invalid_buffer;
131
132     gst_buffer_fill (dest, 0, map.data, gst_buffer_get_size (src));
133
134     gst_buffer_unmap (src, &map);
135     gst_buffer_resize (dest, 0, gst_buffer_get_size (src));
136   }
137
138   GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, pool, "slow copy into buffer %p",
139       dest);
140
141   return GST_FLOW_OK;
142
143 invalid_buffer:
144   {
145     GST_ERROR_OBJECT (pool, "could not map buffer");
146     return GST_FLOW_ERROR;
147   }
148 }
149
150 struct UserPtrData
151 {
152   GstBuffer *buffer;
153   gboolean is_frame;
154   GstVideoFrame frame;
155   GstMapInfo map;
156 };
157
158 static GQuark
159 gst_v4l2_buffer_pool_import_quark (void)
160 {
161   static GQuark quark = 0;
162
163   if (quark == 0)
164     quark = g_quark_from_string ("GstV4l2BufferPoolUsePtrData");
165
166   return quark;
167 }
168
169 static void
170 _unmap_userptr_frame (struct UserPtrData *data)
171 {
172   if (data->is_frame)
173     gst_video_frame_unmap (&data->frame);
174   else
175     gst_buffer_unmap (data->buffer, &data->map);
176
177   if (data->buffer)
178     gst_buffer_unref (data->buffer);
179
180   g_slice_free (struct UserPtrData, data);
181 }
182
183 static GstFlowReturn
184 gst_v4l2_buffer_pool_import_userptr (GstV4l2BufferPool * pool,
185     GstBuffer * dest, GstBuffer * src)
186 {
187   GstFlowReturn ret = GST_FLOW_OK;
188   GstV4l2MemoryGroup *group = NULL;
189   GstMapFlags flags;
190   const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
191   struct UserPtrData *data = NULL;
192
193   GST_LOG_OBJECT (pool, "importing userptr");
194
195   /* get the group */
196   if (!gst_v4l2_is_buffer_valid (dest, &group))
197     goto not_our_buffer;
198
199   if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
200     flags = GST_MAP_READ;
201   else
202     flags = GST_MAP_WRITE;
203
204   data = g_slice_new0 (struct UserPtrData);
205
206   if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
207           finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
208     data->is_frame = TRUE;
209
210     if (!gst_video_frame_map (&data->frame, &pool->caps_info, src, flags))
211       goto invalid_buffer;
212
213     if (!gst_v4l2_allocator_import_userptr (pool->vallocator, group,
214             data->frame.info.size, finfo->n_planes, data->frame.data,
215             data->frame.info.offset))
216       goto import_failed;
217   } else {
218     gsize offset[1] = { 0 };
219     gpointer ptr[1];
220
221     data->is_frame = FALSE;
222
223     if (!gst_buffer_map (src, &data->map, flags))
224       goto invalid_buffer;
225
226     ptr[0] = data->map.data;
227
228     if (!gst_v4l2_allocator_import_userptr (pool->vallocator, group,
229             data->map.size, 1, ptr, offset))
230       goto import_failed;
231   }
232
233   data->buffer = gst_buffer_ref (src);
234
235   gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
236       data, (GDestroyNotify) _unmap_userptr_frame);
237
238   return ret;
239
240 not_our_buffer:
241   {
242     GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
243     return GST_FLOW_ERROR;
244   }
245 invalid_buffer:
246   {
247     GST_ERROR_OBJECT (pool, "could not map buffer");
248     g_slice_free (struct UserPtrData, data);
249     return GST_FLOW_ERROR;
250   }
251 import_failed:
252   {
253     GST_ERROR_OBJECT (pool, "failed to import data");
254     _unmap_userptr_frame (data);
255     return GST_FLOW_ERROR;
256   }
257 }
258
259 static GstFlowReturn
260 gst_v4l2_buffer_pool_import_dmabuf (GstV4l2BufferPool * pool,
261     GstBuffer * dest, GstBuffer * src)
262 {
263   GstV4l2MemoryGroup *group = NULL;
264   GstMemory *dma_mem[GST_VIDEO_MAX_PLANES] = { 0 };
265   guint n_mem = gst_buffer_n_memory (src);
266   gint i;
267
268   GST_LOG_OBJECT (pool, "importing dmabuf");
269
270   if (!gst_v4l2_is_buffer_valid (dest, &group))
271     goto not_our_buffer;
272
273   if (n_mem > GST_VIDEO_MAX_PLANES)
274     goto too_many_mems;
275
276   for (i = 0; i < n_mem; i++)
277     dma_mem[i] = gst_buffer_peek_memory (src, i);
278
279   if (!gst_v4l2_allocator_import_dmabuf (pool->vallocator, group, n_mem,
280           dma_mem))
281     goto import_failed;
282
283   gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
284       gst_buffer_ref (src), (GDestroyNotify) gst_buffer_unref);
285
286   return GST_FLOW_OK;
287
288 not_our_buffer:
289   {
290     GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
291     return GST_FLOW_ERROR;
292   }
293 too_many_mems:
294   {
295     GST_ERROR_OBJECT (pool, "could not map buffer");
296     return GST_FLOW_ERROR;
297   }
298 import_failed:
299   {
300     GST_ERROR_OBJECT (pool, "failed to import dmabuf");
301     return GST_FLOW_ERROR;
302   }
303 }
304
305 static GstFlowReturn
306 gst_v4l2_buffer_pool_prepare_buffer (GstV4l2BufferPool * pool,
307     GstBuffer * dest, GstBuffer * src)
308 {
309   GstFlowReturn ret = GST_FLOW_OK;
310   gboolean own_src = FALSE;
311
312   if (src == NULL) {
313     if (pool->other_pool == NULL) {
314       GST_ERROR_OBJECT (pool, "can't prepare buffer, source buffer missing");
315       return GST_FLOW_ERROR;
316     }
317
318     ret = gst_buffer_pool_acquire_buffer (pool->other_pool, &src, NULL);
319     if (ret != GST_FLOW_OK) {
320       GST_ERROR_OBJECT (pool, "failed to acquire buffer from downstream pool");
321       goto done;
322     }
323
324     own_src = TRUE;
325   }
326
327   switch (pool->obj->mode) {
328     case GST_V4L2_IO_MMAP:
329     case GST_V4L2_IO_DMABUF:
330       ret = gst_v4l2_buffer_pool_copy_buffer (pool, dest, src);
331       break;
332     case GST_V4L2_IO_USERPTR:
333       ret = gst_v4l2_buffer_pool_import_userptr (pool, dest, src);
334       break;
335     case GST_V4L2_IO_DMABUF_IMPORT:
336       ret = gst_v4l2_buffer_pool_import_dmabuf (pool, dest, src);
337       break;
338     default:
339       break;
340   }
341
342   if (own_src)
343     gst_buffer_unref (src);
344
345 done:
346   return ret;
347 }
348
349 static GstFlowReturn
350 gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
351     GstBufferPoolAcquireParams * params)
352 {
353   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
354   GstV4l2MemoryGroup *group = NULL;
355   GstBuffer *newbuf = NULL;
356   GstV4l2Object *obj;
357   GstVideoInfo *info;
358
359   obj = pool->obj;
360   info = &obj->info;
361
362   switch (obj->mode) {
363     case GST_V4L2_IO_RW:
364       newbuf =
365           gst_buffer_new_allocate (pool->allocator, pool->size, &pool->params);
366       break;
367     case GST_V4L2_IO_MMAP:
368       group = gst_v4l2_allocator_alloc_mmap (pool->vallocator);
369       break;
370     case GST_V4L2_IO_DMABUF:
371       group = gst_v4l2_allocator_alloc_dmabuf (pool->vallocator,
372           pool->allocator);
373       break;
374     case GST_V4L2_IO_USERPTR:
375       group = gst_v4l2_allocator_alloc_userptr (pool->vallocator);
376       break;
377     case GST_V4L2_IO_DMABUF_IMPORT:
378       group = gst_v4l2_allocator_alloc_dmabufin (pool->vallocator);
379       break;
380     default:
381       newbuf = NULL;
382       g_assert_not_reached ();
383       break;
384   }
385
386   if (group != NULL) {
387     gint i;
388     newbuf = gst_buffer_new ();
389
390     for (i = 0; i < group->n_mem; i++)
391       gst_buffer_append_memory (newbuf, group->mem[i]);
392   } else if (newbuf == NULL) {
393     goto allocation_failed;
394   }
395
396   /* add metadata to raw video buffers */
397   if (pool->add_videometa)
398     gst_buffer_add_video_meta_full (newbuf, GST_VIDEO_FRAME_FLAG_NONE,
399         GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
400         GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
401         info->offset, info->stride);
402
403   *buffer = newbuf;
404
405   return GST_FLOW_OK;
406
407   /* ERRORS */
408 allocation_failed:
409   {
410     GST_ERROR_OBJECT (pool, "failed to allocate buffer");
411     return GST_FLOW_ERROR;
412   }
413 }
414
415 static gboolean
416 gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
417 {
418   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
419   GstV4l2Object *obj = pool->obj;
420   GstCaps *caps;
421   guint size, min_buffers, max_buffers;
422   GstAllocator *allocator;
423   GstAllocationParams params;
424   gboolean can_allocate = FALSE;
425   gboolean updated = FALSE;
426   gboolean ret;
427
428   pool->add_videometa =
429       gst_buffer_pool_config_has_option (config,
430       GST_BUFFER_POOL_OPTION_VIDEO_META);
431
432   /* parse the config and keep around */
433   if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
434           &max_buffers))
435     goto wrong_config;
436
437   if (!gst_buffer_pool_config_get_allocator (config, &allocator, &params))
438     goto wrong_config;
439
440   GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
441
442   if (pool->allocator)
443     gst_object_unref (pool->allocator);
444   pool->allocator = NULL;
445
446   switch (obj->mode) {
447     case GST_V4L2_IO_DMABUF:
448       pool->allocator = gst_dmabuf_allocator_new ();
449       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
450       break;
451     case GST_V4L2_IO_MMAP:
452       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
453       break;
454     case GST_V4L2_IO_USERPTR:
455       can_allocate =
456           GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
457       break;
458     case GST_V4L2_IO_DMABUF_IMPORT:
459       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
460       break;
461     case GST_V4L2_IO_RW:
462       pool->allocator = g_object_ref (allocator);
463       pool->params = params;
464       /* No need to change the configuration */
465       goto done;
466       break;
467     default:
468       g_assert_not_reached ();
469       break;
470   }
471
472   if (min_buffers < GST_V4L2_MIN_BUFFERS) {
473     updated = TRUE;
474     min_buffers = GST_V4L2_MIN_BUFFERS;
475     GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
476   }
477
478   if (max_buffers > VIDEO_MAX_FRAME || max_buffers == 0) {
479     updated = TRUE;
480     max_buffers = VIDEO_MAX_FRAME;
481     GST_INFO_OBJECT (pool, "reducing maximum buffers to %u", max_buffers);
482   }
483
484   if (min_buffers > max_buffers) {
485     updated = TRUE;
486     min_buffers = max_buffers;
487     GST_INFO_OBJECT (pool, "reducing minimum buffers to %u", min_buffers);
488   } else if (min_buffers != max_buffers) {
489     if (!can_allocate) {
490       updated = TRUE;
491       max_buffers = min_buffers;
492       GST_INFO_OBJECT (pool, "can't allocate, setting maximum to minimum");
493     }
494   }
495
496   if (!pool->add_videometa && obj->need_video_meta) {
497     GST_INFO_OBJECT (pool, "adding needed video meta");
498     updated = TRUE;
499     gst_buffer_pool_config_add_option (config,
500         GST_BUFFER_POOL_OPTION_VIDEO_META);
501   }
502
503   if (updated)
504     gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
505         max_buffers);
506
507   /* keep a GstVideoInfo with defaults for the when we need to copy */
508   gst_video_info_from_caps (&pool->caps_info, caps);
509
510 done:
511   ret = GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
512
513   /* If anything was changed documentation recommand to return FALSE */
514   return !updated && ret;
515
516   /* ERRORS */
517 wrong_config:
518   {
519     GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
520     return FALSE;
521   }
522 }
523
524 static gboolean
525 gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
526 {
527   GstV4l2Object *obj = pool->obj;
528
529   switch (obj->mode) {
530     case GST_V4L2_IO_MMAP:
531     case GST_V4L2_IO_USERPTR:
532     case GST_V4L2_IO_DMABUF:
533     case GST_V4L2_IO_DMABUF_IMPORT:
534       if (!pool->streaming) {
535         if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
536           goto streamon_failed;
537
538         pool->streaming = TRUE;
539
540         GST_DEBUG_OBJECT (pool, "Started streaming");
541       }
542       break;
543     default:
544       break;
545   }
546
547   return TRUE;
548
549 streamon_failed:
550   {
551     GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
552         g_strerror (errno));
553     return FALSE;
554   }
555 }
556
557 static gboolean
558 gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
559 {
560   GstV4l2Object *obj = pool->obj;
561
562   switch (obj->mode) {
563     case GST_V4L2_IO_MMAP:
564     case GST_V4L2_IO_USERPTR:
565     case GST_V4L2_IO_DMABUF:
566     case GST_V4L2_IO_DMABUF_IMPORT:
567       if (pool->streaming) {
568         if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
569           goto streamoff_failed;
570
571         pool->streaming = FALSE;
572
573         GST_DEBUG_OBJECT (pool, "Stopped streaming");
574       }
575       break;
576     default:
577       break;
578   }
579
580   return TRUE;
581
582 streamoff_failed:
583   {
584     GST_ERROR_OBJECT (pool, "error with STREAMOFF %d (%s)", errno,
585         g_strerror (errno));
586     return FALSE;
587   }
588 }
589
590 static void
591 gst_v4l2_buffer_pool_group_released (GstV4l2BufferPool * pool)
592 {
593   GstBufferPoolAcquireParams params = { 0 };
594   GstBuffer *buffer = NULL;
595   GstFlowReturn ret;
596
597   GST_DEBUG_OBJECT (pool, "A buffer was lost, reallocating it");
598
599   params.flags =
600       (GstBufferPoolAcquireFlags) GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT;
601   ret =
602       gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (pool), &buffer, &params);
603
604   if (ret == GST_FLOW_OK)
605     gst_buffer_unref (buffer);
606 }
607
608 static gboolean
609 gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
610 {
611   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
612   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
613   GstV4l2Object *obj = pool->obj;
614   GstStructure *config;
615   GstCaps *caps;
616   guint size, min_buffers, max_buffers;
617   guint max_latency, min_latency, copy_threshold = 0;
618   gboolean can_allocate = FALSE;
619
620   GST_DEBUG_OBJECT (pool, "activating pool");
621
622   config = gst_buffer_pool_get_config (bpool);
623   if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
624           &max_buffers))
625     goto wrong_config;
626
627   min_latency = MAX (GST_V4L2_MIN_BUFFERS, obj->min_buffers);
628
629   switch (obj->mode) {
630     case GST_V4L2_IO_RW:
631       can_allocate = TRUE;
632       break;
633     case GST_V4L2_IO_DMABUF:
634     case GST_V4L2_IO_MMAP:
635     {
636       guint count;
637
638       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
639
640       /* first, lets request buffers, and see how many we can get: */
641       GST_DEBUG_OBJECT (pool, "requesting %d MMAP buffers", min_buffers);
642
643       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
644           V4L2_MEMORY_MMAP);
645
646       if (count < GST_V4L2_MIN_BUFFERS) {
647         min_buffers = count;
648         goto no_buffers;
649       }
650
651       /* V4L2 buffer pool are often very limited in the amount of buffers it
652        * can offer. The copy_threshold will workaround this limitation by
653        * falling back to copy if the pipeline needed more buffers. This also
654        * prevent having to do REQBUFS(N)/REQBUFS(0) everytime configure is
655        * called. */
656       if (count != min_buffers) {
657         GST_WARNING_OBJECT (pool, "using %u buffers instead of %u",
658             count, min_buffers);
659         min_buffers = count;
660         copy_threshold = min_latency;
661
662         /* The initial minimum could be provide either by GstBufferPool or
663          * driver needs. */
664         min_buffers = count;
665       }
666
667       break;
668     }
669     case GST_V4L2_IO_USERPTR:
670     {
671       guint count;
672
673       can_allocate =
674           GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
675
676       GST_DEBUG_OBJECT (pool, "requesting %d USERPTR buffers", min_buffers);
677
678       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
679           V4L2_MEMORY_USERPTR);
680
681       /* There is no rational to not get what we asked */
682       if (count < min_buffers) {
683         min_buffers = count;
684         goto no_buffers;
685       }
686
687       min_buffers = count;
688       break;
689     }
690     case GST_V4L2_IO_DMABUF_IMPORT:
691     {
692       guint count;
693
694       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
695
696       GST_DEBUG_OBJECT (pool, "requesting %d DMABUF buffers", min_buffers);
697
698       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
699           V4L2_MEMORY_DMABUF);
700
701       /* There is no rational to not get what we asked */
702       if (count < min_buffers) {
703         min_buffers = count;
704         goto no_buffers;
705       }
706
707       min_buffers = count;
708       break;
709     }
710     default:
711       min_buffers = 0;
712       copy_threshold = 0;
713       g_assert_not_reached ();
714       break;
715   }
716
717   if (can_allocate)
718     max_latency = max_buffers;
719   else
720     max_latency = min_buffers;
721
722   pool->size = size;
723   pool->copy_threshold = copy_threshold;
724   pool->max_latency = max_latency;
725   pool->min_latency = min_latency;
726   pool->num_queued = 0;
727
728   if (max_buffers < min_buffers)
729     max_buffers = min_buffers;
730
731   gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
732       max_buffers);
733   pclass->set_config (bpool, config);
734   gst_structure_free (config);
735
736   if (pool->other_pool)
737     if (!gst_buffer_pool_set_active (pool->other_pool, TRUE))
738       goto other_pool_failed;
739
740   /* now, allocate the buffers: */
741   if (!pclass->start (bpool))
742     goto start_failed;
743
744   if (!V4L2_TYPE_IS_OUTPUT (obj->type))
745     pool->group_released_handler =
746         g_signal_connect_swapped (pool->vallocator, "group-released",
747         G_CALLBACK (gst_v4l2_buffer_pool_group_released), pool);
748
749   return TRUE;
750
751   /* ERRORS */
752 wrong_config:
753   {
754     GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
755     gst_structure_free (config);
756     return FALSE;
757   }
758 no_buffers:
759   {
760     GST_ERROR_OBJECT (pool,
761         "we received %d buffer from device '%s', we want at least %d",
762         min_buffers, obj->videodev, GST_V4L2_MIN_BUFFERS);
763     gst_structure_free (config);
764     return FALSE;
765   }
766 start_failed:
767   {
768     GST_ERROR_OBJECT (pool, "failed to start streaming");
769     return FALSE;
770   }
771 other_pool_failed:
772   {
773     GST_ERROR_OBJECT (pool, "failed to active the other pool %"
774         GST_PTR_FORMAT, pool->other_pool);
775     return FALSE;
776   }
777 }
778
779 static gboolean
780 gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
781 {
782   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
783   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
784   gboolean ret;
785   gint i;
786
787   GST_DEBUG_OBJECT (pool, "stopping pool");
788
789   if (pool->group_released_handler > 0) {
790     g_signal_handler_disconnect (pool->vallocator,
791         pool->group_released_handler);
792     pool->group_released_handler = 0;
793   }
794
795   if (pool->other_pool) {
796     gst_object_unref (pool->other_pool);
797     pool->other_pool = NULL;
798   }
799
800   if (!gst_v4l2_buffer_pool_streamoff (pool))
801     goto streamoff_failed;
802
803   if (pool->vallocator)
804     gst_v4l2_allocator_flush (pool->vallocator);
805
806   for (i = 0; i < VIDEO_MAX_FRAME; i++) {
807     if (pool->buffers[i]) {
808       GstBuffer *buffer = pool->buffers[i];
809
810       pool->buffers[i] = NULL;
811
812       if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
813         gst_buffer_unref (buffer);
814       else
815         pclass->release_buffer (bpool, buffer);
816
817       g_atomic_int_add (&pool->num_queued, -1);
818     }
819   }
820
821   ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
822
823   if (ret && pool->vallocator) {
824     GstV4l2Return vret;
825
826     vret = gst_v4l2_allocator_stop (pool->vallocator);
827
828     if (vret == GST_V4L2_BUSY)
829       GST_WARNING_OBJECT (pool, "some buffers are still outstanding");
830
831     ret = (vret == GST_V4L2_OK);
832   }
833
834   return ret;
835
836   /* ERRORS */
837 streamoff_failed:
838   GST_ERROR_OBJECT (pool, "device refused to stop streaming");
839   return FALSE;
840 }
841
842 static void
843 gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
844 {
845   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
846
847   GST_DEBUG_OBJECT (pool, "start flushing");
848
849   gst_poll_set_flushing (pool->poll, TRUE);
850
851   GST_OBJECT_LOCK (pool);
852   pool->empty = FALSE;
853   g_cond_broadcast (&pool->empty_cond);
854   GST_OBJECT_UNLOCK (pool);
855
856   if (pool->other_pool)
857     gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
858 }
859
860 static void
861 gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool)
862 {
863   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
864   GstV4l2Object *obj = pool->obj;
865   gint i;
866
867   GST_DEBUG_OBJECT (pool, "stop flushing");
868
869   /* If we haven't started streaming yet, simply call streamon */
870   if (!pool->streaming)
871     goto streamon;
872
873   if (pool->other_pool)
874     gst_buffer_pool_set_flushing (pool->other_pool, FALSE);
875
876   if (!gst_v4l2_buffer_pool_streamoff (pool))
877     goto stop_failed;
878
879   gst_v4l2_allocator_flush (pool->vallocator);
880
881   /* Reset our state */
882   switch (obj->mode) {
883     case GST_V4L2_IO_RW:
884       break;
885     case GST_V4L2_IO_MMAP:
886     case GST_V4L2_IO_USERPTR:
887     case GST_V4L2_IO_DMABUF:
888     case GST_V4L2_IO_DMABUF_IMPORT:
889     {
890       gsize num_allocated;
891
892       num_allocated = gst_v4l2_allocator_num_allocated (pool->vallocator);
893
894       for (i = 0; i < num_allocated; i++) {
895         /* Re-enqueue buffers */
896         if (pool->buffers[i]) {
897           GstBufferPool *bpool = (GstBufferPool *) pool;
898           GstBuffer *buffer = pool->buffers[i];
899
900           pool->buffers[i] = NULL;
901
902           /* Remove qdata, this will unmap any map data in
903            * userptr/dmabuf-import */
904           gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
905               GST_V4L2_IMPORT_QUARK, NULL, NULL);
906
907           if (V4L2_TYPE_IS_OUTPUT (obj->type))
908             gst_buffer_unref (buffer);
909           else
910             gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
911
912           g_atomic_int_add (&pool->num_queued, -1);
913         }
914       }
915
916       break;
917     }
918     default:
919       g_assert_not_reached ();
920       break;
921   }
922
923 streamon:
924   /* Start streaming on capture device only */
925   if (!V4L2_TYPE_IS_OUTPUT (obj->type))
926     gst_v4l2_buffer_pool_streamon (pool);
927
928   gst_poll_set_flushing (pool->poll, FALSE);
929
930   return;
931
932   /* ERRORS */
933 stop_failed:
934   {
935     GST_ERROR_OBJECT (pool, "device refused to flush");
936   }
937 }
938
939 static GstFlowReturn
940 gst_v4l2_buffer_pool_poll (GstV4l2BufferPool * pool)
941 {
942   gint ret;
943
944   GST_OBJECT_LOCK (pool);
945   while (pool->empty)
946     g_cond_wait (&pool->empty_cond, GST_OBJECT_GET_LOCK (pool));
947   GST_OBJECT_UNLOCK (pool);
948
949   if (!pool->can_poll_device)
950     goto done;
951
952   GST_LOG_OBJECT (pool, "polling device");
953
954 again:
955   ret = gst_poll_wait (pool->poll, GST_CLOCK_TIME_NONE);
956   if (G_UNLIKELY (ret < 0)) {
957     switch (errno) {
958       case EBUSY:
959         goto stopped;
960       case EAGAIN:
961       case EINTR:
962         goto again;
963       case ENXIO:
964         GST_WARNING_OBJECT (pool,
965             "v4l2 device doesn't support polling. Disabling"
966             " using libv4l2 in this case may cause deadlocks");
967         pool->can_poll_device = FALSE;
968         goto done;
969       default:
970         goto select_error;
971     }
972   }
973
974   if (gst_poll_fd_has_error (pool->poll, &pool->pollfd))
975     goto select_error;
976
977 done:
978   return GST_FLOW_OK;
979
980   /* ERRORS */
981 stopped:
982   {
983     GST_DEBUG_OBJECT (pool, "stop called");
984     return GST_FLOW_FLUSHING;
985   }
986 select_error:
987   {
988     GST_ELEMENT_ERROR (pool->obj->element, RESOURCE, READ, (NULL),
989         ("poll error %d: %s (%d)", ret, g_strerror (errno), errno));
990     return GST_FLOW_ERROR;
991   }
992 }
993
994 static GstFlowReturn
995 gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf)
996 {
997   GstV4l2MemoryGroup *group = NULL;
998   gint index;
999
1000   if (!gst_v4l2_is_buffer_valid (buf, &group)) {
1001     GST_LOG_OBJECT (pool, "unref copied/invalid buffer %p", buf);
1002     gst_buffer_unref (buf);
1003     return GST_FLOW_OK;
1004   }
1005
1006   index = group->buffer.index;
1007
1008   if (pool->buffers[index] != NULL)
1009     goto already_queued;
1010
1011   GST_LOG_OBJECT (pool, "queuing buffer %i", index);
1012
1013   g_atomic_int_inc (&pool->num_queued);
1014   pool->buffers[index] = buf;
1015
1016   if (!gst_v4l2_allocator_qbuf (pool->vallocator, group))
1017     goto queue_failed;
1018
1019   GST_OBJECT_LOCK (pool);
1020   pool->empty = FALSE;
1021   g_cond_signal (&pool->empty_cond);
1022   GST_OBJECT_UNLOCK (pool);
1023
1024   return GST_FLOW_OK;
1025
1026 already_queued:
1027   {
1028     GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
1029     return GST_FLOW_ERROR;
1030   }
1031 queue_failed:
1032   {
1033     GST_ERROR_OBJECT (pool, "could not queue a buffer %i", index);
1034     /* Mark broken buffer to the allocator */
1035     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY);
1036     g_atomic_int_add (&pool->num_queued, -1);
1037     pool->buffers[index] = NULL;
1038     return GST_FLOW_ERROR;
1039   }
1040 }
1041
1042 static GstFlowReturn
1043 gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer)
1044 {
1045   GstFlowReturn res;
1046   GstBuffer *outbuf;
1047   GstV4l2Object *obj = pool->obj;
1048   GstClockTime timestamp;
1049   GstV4l2MemoryGroup *group;
1050   gint i;
1051
1052   if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK)
1053     goto poll_failed;
1054
1055   GST_LOG_OBJECT (pool, "dequeueing a buffer");
1056
1057   group = gst_v4l2_allocator_dqbuf (pool->vallocator);
1058   if (group == NULL)
1059     goto dqbuf_failed;
1060
1061   /* get our GstBuffer with that index from the pool, if the buffer was
1062    * outstanding we have a serious problem.
1063    */
1064   outbuf = pool->buffers[group->buffer.index];
1065   if (outbuf == NULL)
1066     goto no_buffer;
1067
1068   /* mark the buffer outstanding */
1069   pool->buffers[group->buffer.index] = NULL;
1070   if (g_atomic_int_dec_and_test (&pool->num_queued)) {
1071     GST_OBJECT_LOCK (pool);
1072     pool->empty = TRUE;
1073     GST_OBJECT_UNLOCK (pool);
1074   }
1075
1076   timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
1077
1078 #ifndef GST_DISABLE_GST_DEBUG
1079   for (i = 0; i < group->n_mem; i++) {
1080     GST_LOG_OBJECT (pool,
1081         "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %"
1082         GST_TIME_FORMAT ", pool-queued=%d, buffer=%p", outbuf,
1083         group->buffer.sequence, group->buffer.index, group->mem[i],
1084         group->planes[i].bytesused, i, group->buffer.flags,
1085         GST_TIME_ARGS (timestamp), pool->num_queued, outbuf);
1086   }
1087 #endif
1088
1089   /* set top/bottom field first if v4l2_buffer has the information */
1090   switch (group->buffer.field) {
1091     case V4L2_FIELD_NONE:
1092       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1093       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1094       break;
1095     case V4L2_FIELD_INTERLACED_TB:
1096       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1097       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1098       break;
1099     case V4L2_FIELD_INTERLACED_BT:
1100       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1101       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1102       break;
1103     default:
1104       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1105       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1106       GST_FIXME_OBJECT (pool,
1107           "Unhandled enum v4l2_field %d - treating as progressive",
1108           group->buffer.field);
1109   }
1110
1111   if (GST_VIDEO_INFO_FORMAT (&obj->info) == GST_VIDEO_FORMAT_ENCODED) {
1112     if (group->buffer.flags & V4L2_BUF_FLAG_KEYFRAME)
1113       GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1114     else
1115       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1116   }
1117
1118   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1119
1120   *buffer = outbuf;
1121
1122   return GST_FLOW_OK;
1123
1124   /* ERRORS */
1125 poll_failed:
1126   {
1127     GST_DEBUG_OBJECT (pool, "poll error %s", gst_flow_get_name (res));
1128     return res;
1129   }
1130 dqbuf_failed:
1131   {
1132     return GST_FLOW_ERROR;
1133   }
1134 no_buffer:
1135   {
1136     GST_ERROR_OBJECT (pool, "No free buffer found in the pool at index %d.",
1137         group->buffer.index);
1138     return GST_FLOW_ERROR;
1139   }
1140 }
1141
1142 static GstFlowReturn
1143 gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
1144     GstBufferPoolAcquireParams * params)
1145 {
1146   GstFlowReturn ret;
1147   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1148   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1149   GstV4l2Object *obj = pool->obj;
1150
1151   GST_DEBUG_OBJECT (pool, "acquire");
1152
1153   /* If this is being called to resurect a lost buffer */
1154   if (params && params->flags & GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT) {
1155     ret = pclass->acquire_buffer (bpool, buffer, params);
1156     goto done;
1157   }
1158
1159   switch (obj->type) {
1160     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1161     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1162       /* capture, This function should return a buffer with new captured data */
1163       switch (obj->mode) {
1164         case GST_V4L2_IO_RW:
1165         {
1166           /* take empty buffer from the pool */
1167           ret = pclass->acquire_buffer (bpool, buffer, params);
1168           break;
1169         }
1170         case GST_V4L2_IO_DMABUF:
1171         case GST_V4L2_IO_MMAP:
1172         {
1173           /* just dequeue a buffer, we basically use the queue of v4l2 as the
1174            * storage for our buffers. This function does poll first so we can
1175            * interrupt it fine. */
1176           ret = gst_v4l2_buffer_pool_dqbuf (pool, buffer);
1177           if (G_UNLIKELY (ret != GST_FLOW_OK))
1178             goto done;
1179           break;
1180         }
1181         case GST_V4L2_IO_USERPTR:
1182         case GST_V4L2_IO_DMABUF_IMPORT:
1183         {
1184           /* dequeue filled buffer */
1185           ret = gst_v4l2_buffer_pool_dqbuf (pool, buffer);
1186           break;
1187         }
1188         default:
1189           ret = GST_FLOW_ERROR;
1190           g_assert_not_reached ();
1191           break;
1192       }
1193       break;
1194
1195
1196     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1197     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1198       /* playback, This function should return an empty buffer */
1199       switch (obj->mode) {
1200         case GST_V4L2_IO_RW:
1201           /* get an empty buffer */
1202           ret = pclass->acquire_buffer (bpool, buffer, params);
1203           break;
1204
1205         case GST_V4L2_IO_MMAP:
1206         case GST_V4L2_IO_DMABUF:
1207         case GST_V4L2_IO_USERPTR:
1208         case GST_V4L2_IO_DMABUF_IMPORT:
1209           /* get a free unqueued buffer */
1210           ret = pclass->acquire_buffer (bpool, buffer, params);
1211           break;
1212
1213         default:
1214           ret = GST_FLOW_ERROR;
1215           g_assert_not_reached ();
1216           break;
1217       }
1218       break;
1219
1220     default:
1221       ret = GST_FLOW_ERROR;
1222       g_assert_not_reached ();
1223       break;
1224   }
1225 done:
1226   return ret;
1227 }
1228
1229 static void
1230 gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
1231 {
1232   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1233   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1234   GstV4l2Object *obj = pool->obj;
1235
1236   GST_DEBUG_OBJECT (pool, "release buffer %p", buffer);
1237
1238   switch (obj->type) {
1239     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1240     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1241       /* capture, put the buffer back in the queue so that we can refill it
1242        * later. */
1243       switch (obj->mode) {
1244         case GST_V4L2_IO_RW:
1245           /* release back in the pool */
1246           pclass->release_buffer (bpool, buffer);
1247           break;
1248
1249         case GST_V4L2_IO_DMABUF:
1250         case GST_V4L2_IO_MMAP:
1251         case GST_V4L2_IO_USERPTR:
1252         case GST_V4L2_IO_DMABUF_IMPORT:
1253         {
1254           if (gst_v4l2_is_buffer_valid (buffer, NULL)) {
1255             /* queue back in the device */
1256             if (pool->other_pool)
1257               gst_v4l2_buffer_pool_prepare_buffer (pool, buffer, NULL);
1258             if (gst_v4l2_buffer_pool_qbuf (pool, buffer) != GST_FLOW_OK)
1259               pclass->release_buffer (bpool, buffer);
1260           } else {
1261             /* Simply release invalide/modified buffer, the allocator will
1262              * give it back later */
1263             GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1264             pclass->release_buffer (bpool, buffer);
1265           }
1266           break;
1267         }
1268         default:
1269           g_assert_not_reached ();
1270           break;
1271       }
1272       break;
1273
1274     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1275     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1276       switch (obj->mode) {
1277         case GST_V4L2_IO_RW:
1278           /* release back in the pool */
1279           pclass->release_buffer (bpool, buffer);
1280           break;
1281
1282         case GST_V4L2_IO_MMAP:
1283         case GST_V4L2_IO_DMABUF:
1284         case GST_V4L2_IO_USERPTR:
1285         case GST_V4L2_IO_DMABUF_IMPORT:
1286         {
1287           GstV4l2MemoryGroup *group;
1288           guint index;
1289
1290           if (!gst_v4l2_is_buffer_valid (buffer, &group)) {
1291             /* Simply release invalide/modified buffer, the allocator will
1292              * give it back later */
1293             GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1294             pclass->release_buffer (bpool, buffer);
1295             break;
1296           }
1297
1298           index = group->buffer.index;
1299
1300           if (pool->buffers[index] == NULL) {
1301             GST_LOG_OBJECT (pool, "buffer %u not queued, putting on free list",
1302                 index);
1303
1304             /* Remove qdata, this will unmap any map data in userptr */
1305             gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
1306                 GST_V4L2_IMPORT_QUARK, NULL, NULL);
1307
1308             /* reset to default size */
1309             gst_v4l2_allocator_reset_group (pool->vallocator, group);
1310
1311             /* playback, put the buffer back in the queue to refill later. */
1312             pclass->release_buffer (bpool, buffer);
1313           } else {
1314             /* We keep a ref on queued buffer, so this should never happen */
1315             g_assert_not_reached ();
1316           }
1317           break;
1318         }
1319
1320         default:
1321           g_assert_not_reached ();
1322           break;
1323       }
1324       break;
1325
1326     default:
1327       g_assert_not_reached ();
1328       break;
1329   }
1330 }
1331
1332 static void
1333 gst_v4l2_buffer_pool_dispose (GObject * object)
1334 {
1335   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1336   gint i;
1337
1338   for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1339     if (pool->buffers[i])
1340       gst_buffer_replace (&(pool->buffers[i]), NULL);
1341   }
1342
1343   if (pool->vallocator)
1344     gst_object_unref (pool->vallocator);
1345   pool->vallocator = NULL;
1346
1347   if (pool->allocator)
1348     gst_object_unref (pool->allocator);
1349   pool->allocator = NULL;
1350
1351   if (pool->other_pool)
1352     gst_object_unref (pool->other_pool);
1353   pool->other_pool = NULL;
1354
1355   G_OBJECT_CLASS (parent_class)->dispose (object);
1356 }
1357
1358 static void
1359 gst_v4l2_buffer_pool_finalize (GObject * object)
1360 {
1361   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1362
1363   if (pool->video_fd >= 0)
1364     v4l2_close (pool->video_fd);
1365
1366   gst_poll_free (pool->poll);
1367
1368   /* FIXME Is this required to keep around ?
1369    * This can't be done in dispose method because we must not set pointer
1370    * to NULL as it is part of the v4l2object and dispose could be called
1371    * multiple times */
1372   gst_object_unref (pool->obj->element);
1373
1374   g_cond_clear (&pool->empty_cond);
1375
1376   /* FIXME have we done enough here ? */
1377
1378   G_OBJECT_CLASS (parent_class)->finalize (object);
1379 }
1380
1381 static void
1382 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
1383 {
1384   pool->poll = gst_poll_new (TRUE);
1385   pool->can_poll_device = TRUE;
1386   g_cond_init (&pool->empty_cond);
1387   pool->empty = TRUE;
1388 }
1389
1390 static void
1391 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
1392 {
1393   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1394   GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
1395
1396   object_class->dispose = gst_v4l2_buffer_pool_dispose;
1397   object_class->finalize = gst_v4l2_buffer_pool_finalize;
1398
1399   bufferpool_class->start = gst_v4l2_buffer_pool_start;
1400   bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
1401   bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
1402   bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
1403   bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
1404   bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
1405   bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
1406   bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
1407 }
1408
1409 /**
1410  * gst_v4l2_buffer_pool_new:
1411  * @obj:  the v4l2 object owning the pool
1412  *
1413  * Construct a new buffer pool.
1414  *
1415  * Returns: the new pool, use gst_object_unref() to free resources
1416  */
1417 GstBufferPool *
1418 gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
1419 {
1420   GstV4l2BufferPool *pool;
1421   GstStructure *config;
1422   gchar *name, *parent_name;
1423   gint fd;
1424
1425   fd = v4l2_dup (obj->video_fd);
1426   if (fd < 0)
1427     goto dup_failed;
1428
1429   /* setting a significant unique name */
1430   parent_name = gst_object_get_name (GST_OBJECT (obj->element));
1431   name = g_strconcat (parent_name, ":", "pool:",
1432       V4L2_TYPE_IS_OUTPUT (obj->type) ? "sink" : "src", NULL);
1433   g_free (parent_name);
1434
1435   pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL,
1436       "name", name, NULL);
1437   g_free (name);
1438
1439   gst_poll_fd_init (&pool->pollfd);
1440   pool->pollfd.fd = fd;
1441   gst_poll_add_fd (pool->poll, &pool->pollfd);
1442   if (V4L2_TYPE_IS_OUTPUT (obj->type))
1443     gst_poll_fd_ctl_write (pool->poll, &pool->pollfd, TRUE);
1444   else
1445     gst_poll_fd_ctl_read (pool->poll, &pool->pollfd, TRUE);
1446
1447   pool->video_fd = fd;
1448   pool->obj = obj;
1449   pool->can_poll_device = TRUE;
1450
1451   pool->vallocator =
1452       gst_v4l2_allocator_new (GST_OBJECT (pool), obj->video_fd, &obj->format);
1453   if (pool->vallocator == NULL)
1454     goto allocator_failed;
1455
1456   gst_object_ref (obj->element);
1457
1458   config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
1459   gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
1460   /* This will simply set a default config, but will not configure the pool
1461    * because min and max are not valid */
1462   gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
1463
1464   return GST_BUFFER_POOL (pool);
1465
1466   /* ERRORS */
1467 dup_failed:
1468   {
1469     GST_ERROR ("failed to dup fd %d (%s)", errno, g_strerror (errno));
1470     return NULL;
1471   }
1472 allocator_failed:
1473   {
1474     GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator");
1475     return NULL;
1476   }
1477 }
1478
1479 static GstFlowReturn
1480 gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
1481 {
1482   GstFlowReturn res;
1483   GstV4l2Object *obj = pool->obj;
1484   gint amount;
1485   GstMapInfo map;
1486   gint toread;
1487
1488   toread = obj->info.size;
1489
1490   GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);
1491
1492   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1493
1494   do {
1495     if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK)
1496       goto poll_error;
1497
1498     amount = v4l2_read (obj->video_fd, map.data, toread);
1499
1500     if (amount == toread) {
1501       break;
1502     } else if (amount == -1) {
1503       if (errno == EAGAIN || errno == EINTR) {
1504         continue;
1505       } else
1506         goto read_error;
1507     } else {
1508       /* short reads can happen if a signal interrupts the read */
1509       continue;
1510     }
1511   } while (TRUE);
1512
1513   GST_LOG_OBJECT (pool, "read %d bytes", amount);
1514   gst_buffer_unmap (buf, &map);
1515   gst_buffer_resize (buf, 0, amount);
1516
1517   return GST_FLOW_OK;
1518
1519   /* ERRORS */
1520 poll_error:
1521   {
1522     GST_DEBUG ("poll error %s", gst_flow_get_name (res));
1523     goto cleanup;
1524   }
1525 read_error:
1526   {
1527     GST_ELEMENT_ERROR (obj->element, RESOURCE, READ,
1528         (_("Error reading %d bytes from device '%s'."),
1529             toread, obj->videodev), GST_ERROR_SYSTEM);
1530     res = GST_FLOW_ERROR;
1531     goto cleanup;
1532   }
1533 cleanup:
1534   {
1535     gst_buffer_unmap (buf, &map);
1536     gst_buffer_resize (buf, 0, 0);
1537     return res;
1538   }
1539 }
1540
1541 /**
1542  * gst_v4l2_buffer_pool_process:
1543  * @bpool: a #GstBufferPool
1544  * @buf: a #GstBuffer, maybe be replaced
1545  *
1546  * Process @buf in @bpool. For capture devices, this functions fills @buf with
1547  * data from the device. For output devices, this functions send the contents of
1548  * @buf to the device for playback.
1549  *
1550  * Returns: %GST_FLOW_OK on success.
1551  */
1552 GstFlowReturn
1553 gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
1554 {
1555   GstFlowReturn ret = GST_FLOW_OK;
1556   GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool);
1557   GstV4l2Object *obj = pool->obj;
1558
1559   GST_DEBUG_OBJECT (pool, "process buffer %p", buf);
1560
1561   g_return_val_if_fail (gst_buffer_pool_is_active (bpool), GST_FLOW_ERROR);
1562
1563   if (GST_BUFFER_POOL_IS_FLUSHING (pool))
1564     return GST_FLOW_FLUSHING;
1565
1566   switch (obj->type) {
1567     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1568     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1569       /* capture */
1570       switch (obj->mode) {
1571         case GST_V4L2_IO_RW:
1572           /* capture into the buffer */
1573           ret = gst_v4l2_do_read (pool, *buf);
1574           break;
1575
1576         case GST_V4L2_IO_MMAP:
1577         case GST_V4L2_IO_DMABUF:
1578         {
1579           GstBuffer *tmp;
1580
1581           if ((*buf)->pool == bpool) {
1582             if (gst_buffer_get_size (*buf) == 0)
1583               goto eos;
1584
1585             /* start copying buffers when we are running low on buffers */
1586             if (g_atomic_int_get (&pool->num_queued) < pool->copy_threshold) {
1587               GstBuffer *copy;
1588
1589               if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
1590
1591                 if (gst_buffer_pool_acquire_buffer (bpool, &copy,
1592                         NULL) == GST_FLOW_OK) {
1593                   gst_v4l2_buffer_pool_release_buffer (bpool, copy);
1594                   goto done;
1595                 }
1596               }
1597
1598               /* copy the buffer */
1599               copy = gst_buffer_copy_region (*buf,
1600                   GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1);
1601               GST_LOG_OBJECT (pool, "copy buffer %p->%p", *buf, copy);
1602
1603               /* and requeue so that we can continue capturing */
1604               gst_buffer_unref (*buf);
1605               *buf = copy;
1606             }
1607
1608             /* nothing, data was inside the buffer when we did _acquire() */
1609             goto done;
1610           }
1611
1612           /* buffer not from our pool, grab a frame and copy it into the target */
1613           if ((ret = gst_v4l2_buffer_pool_dqbuf (pool, &tmp)) != GST_FLOW_OK)
1614             goto done;
1615
1616           /* An empty buffer on capture indicates the end of stream */
1617           if (gst_buffer_get_size (tmp) == 0) {
1618             gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
1619             goto eos;
1620           }
1621
1622           ret = gst_v4l2_buffer_pool_copy_buffer (pool, *buf, tmp);
1623
1624           /* an queue the buffer again after the copy */
1625           gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
1626
1627           if (ret != GST_FLOW_OK)
1628             goto copy_failed;
1629           break;
1630         }
1631
1632         case GST_V4L2_IO_USERPTR:
1633         {
1634           struct UserPtrData *data;
1635
1636           /* Replace our buffer with downstream allocated buffer */
1637           data = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
1638               GST_V4L2_IMPORT_QUARK);
1639           gst_buffer_replace (buf, data->buffer);
1640           _unmap_userptr_frame (data);
1641           break;
1642         }
1643
1644         case GST_V4L2_IO_DMABUF_IMPORT:
1645         {
1646           GstBuffer *tmp;
1647
1648           /* Replace our buffer with downstream allocated buffer */
1649           tmp = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
1650               GST_V4L2_IMPORT_QUARK);
1651           gst_buffer_replace (buf, tmp);
1652           gst_buffer_unref (tmp);
1653           break;
1654         }
1655
1656         default:
1657           g_assert_not_reached ();
1658           break;
1659       }
1660       break;
1661
1662     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1663     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1664       /* playback */
1665       switch (obj->mode) {
1666         case GST_V4L2_IO_RW:
1667           /* FIXME, do write() */
1668           GST_WARNING_OBJECT (pool, "implement write()");
1669           break;
1670
1671         case GST_V4L2_IO_USERPTR:
1672         case GST_V4L2_IO_DMABUF_IMPORT:
1673         case GST_V4L2_IO_DMABUF:
1674         case GST_V4L2_IO_MMAP:
1675         {
1676           GstBuffer *to_queue = NULL;
1677           GstV4l2MemoryGroup *group;
1678           gint index;
1679
1680           if ((*buf)->pool != bpool)
1681             goto copying;
1682
1683           if (!gst_v4l2_is_buffer_valid (*buf, &group))
1684             goto copying;
1685
1686           index = group->buffer.index;
1687
1688           GST_LOG_OBJECT (pool, "processing buffer %i from our pool", index);
1689
1690           index = group->buffer.index;
1691           if (pool->buffers[index] != NULL) {
1692             GST_LOG_OBJECT (pool, "buffer %i already queued, copying", index);
1693             goto copying;
1694           }
1695
1696           /* we can queue directly */
1697           to_queue = gst_buffer_ref (*buf);
1698
1699         copying:
1700           if (to_queue == NULL) {
1701             GstBufferPoolAcquireParams params = { 0 };
1702
1703             GST_LOG_OBJECT (pool, "alloc buffer from our pool");
1704
1705             /* this can return EOS if all buffers are outstanding which would
1706              * be strange because we would expect the upstream element to have
1707              * allocated them and returned to us.. */
1708             params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
1709             ret = gst_buffer_pool_acquire_buffer (bpool, &to_queue, &params);
1710             if (ret != GST_FLOW_OK)
1711               goto acquire_failed;
1712
1713             ret = gst_v4l2_buffer_pool_prepare_buffer (pool, to_queue, *buf);
1714             if (ret != GST_FLOW_OK) {
1715               gst_buffer_unref (to_queue);
1716               goto prepare_failed;
1717             }
1718           }
1719
1720           if ((ret = gst_v4l2_buffer_pool_qbuf (pool, to_queue)) != GST_FLOW_OK)
1721             goto queue_failed;
1722
1723           /* if we are not streaming yet (this is the first buffer, start
1724            * streaming now */
1725           if (!gst_v4l2_buffer_pool_streamon (pool)) {
1726             /* don't check return value because qbuf would have failed */
1727             gst_v4l2_is_buffer_valid (to_queue, &group);
1728
1729             /* qbuf has taken the ref of the to_queue buffer but we are no in
1730              * streaming state, so the flush logic won't be performed.
1731              * To avoid leaks, flush the allocator and restore the queued
1732              * buffer as non-queued */
1733             gst_v4l2_allocator_flush (pool->vallocator);
1734
1735             pool->buffers[group->buffer.index] = NULL;
1736
1737             gst_mini_object_set_qdata (GST_MINI_OBJECT (to_queue),
1738                 GST_V4L2_IMPORT_QUARK, NULL, NULL);
1739             gst_buffer_unref (to_queue);
1740             g_atomic_int_add (&pool->num_queued, -1);
1741             goto start_failed;
1742           }
1743
1744           if (g_atomic_int_get (&pool->num_queued) >= pool->min_latency) {
1745             GstBuffer *out;
1746             /* all buffers are queued, try to dequeue one and release it back
1747              * into the pool so that _acquire can get to it again. */
1748             ret = gst_v4l2_buffer_pool_dqbuf (pool, &out);
1749             if (ret == GST_FLOW_OK)
1750               /* release the rendered buffer back into the pool. This wakes up any
1751                * thread waiting for a buffer in _acquire(). */
1752               gst_buffer_unref (out);
1753           }
1754           break;
1755         }
1756         default:
1757           g_assert_not_reached ();
1758           break;
1759       }
1760       break;
1761     default:
1762       g_assert_not_reached ();
1763       break;
1764   }
1765 done:
1766   return ret;
1767
1768   /* ERRORS */
1769 copy_failed:
1770   {
1771     GST_ERROR_OBJECT (pool, "failed to copy buffer");
1772     return ret;
1773   }
1774 eos:
1775   {
1776     GST_DEBUG_OBJECT (pool, "end of stream reached");
1777     return GST_FLOW_EOS;
1778   }
1779 acquire_failed:
1780   {
1781     if (ret == GST_FLOW_FLUSHING)
1782       GST_DEBUG_OBJECT (pool, "flushing");
1783     else
1784       GST_WARNING_OBJECT (pool, "failed to acquire a buffer: %s",
1785           gst_flow_get_name (ret));
1786     return ret;
1787   }
1788 prepare_failed:
1789   {
1790     GST_ERROR_OBJECT (pool, "failed to prepare data");
1791     return ret;
1792   }
1793 queue_failed:
1794   {
1795     GST_ERROR_OBJECT (pool, "failed to queue buffer");
1796     return ret;
1797   }
1798 start_failed:
1799   {
1800     GST_ERROR_OBJECT (pool, "failed to start streaming");
1801     return GST_FLOW_ERROR;
1802   }
1803 }
1804
1805 void
1806 gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
1807     GstBufferPool * other_pool)
1808 {
1809   g_return_if_fail (!gst_buffer_pool_is_active (GST_BUFFER_POOL (pool)));
1810
1811   if (pool->other_pool)
1812     gst_object_unref (pool->other_pool);
1813   pool->other_pool = gst_object_ref (other_pool);
1814 }