[v4l2] Change feature name
[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@gmail.com>
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 "gstv4l2object.h"
46 #include "gst/gst-i18n-plugin.h"
47 #include <gst/glib-compat-private.h>
48 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
49 #include <gst/allocators/gsttizenmemory.h>
50 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
51
52 GST_DEBUG_CATEGORY_STATIC (v4l2bufferpool_debug);
53 GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE);
54 #define GST_CAT_DEFAULT v4l2bufferpool_debug
55
56 #define GST_V4L2_IMPORT_QUARK gst_v4l2_buffer_pool_import_quark ()
57
58 /*
59  * GstV4l2BufferPool:
60  */
61 #define gst_v4l2_buffer_pool_parent_class parent_class
62 G_DEFINE_TYPE (GstV4l2BufferPool, gst_v4l2_buffer_pool, GST_TYPE_BUFFER_POOL);
63
64 enum _GstV4l2BufferPoolAcquireFlags
65 {
66   GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT =
67       GST_BUFFER_POOL_ACQUIRE_FLAG_LAST,
68   GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_LAST
69 };
70
71 static void gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool,
72     GstBuffer * buffer);
73 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
74 typedef struct _GstV4l2TizenBuffer GstV4l2TizenBuffer;
75 struct _GstV4l2TizenBuffer {
76   int index;
77   GstBuffer *gst_buffer;
78   GstBuffer *v4l2_buffer;
79   GstV4l2BufferPool *v4l2_pool;
80 };
81
82 static void gst_v4l2_tizen_buffer_finalize (GstV4l2TizenBuffer *tizen_buffer)
83 {
84   GstV4l2BufferPool *pool = NULL;
85
86   if (!tizen_buffer) {
87     GST_ERROR ("NULL buffer");
88     return;
89   }
90
91   pool = tizen_buffer->v4l2_pool;
92
93   gst_v4l2_buffer_pool_release_buffer (GST_BUFFER_POOL_CAST (pool), tizen_buffer->v4l2_buffer);
94
95   g_mutex_lock (&pool->buffer_lock);
96
97   pool->live_buffer_count--;
98
99   GST_DEBUG_OBJECT (pool, "release buffer[%d][tizen:%p,v4l2:%p,gst:%p], live[%d]",
100       tizen_buffer->index, tizen_buffer, tizen_buffer->v4l2_buffer,
101       tizen_buffer->gst_buffer, pool->live_buffer_count);
102
103   g_cond_signal (&pool->buffer_cond);
104
105   g_mutex_unlock (&pool->buffer_lock);
106
107   g_free(tizen_buffer);
108 }
109
110 static GstV4l2TizenBuffer *gst_v4l2_tizen_buffer_new (GstBuffer *v4l2_buffer, int index, GstV4l2BufferPool *v4l2_pool)
111 {
112   GstV4l2TizenBuffer *tizen_buffer = NULL;
113   GstMemory *memory = NULL;
114
115   tizen_buffer = g_new0 (GstV4l2TizenBuffer, 1);
116   tizen_buffer->index = index;
117   tizen_buffer->v4l2_buffer = v4l2_buffer;
118   tizen_buffer->gst_buffer = gst_buffer_new ();
119   tizen_buffer->v4l2_pool = v4l2_pool;
120
121   memory = gst_tizen_allocator_alloc_surface (v4l2_pool->tallocator,
122       &v4l2_pool->obj->info, v4l2_pool->vallocator->groups[index]->surface, (gpointer)tizen_buffer,
123       (GDestroyNotify)gst_v4l2_tizen_buffer_finalize);
124
125   gst_buffer_append_memory (tizen_buffer->gst_buffer, memory);
126   gst_buffer_set_size (tizen_buffer->gst_buffer, v4l2_pool->vallocator->s_info.size);
127
128   g_mutex_lock (&v4l2_pool->buffer_lock);
129
130   v4l2_pool->live_buffer_count++;
131
132   GST_DEBUG_OBJECT (v4l2_pool, "new buffer[tizen:%p,v4l2:%p,gst:%p], size[%d], live[%d]",
133       tizen_buffer, v4l2_buffer, tizen_buffer->gst_buffer,
134       v4l2_pool->vallocator->s_info.size, v4l2_pool->live_buffer_count);
135
136   g_mutex_unlock (&v4l2_pool->buffer_lock);
137
138   return tizen_buffer;
139 }
140 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
141
142 static gboolean
143 gst_v4l2_is_buffer_valid (GstBuffer * buffer, GstV4l2MemoryGroup ** out_group)
144 {
145   GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
146   gboolean valid = FALSE;
147
148   if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))
149     goto done;
150
151   if (gst_is_dmabuf_memory (mem))
152     mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
153         GST_V4L2_MEMORY_QUARK);
154
155   if (mem && gst_is_v4l2_memory (mem)) {
156     GstV4l2Memory *vmem = (GstV4l2Memory *) mem;
157     GstV4l2MemoryGroup *group = vmem->group;
158     gint i;
159
160     if (group->n_mem != gst_buffer_n_memory (buffer))
161       goto done;
162
163     for (i = 0; i < group->n_mem; i++) {
164       if (group->mem[i] != gst_buffer_peek_memory (buffer, i))
165         goto done;
166
167       if (!gst_memory_is_writable (group->mem[i]))
168         goto done;
169     }
170
171     valid = TRUE;
172     if (out_group)
173       *out_group = group;
174   }
175
176 done:
177   return valid;
178 }
179
180 static GstFlowReturn
181 gst_v4l2_buffer_pool_copy_buffer (GstV4l2BufferPool * pool, GstBuffer * dest,
182     GstBuffer * src)
183 {
184   const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
185
186   GST_LOG_OBJECT (pool, "copying buffer");
187
188   if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
189           finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
190     GstVideoFrame src_frame, dest_frame;
191
192     GST_DEBUG_OBJECT (pool, "copy video frame");
193
194     /* we have raw video, use videoframe copy to get strides right */
195     if (!gst_video_frame_map (&src_frame, &pool->caps_info, src, GST_MAP_READ))
196       goto invalid_buffer;
197
198     if (!gst_video_frame_map (&dest_frame, &pool->caps_info, dest,
199             GST_MAP_WRITE)) {
200       gst_video_frame_unmap (&src_frame);
201       goto invalid_buffer;
202     }
203
204     gst_video_frame_copy (&dest_frame, &src_frame);
205
206     gst_video_frame_unmap (&src_frame);
207     gst_video_frame_unmap (&dest_frame);
208   } else {
209     GstMapInfo map;
210
211     GST_DEBUG_OBJECT (pool, "copy raw bytes");
212
213     if (!gst_buffer_map (src, &map, GST_MAP_READ))
214       goto invalid_buffer;
215
216     gst_buffer_fill (dest, 0, map.data, gst_buffer_get_size (src));
217
218     gst_buffer_unmap (src, &map);
219     gst_buffer_resize (dest, 0, gst_buffer_get_size (src));
220   }
221
222   gst_buffer_copy_into (dest, src,
223       GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
224
225   GST_CAT_LOG_OBJECT (CAT_PERFORMANCE, pool, "slow copy into buffer %p", dest);
226
227   return GST_FLOW_OK;
228
229 invalid_buffer:
230   {
231     GST_ERROR_OBJECT (pool, "could not map buffer");
232     return GST_FLOW_ERROR;
233   }
234 }
235
236 struct UserPtrData
237 {
238   GstBuffer *buffer;
239   gboolean is_frame;
240   GstVideoFrame frame;
241   GstMapInfo map;
242 };
243
244 static GQuark
245 gst_v4l2_buffer_pool_import_quark (void)
246 {
247   static GQuark quark = 0;
248
249   if (quark == 0)
250     quark = g_quark_from_string ("GstV4l2BufferPoolUsePtrData");
251
252   return quark;
253 }
254
255 static void
256 _unmap_userptr_frame (struct UserPtrData *data)
257 {
258   if (data->is_frame)
259     gst_video_frame_unmap (&data->frame);
260   else
261     gst_buffer_unmap (data->buffer, &data->map);
262
263   if (data->buffer)
264     gst_buffer_unref (data->buffer);
265
266   g_slice_free (struct UserPtrData, data);
267 }
268
269 static GstFlowReturn
270 gst_v4l2_buffer_pool_import_userptr (GstV4l2BufferPool * pool,
271     GstBuffer * dest, GstBuffer * src)
272 {
273   GstFlowReturn ret = GST_FLOW_OK;
274   GstV4l2MemoryGroup *group = NULL;
275   GstMapFlags flags;
276   const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
277   struct UserPtrData *data = NULL;
278
279   GST_LOG_OBJECT (pool, "importing userptr");
280
281   /* get the group */
282   if (!gst_v4l2_is_buffer_valid (dest, &group))
283     goto not_our_buffer;
284
285   if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
286     flags = GST_MAP_READ;
287   else
288     flags = GST_MAP_WRITE;
289
290   data = g_slice_new0 (struct UserPtrData);
291
292   if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
293           finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
294     gsize size[GST_VIDEO_MAX_PLANES] = { 0, };
295     gint i;
296
297     data->is_frame = TRUE;
298
299     if (!gst_video_frame_map (&data->frame, &pool->caps_info, src, flags))
300       goto invalid_buffer;
301
302     for (i = 0; i < GST_VIDEO_FORMAT_INFO_N_PLANES (finfo); i++) {
303       if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
304         gint tinfo = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i);
305         gint pstride;
306         guint pheight;
307
308         pstride = GST_VIDEO_TILE_X_TILES (tinfo) <<
309             GST_VIDEO_FORMAT_INFO_TILE_WS (finfo);
310
311         pheight = GST_VIDEO_TILE_Y_TILES (tinfo) <<
312             GST_VIDEO_FORMAT_INFO_TILE_HS (finfo);
313
314         size[i] = pstride * pheight;
315       } else {
316         size[i] = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i) *
317             GST_VIDEO_FRAME_COMP_HEIGHT (&data->frame, i);
318       }
319     }
320
321     /* In the single planar API, planes must be contiguous in memory and
322      * therefore they must have expected size. ie: no padding.
323      * To check these conditions, we check that plane 'i' start address
324      * + plane 'i' size equals to plane 'i+1' start address */
325     if (!V4L2_TYPE_IS_MULTIPLANAR (pool->obj->type)) {
326       for (i = 0; i < (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) - 1); i++) {
327         const struct v4l2_pix_format *pix_fmt = &pool->obj->format.fmt.pix;
328         gpointer tmp;
329         gint estride = gst_v4l2_object_extrapolate_stride (finfo, i,
330             pix_fmt->bytesperline);
331         guint eheight = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i,
332             pix_fmt->height);
333
334         tmp = ((guint8 *) data->frame.data[i]) + estride * eheight;
335         if (tmp != data->frame.data[i + 1])
336           goto non_contiguous_mem;
337       }
338     }
339
340     if (!gst_v4l2_allocator_import_userptr (pool->vallocator, group,
341             data->frame.info.size, finfo->n_planes, data->frame.data, size))
342       goto import_failed;
343   } else {
344     gpointer ptr[1];
345     gsize size[1];
346
347     data->is_frame = FALSE;
348
349     if (!gst_buffer_map (src, &data->map, flags))
350       goto invalid_buffer;
351
352     ptr[0] = data->map.data;
353     size[0] = data->map.size;
354
355     if (!gst_v4l2_allocator_import_userptr (pool->vallocator, group,
356             data->map.size, 1, ptr, size))
357       goto import_failed;
358   }
359
360   data->buffer = gst_buffer_ref (src);
361
362   gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
363       data, (GDestroyNotify) _unmap_userptr_frame);
364
365   gst_buffer_copy_into (dest, src,
366       GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
367
368   return ret;
369
370 not_our_buffer:
371   {
372     GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
373     return GST_FLOW_ERROR;
374   }
375 invalid_buffer:
376   {
377     GST_ERROR_OBJECT (pool, "could not map buffer");
378     g_slice_free (struct UserPtrData, data);
379     return GST_FLOW_ERROR;
380   }
381 non_contiguous_mem:
382   {
383     GST_ERROR_OBJECT (pool, "memory is not contiguous or plane size mismatch");
384     _unmap_userptr_frame (data);
385     return GST_FLOW_ERROR;
386   }
387 import_failed:
388   {
389     GST_ERROR_OBJECT (pool, "failed to import data");
390     _unmap_userptr_frame (data);
391     return GST_FLOW_ERROR;
392   }
393 }
394
395 static GstFlowReturn
396 gst_v4l2_buffer_pool_import_dmabuf (GstV4l2BufferPool * pool,
397     GstBuffer * dest, GstBuffer * src)
398 {
399   GstV4l2MemoryGroup *group = NULL;
400   GstMemory *dma_mem[GST_VIDEO_MAX_PLANES] = { 0 };
401   guint n_mem = gst_buffer_n_memory (src);
402   gint i;
403
404   GST_LOG_OBJECT (pool, "importing dmabuf");
405
406   if (!gst_v4l2_is_buffer_valid (dest, &group))
407     goto not_our_buffer;
408
409   if (n_mem > GST_VIDEO_MAX_PLANES)
410     goto too_many_mems;
411
412   for (i = 0; i < n_mem; i++)
413     dma_mem[i] = gst_buffer_peek_memory (src, i);
414
415   if (!gst_v4l2_allocator_import_dmabuf (pool->vallocator, group, n_mem,
416           dma_mem))
417     goto import_failed;
418
419   gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
420       gst_buffer_ref (src), (GDestroyNotify) gst_buffer_unref);
421
422   gst_buffer_copy_into (dest, src,
423       GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
424
425   return GST_FLOW_OK;
426
427 not_our_buffer:
428   {
429     GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
430     return GST_FLOW_ERROR;
431   }
432 too_many_mems:
433   {
434     GST_ERROR_OBJECT (pool, "could not map buffer");
435     return GST_FLOW_ERROR;
436   }
437 import_failed:
438   {
439     GST_ERROR_OBJECT (pool, "failed to import dmabuf");
440     return GST_FLOW_ERROR;
441   }
442 }
443
444 static GstFlowReturn
445 gst_v4l2_buffer_pool_prepare_buffer (GstV4l2BufferPool * pool,
446     GstBuffer * dest, GstBuffer * src)
447 {
448   GstFlowReturn ret = GST_FLOW_OK;
449   gboolean own_src = FALSE;
450
451   if (src == NULL) {
452     if (pool->other_pool == NULL) {
453       GST_ERROR_OBJECT (pool, "can't prepare buffer, source buffer missing");
454       return GST_FLOW_ERROR;
455     }
456
457     ret = gst_buffer_pool_acquire_buffer (pool->other_pool, &src, NULL);
458     if (ret != GST_FLOW_OK) {
459       GST_ERROR_OBJECT (pool, "failed to acquire buffer from downstream pool");
460       goto done;
461     }
462
463     own_src = TRUE;
464   }
465
466   switch (pool->obj->mode) {
467     case GST_V4L2_IO_MMAP:
468     case GST_V4L2_IO_DMABUF:
469       ret = gst_v4l2_buffer_pool_copy_buffer (pool, dest, src);
470       break;
471     case GST_V4L2_IO_USERPTR:
472       ret = gst_v4l2_buffer_pool_import_userptr (pool, dest, src);
473       break;
474     case GST_V4L2_IO_DMABUF_IMPORT:
475       ret = gst_v4l2_buffer_pool_import_dmabuf (pool, dest, src);
476       break;
477     default:
478       break;
479   }
480
481   if (own_src)
482     gst_buffer_unref (src);
483
484 done:
485   return ret;
486 }
487
488 static GstFlowReturn
489 gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
490     GstBufferPoolAcquireParams * params)
491 {
492   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
493   GstV4l2MemoryGroup *group = NULL;
494   GstBuffer *newbuf = NULL;
495   GstV4l2Object *obj;
496   GstVideoInfo *info;
497
498   obj = pool->obj;
499   info = &obj->info;
500
501   switch (obj->mode) {
502     case GST_V4L2_IO_RW:
503       newbuf =
504           gst_buffer_new_allocate (pool->allocator, pool->size, &pool->params);
505       break;
506     case GST_V4L2_IO_MMAP:
507       group = gst_v4l2_allocator_alloc_mmap (pool->vallocator);
508       break;
509     case GST_V4L2_IO_DMABUF:
510       group = gst_v4l2_allocator_alloc_dmabuf (pool->vallocator,
511           pool->allocator);
512       break;
513     case GST_V4L2_IO_USERPTR:
514       group = gst_v4l2_allocator_alloc_userptr (pool->vallocator);
515       break;
516     case GST_V4L2_IO_DMABUF_IMPORT:
517       group = gst_v4l2_allocator_alloc_dmabufin (pool->vallocator);
518       break;
519     default:
520       newbuf = NULL;
521       g_assert_not_reached ();
522       break;
523   }
524
525   if (group != NULL) {
526     gint i;
527     newbuf = gst_buffer_new ();
528
529     for (i = 0; i < group->n_mem; i++)
530       gst_buffer_append_memory (newbuf, group->mem[i]);
531   } else if (newbuf == NULL) {
532     goto allocation_failed;
533   }
534
535   /* add metadata to raw video buffers */
536   if (pool->add_videometa)
537     gst_buffer_add_video_meta_full (newbuf, GST_VIDEO_FRAME_FLAG_NONE,
538         GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
539         GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
540         info->offset, info->stride);
541
542   *buffer = newbuf;
543
544   return GST_FLOW_OK;
545
546   /* ERRORS */
547 allocation_failed:
548   {
549     GST_ERROR_OBJECT (pool, "failed to allocate buffer");
550     return GST_FLOW_ERROR;
551   }
552 }
553
554 static gboolean
555 gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
556 {
557   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
558   GstV4l2Object *obj = pool->obj;
559   GstCaps *caps;
560   guint size, min_buffers, max_buffers;
561   GstAllocator *allocator;
562   GstAllocationParams params;
563   gboolean can_allocate = FALSE;
564   gboolean updated = FALSE;
565   gboolean ret;
566
567   pool->add_videometa =
568       gst_buffer_pool_config_has_option (config,
569       GST_BUFFER_POOL_OPTION_VIDEO_META);
570
571   /* parse the config and keep around */
572   if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
573           &max_buffers))
574     goto wrong_config;
575
576   if (!gst_buffer_pool_config_get_allocator (config, &allocator, &params))
577     goto wrong_config;
578
579   GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
580
581   if (pool->allocator)
582     gst_object_unref (pool->allocator);
583   pool->allocator = NULL;
584
585   switch (obj->mode) {
586     case GST_V4L2_IO_DMABUF:
587       pool->allocator = gst_dmabuf_allocator_new ();
588       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
589       break;
590     case GST_V4L2_IO_MMAP:
591       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
592       break;
593     case GST_V4L2_IO_USERPTR:
594       can_allocate =
595           GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
596       break;
597     case GST_V4L2_IO_DMABUF_IMPORT:
598       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
599       break;
600     case GST_V4L2_IO_RW:
601       if (allocator)
602         pool->allocator = g_object_ref (allocator);
603       pool->params = params;
604       /* No need to change the configuration */
605       goto done;
606       break;
607     default:
608       g_assert_not_reached ();
609       break;
610   }
611
612   /* libv4l2 conversion code does not handle CREATE_BUFS, and may lead to
613    * instability and crash, disable it for now */
614   if (can_allocate && obj->fmtdesc->flags & V4L2_FMT_FLAG_EMULATED) {
615     GST_WARNING_OBJECT (pool,
616         "libv4l2 converter detected, disabling CREATE_BUFS");
617     can_allocate = FALSE;
618     GST_OBJECT_FLAG_UNSET (pool->vallocator,
619         GST_V4L2_ALLOCATOR_FLAG_MMAP_CREATE_BUFS
620         | GST_V4L2_ALLOCATOR_FLAG_USERPTR_CREATE_BUFS
621         | GST_V4L2_ALLOCATOR_FLAG_DMABUF_CREATE_BUFS);
622   }
623
624   if (min_buffers < GST_V4L2_MIN_BUFFERS) {
625     updated = TRUE;
626     min_buffers = GST_V4L2_MIN_BUFFERS;
627     GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
628   }
629
630   /* respect driver requirements */
631   if (min_buffers < obj->min_buffers) {
632     updated = TRUE;
633     min_buffers = obj->min_buffers;
634     GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
635   }
636
637   if (max_buffers > VIDEO_MAX_FRAME || max_buffers == 0) {
638     updated = TRUE;
639     max_buffers = VIDEO_MAX_FRAME;
640     GST_INFO_OBJECT (pool, "reducing maximum buffers to %u", max_buffers);
641   }
642
643   if (min_buffers > max_buffers) {
644     updated = TRUE;
645     min_buffers = max_buffers;
646     GST_INFO_OBJECT (pool, "reducing minimum buffers to %u", min_buffers);
647   } else if (min_buffers != max_buffers) {
648     if (!can_allocate) {
649       updated = TRUE;
650       max_buffers = min_buffers;
651       GST_INFO_OBJECT (pool, "can't allocate, setting maximum to minimum");
652     }
653   }
654
655   if (!pool->add_videometa && obj->need_video_meta) {
656     GST_INFO_OBJECT (pool, "adding needed video meta");
657     updated = TRUE;
658     gst_buffer_pool_config_add_option (config,
659         GST_BUFFER_POOL_OPTION_VIDEO_META);
660   }
661
662   /* Always update the config to ensure the configured size matches */
663   gst_buffer_pool_config_set_params (config, caps, obj->info.size, min_buffers,
664       max_buffers);
665
666   /* keep a GstVideoInfo with defaults for the when we need to copy */
667   gst_video_info_from_caps (&pool->caps_info, caps);
668
669 done:
670   ret = GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
671
672   /* If anything was changed documentation recommand to return FALSE */
673   return !updated && ret;
674
675   /* ERRORS */
676 wrong_config:
677   {
678     GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
679     return FALSE;
680   }
681 }
682
683 static GstFlowReturn
684 gst_v4l2_buffer_pool_resurrect_buffer (GstV4l2BufferPool * pool)
685 {
686   GstBufferPoolAcquireParams params = { 0 };
687   GstBuffer *buffer = NULL;
688   GstFlowReturn ret;
689
690   GST_DEBUG_OBJECT (pool, "A buffer was lost, reallocating it");
691
692   /* block recursive calls to this function */
693   g_signal_handler_block (pool->vallocator, pool->group_released_handler);
694
695   params.flags =
696       (GstBufferPoolAcquireFlags) GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT |
697       GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
698   ret =
699       gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (pool), &buffer, &params);
700
701   if (ret == GST_FLOW_OK)
702     gst_buffer_unref (buffer);
703
704   g_signal_handler_unblock (pool->vallocator, pool->group_released_handler);
705
706   return ret;
707 }
708
709 static gboolean
710 gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
711 {
712   GstV4l2Object *obj = pool->obj;
713
714   if (pool->streaming)
715     return TRUE;
716
717   switch (obj->mode) {
718     case GST_V4L2_IO_MMAP:
719     case GST_V4L2_IO_USERPTR:
720     case GST_V4L2_IO_DMABUF:
721     case GST_V4L2_IO_DMABUF_IMPORT:
722       if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) {
723         guint num_queued;
724         guint i, n = 0;
725
726         num_queued = g_atomic_int_get (&pool->num_queued);
727         if (num_queued < pool->num_allocated)
728           n = pool->num_allocated - num_queued;
729
730         /* For captures, we need to enqueue buffers before we start streaming,
731          * so the driver don't underflow immediatly. As we have put then back
732          * into the base class queue, resurrect them, then releasing will queue
733          * them back. */
734         for (i = 0; i < n; i++)
735           gst_v4l2_buffer_pool_resurrect_buffer (pool);
736       }
737
738       if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
739         goto streamon_failed;
740
741       pool->streaming = TRUE;
742
743       GST_DEBUG_OBJECT (pool, "Started streaming");
744       break;
745     default:
746       break;
747   }
748
749   return TRUE;
750
751 streamon_failed:
752   {
753     GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
754         g_strerror (errno));
755     return FALSE;
756   }
757 }
758
759 /* Call with streamlock held, or when streaming threads are down */
760 static void
761 gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
762 {
763   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
764   GstV4l2Object *obj = pool->obj;
765   gint i;
766 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
767   gint64 end_time = 0;
768 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
769
770   if (!pool->streaming)
771     return;
772
773 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
774   if (obj->tbm_output && !V4L2_TYPE_IS_OUTPUT(pool->obj->type)) {
775     g_mutex_lock (&pool->buffer_lock);
776
777     GST_INFO_OBJECT (pool, "live buffer[%d]", pool->live_buffer_count);
778
779     if (pool->live_buffer_count > 0) {
780       end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
781
782       do {
783         GST_WARNING_OBJECT (pool, "wait for live buffer[%d]", pool->live_buffer_count);
784
785         if (!g_cond_wait_until (&pool->buffer_cond, &pool->buffer_lock, end_time)) {
786           GST_ERROR_OBJECT (pool, "failed to wait live buffer[%d]", pool->live_buffer_count);
787           break;
788         }
789
790         GST_WARNING_OBJECT (pool, "signal received, check again : live count[%d]",
791             pool->live_buffer_count);
792       } while (pool->live_buffer_count > 0);
793     }
794
795     g_mutex_unlock (&pool->buffer_lock);
796   }
797 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
798   switch (obj->mode) {
799     case GST_V4L2_IO_MMAP:
800     case GST_V4L2_IO_USERPTR:
801     case GST_V4L2_IO_DMABUF:
802     case GST_V4L2_IO_DMABUF_IMPORT:
803
804       if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
805         GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
806             errno, g_strerror (errno));
807
808       pool->streaming = FALSE;
809
810       GST_DEBUG_OBJECT (pool, "Stopped streaming");
811
812       if (pool->vallocator)
813         gst_v4l2_allocator_flush (pool->vallocator);
814       break;
815     default:
816       break;
817   }
818
819   for (i = 0; i < VIDEO_MAX_FRAME; i++) {
820     if (pool->buffers[i]) {
821       GstBuffer *buffer = pool->buffers[i];
822       GstBufferPool *bpool = GST_BUFFER_POOL (pool);
823
824       pool->buffers[i] = NULL;
825
826       if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
827         gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
828       else                      /* Don't re-enqueue capture buffer on stop */
829         pclass->release_buffer (bpool, buffer);
830
831       g_atomic_int_add (&pool->num_queued, -1);
832     }
833   }
834 }
835
836 static gboolean
837 gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
838 {
839   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
840   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
841   GstV4l2Object *obj = pool->obj;
842   GstStructure *config;
843   GstCaps *caps;
844   guint size, min_buffers, max_buffers;
845   guint max_latency, min_latency, copy_threshold = 0;
846   gboolean can_allocate = FALSE, ret = TRUE;
847
848   GST_DEBUG_OBJECT (pool, "activating pool");
849
850   if (pool->other_pool) {
851     GstBuffer *buffer;
852
853     if (!gst_buffer_pool_set_active (pool->other_pool, TRUE))
854       goto other_pool_failed;
855
856     if (gst_buffer_pool_acquire_buffer (pool->other_pool, &buffer, NULL) !=
857         GST_FLOW_OK)
858       goto other_pool_failed;
859
860     if (!gst_v4l2_object_try_import (obj, buffer)) {
861       gst_buffer_unref (buffer);
862       goto cannot_import;
863     }
864     gst_buffer_unref (buffer);
865   }
866
867   config = gst_buffer_pool_get_config (bpool);
868   if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
869           &max_buffers))
870     goto wrong_config;
871
872   min_latency = MAX (GST_V4L2_MIN_BUFFERS, obj->min_buffers);
873
874   switch (obj->mode) {
875     case GST_V4L2_IO_RW:
876       can_allocate = TRUE;
877 #ifdef HAVE_LIBV4L2
878       /* This workaround a unfixable bug in libv4l2 when RW is emulated on top
879        * of MMAP. In this case, the first read initialize the queues, but the
880        * poll before that will always fail. Doing an empty read, forces the
881        * queue to be initialized now. We only do this if we have a streaming
882        * driver. */
883       if (obj->device_caps & V4L2_CAP_STREAMING)
884         obj->read (obj->video_fd, NULL, 0);
885 #endif
886       break;
887     case GST_V4L2_IO_DMABUF:
888     case GST_V4L2_IO_MMAP:
889     {
890       guint count;
891
892       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
893
894       /* first, lets request buffers, and see how many we can get: */
895       GST_DEBUG_OBJECT (pool, "requesting %d MMAP buffers", min_buffers);
896
897       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
898           V4L2_MEMORY_MMAP);
899       pool->num_allocated = count;
900
901       if (count < GST_V4L2_MIN_BUFFERS) {
902         min_buffers = count;
903         goto no_buffers;
904       }
905
906       /* V4L2 buffer pool are often very limited in the amount of buffers it
907        * can offer. The copy_threshold will workaround this limitation by
908        * falling back to copy if the pipeline needed more buffers. This also
909        * prevent having to do REQBUFS(N)/REQBUFS(0) everytime configure is
910        * called. */
911       if (count != min_buffers || pool->enable_copy_threshold) {
912         GST_WARNING_OBJECT (pool,
913             "Uncertain or not enough buffers, enabling copy threshold");
914         min_buffers = count;
915         copy_threshold = min_latency;
916       }
917
918       break;
919     }
920     case GST_V4L2_IO_USERPTR:
921     {
922       guint count;
923
924       can_allocate =
925           GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
926
927       GST_DEBUG_OBJECT (pool, "requesting %d USERPTR buffers", min_buffers);
928
929       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
930           V4L2_MEMORY_USERPTR);
931
932       /* There is no rational to not get what we asked */
933       if (count < min_buffers) {
934         min_buffers = count;
935         goto no_buffers;
936       }
937
938       min_buffers = count;
939       break;
940     }
941     case GST_V4L2_IO_DMABUF_IMPORT:
942     {
943       guint count;
944
945       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
946
947       GST_DEBUG_OBJECT (pool, "requesting %d DMABUF buffers", min_buffers);
948
949       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
950           V4L2_MEMORY_DMABUF);
951
952       /* There is no rational to not get what we asked */
953       if (count < min_buffers) {
954         min_buffers = count;
955         goto no_buffers;
956       }
957
958       min_buffers = count;
959       break;
960     }
961     default:
962       min_buffers = 0;
963       copy_threshold = 0;
964       g_assert_not_reached ();
965       break;
966   }
967
968   if (can_allocate)
969     max_latency = max_buffers;
970   else
971     max_latency = min_buffers;
972
973   pool->size = size;
974   pool->copy_threshold = copy_threshold;
975   pool->max_latency = max_latency;
976   pool->min_latency = min_latency;
977   pool->num_queued = 0;
978
979   if (max_buffers != 0 && max_buffers < min_buffers)
980     max_buffers = min_buffers;
981
982   gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
983       max_buffers);
984   pclass->set_config (bpool, config);
985   gst_structure_free (config);
986
987   /* now, allocate the buffers: */
988   if (!pclass->start (bpool))
989     goto start_failed;
990
991   if (!V4L2_TYPE_IS_OUTPUT (obj->type)) {
992     if (g_atomic_int_get (&pool->num_queued) < min_buffers)
993       goto queue_failed;
994
995     pool->group_released_handler =
996         g_signal_connect_swapped (pool->vallocator, "group-released",
997         G_CALLBACK (gst_v4l2_buffer_pool_resurrect_buffer), pool);
998     ret = gst_v4l2_buffer_pool_streamon (pool);
999   }
1000
1001   return ret;
1002
1003   /* ERRORS */
1004 wrong_config:
1005   {
1006     GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
1007     gst_structure_free (config);
1008     return FALSE;
1009   }
1010 no_buffers:
1011   {
1012     GST_ERROR_OBJECT (pool,
1013         "we received %d buffer from device '%s', we want at least %d",
1014         min_buffers, obj->videodev, GST_V4L2_MIN_BUFFERS);
1015     gst_structure_free (config);
1016     return FALSE;
1017   }
1018 start_failed:
1019   {
1020     GST_ERROR_OBJECT (pool, "allocate failed");
1021     return FALSE;
1022   }
1023 other_pool_failed:
1024   {
1025     GST_ERROR_OBJECT (pool, "failed to activate the other pool %"
1026         GST_PTR_FORMAT, pool->other_pool);
1027     return FALSE;
1028   }
1029 queue_failed:
1030   {
1031     GST_ERROR_OBJECT (pool, "failed to queue buffers into the capture queue");
1032     return FALSE;
1033   }
1034 cannot_import:
1035   {
1036     GST_ERROR_OBJECT (pool, "cannot import buffers from downstream pool");
1037     return FALSE;
1038   }
1039 }
1040
1041 static gboolean
1042 gst_v4l2_buffer_pool_vallocator_stop (GstV4l2BufferPool * pool)
1043 {
1044   GstV4l2Return vret;
1045
1046   if (!pool->vallocator)
1047     return TRUE;
1048
1049   vret = gst_v4l2_allocator_stop (pool->vallocator);
1050
1051   if (vret == GST_V4L2_BUSY)
1052     GST_WARNING_OBJECT (pool, "some buffers are still outstanding");
1053
1054   return (vret == GST_V4L2_OK);
1055 }
1056
1057 static gboolean
1058 gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
1059 {
1060   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1061   gboolean ret;
1062
1063   if (pool->orphaned)
1064     return gst_v4l2_buffer_pool_vallocator_stop (pool);
1065
1066   GST_DEBUG_OBJECT (pool, "stopping pool");
1067
1068   if (pool->group_released_handler > 0) {
1069     g_signal_handler_disconnect (pool->vallocator,
1070         pool->group_released_handler);
1071     pool->group_released_handler = 0;
1072   }
1073
1074   if (pool->other_pool) {
1075     gst_buffer_pool_set_active (pool->other_pool, FALSE);
1076     gst_object_unref (pool->other_pool);
1077     pool->other_pool = NULL;
1078   }
1079
1080   gst_v4l2_buffer_pool_streamoff (pool);
1081
1082   ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
1083
1084   if (ret)
1085     ret = gst_v4l2_buffer_pool_vallocator_stop (pool);
1086
1087   return ret;
1088 }
1089
1090 gboolean
1091 gst_v4l2_buffer_pool_orphan (GstBufferPool ** bpool)
1092 {
1093   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (*bpool);
1094   gboolean ret;
1095
1096   if (!GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (pool->vallocator))
1097     return FALSE;
1098
1099   if (g_getenv ("GST_V4L2_FORCE_DRAIN"))
1100     return FALSE;
1101
1102   GST_DEBUG_OBJECT (pool, "orphaning pool");
1103
1104   gst_buffer_pool_set_active (*bpool, FALSE);
1105   /*
1106    * If the buffer pool has outstanding buffers, it will not be stopped
1107    * by the base class when set inactive. Stop it manually and mark it
1108    * as orphaned
1109    */
1110   ret = gst_v4l2_buffer_pool_stop (*bpool);
1111   if (!ret)
1112     ret = gst_v4l2_allocator_orphan (pool->vallocator);
1113
1114   if (!ret)
1115     goto orphan_failed;
1116
1117   pool->orphaned = TRUE;
1118   gst_object_unref (*bpool);
1119   *bpool = NULL;
1120
1121 orphan_failed:
1122   return ret;
1123 }
1124
1125 static void
1126 gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
1127 {
1128   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1129
1130   GST_DEBUG_OBJECT (pool, "start flushing");
1131
1132   gst_poll_set_flushing (pool->poll, TRUE);
1133
1134   GST_OBJECT_LOCK (pool);
1135   pool->empty = FALSE;
1136   g_cond_broadcast (&pool->empty_cond);
1137   GST_OBJECT_UNLOCK (pool);
1138
1139   if (pool->other_pool)
1140     gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
1141 }
1142
1143 static void
1144 gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool)
1145 {
1146   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1147
1148   GST_DEBUG_OBJECT (pool, "stop flushing");
1149
1150   if (pool->other_pool)
1151     gst_buffer_pool_set_flushing (pool->other_pool, FALSE);
1152
1153   gst_poll_set_flushing (pool->poll, FALSE);
1154 }
1155
1156 static GstFlowReturn
1157 gst_v4l2_buffer_pool_poll (GstV4l2BufferPool * pool, gboolean wait)
1158 {
1159   gint ret;
1160   GstClockTime timeout;
1161
1162   if (wait)
1163     timeout = GST_CLOCK_TIME_NONE;
1164   else
1165     timeout = 0;
1166
1167   /* In RW mode there is no queue, hence no need to wait while the queue is
1168    * empty */
1169   if (pool->obj->mode != GST_V4L2_IO_RW) {
1170     GST_OBJECT_LOCK (pool);
1171
1172     if (!wait && pool->empty) {
1173       GST_OBJECT_UNLOCK (pool);
1174       goto no_buffers;
1175     }
1176
1177     while (pool->empty)
1178       g_cond_wait (&pool->empty_cond, GST_OBJECT_GET_LOCK (pool));
1179
1180     GST_OBJECT_UNLOCK (pool);
1181   }
1182
1183   if (!pool->can_poll_device) {
1184     if (wait)
1185       goto done;
1186     else
1187       goto no_buffers;
1188   }
1189
1190   GST_LOG_OBJECT (pool, "polling device");
1191
1192 again:
1193   ret = gst_poll_wait (pool->poll, timeout);
1194   if (G_UNLIKELY (ret < 0)) {
1195     switch (errno) {
1196       case EBUSY:
1197         goto stopped;
1198       case EAGAIN:
1199       case EINTR:
1200         goto again;
1201       case ENXIO:
1202         GST_WARNING_OBJECT (pool,
1203             "v4l2 device doesn't support polling. Disabling"
1204             " using libv4l2 in this case may cause deadlocks");
1205         pool->can_poll_device = FALSE;
1206         goto done;
1207       default:
1208         goto select_error;
1209     }
1210   }
1211
1212   if (gst_poll_fd_has_error (pool->poll, &pool->pollfd))
1213     goto select_error;
1214
1215   if (ret == 0)
1216     goto no_buffers;
1217
1218 done:
1219   return GST_FLOW_OK;
1220
1221   /* ERRORS */
1222 stopped:
1223   {
1224     GST_DEBUG_OBJECT (pool, "stop called");
1225     return GST_FLOW_FLUSHING;
1226   }
1227 select_error:
1228   {
1229     GST_ELEMENT_ERROR (pool->obj->element, RESOURCE, READ, (NULL),
1230         ("poll error %d: %s (%d)", ret, g_strerror (errno), errno));
1231     return GST_FLOW_ERROR;
1232   }
1233 no_buffers:
1234   return GST_FLOW_CUSTOM_SUCCESS;
1235 }
1236
1237 static GstFlowReturn
1238 gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
1239     GstV4l2MemoryGroup * group)
1240 {
1241   const GstV4l2Object *obj = pool->obj;
1242   GstClockTime timestamp;
1243   gint index;
1244
1245   index = group->buffer.index;
1246
1247   if (pool->buffers[index] != NULL)
1248     goto already_queued;
1249
1250   GST_LOG_OBJECT (pool, "queuing buffer %i", index);
1251
1252   if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
1253     enum v4l2_field field;
1254
1255     /* Except when field is set to alternate, buffer field is the same as
1256      * the one defined in format */
1257     if (V4L2_TYPE_IS_MULTIPLANAR (obj->type))
1258       field = obj->format.fmt.pix_mp.field;
1259     else
1260       field = obj->format.fmt.pix.field;
1261
1262     /* NB: At this moment, we can't have alternate mode because it not handled
1263      * yet */
1264     if (field == V4L2_FIELD_ALTERNATE) {
1265       if (GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_FRAME_FLAG_TFF))
1266         field = V4L2_FIELD_TOP;
1267       else
1268         field = V4L2_FIELD_BOTTOM;
1269     }
1270
1271     group->buffer.field = field;
1272   }
1273
1274   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1275     timestamp = GST_BUFFER_TIMESTAMP (buf);
1276     GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp);
1277   }
1278
1279   GST_OBJECT_LOCK (pool);
1280   g_atomic_int_inc (&pool->num_queued);
1281   pool->buffers[index] = buf;
1282
1283   if (!gst_v4l2_allocator_qbuf (pool->vallocator, group))
1284     goto queue_failed;
1285
1286   pool->empty = FALSE;
1287   g_cond_signal (&pool->empty_cond);
1288   GST_OBJECT_UNLOCK (pool);
1289
1290   return GST_FLOW_OK;
1291
1292 already_queued:
1293   {
1294     GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
1295     return GST_FLOW_ERROR;
1296   }
1297 queue_failed:
1298   {
1299     GST_ERROR_OBJECT (pool, "could not queue a buffer %i", index);
1300     /* Mark broken buffer to the allocator */
1301     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY);
1302     g_atomic_int_add (&pool->num_queued, -1);
1303     pool->buffers[index] = NULL;
1304     GST_OBJECT_UNLOCK (pool);
1305     return GST_FLOW_ERROR;
1306   }
1307 }
1308
1309 static GstFlowReturn
1310 gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
1311     gboolean wait)
1312 {
1313   GstFlowReturn res;
1314   GstBuffer *outbuf = NULL;
1315   GstV4l2Object *obj = pool->obj;
1316   GstClockTime timestamp;
1317   GstV4l2MemoryGroup *group;
1318   GstVideoMeta *vmeta;
1319   gsize size;
1320   gint i;
1321 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1322   GstV4l2TizenBuffer *tizen_buffer = NULL;
1323 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1324
1325   if ((res = gst_v4l2_buffer_pool_poll (pool, wait)) < GST_FLOW_OK)
1326     goto poll_failed;
1327
1328   if (res == GST_FLOW_CUSTOM_SUCCESS) {
1329     GST_LOG_OBJECT (pool, "nothing to dequeue");
1330     goto done;
1331   }
1332
1333   GST_LOG_OBJECT (pool, "dequeueing a buffer");
1334
1335   res = gst_v4l2_allocator_dqbuf (pool->vallocator, &group);
1336   if (res == GST_FLOW_EOS)
1337     goto eos;
1338   if (res != GST_FLOW_OK)
1339     goto dqbuf_failed;
1340
1341   /* get our GstBuffer with that index from the pool, if the buffer was
1342    * outstanding we have a serious problem.
1343    */
1344   outbuf = pool->buffers[group->buffer.index];
1345   if (outbuf == NULL)
1346     goto no_buffer;
1347
1348   /* mark the buffer outstanding */
1349   pool->buffers[group->buffer.index] = NULL;
1350   if (g_atomic_int_dec_and_test (&pool->num_queued)) {
1351     GST_OBJECT_LOCK (pool);
1352     pool->empty = TRUE;
1353     GST_OBJECT_UNLOCK (pool);
1354   }
1355
1356   timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
1357
1358   size = 0;
1359   vmeta = gst_buffer_get_video_meta (outbuf);
1360   for (i = 0; i < group->n_mem; i++) {
1361     GST_LOG_OBJECT (pool,
1362         "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %"
1363         GST_TIME_FORMAT ", pool-queued=%d, buffer=%p", outbuf,
1364         group->buffer.sequence, group->buffer.index, group->mem[i],
1365         group->planes[i].bytesused, i, group->buffer.flags,
1366         GST_TIME_ARGS (timestamp), pool->num_queued, outbuf);
1367
1368     if (vmeta) {
1369       vmeta->offset[i] = size;
1370       size += gst_memory_get_sizes (group->mem[i], NULL, NULL);
1371     }
1372   }
1373
1374   /* Ignore timestamp and field for OUTPUT device */
1375   if (V4L2_TYPE_IS_OUTPUT (obj->type))
1376     goto done;
1377
1378   /* Check for driver bug in reporting feild */
1379   if (group->buffer.field == V4L2_FIELD_ANY) {
1380     /* Only warn once to avoid the spamming */
1381 #ifndef GST_DISABLE_GST_DEBUG
1382     if (!pool->has_warned_on_buggy_field) {
1383       pool->has_warned_on_buggy_field = TRUE;
1384       GST_WARNING_OBJECT (pool,
1385           "Driver should never set v4l2_buffer.field to ANY");
1386     }
1387 #endif
1388
1389     /* Use the value from the format (works for UVC bug) */
1390     group->buffer.field = obj->format.fmt.pix.field;
1391
1392     /* If driver also has buggy S_FMT, assume progressive */
1393     if (group->buffer.field == V4L2_FIELD_ANY) {
1394 #ifndef GST_DISABLE_GST_DEBUG
1395       if (!pool->has_warned_on_buggy_field) {
1396         pool->has_warned_on_buggy_field = TRUE;
1397         GST_WARNING_OBJECT (pool,
1398             "Driver should never set v4l2_format.pix.field to ANY");
1399       }
1400 #endif
1401
1402       group->buffer.field = V4L2_FIELD_NONE;
1403     }
1404   }
1405
1406   /* set top/bottom field first if v4l2_buffer has the information */
1407   switch (group->buffer.field) {
1408     case V4L2_FIELD_NONE:
1409       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1410       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1411       break;
1412     case V4L2_FIELD_INTERLACED_TB:
1413       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1414       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1415       break;
1416     case V4L2_FIELD_INTERLACED_BT:
1417       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1418       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1419       break;
1420     case V4L2_FIELD_INTERLACED:
1421       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1422       if (obj->tv_norm == V4L2_STD_NTSC_M ||
1423           obj->tv_norm == V4L2_STD_NTSC_M_JP ||
1424           obj->tv_norm == V4L2_STD_NTSC_M_KR) {
1425         GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1426       } else {
1427         GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1428       }
1429       break;
1430     default:
1431       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1432       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1433       GST_FIXME_OBJECT (pool,
1434           "Unhandled enum v4l2_field %d - treating as progressive",
1435           group->buffer.field);
1436       break;
1437   }
1438
1439   if (GST_VIDEO_INFO_FORMAT (&obj->info) == GST_VIDEO_FORMAT_ENCODED) {
1440     if ((group->buffer.flags & V4L2_BUF_FLAG_KEYFRAME) ||
1441         GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_MJPEG ||
1442         GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_JPEG ||
1443         GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_PJPG)
1444       GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1445     else
1446       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1447   }
1448
1449   if (group->buffer.flags & V4L2_BUF_FLAG_ERROR)
1450     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_CORRUPTED);
1451
1452   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1453   GST_BUFFER_OFFSET (outbuf) = group->buffer.sequence;
1454   GST_BUFFER_OFFSET_END (outbuf) = group->buffer.sequence + 1;
1455
1456 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1457   if (group->surface) {
1458     tizen_buffer = gst_v4l2_tizen_buffer_new (outbuf, group->buffer.index, pool);
1459     if (!tizen_buffer) {
1460       GST_ERROR_OBJECT (pool, "tizen buffer failed for index[%d]", group->buffer.index);
1461       goto no_buffer;
1462     }
1463     outbuf = tizen_buffer->gst_buffer;
1464   }
1465 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1466 done:
1467   *buffer = outbuf;
1468
1469   return res;
1470
1471   /* ERRORS */
1472 poll_failed:
1473   {
1474     GST_DEBUG_OBJECT (pool, "poll error %s", gst_flow_get_name (res));
1475     return res;
1476   }
1477 eos:
1478   {
1479     return GST_FLOW_EOS;
1480   }
1481 dqbuf_failed:
1482   {
1483     return GST_FLOW_ERROR;
1484   }
1485 no_buffer:
1486   {
1487     GST_ERROR_OBJECT (pool, "No free buffer found in the pool at index %d.",
1488         group->buffer.index);
1489     return GST_FLOW_ERROR;
1490   }
1491 }
1492
1493 static GstFlowReturn
1494 gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
1495     GstBufferPoolAcquireParams * params)
1496 {
1497   GstFlowReturn ret;
1498   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1499   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1500   GstV4l2Object *obj = pool->obj;
1501
1502   GST_DEBUG_OBJECT (pool, "acquire");
1503
1504   /* If this is being called to resurrect a lost buffer */
1505   if (params && params->flags & GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT) {
1506     ret = pclass->acquire_buffer (bpool, buffer, params);
1507     goto done;
1508   }
1509
1510   switch (obj->type) {
1511     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1512     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1513       /* capture, This function should return a buffer with new captured data */
1514       switch (obj->mode) {
1515         case GST_V4L2_IO_RW:
1516         {
1517           /* take empty buffer from the pool */
1518           ret = pclass->acquire_buffer (bpool, buffer, params);
1519           break;
1520         }
1521         case GST_V4L2_IO_DMABUF:
1522         case GST_V4L2_IO_MMAP:
1523         case GST_V4L2_IO_USERPTR:
1524         case GST_V4L2_IO_DMABUF_IMPORT:
1525         {
1526           /* just dequeue a buffer, we basically use the queue of v4l2 as the
1527            * storage for our buffers. This function does poll first so we can
1528            * interrupt it fine. */
1529           ret = gst_v4l2_buffer_pool_dqbuf (pool, buffer, TRUE);
1530           break;
1531         }
1532         default:
1533           ret = GST_FLOW_ERROR;
1534           g_assert_not_reached ();
1535           break;
1536       }
1537       break;
1538
1539
1540     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1541     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1542       /* playback, This function should return an empty buffer */
1543       switch (obj->mode) {
1544         case GST_V4L2_IO_RW:
1545           /* get an empty buffer */
1546           ret = pclass->acquire_buffer (bpool, buffer, params);
1547           break;
1548
1549         case GST_V4L2_IO_MMAP:
1550         case GST_V4L2_IO_DMABUF:
1551         case GST_V4L2_IO_USERPTR:
1552         case GST_V4L2_IO_DMABUF_IMPORT:
1553           /* get a free unqueued buffer */
1554           ret = pclass->acquire_buffer (bpool, buffer, params);
1555           break;
1556
1557         default:
1558           ret = GST_FLOW_ERROR;
1559           g_assert_not_reached ();
1560           break;
1561       }
1562       break;
1563
1564     default:
1565       ret = GST_FLOW_ERROR;
1566       g_assert_not_reached ();
1567       break;
1568   }
1569 done:
1570   return ret;
1571 }
1572
1573 static void
1574 gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
1575 {
1576   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1577   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1578   GstV4l2Object *obj = pool->obj;
1579
1580   GST_DEBUG_OBJECT (pool, "release buffer %p", buffer);
1581
1582   /* If the buffer's pool has been orphaned, dispose of it so that
1583    * the pool resources can be freed */
1584   if (pool->orphaned) {
1585     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1586     pclass->release_buffer (bpool, buffer);
1587     return;
1588   }
1589
1590   switch (obj->type) {
1591     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1592     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1593       /* capture, put the buffer back in the queue so that we can refill it
1594        * later. */
1595       switch (obj->mode) {
1596         case GST_V4L2_IO_RW:
1597           /* release back in the pool */
1598           pclass->release_buffer (bpool, buffer);
1599           break;
1600
1601         case GST_V4L2_IO_DMABUF:
1602         case GST_V4L2_IO_MMAP:
1603         case GST_V4L2_IO_USERPTR:
1604         case GST_V4L2_IO_DMABUF_IMPORT:
1605         {
1606           GstV4l2MemoryGroup *group;
1607           if (gst_v4l2_is_buffer_valid (buffer, &group)) {
1608             GstFlowReturn ret = GST_FLOW_OK;
1609
1610             gst_v4l2_allocator_reset_group (pool->vallocator, group);
1611             /* queue back in the device */
1612             if (pool->other_pool)
1613               ret = gst_v4l2_buffer_pool_prepare_buffer (pool, buffer, NULL);
1614             if (ret != GST_FLOW_OK ||
1615                 gst_v4l2_buffer_pool_qbuf (pool, buffer, group) != GST_FLOW_OK)
1616               pclass->release_buffer (bpool, buffer);
1617           } else {
1618             /* Simply release invalide/modified buffer, the allocator will
1619              * give it back later */
1620             GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1621             pclass->release_buffer (bpool, buffer);
1622           }
1623           break;
1624         }
1625         default:
1626           g_assert_not_reached ();
1627           break;
1628       }
1629       break;
1630
1631     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1632     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1633       switch (obj->mode) {
1634         case GST_V4L2_IO_RW:
1635           /* release back in the pool */
1636           pclass->release_buffer (bpool, buffer);
1637           break;
1638
1639         case GST_V4L2_IO_MMAP:
1640         case GST_V4L2_IO_DMABUF:
1641         case GST_V4L2_IO_USERPTR:
1642         case GST_V4L2_IO_DMABUF_IMPORT:
1643         {
1644           GstV4l2MemoryGroup *group;
1645           guint index;
1646
1647           if (!gst_v4l2_is_buffer_valid (buffer, &group)) {
1648             /* Simply release invalide/modified buffer, the allocator will
1649              * give it back later */
1650             GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1651             pclass->release_buffer (bpool, buffer);
1652             break;
1653           }
1654
1655           index = group->buffer.index;
1656
1657           if (pool->buffers[index] == NULL) {
1658             GST_LOG_OBJECT (pool, "buffer %u not queued, putting on free list",
1659                 index);
1660
1661             /* Remove qdata, this will unmap any map data in userptr */
1662             gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
1663                 GST_V4L2_IMPORT_QUARK, NULL, NULL);
1664
1665             /* reset to default size */
1666             gst_v4l2_allocator_reset_group (pool->vallocator, group);
1667
1668             /* playback, put the buffer back in the queue to refill later. */
1669             pclass->release_buffer (bpool, buffer);
1670           } else {
1671             /* the buffer is queued in the device but maybe not played yet. We just
1672              * leave it there and not make it available for future calls to acquire
1673              * for now. The buffer will be dequeued and reused later. */
1674             GST_LOG_OBJECT (pool, "buffer %u is queued", index);
1675           }
1676           break;
1677         }
1678
1679         default:
1680           g_assert_not_reached ();
1681           break;
1682       }
1683       break;
1684
1685     default:
1686       g_assert_not_reached ();
1687       break;
1688   }
1689 }
1690
1691 static void
1692 gst_v4l2_buffer_pool_dispose (GObject * object)
1693 {
1694   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1695
1696   if (pool->vallocator)
1697     gst_object_unref (pool->vallocator);
1698   pool->vallocator = NULL;
1699
1700   if (pool->allocator)
1701     gst_object_unref (pool->allocator);
1702   pool->allocator = NULL;
1703
1704 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1705   g_cond_clear (&pool->buffer_cond);
1706   g_mutex_clear (&pool->buffer_lock);
1707
1708   if (pool->tallocator)
1709     gst_object_unref (pool->tallocator);
1710   pool->tallocator = NULL;
1711 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1712   if (pool->other_pool)
1713     gst_object_unref (pool->other_pool);
1714   pool->other_pool = NULL;
1715
1716   G_OBJECT_CLASS (parent_class)->dispose (object);
1717 }
1718
1719 static void
1720 gst_v4l2_buffer_pool_finalize (GObject * object)
1721 {
1722   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1723
1724   if (pool->video_fd >= 0)
1725     pool->obj->close (pool->video_fd);
1726
1727   gst_poll_free (pool->poll);
1728
1729   /* This can't be done in dispose method because we must not set pointer
1730    * to NULL as it is part of the v4l2object and dispose could be called
1731    * multiple times */
1732   gst_object_unref (pool->obj->element);
1733
1734   g_cond_clear (&pool->empty_cond);
1735
1736   /* FIXME have we done enough here ? */
1737
1738   G_OBJECT_CLASS (parent_class)->finalize (object);
1739 }
1740
1741 static void
1742 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
1743 {
1744   pool->poll = gst_poll_new (TRUE);
1745   pool->can_poll_device = TRUE;
1746   g_cond_init (&pool->empty_cond);
1747   pool->empty = TRUE;
1748   pool->orphaned = FALSE;
1749 }
1750
1751 static void
1752 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
1753 {
1754   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1755   GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
1756
1757   object_class->dispose = gst_v4l2_buffer_pool_dispose;
1758   object_class->finalize = gst_v4l2_buffer_pool_finalize;
1759
1760   bufferpool_class->start = gst_v4l2_buffer_pool_start;
1761   bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
1762   bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
1763   bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
1764   bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
1765   bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
1766   bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
1767   bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
1768
1769   GST_DEBUG_CATEGORY_INIT (v4l2bufferpool_debug, "v4l2bufferpool", 0,
1770       "V4L2 Buffer Pool");
1771   GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
1772 }
1773
1774 /**
1775  * gst_v4l2_buffer_pool_new:
1776  * @obj:  the v4l2 object owning the pool
1777  *
1778  * Construct a new buffer pool.
1779  *
1780  * Returns: the new pool, use gst_object_unref() to free resources
1781  */
1782 GstBufferPool *
1783 gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
1784 {
1785   GstV4l2BufferPool *pool;
1786   GstStructure *config;
1787   gchar *name, *parent_name;
1788   gint fd;
1789
1790   fd = obj->dup (obj->video_fd);
1791   if (fd < 0)
1792     goto dup_failed;
1793
1794   /* setting a significant unique name */
1795   parent_name = gst_object_get_name (GST_OBJECT (obj->element));
1796   name = g_strconcat (parent_name, ":", "pool:",
1797       V4L2_TYPE_IS_OUTPUT (obj->type) ? "sink" : "src", NULL);
1798   g_free (parent_name);
1799
1800   pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL,
1801       "name", name, NULL);
1802   g_object_ref_sink (pool);
1803   g_free (name);
1804
1805   gst_poll_fd_init (&pool->pollfd);
1806   pool->pollfd.fd = fd;
1807   gst_poll_add_fd (pool->poll, &pool->pollfd);
1808   if (V4L2_TYPE_IS_OUTPUT (obj->type))
1809     gst_poll_fd_ctl_write (pool->poll, &pool->pollfd, TRUE);
1810   else
1811     gst_poll_fd_ctl_read (pool->poll, &pool->pollfd, TRUE);
1812
1813   pool->video_fd = fd;
1814   pool->obj = obj;
1815   pool->can_poll_device = TRUE;
1816
1817 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1818   pool->tallocator = gst_tizen_allocator_new ();
1819   if (pool->tallocator == NULL)
1820     goto allocator_failed;
1821
1822   g_mutex_init (&pool->buffer_lock);
1823   g_cond_init (&pool->buffer_cond);
1824 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1825   pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj);
1826   if (pool->vallocator == NULL)
1827     goto allocator_failed;
1828
1829   gst_object_ref (obj->element);
1830
1831   config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
1832   gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
1833   /* This will simply set a default config, but will not configure the pool
1834    * because min and max are not valid */
1835   gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
1836
1837   return GST_BUFFER_POOL (pool);
1838
1839   /* ERRORS */
1840 dup_failed:
1841   {
1842     GST_ERROR ("failed to dup fd %d (%s)", errno, g_strerror (errno));
1843     return NULL;
1844   }
1845 allocator_failed:
1846   {
1847 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1848     if (pool->tallocator) {
1849       gst_object_unref (pool->tallocator);
1850       pool->tallocator = NULL;
1851     }
1852 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1853     GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator");
1854     gst_object_unref (pool);
1855     return NULL;
1856   }
1857 }
1858
1859 static GstFlowReturn
1860 gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
1861 {
1862   GstFlowReturn res;
1863   GstV4l2Object *obj = pool->obj;
1864   gint amount;
1865   GstMapInfo map;
1866   gint toread;
1867
1868   toread = obj->info.size;
1869
1870   GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);
1871
1872   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1873
1874   do {
1875     if ((res = gst_v4l2_buffer_pool_poll (pool, TRUE)) != GST_FLOW_OK)
1876       goto poll_error;
1877
1878     amount = obj->read (obj->video_fd, map.data, toread);
1879
1880     if (amount == toread) {
1881       break;
1882     } else if (amount == -1) {
1883       if (errno == EAGAIN || errno == EINTR) {
1884         continue;
1885       } else
1886         goto read_error;
1887     } else {
1888       /* short reads can happen if a signal interrupts the read */
1889       continue;
1890     }
1891   } while (TRUE);
1892
1893   GST_LOG_OBJECT (pool, "read %d bytes", amount);
1894   gst_buffer_unmap (buf, &map);
1895   gst_buffer_resize (buf, 0, amount);
1896
1897   return GST_FLOW_OK;
1898
1899   /* ERRORS */
1900 poll_error:
1901   {
1902     GST_DEBUG ("poll error %s", gst_flow_get_name (res));
1903     goto cleanup;
1904   }
1905 read_error:
1906   {
1907     GST_ELEMENT_ERROR (obj->element, RESOURCE, READ,
1908         (_("Error reading %d bytes from device '%s'."),
1909             toread, obj->videodev), GST_ERROR_SYSTEM);
1910     res = GST_FLOW_ERROR;
1911     goto cleanup;
1912   }
1913 cleanup:
1914   {
1915     gst_buffer_unmap (buf, &map);
1916     gst_buffer_resize (buf, 0, 0);
1917     return res;
1918   }
1919 }
1920
1921 /**
1922  * gst_v4l2_buffer_pool_process:
1923  * @bpool: a #GstBufferPool
1924  * @buf: a #GstBuffer, maybe be replaced
1925  *
1926  * Process @buf in @bpool. For capture devices, this functions fills @buf with
1927  * data from the device. For output devices, this functions send the contents of
1928  * @buf to the device for playback.
1929  *
1930  * Returns: %GST_FLOW_OK on success.
1931  */
1932 GstFlowReturn
1933 gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
1934 {
1935   GstFlowReturn ret = GST_FLOW_OK;
1936   GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool);
1937   GstV4l2Object *obj = pool->obj;
1938
1939   GST_DEBUG_OBJECT (pool, "process buffer %p", buf);
1940
1941   if (GST_BUFFER_POOL_IS_FLUSHING (pool))
1942     return GST_FLOW_FLUSHING;
1943
1944   switch (obj->type) {
1945     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1946     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1947       /* capture */
1948       switch (obj->mode) {
1949         case GST_V4L2_IO_RW:
1950           /* capture into the buffer */
1951           ret = gst_v4l2_do_read (pool, *buf);
1952           break;
1953
1954         case GST_V4L2_IO_MMAP:
1955         case GST_V4L2_IO_DMABUF:
1956         {
1957           GstBuffer *tmp;
1958
1959           if ((*buf)->pool == bpool) {
1960             guint num_queued;
1961             gsize size = gst_buffer_get_size (*buf);
1962
1963             /* Legacy M2M devices return empty buffer when drained */
1964             if (size == 0 && GST_V4L2_IS_M2M (obj->device_caps))
1965               goto eos;
1966
1967             if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) !=
1968                 GST_VIDEO_FORMAT_ENCODED && size < pool->size)
1969               goto buffer_truncated;
1970
1971             num_queued = g_atomic_int_get (&pool->num_queued);
1972             GST_TRACE_OBJECT (pool, "Only %i buffer left in the capture queue.",
1973                 num_queued);
1974
1975             /* If we have no more buffer, and can allocate it time to do so */
1976             if (num_queued == 0) {
1977               if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
1978                 ret = gst_v4l2_buffer_pool_resurrect_buffer (pool);
1979                 if (ret == GST_FLOW_OK)
1980                   goto done;
1981               }
1982             }
1983
1984             /* start copying buffers when we are running low on buffers */
1985             if (num_queued < pool->copy_threshold) {
1986               GstBuffer *copy;
1987
1988               if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
1989                 ret = gst_v4l2_buffer_pool_resurrect_buffer (pool);
1990                 if (ret == GST_FLOW_OK)
1991                   goto done;
1992               }
1993
1994               /* copy the buffer */
1995               copy = gst_buffer_copy_region (*buf,
1996                   GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1);
1997               GST_LOG_OBJECT (pool, "copy buffer %p->%p", *buf, copy);
1998
1999               /* and requeue so that we can continue capturing */
2000               gst_buffer_unref (*buf);
2001               *buf = copy;
2002             }
2003
2004             ret = GST_FLOW_OK;
2005             /* nothing, data was inside the buffer when we did _acquire() */
2006             goto done;
2007           }
2008
2009           /* buffer not from our pool, grab a frame and copy it into the target */
2010           if ((ret = gst_v4l2_buffer_pool_dqbuf (pool, &tmp, TRUE))
2011               != GST_FLOW_OK)
2012             goto done;
2013
2014           /* An empty buffer on capture indicates the end of stream */
2015           if (gst_buffer_get_size (tmp) == 0) {
2016             gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
2017
2018             /* Legacy M2M devices return empty buffer when drained */
2019             if (GST_V4L2_IS_M2M (obj->device_caps))
2020               goto eos;
2021           }
2022 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
2023           if (pool->obj->tbm_output && pool->obj->mode == GST_V4L2_IO_DMABUF) {
2024             gst_buffer_unref (*buf);
2025             *buf = tmp;
2026           } else {
2027 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
2028           ret = gst_v4l2_buffer_pool_copy_buffer (pool, *buf, tmp);
2029
2030           /* an queue the buffer again after the copy */
2031           gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
2032 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
2033           }
2034 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
2035
2036           if (ret != GST_FLOW_OK)
2037             goto copy_failed;
2038           break;
2039         }
2040
2041         case GST_V4L2_IO_USERPTR:
2042         {
2043           struct UserPtrData *data;
2044           GstBuffer *tmp;
2045
2046           /* Replace our buffer with downstream allocated buffer */
2047           data = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2048               GST_V4L2_IMPORT_QUARK);
2049           tmp = gst_buffer_ref (data->buffer);
2050           _unmap_userptr_frame (data);
2051
2052           /* Now tmp is writable, copy the flags and timestamp */
2053           gst_buffer_copy_into (tmp, *buf,
2054               GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2055
2056           gst_buffer_replace (buf, tmp);
2057           gst_buffer_unref (tmp);
2058           break;
2059         }
2060
2061         case GST_V4L2_IO_DMABUF_IMPORT:
2062         {
2063           GstBuffer *tmp;
2064
2065           /* Replace our buffer with downstream allocated buffer */
2066           tmp = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2067               GST_V4L2_IMPORT_QUARK);
2068
2069           gst_buffer_copy_into (tmp, *buf,
2070               GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2071
2072           gst_buffer_replace (buf, tmp);
2073           gst_buffer_unref (tmp);
2074           break;
2075         }
2076
2077         default:
2078           g_assert_not_reached ();
2079           break;
2080       }
2081       break;
2082
2083     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2084     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2085       /* playback */
2086       switch (obj->mode) {
2087         case GST_V4L2_IO_RW:
2088           /* FIXME, do write() */
2089           GST_WARNING_OBJECT (pool, "implement write()");
2090           break;
2091
2092         case GST_V4L2_IO_USERPTR:
2093         case GST_V4L2_IO_DMABUF_IMPORT:
2094         case GST_V4L2_IO_DMABUF:
2095         case GST_V4L2_IO_MMAP:
2096         {
2097           GstBuffer *to_queue = NULL;
2098           GstBuffer *buffer;
2099           GstV4l2MemoryGroup *group;
2100           gint index;
2101
2102           if ((*buf)->pool != bpool)
2103             goto copying;
2104
2105           if (!gst_v4l2_is_buffer_valid (*buf, &group))
2106             goto copying;
2107
2108           index = group->buffer.index;
2109
2110           GST_LOG_OBJECT (pool, "processing buffer %i from our pool", index);
2111
2112           if (pool->buffers[index] != NULL) {
2113             GST_LOG_OBJECT (pool, "buffer %i already queued, copying", index);
2114             goto copying;
2115           }
2116
2117           /* we can queue directly */
2118           to_queue = gst_buffer_ref (*buf);
2119
2120         copying:
2121           if (to_queue == NULL) {
2122             GstBufferPoolAcquireParams params = { 0 };
2123
2124             GST_LOG_OBJECT (pool, "alloc buffer from our pool");
2125
2126             /* this can return EOS if all buffers are outstanding which would
2127              * be strange because we would expect the upstream element to have
2128              * allocated them and returned to us.. */
2129             params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
2130             ret = gst_buffer_pool_acquire_buffer (bpool, &to_queue, &params);
2131             if (ret != GST_FLOW_OK)
2132               goto acquire_failed;
2133
2134             ret = gst_v4l2_buffer_pool_prepare_buffer (pool, to_queue, *buf);
2135             if (ret != GST_FLOW_OK) {
2136               gst_buffer_unref (to_queue);
2137               goto prepare_failed;
2138             }
2139
2140             /* retreive the group */
2141             gst_v4l2_is_buffer_valid (to_queue, &group);
2142           }
2143
2144           if ((ret = gst_v4l2_buffer_pool_qbuf (pool, to_queue, group))
2145               != GST_FLOW_OK)
2146             goto queue_failed;
2147
2148           /* if we are not streaming yet (this is the first buffer, start
2149            * streaming now */
2150           if (!gst_v4l2_buffer_pool_streamon (pool)) {
2151             /* don't check return value because qbuf would have failed */
2152             gst_v4l2_is_buffer_valid (to_queue, &group);
2153
2154             /* qbuf has stored to_queue buffer but we are not in
2155              * streaming state, so the flush logic won't be performed.
2156              * To avoid leaks, flush the allocator and restore the queued
2157              * buffer as non-queued */
2158             gst_v4l2_allocator_flush (pool->vallocator);
2159
2160             pool->buffers[group->buffer.index] = NULL;
2161
2162             gst_mini_object_set_qdata (GST_MINI_OBJECT (to_queue),
2163                 GST_V4L2_IMPORT_QUARK, NULL, NULL);
2164             gst_buffer_unref (to_queue);
2165             g_atomic_int_add (&pool->num_queued, -1);
2166             goto start_failed;
2167           }
2168
2169           /* Remove our ref, we will still hold this buffer in acquire as needed,
2170            * otherwise the pool will think it is outstanding and will refuse to stop. */
2171           gst_buffer_unref (to_queue);
2172
2173           /* release as many buffer as possible */
2174           while (gst_v4l2_buffer_pool_dqbuf (pool, &buffer, FALSE) ==
2175               GST_FLOW_OK) {
2176             if (buffer->pool == NULL)
2177               gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
2178           }
2179
2180           if (g_atomic_int_get (&pool->num_queued) >= pool->min_latency) {
2181             /* all buffers are queued, try to dequeue one and release it back
2182              * into the pool so that _acquire can get to it again. */
2183             ret = gst_v4l2_buffer_pool_dqbuf (pool, &buffer, TRUE);
2184             if (ret == GST_FLOW_OK && buffer->pool == NULL)
2185               /* release the rendered buffer back into the pool. This wakes up any
2186                * thread waiting for a buffer in _acquire(). */
2187               gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
2188           }
2189           break;
2190         }
2191         default:
2192           g_assert_not_reached ();
2193           break;
2194       }
2195       break;
2196     default:
2197       g_assert_not_reached ();
2198       break;
2199   }
2200 done:
2201   return ret;
2202
2203   /* ERRORS */
2204 copy_failed:
2205   {
2206     GST_ERROR_OBJECT (pool, "failed to copy buffer");
2207     return ret;
2208   }
2209 buffer_truncated:
2210   {
2211     GST_WARNING_OBJECT (pool,
2212         "Dropping truncated buffer, this is likely a driver bug.");
2213     gst_buffer_unref (*buf);
2214     *buf = NULL;
2215     return GST_V4L2_FLOW_CORRUPTED_BUFFER;
2216   }
2217 eos:
2218   {
2219     GST_DEBUG_OBJECT (pool, "end of stream reached");
2220     gst_buffer_unref (*buf);
2221     *buf = NULL;
2222     return GST_V4L2_FLOW_LAST_BUFFER;
2223   }
2224 acquire_failed:
2225   {
2226     if (ret == GST_FLOW_FLUSHING)
2227       GST_DEBUG_OBJECT (pool, "flushing");
2228     else
2229       GST_WARNING_OBJECT (pool, "failed to acquire a buffer: %s",
2230           gst_flow_get_name (ret));
2231     return ret;
2232   }
2233 prepare_failed:
2234   {
2235     GST_ERROR_OBJECT (pool, "failed to prepare data");
2236     return ret;
2237   }
2238 queue_failed:
2239   {
2240     GST_ERROR_OBJECT (pool, "failed to queue buffer");
2241     return ret;
2242   }
2243 start_failed:
2244   {
2245     GST_ERROR_OBJECT (pool, "failed to start streaming");
2246     return GST_FLOW_ERROR;
2247   }
2248 }
2249
2250 void
2251 gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
2252     GstBufferPool * other_pool)
2253 {
2254   g_return_if_fail (!gst_buffer_pool_is_active (GST_BUFFER_POOL (pool)));
2255
2256   if (pool->other_pool)
2257     gst_object_unref (pool->other_pool);
2258   pool->other_pool = gst_object_ref (other_pool);
2259 }
2260
2261 void
2262 gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool, gboolean copy)
2263 {
2264   GST_OBJECT_LOCK (pool);
2265   pool->enable_copy_threshold = copy;
2266   GST_OBJECT_UNLOCK (pool);
2267 }
2268
2269 gboolean
2270 gst_v4l2_buffer_pool_flush (GstBufferPool * bpool)
2271 {
2272   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
2273   gboolean ret = TRUE;
2274
2275   gst_v4l2_buffer_pool_streamoff (pool);
2276
2277   if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type))
2278     ret = gst_v4l2_buffer_pool_streamon (pool);
2279
2280   return ret;
2281 }