v4l2bufferpool: Only resurrect the right amount of buffers
[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       if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) {
721         guint num_queued;
722         guint i, n = 0;
723
724         num_queued = g_atomic_int_get (&pool->num_queued);
725         if (num_queued < pool->num_allocated)
726           n = pool->num_allocated - num_queued;
727
728         /* For captures, we need to enqueue buffers before we start streaming,
729          * so the driver don't underflow immediatly. As we have put then back
730          * into the base class queue, resurrect them, then releasing will queue
731          * them back. */
732         for (i = 0; i < n; i++)
733           gst_v4l2_buffer_pool_resurrect_buffer (pool);
734       }
735
736       if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
737         goto streamon_failed;
738
739       pool->streaming = TRUE;
740
741       GST_DEBUG_OBJECT (pool, "Started streaming");
742       break;
743     default:
744       break;
745   }
746
747   return TRUE;
748
749 streamon_failed:
750   {
751     GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
752         g_strerror (errno));
753     return FALSE;
754   }
755 }
756
757 /* Call with streamlock held, or when streaming threads are down */
758 static void
759 gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
760 {
761   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
762   GstV4l2Object *obj = pool->obj;
763   gint i;
764 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
765   gint64 end_time = 0;
766 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
767
768   if (!pool->streaming)
769     return;
770
771 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
772   if (!V4L2_TYPE_IS_OUTPUT(pool->obj->type)) {
773     g_mutex_lock (&pool->buffer_lock);
774
775     GST_INFO_OBJECT (pool, "live buffer[%d]", pool->live_buffer_count);
776
777     if (pool->live_buffer_count > 0) {
778       end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
779
780       do {
781         GST_WARNING_OBJECT (pool, "wait for live buffer[%d]", pool->live_buffer_count);
782
783         if (!g_cond_wait_until (&pool->buffer_cond, &pool->buffer_lock, end_time)) {
784           GST_ERROR_OBJECT (pool, "failed to wait live buffer[%d]", pool->live_buffer_count);
785           break;
786         }
787
788         GST_WARNING_OBJECT (pool, "signal received, check again : live count[%d]",
789             pool->live_buffer_count);
790       } while (pool->live_buffer_count > 0);
791     }
792
793     g_mutex_unlock (&pool->buffer_lock);
794   }
795 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
796   switch (obj->mode) {
797     case GST_V4L2_IO_MMAP:
798     case GST_V4L2_IO_USERPTR:
799     case GST_V4L2_IO_DMABUF:
800     case GST_V4L2_IO_DMABUF_IMPORT:
801
802       if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
803         GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
804             errno, g_strerror (errno));
805
806       pool->streaming = FALSE;
807
808       GST_DEBUG_OBJECT (pool, "Stopped streaming");
809
810       if (pool->vallocator)
811         gst_v4l2_allocator_flush (pool->vallocator);
812       break;
813     default:
814       break;
815   }
816
817   for (i = 0; i < VIDEO_MAX_FRAME; i++) {
818     if (pool->buffers[i]) {
819       GstBuffer *buffer = pool->buffers[i];
820       GstBufferPool *bpool = GST_BUFFER_POOL (pool);
821
822       pool->buffers[i] = NULL;
823
824       if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
825         gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
826       else                      /* Don't re-enqueue capture buffer on stop */
827         pclass->release_buffer (bpool, buffer);
828
829       g_atomic_int_add (&pool->num_queued, -1);
830     }
831   }
832 }
833
834 static gboolean
835 gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
836 {
837   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
838   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
839   GstV4l2Object *obj = pool->obj;
840   GstStructure *config;
841   GstCaps *caps;
842   guint size, min_buffers, max_buffers;
843   guint max_latency, min_latency, copy_threshold = 0;
844   gboolean can_allocate = FALSE, ret = TRUE;
845
846   GST_DEBUG_OBJECT (pool, "activating pool");
847
848   if (pool->other_pool) {
849     GstBuffer *buffer;
850
851     if (!gst_buffer_pool_set_active (pool->other_pool, TRUE))
852       goto other_pool_failed;
853
854     if (gst_buffer_pool_acquire_buffer (pool->other_pool, &buffer, NULL) !=
855         GST_FLOW_OK)
856       goto other_pool_failed;
857
858     if (!gst_v4l2_object_try_import (obj, buffer)) {
859       gst_buffer_unref (buffer);
860       goto cannot_import;
861     }
862     gst_buffer_unref (buffer);
863   }
864
865   config = gst_buffer_pool_get_config (bpool);
866   if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
867           &max_buffers))
868     goto wrong_config;
869
870   min_latency = MAX (GST_V4L2_MIN_BUFFERS, obj->min_buffers);
871
872   switch (obj->mode) {
873     case GST_V4L2_IO_RW:
874       can_allocate = TRUE;
875 #ifdef HAVE_LIBV4L2
876       /* This workaround a unfixable bug in libv4l2 when RW is emulated on top
877        * of MMAP. In this case, the first read initialize the queues, but the
878        * poll before that will always fail. Doing an empty read, forces the
879        * queue to be initialized now. We only do this if we have a streaming
880        * driver. */
881       if (obj->device_caps & V4L2_CAP_STREAMING)
882         obj->read (obj->video_fd, NULL, 0);
883 #endif
884       break;
885     case GST_V4L2_IO_DMABUF:
886     case GST_V4L2_IO_MMAP:
887     {
888       guint count;
889
890       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
891
892       /* first, lets request buffers, and see how many we can get: */
893       GST_DEBUG_OBJECT (pool, "requesting %d MMAP buffers", min_buffers);
894
895       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
896           V4L2_MEMORY_MMAP);
897       pool->num_allocated = count;
898
899       if (count < GST_V4L2_MIN_BUFFERS) {
900         min_buffers = count;
901         goto no_buffers;
902       }
903
904       /* V4L2 buffer pool are often very limited in the amount of buffers it
905        * can offer. The copy_threshold will workaround this limitation by
906        * falling back to copy if the pipeline needed more buffers. This also
907        * prevent having to do REQBUFS(N)/REQBUFS(0) everytime configure is
908        * called. */
909       if (count != min_buffers || pool->enable_copy_threshold) {
910         GST_WARNING_OBJECT (pool,
911             "Uncertain or not enough buffers, enabling copy threshold");
912         min_buffers = count;
913         copy_threshold = min_latency;
914       }
915
916       break;
917     }
918     case GST_V4L2_IO_USERPTR:
919     {
920       guint count;
921
922       can_allocate =
923           GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
924
925       GST_DEBUG_OBJECT (pool, "requesting %d USERPTR buffers", min_buffers);
926
927       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
928           V4L2_MEMORY_USERPTR);
929
930       /* There is no rational to not get what we asked */
931       if (count < min_buffers) {
932         min_buffers = count;
933         goto no_buffers;
934       }
935
936       min_buffers = count;
937       break;
938     }
939     case GST_V4L2_IO_DMABUF_IMPORT:
940     {
941       guint count;
942
943       can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
944
945       GST_DEBUG_OBJECT (pool, "requesting %d DMABUF buffers", min_buffers);
946
947       count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
948           V4L2_MEMORY_DMABUF);
949
950       /* There is no rational to not get what we asked */
951       if (count < min_buffers) {
952         min_buffers = count;
953         goto no_buffers;
954       }
955
956       min_buffers = count;
957       break;
958     }
959     default:
960       min_buffers = 0;
961       copy_threshold = 0;
962       g_assert_not_reached ();
963       break;
964   }
965
966   if (can_allocate)
967     max_latency = max_buffers;
968   else
969     max_latency = min_buffers;
970
971   pool->size = size;
972   pool->copy_threshold = copy_threshold;
973   pool->max_latency = max_latency;
974   pool->min_latency = min_latency;
975   pool->num_queued = 0;
976
977   if (max_buffers != 0 && max_buffers < min_buffers)
978     max_buffers = min_buffers;
979
980   gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
981       max_buffers);
982   pclass->set_config (bpool, config);
983   gst_structure_free (config);
984
985   /* now, allocate the buffers: */
986   if (!pclass->start (bpool))
987     goto start_failed;
988
989   if (!V4L2_TYPE_IS_OUTPUT (obj->type)) {
990     if (g_atomic_int_get (&pool->num_queued) < min_buffers)
991       goto queue_failed;
992
993     pool->group_released_handler =
994         g_signal_connect_swapped (pool->vallocator, "group-released",
995         G_CALLBACK (gst_v4l2_buffer_pool_resurrect_buffer), pool);
996     ret = gst_v4l2_buffer_pool_streamon (pool);
997   }
998
999   return ret;
1000
1001   /* ERRORS */
1002 wrong_config:
1003   {
1004     GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
1005     gst_structure_free (config);
1006     return FALSE;
1007   }
1008 no_buffers:
1009   {
1010     GST_ERROR_OBJECT (pool,
1011         "we received %d buffer from device '%s', we want at least %d",
1012         min_buffers, obj->videodev, GST_V4L2_MIN_BUFFERS);
1013     gst_structure_free (config);
1014     return FALSE;
1015   }
1016 start_failed:
1017   {
1018     GST_ERROR_OBJECT (pool, "allocate failed");
1019     return FALSE;
1020   }
1021 other_pool_failed:
1022   {
1023     GST_ERROR_OBJECT (pool, "failed to activate the other pool %"
1024         GST_PTR_FORMAT, pool->other_pool);
1025     return FALSE;
1026   }
1027 queue_failed:
1028   {
1029     GST_ERROR_OBJECT (pool, "failed to queue buffers into the capture queue");
1030     return FALSE;
1031   }
1032 cannot_import:
1033   {
1034     GST_ERROR_OBJECT (pool, "cannot import buffers from downstream pool");
1035     return FALSE;
1036   }
1037 }
1038
1039 static gboolean
1040 gst_v4l2_buffer_pool_vallocator_stop (GstV4l2BufferPool * pool)
1041 {
1042   GstV4l2Return vret;
1043
1044   if (!pool->vallocator)
1045     return TRUE;
1046
1047   vret = gst_v4l2_allocator_stop (pool->vallocator);
1048
1049   if (vret == GST_V4L2_BUSY)
1050     GST_WARNING_OBJECT (pool, "some buffers are still outstanding");
1051
1052   return (vret == GST_V4L2_OK);
1053 }
1054
1055 static gboolean
1056 gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
1057 {
1058   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1059   gboolean ret;
1060
1061   if (pool->orphaned)
1062     return gst_v4l2_buffer_pool_vallocator_stop (pool);
1063
1064   GST_DEBUG_OBJECT (pool, "stopping pool");
1065
1066   if (pool->group_released_handler > 0) {
1067     g_signal_handler_disconnect (pool->vallocator,
1068         pool->group_released_handler);
1069     pool->group_released_handler = 0;
1070   }
1071
1072   if (pool->other_pool) {
1073     gst_buffer_pool_set_active (pool->other_pool, FALSE);
1074     gst_object_unref (pool->other_pool);
1075     pool->other_pool = NULL;
1076   }
1077
1078   gst_v4l2_buffer_pool_streamoff (pool);
1079
1080   ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
1081
1082   if (ret)
1083     ret = gst_v4l2_buffer_pool_vallocator_stop (pool);
1084
1085   return ret;
1086 }
1087
1088 gboolean
1089 gst_v4l2_buffer_pool_orphan (GstBufferPool ** bpool)
1090 {
1091   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (*bpool);
1092   gboolean ret;
1093
1094   if (!GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (pool->vallocator))
1095     return FALSE;
1096
1097   if (g_getenv ("GST_V4L2_FORCE_DRAIN"))
1098     return FALSE;
1099
1100   GST_DEBUG_OBJECT (pool, "orphaning pool");
1101
1102   gst_buffer_pool_set_active (*bpool, FALSE);
1103   /*
1104    * If the buffer pool has outstanding buffers, it will not be stopped
1105    * by the base class when set inactive. Stop it manually and mark it
1106    * as orphaned
1107    */
1108   ret = gst_v4l2_buffer_pool_stop (*bpool);
1109   if (!ret)
1110     ret = gst_v4l2_allocator_orphan (pool->vallocator);
1111
1112   if (!ret)
1113     goto orphan_failed;
1114
1115   pool->orphaned = TRUE;
1116   gst_object_unref (*bpool);
1117   *bpool = NULL;
1118
1119 orphan_failed:
1120   return ret;
1121 }
1122
1123 static void
1124 gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
1125 {
1126   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1127
1128   GST_DEBUG_OBJECT (pool, "start flushing");
1129
1130   gst_poll_set_flushing (pool->poll, TRUE);
1131
1132   GST_OBJECT_LOCK (pool);
1133   pool->empty = FALSE;
1134   g_cond_broadcast (&pool->empty_cond);
1135   GST_OBJECT_UNLOCK (pool);
1136
1137   if (pool->other_pool)
1138     gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
1139 }
1140
1141 static void
1142 gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool)
1143 {
1144   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1145
1146   GST_DEBUG_OBJECT (pool, "stop flushing");
1147
1148   if (pool->other_pool)
1149     gst_buffer_pool_set_flushing (pool->other_pool, FALSE);
1150
1151   gst_poll_set_flushing (pool->poll, FALSE);
1152 }
1153
1154 static GstFlowReturn
1155 gst_v4l2_buffer_pool_poll (GstV4l2BufferPool * pool, gboolean wait)
1156 {
1157   gint ret;
1158   GstClockTime timeout;
1159
1160   if (wait)
1161     timeout = GST_CLOCK_TIME_NONE;
1162   else
1163     timeout = 0;
1164
1165   /* In RW mode there is no queue, hence no need to wait while the queue is
1166    * empty */
1167   if (pool->obj->mode != GST_V4L2_IO_RW) {
1168     GST_OBJECT_LOCK (pool);
1169
1170     if (!wait && pool->empty) {
1171       GST_OBJECT_UNLOCK (pool);
1172       goto no_buffers;
1173     }
1174
1175     while (pool->empty)
1176       g_cond_wait (&pool->empty_cond, GST_OBJECT_GET_LOCK (pool));
1177
1178     GST_OBJECT_UNLOCK (pool);
1179   }
1180
1181   if (!pool->can_poll_device) {
1182     if (wait)
1183       goto done;
1184     else
1185       goto no_buffers;
1186   }
1187
1188   GST_LOG_OBJECT (pool, "polling device");
1189
1190 again:
1191   ret = gst_poll_wait (pool->poll, timeout);
1192   if (G_UNLIKELY (ret < 0)) {
1193     switch (errno) {
1194       case EBUSY:
1195         goto stopped;
1196       case EAGAIN:
1197       case EINTR:
1198         goto again;
1199       case ENXIO:
1200         GST_WARNING_OBJECT (pool,
1201             "v4l2 device doesn't support polling. Disabling"
1202             " using libv4l2 in this case may cause deadlocks");
1203         pool->can_poll_device = FALSE;
1204         goto done;
1205       default:
1206         goto select_error;
1207     }
1208   }
1209
1210   if (gst_poll_fd_has_error (pool->poll, &pool->pollfd))
1211     goto select_error;
1212
1213   if (ret == 0)
1214     goto no_buffers;
1215
1216 done:
1217   return GST_FLOW_OK;
1218
1219   /* ERRORS */
1220 stopped:
1221   {
1222     GST_DEBUG_OBJECT (pool, "stop called");
1223     return GST_FLOW_FLUSHING;
1224   }
1225 select_error:
1226   {
1227     GST_ELEMENT_ERROR (pool->obj->element, RESOURCE, READ, (NULL),
1228         ("poll error %d: %s (%d)", ret, g_strerror (errno), errno));
1229     return GST_FLOW_ERROR;
1230   }
1231 no_buffers:
1232   return GST_FLOW_CUSTOM_SUCCESS;
1233 }
1234
1235 static GstFlowReturn
1236 gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
1237     GstV4l2MemoryGroup * group)
1238 {
1239   const GstV4l2Object *obj = pool->obj;
1240   GstClockTime timestamp;
1241   gint index;
1242
1243   index = group->buffer.index;
1244
1245   if (pool->buffers[index] != NULL)
1246     goto already_queued;
1247
1248   GST_LOG_OBJECT (pool, "queuing buffer %i", index);
1249
1250   if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
1251     enum v4l2_field field;
1252
1253     /* Except when field is set to alternate, buffer field is the same as
1254      * the one defined in format */
1255     if (V4L2_TYPE_IS_MULTIPLANAR (obj->type))
1256       field = obj->format.fmt.pix_mp.field;
1257     else
1258       field = obj->format.fmt.pix.field;
1259
1260     /* NB: At this moment, we can't have alternate mode because it not handled
1261      * yet */
1262     if (field == V4L2_FIELD_ALTERNATE) {
1263       if (GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_FRAME_FLAG_TFF))
1264         field = V4L2_FIELD_TOP;
1265       else
1266         field = V4L2_FIELD_BOTTOM;
1267     }
1268
1269     group->buffer.field = field;
1270   }
1271
1272   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1273     timestamp = GST_BUFFER_TIMESTAMP (buf);
1274     GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp);
1275   }
1276
1277   GST_OBJECT_LOCK (pool);
1278   g_atomic_int_inc (&pool->num_queued);
1279   pool->buffers[index] = buf;
1280
1281   if (!gst_v4l2_allocator_qbuf (pool->vallocator, group))
1282     goto queue_failed;
1283
1284   pool->empty = FALSE;
1285   g_cond_signal (&pool->empty_cond);
1286   GST_OBJECT_UNLOCK (pool);
1287
1288   return GST_FLOW_OK;
1289
1290 already_queued:
1291   {
1292     GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
1293     return GST_FLOW_ERROR;
1294   }
1295 queue_failed:
1296   {
1297     GST_ERROR_OBJECT (pool, "could not queue a buffer %i", index);
1298     /* Mark broken buffer to the allocator */
1299     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY);
1300     g_atomic_int_add (&pool->num_queued, -1);
1301     pool->buffers[index] = NULL;
1302     GST_OBJECT_UNLOCK (pool);
1303     return GST_FLOW_ERROR;
1304   }
1305 }
1306
1307 static GstFlowReturn
1308 gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
1309     gboolean wait)
1310 {
1311   GstFlowReturn res;
1312   GstBuffer *outbuf = NULL;
1313   GstV4l2Object *obj = pool->obj;
1314   GstClockTime timestamp;
1315   GstV4l2MemoryGroup *group;
1316   GstVideoMeta *vmeta;
1317   gsize size;
1318   gint i;
1319 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
1320   GstV4l2TizenBuffer *tizen_buffer = NULL;
1321 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
1322
1323   if ((res = gst_v4l2_buffer_pool_poll (pool, wait)) < GST_FLOW_OK)
1324     goto poll_failed;
1325
1326   if (res == GST_FLOW_CUSTOM_SUCCESS) {
1327     GST_LOG_OBJECT (pool, "nothing to dequeue");
1328     goto done;
1329   }
1330
1331   GST_LOG_OBJECT (pool, "dequeueing a buffer");
1332
1333   res = gst_v4l2_allocator_dqbuf (pool->vallocator, &group);
1334   if (res == GST_FLOW_EOS)
1335     goto eos;
1336   if (res != GST_FLOW_OK)
1337     goto dqbuf_failed;
1338
1339   /* get our GstBuffer with that index from the pool, if the buffer was
1340    * outstanding we have a serious problem.
1341    */
1342   outbuf = pool->buffers[group->buffer.index];
1343   if (outbuf == NULL)
1344     goto no_buffer;
1345
1346   /* mark the buffer outstanding */
1347   pool->buffers[group->buffer.index] = NULL;
1348   if (g_atomic_int_dec_and_test (&pool->num_queued)) {
1349     GST_OBJECT_LOCK (pool);
1350     pool->empty = TRUE;
1351     GST_OBJECT_UNLOCK (pool);
1352   }
1353
1354   timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
1355
1356   size = 0;
1357   vmeta = gst_buffer_get_video_meta (outbuf);
1358   for (i = 0; i < group->n_mem; i++) {
1359     GST_LOG_OBJECT (pool,
1360         "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %"
1361         GST_TIME_FORMAT ", pool-queued=%d, buffer=%p", outbuf,
1362         group->buffer.sequence, group->buffer.index, group->mem[i],
1363         group->planes[i].bytesused, i, group->buffer.flags,
1364         GST_TIME_ARGS (timestamp), pool->num_queued, outbuf);
1365
1366     if (vmeta) {
1367       vmeta->offset[i] = size;
1368       size += gst_memory_get_sizes (group->mem[i], NULL, NULL);
1369     }
1370   }
1371
1372   /* Ignore timestamp and field for OUTPUT device */
1373   if (V4L2_TYPE_IS_OUTPUT (obj->type))
1374     goto done;
1375
1376   /* Check for driver bug in reporting feild */
1377   if (group->buffer.field == V4L2_FIELD_ANY) {
1378     /* Only warn once to avoid the spamming */
1379 #ifndef GST_DISABLE_GST_DEBUG
1380     if (!pool->has_warned_on_buggy_field) {
1381       pool->has_warned_on_buggy_field = TRUE;
1382       GST_WARNING_OBJECT (pool,
1383           "Driver should never set v4l2_buffer.field to ANY");
1384     }
1385 #endif
1386
1387     /* Use the value from the format (works for UVC bug) */
1388     group->buffer.field = obj->format.fmt.pix.field;
1389
1390     /* If driver also has buggy S_FMT, assume progressive */
1391     if (group->buffer.field == V4L2_FIELD_ANY) {
1392 #ifndef GST_DISABLE_GST_DEBUG
1393       if (!pool->has_warned_on_buggy_field) {
1394         pool->has_warned_on_buggy_field = TRUE;
1395         GST_WARNING_OBJECT (pool,
1396             "Driver should never set v4l2_format.pix.field to ANY");
1397       }
1398 #endif
1399
1400       group->buffer.field = V4L2_FIELD_NONE;
1401     }
1402   }
1403
1404   /* set top/bottom field first if v4l2_buffer has the information */
1405   switch (group->buffer.field) {
1406     case V4L2_FIELD_NONE:
1407       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1408       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1409       break;
1410     case V4L2_FIELD_INTERLACED_TB:
1411       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1412       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1413       break;
1414     case V4L2_FIELD_INTERLACED_BT:
1415       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1416       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1417       break;
1418     case V4L2_FIELD_INTERLACED:
1419       GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1420       if (obj->tv_norm == V4L2_STD_NTSC_M ||
1421           obj->tv_norm == V4L2_STD_NTSC_M_JP ||
1422           obj->tv_norm == V4L2_STD_NTSC_M_KR) {
1423         GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1424       } else {
1425         GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1426       }
1427       break;
1428     default:
1429       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1430       GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1431       GST_FIXME_OBJECT (pool,
1432           "Unhandled enum v4l2_field %d - treating as progressive",
1433           group->buffer.field);
1434       break;
1435   }
1436
1437   if (GST_VIDEO_INFO_FORMAT (&obj->info) == GST_VIDEO_FORMAT_ENCODED) {
1438     if ((group->buffer.flags & V4L2_BUF_FLAG_KEYFRAME) ||
1439         GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_MJPEG ||
1440         GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_JPEG ||
1441         GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_PJPG)
1442       GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1443     else
1444       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1445   }
1446
1447   if (group->buffer.flags & V4L2_BUF_FLAG_ERROR)
1448     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_CORRUPTED);
1449
1450   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1451   GST_BUFFER_OFFSET (outbuf) = group->buffer.sequence;
1452   GST_BUFFER_OFFSET_END (outbuf) = group->buffer.sequence + 1;
1453
1454 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
1455   if (group->surface) {
1456     tizen_buffer = gst_v4l2_tizen_buffer_new (outbuf, group->buffer.index, pool);
1457     if (!tizen_buffer) {
1458       GST_ERROR_OBJECT (pool, "tizen buffer failed for index[%d]", group->buffer.index);
1459       goto no_buffer;
1460     }
1461     outbuf = tizen_buffer->gst_buffer;
1462   }
1463 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
1464 done:
1465   *buffer = outbuf;
1466
1467   return res;
1468
1469   /* ERRORS */
1470 poll_failed:
1471   {
1472     GST_DEBUG_OBJECT (pool, "poll error %s", gst_flow_get_name (res));
1473     return res;
1474   }
1475 eos:
1476   {
1477     return GST_FLOW_EOS;
1478   }
1479 dqbuf_failed:
1480   {
1481     return GST_FLOW_ERROR;
1482   }
1483 no_buffer:
1484   {
1485     GST_ERROR_OBJECT (pool, "No free buffer found in the pool at index %d.",
1486         group->buffer.index);
1487     return GST_FLOW_ERROR;
1488   }
1489 }
1490
1491 static GstFlowReturn
1492 gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
1493     GstBufferPoolAcquireParams * params)
1494 {
1495   GstFlowReturn ret;
1496   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1497   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1498   GstV4l2Object *obj = pool->obj;
1499
1500   GST_DEBUG_OBJECT (pool, "acquire");
1501
1502   /* If this is being called to resurrect a lost buffer */
1503   if (params && params->flags & GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT) {
1504     ret = pclass->acquire_buffer (bpool, buffer, params);
1505     goto done;
1506   }
1507
1508   switch (obj->type) {
1509     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1510     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1511       /* capture, This function should return a buffer with new captured data */
1512       switch (obj->mode) {
1513         case GST_V4L2_IO_RW:
1514         {
1515           /* take empty buffer from the pool */
1516           ret = pclass->acquire_buffer (bpool, buffer, params);
1517           break;
1518         }
1519         case GST_V4L2_IO_DMABUF:
1520         case GST_V4L2_IO_MMAP:
1521         case GST_V4L2_IO_USERPTR:
1522         case GST_V4L2_IO_DMABUF_IMPORT:
1523         {
1524           /* just dequeue a buffer, we basically use the queue of v4l2 as the
1525            * storage for our buffers. This function does poll first so we can
1526            * interrupt it fine. */
1527           ret = gst_v4l2_buffer_pool_dqbuf (pool, buffer, TRUE);
1528           break;
1529         }
1530         default:
1531           ret = GST_FLOW_ERROR;
1532           g_assert_not_reached ();
1533           break;
1534       }
1535       break;
1536
1537
1538     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1539     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1540       /* playback, This function should return an empty buffer */
1541       switch (obj->mode) {
1542         case GST_V4L2_IO_RW:
1543           /* get an empty buffer */
1544           ret = pclass->acquire_buffer (bpool, buffer, params);
1545           break;
1546
1547         case GST_V4L2_IO_MMAP:
1548         case GST_V4L2_IO_DMABUF:
1549         case GST_V4L2_IO_USERPTR:
1550         case GST_V4L2_IO_DMABUF_IMPORT:
1551           /* get a free unqueued buffer */
1552           ret = pclass->acquire_buffer (bpool, buffer, params);
1553           break;
1554
1555         default:
1556           ret = GST_FLOW_ERROR;
1557           g_assert_not_reached ();
1558           break;
1559       }
1560       break;
1561
1562     default:
1563       ret = GST_FLOW_ERROR;
1564       g_assert_not_reached ();
1565       break;
1566   }
1567 done:
1568   return ret;
1569 }
1570
1571 static void
1572 gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
1573 {
1574   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1575   GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1576   GstV4l2Object *obj = pool->obj;
1577
1578   GST_DEBUG_OBJECT (pool, "release buffer %p", buffer);
1579
1580   /* If the buffer's pool has been orphaned, dispose of it so that
1581    * the pool resources can be freed */
1582   if (pool->orphaned) {
1583     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1584     pclass->release_buffer (bpool, buffer);
1585     return;
1586   }
1587
1588   switch (obj->type) {
1589     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1590     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1591       /* capture, put the buffer back in the queue so that we can refill it
1592        * later. */
1593       switch (obj->mode) {
1594         case GST_V4L2_IO_RW:
1595           /* release back in the pool */
1596           pclass->release_buffer (bpool, buffer);
1597           break;
1598
1599         case GST_V4L2_IO_DMABUF:
1600         case GST_V4L2_IO_MMAP:
1601         case GST_V4L2_IO_USERPTR:
1602         case GST_V4L2_IO_DMABUF_IMPORT:
1603         {
1604           GstV4l2MemoryGroup *group;
1605           if (gst_v4l2_is_buffer_valid (buffer, &group)) {
1606             GstFlowReturn ret = GST_FLOW_OK;
1607
1608             gst_v4l2_allocator_reset_group (pool->vallocator, group);
1609             /* queue back in the device */
1610             if (pool->other_pool)
1611               ret = gst_v4l2_buffer_pool_prepare_buffer (pool, buffer, NULL);
1612             if (ret != GST_FLOW_OK ||
1613                 gst_v4l2_buffer_pool_qbuf (pool, buffer, group) != GST_FLOW_OK)
1614               pclass->release_buffer (bpool, buffer);
1615           } else {
1616             /* Simply release invalide/modified buffer, the allocator will
1617              * give it back later */
1618             GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1619             pclass->release_buffer (bpool, buffer);
1620           }
1621           break;
1622         }
1623         default:
1624           g_assert_not_reached ();
1625           break;
1626       }
1627       break;
1628
1629     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1630     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1631       switch (obj->mode) {
1632         case GST_V4L2_IO_RW:
1633           /* release back in the pool */
1634           pclass->release_buffer (bpool, buffer);
1635           break;
1636
1637         case GST_V4L2_IO_MMAP:
1638         case GST_V4L2_IO_DMABUF:
1639         case GST_V4L2_IO_USERPTR:
1640         case GST_V4L2_IO_DMABUF_IMPORT:
1641         {
1642           GstV4l2MemoryGroup *group;
1643           guint index;
1644
1645           if (!gst_v4l2_is_buffer_valid (buffer, &group)) {
1646             /* Simply release invalide/modified buffer, the allocator will
1647              * give it back later */
1648             GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1649             pclass->release_buffer (bpool, buffer);
1650             break;
1651           }
1652
1653           index = group->buffer.index;
1654
1655           if (pool->buffers[index] == NULL) {
1656             GST_LOG_OBJECT (pool, "buffer %u not queued, putting on free list",
1657                 index);
1658
1659             /* Remove qdata, this will unmap any map data in userptr */
1660             gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
1661                 GST_V4L2_IMPORT_QUARK, NULL, NULL);
1662
1663             /* reset to default size */
1664             gst_v4l2_allocator_reset_group (pool->vallocator, group);
1665
1666             /* playback, put the buffer back in the queue to refill later. */
1667             pclass->release_buffer (bpool, buffer);
1668           } else {
1669             /* the buffer is queued in the device but maybe not played yet. We just
1670              * leave it there and not make it available for future calls to acquire
1671              * for now. The buffer will be dequeued and reused later. */
1672             GST_LOG_OBJECT (pool, "buffer %u is queued", index);
1673           }
1674           break;
1675         }
1676
1677         default:
1678           g_assert_not_reached ();
1679           break;
1680       }
1681       break;
1682
1683     default:
1684       g_assert_not_reached ();
1685       break;
1686   }
1687 }
1688
1689 static void
1690 gst_v4l2_buffer_pool_dispose (GObject * object)
1691 {
1692   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1693
1694   if (pool->vallocator)
1695     gst_object_unref (pool->vallocator);
1696   pool->vallocator = NULL;
1697
1698   if (pool->allocator)
1699     gst_object_unref (pool->allocator);
1700   pool->allocator = NULL;
1701
1702 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
1703   g_cond_clear (&pool->buffer_cond);
1704   g_mutex_clear (&pool->buffer_lock);
1705
1706   if (pool->tallocator)
1707     gst_object_unref (pool->tallocator);
1708   pool->tallocator = NULL;
1709 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
1710   if (pool->other_pool)
1711     gst_object_unref (pool->other_pool);
1712   pool->other_pool = NULL;
1713
1714   G_OBJECT_CLASS (parent_class)->dispose (object);
1715 }
1716
1717 static void
1718 gst_v4l2_buffer_pool_finalize (GObject * object)
1719 {
1720   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1721
1722   if (pool->video_fd >= 0)
1723     pool->obj->close (pool->video_fd);
1724
1725   gst_poll_free (pool->poll);
1726
1727   /* This can't be done in dispose method because we must not set pointer
1728    * to NULL as it is part of the v4l2object and dispose could be called
1729    * multiple times */
1730   gst_object_unref (pool->obj->element);
1731
1732   g_cond_clear (&pool->empty_cond);
1733
1734   /* FIXME have we done enough here ? */
1735
1736   G_OBJECT_CLASS (parent_class)->finalize (object);
1737 }
1738
1739 static void
1740 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
1741 {
1742   pool->poll = gst_poll_new (TRUE);
1743   pool->can_poll_device = TRUE;
1744   g_cond_init (&pool->empty_cond);
1745   pool->empty = TRUE;
1746   pool->orphaned = FALSE;
1747 }
1748
1749 static void
1750 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
1751 {
1752   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1753   GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
1754
1755   object_class->dispose = gst_v4l2_buffer_pool_dispose;
1756   object_class->finalize = gst_v4l2_buffer_pool_finalize;
1757
1758   bufferpool_class->start = gst_v4l2_buffer_pool_start;
1759   bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
1760   bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
1761   bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
1762   bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
1763   bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
1764   bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
1765   bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
1766
1767   GST_DEBUG_CATEGORY_INIT (v4l2bufferpool_debug, "v4l2bufferpool", 0,
1768       "V4L2 Buffer Pool");
1769   GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
1770 }
1771
1772 /**
1773  * gst_v4l2_buffer_pool_new:
1774  * @obj:  the v4l2 object owning the pool
1775  *
1776  * Construct a new buffer pool.
1777  *
1778  * Returns: the new pool, use gst_object_unref() to free resources
1779  */
1780 GstBufferPool *
1781 gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
1782 {
1783   GstV4l2BufferPool *pool;
1784   GstStructure *config;
1785   gchar *name, *parent_name;
1786   gint fd;
1787
1788   fd = obj->dup (obj->video_fd);
1789   if (fd < 0)
1790     goto dup_failed;
1791
1792   /* setting a significant unique name */
1793   parent_name = gst_object_get_name (GST_OBJECT (obj->element));
1794   name = g_strconcat (parent_name, ":", "pool:",
1795       V4L2_TYPE_IS_OUTPUT (obj->type) ? "sink" : "src", NULL);
1796   g_free (parent_name);
1797
1798   pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL,
1799       "name", name, NULL);
1800   g_object_ref_sink (pool);
1801   g_free (name);
1802
1803   gst_poll_fd_init (&pool->pollfd);
1804   pool->pollfd.fd = fd;
1805   gst_poll_add_fd (pool->poll, &pool->pollfd);
1806   if (V4L2_TYPE_IS_OUTPUT (obj->type))
1807     gst_poll_fd_ctl_write (pool->poll, &pool->pollfd, TRUE);
1808   else
1809     gst_poll_fd_ctl_read (pool->poll, &pool->pollfd, TRUE);
1810
1811   pool->video_fd = fd;
1812   pool->obj = obj;
1813   pool->can_poll_device = TRUE;
1814
1815 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
1816   pool->tallocator = gst_tizen_allocator_new ();
1817   if (pool->tallocator == NULL)
1818     goto allocator_failed;
1819
1820   g_mutex_init (&pool->buffer_lock);
1821   g_cond_init (&pool->buffer_cond);
1822 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
1823   pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj);
1824   if (pool->vallocator == NULL)
1825     goto allocator_failed;
1826
1827   gst_object_ref (obj->element);
1828
1829   config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
1830   gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
1831   /* This will simply set a default config, but will not configure the pool
1832    * because min and max are not valid */
1833   gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
1834
1835   return GST_BUFFER_POOL (pool);
1836
1837   /* ERRORS */
1838 dup_failed:
1839   {
1840     GST_ERROR ("failed to dup fd %d (%s)", errno, g_strerror (errno));
1841     return NULL;
1842   }
1843 allocator_failed:
1844   {
1845 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
1846     if (pool->tallocator) {
1847       gst_object_unref (pool->tallocator);
1848       pool->tallocator = NULL;
1849     }
1850 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
1851     GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator");
1852     gst_object_unref (pool);
1853     return NULL;
1854   }
1855 }
1856
1857 static GstFlowReturn
1858 gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
1859 {
1860   GstFlowReturn res;
1861   GstV4l2Object *obj = pool->obj;
1862   gint amount;
1863   GstMapInfo map;
1864   gint toread;
1865
1866   toread = obj->info.size;
1867
1868   GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);
1869
1870   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1871
1872   do {
1873     if ((res = gst_v4l2_buffer_pool_poll (pool, TRUE)) != GST_FLOW_OK)
1874       goto poll_error;
1875
1876     amount = obj->read (obj->video_fd, map.data, toread);
1877
1878     if (amount == toread) {
1879       break;
1880     } else if (amount == -1) {
1881       if (errno == EAGAIN || errno == EINTR) {
1882         continue;
1883       } else
1884         goto read_error;
1885     } else {
1886       /* short reads can happen if a signal interrupts the read */
1887       continue;
1888     }
1889   } while (TRUE);
1890
1891   GST_LOG_OBJECT (pool, "read %d bytes", amount);
1892   gst_buffer_unmap (buf, &map);
1893   gst_buffer_resize (buf, 0, amount);
1894
1895   return GST_FLOW_OK;
1896
1897   /* ERRORS */
1898 poll_error:
1899   {
1900     GST_DEBUG ("poll error %s", gst_flow_get_name (res));
1901     goto cleanup;
1902   }
1903 read_error:
1904   {
1905     GST_ELEMENT_ERROR (obj->element, RESOURCE, READ,
1906         (_("Error reading %d bytes from device '%s'."),
1907             toread, obj->videodev), GST_ERROR_SYSTEM);
1908     res = GST_FLOW_ERROR;
1909     goto cleanup;
1910   }
1911 cleanup:
1912   {
1913     gst_buffer_unmap (buf, &map);
1914     gst_buffer_resize (buf, 0, 0);
1915     return res;
1916   }
1917 }
1918
1919 /**
1920  * gst_v4l2_buffer_pool_process:
1921  * @bpool: a #GstBufferPool
1922  * @buf: a #GstBuffer, maybe be replaced
1923  *
1924  * Process @buf in @bpool. For capture devices, this functions fills @buf with
1925  * data from the device. For output devices, this functions send the contents of
1926  * @buf to the device for playback.
1927  *
1928  * Returns: %GST_FLOW_OK on success.
1929  */
1930 GstFlowReturn
1931 gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
1932 {
1933   GstFlowReturn ret = GST_FLOW_OK;
1934   GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool);
1935   GstV4l2Object *obj = pool->obj;
1936
1937   GST_DEBUG_OBJECT (pool, "process buffer %p", buf);
1938
1939   if (GST_BUFFER_POOL_IS_FLUSHING (pool))
1940     return GST_FLOW_FLUSHING;
1941
1942   switch (obj->type) {
1943     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1944     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1945       /* capture */
1946       switch (obj->mode) {
1947         case GST_V4L2_IO_RW:
1948           /* capture into the buffer */
1949           ret = gst_v4l2_do_read (pool, *buf);
1950           break;
1951
1952         case GST_V4L2_IO_MMAP:
1953         case GST_V4L2_IO_DMABUF:
1954         {
1955           GstBuffer *tmp;
1956
1957           if ((*buf)->pool == bpool) {
1958             guint num_queued;
1959             gsize size = gst_buffer_get_size (*buf);
1960
1961             /* Legacy M2M devices return empty buffer when drained */
1962             if (size == 0 && GST_V4L2_IS_M2M (obj->device_caps))
1963               goto eos;
1964
1965             if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) !=
1966                 GST_VIDEO_FORMAT_ENCODED && size < pool->size)
1967               goto buffer_truncated;
1968
1969             num_queued = g_atomic_int_get (&pool->num_queued);
1970             GST_TRACE_OBJECT (pool, "Only %i buffer left in the capture queue.",
1971                 num_queued);
1972
1973             /* If we have no more buffer, and can allocate it time to do so */
1974             if (num_queued == 0) {
1975               if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
1976                 ret = gst_v4l2_buffer_pool_resurrect_buffer (pool);
1977                 if (ret == GST_FLOW_OK)
1978                   goto done;
1979               }
1980             }
1981
1982             /* start copying buffers when we are running low on buffers */
1983             if (num_queued < pool->copy_threshold) {
1984               GstBuffer *copy;
1985
1986               if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
1987                 ret = gst_v4l2_buffer_pool_resurrect_buffer (pool);
1988                 if (ret == GST_FLOW_OK)
1989                   goto done;
1990               }
1991
1992               /* copy the buffer */
1993               copy = gst_buffer_copy_region (*buf,
1994                   GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1);
1995               GST_LOG_OBJECT (pool, "copy buffer %p->%p", *buf, copy);
1996
1997               /* and requeue so that we can continue capturing */
1998               gst_buffer_unref (*buf);
1999               *buf = copy;
2000             }
2001
2002             ret = GST_FLOW_OK;
2003             /* nothing, data was inside the buffer when we did _acquire() */
2004             goto done;
2005           }
2006
2007           /* buffer not from our pool, grab a frame and copy it into the target */
2008           if ((ret = gst_v4l2_buffer_pool_dqbuf (pool, &tmp, TRUE))
2009               != GST_FLOW_OK)
2010             goto done;
2011
2012           /* An empty buffer on capture indicates the end of stream */
2013           if (gst_buffer_get_size (tmp) == 0) {
2014             gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
2015
2016             /* Legacy M2M devices return empty buffer when drained */
2017             if (GST_V4L2_IS_M2M (obj->device_caps))
2018               goto eos;
2019           }
2020 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
2021           if (pool->obj->mode == GST_V4L2_IO_DMABUF) {
2022             gst_buffer_unref (*buf);
2023             *buf = tmp;
2024           } else {
2025 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
2026           ret = gst_v4l2_buffer_pool_copy_buffer (pool, *buf, tmp);
2027
2028           /* an queue the buffer again after the copy */
2029           gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
2030 #ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
2031           }
2032 #endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
2033
2034           if (ret != GST_FLOW_OK)
2035             goto copy_failed;
2036           break;
2037         }
2038
2039         case GST_V4L2_IO_USERPTR:
2040         {
2041           struct UserPtrData *data;
2042           GstBuffer *tmp;
2043
2044           /* Replace our buffer with downstream allocated buffer */
2045           data = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2046               GST_V4L2_IMPORT_QUARK);
2047           tmp = gst_buffer_ref (data->buffer);
2048           _unmap_userptr_frame (data);
2049
2050           /* Now tmp is writable, copy the flags and timestamp */
2051           gst_buffer_copy_into (tmp, *buf,
2052               GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2053
2054           gst_buffer_replace (buf, tmp);
2055           gst_buffer_unref (tmp);
2056           break;
2057         }
2058
2059         case GST_V4L2_IO_DMABUF_IMPORT:
2060         {
2061           GstBuffer *tmp;
2062
2063           /* Replace our buffer with downstream allocated buffer */
2064           tmp = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2065               GST_V4L2_IMPORT_QUARK);
2066
2067           gst_buffer_copy_into (tmp, *buf,
2068               GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2069
2070           gst_buffer_replace (buf, tmp);
2071           gst_buffer_unref (tmp);
2072           break;
2073         }
2074
2075         default:
2076           g_assert_not_reached ();
2077           break;
2078       }
2079       break;
2080
2081     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2082     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2083       /* playback */
2084       switch (obj->mode) {
2085         case GST_V4L2_IO_RW:
2086           /* FIXME, do write() */
2087           GST_WARNING_OBJECT (pool, "implement write()");
2088           break;
2089
2090         case GST_V4L2_IO_USERPTR:
2091         case GST_V4L2_IO_DMABUF_IMPORT:
2092         case GST_V4L2_IO_DMABUF:
2093         case GST_V4L2_IO_MMAP:
2094         {
2095           GstBuffer *to_queue = NULL;
2096           GstBuffer *buffer;
2097           GstV4l2MemoryGroup *group;
2098           gint index;
2099
2100           if ((*buf)->pool != bpool)
2101             goto copying;
2102
2103           if (!gst_v4l2_is_buffer_valid (*buf, &group))
2104             goto copying;
2105
2106           index = group->buffer.index;
2107
2108           GST_LOG_OBJECT (pool, "processing buffer %i from our pool", index);
2109
2110           if (pool->buffers[index] != NULL) {
2111             GST_LOG_OBJECT (pool, "buffer %i already queued, copying", index);
2112             goto copying;
2113           }
2114
2115           /* we can queue directly */
2116           to_queue = gst_buffer_ref (*buf);
2117
2118         copying:
2119           if (to_queue == NULL) {
2120             GstBufferPoolAcquireParams params = { 0 };
2121
2122             GST_LOG_OBJECT (pool, "alloc buffer from our pool");
2123
2124             /* this can return EOS if all buffers are outstanding which would
2125              * be strange because we would expect the upstream element to have
2126              * allocated them and returned to us.. */
2127             params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
2128             ret = gst_buffer_pool_acquire_buffer (bpool, &to_queue, &params);
2129             if (ret != GST_FLOW_OK)
2130               goto acquire_failed;
2131
2132             ret = gst_v4l2_buffer_pool_prepare_buffer (pool, to_queue, *buf);
2133             if (ret != GST_FLOW_OK) {
2134               gst_buffer_unref (to_queue);
2135               goto prepare_failed;
2136             }
2137
2138             /* retreive the group */
2139             gst_v4l2_is_buffer_valid (to_queue, &group);
2140           }
2141
2142           if ((ret = gst_v4l2_buffer_pool_qbuf (pool, to_queue, group))
2143               != GST_FLOW_OK)
2144             goto queue_failed;
2145
2146           /* if we are not streaming yet (this is the first buffer, start
2147            * streaming now */
2148           if (!gst_v4l2_buffer_pool_streamon (pool)) {
2149             /* don't check return value because qbuf would have failed */
2150             gst_v4l2_is_buffer_valid (to_queue, &group);
2151
2152             /* qbuf has stored to_queue buffer but we are not in
2153              * streaming state, so the flush logic won't be performed.
2154              * To avoid leaks, flush the allocator and restore the queued
2155              * buffer as non-queued */
2156             gst_v4l2_allocator_flush (pool->vallocator);
2157
2158             pool->buffers[group->buffer.index] = NULL;
2159
2160             gst_mini_object_set_qdata (GST_MINI_OBJECT (to_queue),
2161                 GST_V4L2_IMPORT_QUARK, NULL, NULL);
2162             gst_buffer_unref (to_queue);
2163             g_atomic_int_add (&pool->num_queued, -1);
2164             goto start_failed;
2165           }
2166
2167           /* Remove our ref, we will still hold this buffer in acquire as needed,
2168            * otherwise the pool will think it is outstanding and will refuse to stop. */
2169           gst_buffer_unref (to_queue);
2170
2171           /* release as many buffer as possible */
2172           while (gst_v4l2_buffer_pool_dqbuf (pool, &buffer, FALSE) ==
2173               GST_FLOW_OK) {
2174             if (buffer->pool == NULL)
2175               gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
2176           }
2177
2178           if (g_atomic_int_get (&pool->num_queued) >= pool->min_latency) {
2179             /* all buffers are queued, try to dequeue one and release it back
2180              * into the pool so that _acquire can get to it again. */
2181             ret = gst_v4l2_buffer_pool_dqbuf (pool, &buffer, TRUE);
2182             if (ret == GST_FLOW_OK && buffer->pool == NULL)
2183               /* release the rendered buffer back into the pool. This wakes up any
2184                * thread waiting for a buffer in _acquire(). */
2185               gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
2186           }
2187           break;
2188         }
2189         default:
2190           g_assert_not_reached ();
2191           break;
2192       }
2193       break;
2194     default:
2195       g_assert_not_reached ();
2196       break;
2197   }
2198 done:
2199   return ret;
2200
2201   /* ERRORS */
2202 copy_failed:
2203   {
2204     GST_ERROR_OBJECT (pool, "failed to copy buffer");
2205     return ret;
2206   }
2207 buffer_truncated:
2208   {
2209     GST_WARNING_OBJECT (pool,
2210         "Dropping truncated buffer, this is likely a driver bug.");
2211     gst_buffer_unref (*buf);
2212     *buf = NULL;
2213     return GST_V4L2_FLOW_CORRUPTED_BUFFER;
2214   }
2215 eos:
2216   {
2217     GST_DEBUG_OBJECT (pool, "end of stream reached");
2218     gst_buffer_unref (*buf);
2219     *buf = NULL;
2220     return GST_V4L2_FLOW_LAST_BUFFER;
2221   }
2222 acquire_failed:
2223   {
2224     if (ret == GST_FLOW_FLUSHING)
2225       GST_DEBUG_OBJECT (pool, "flushing");
2226     else
2227       GST_WARNING_OBJECT (pool, "failed to acquire a buffer: %s",
2228           gst_flow_get_name (ret));
2229     return ret;
2230   }
2231 prepare_failed:
2232   {
2233     GST_ERROR_OBJECT (pool, "failed to prepare data");
2234     return ret;
2235   }
2236 queue_failed:
2237   {
2238     GST_ERROR_OBJECT (pool, "failed to queue buffer");
2239     return ret;
2240   }
2241 start_failed:
2242   {
2243     GST_ERROR_OBJECT (pool, "failed to start streaming");
2244     return GST_FLOW_ERROR;
2245   }
2246 }
2247
2248 void
2249 gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
2250     GstBufferPool * other_pool)
2251 {
2252   g_return_if_fail (!gst_buffer_pool_is_active (GST_BUFFER_POOL (pool)));
2253
2254   if (pool->other_pool)
2255     gst_object_unref (pool->other_pool);
2256   pool->other_pool = gst_object_ref (other_pool);
2257 }
2258
2259 void
2260 gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool, gboolean copy)
2261 {
2262   GST_OBJECT_LOCK (pool);
2263   pool->enable_copy_threshold = copy;
2264   GST_OBJECT_UNLOCK (pool);
2265 }
2266
2267 gboolean
2268 gst_v4l2_buffer_pool_flush (GstBufferPool * bpool)
2269 {
2270   GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
2271   gboolean ret = TRUE;
2272
2273   gst_v4l2_buffer_pool_streamoff (pool);
2274
2275   if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type))
2276     ret = gst_v4l2_buffer_pool_streamon (pool);
2277
2278   return ret;
2279 }