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