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/
7 * gstv4l2bufferpool.c V4L2 buffer pool class
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.
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.
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.
30 # define _GNU_SOURCE /* O_CLOEXEC */
38 #include "gst/video/video.h"
39 #include "gst/video/gstvideometa.h"
40 #include "gst/video/gstvideopool.h"
41 #include "gst/allocators/gstdmabuf.h"
43 #include <gstv4l2bufferpool.h>
45 #include "gstv4l2object.h"
46 #include <glib/gi18n-lib.h>
47 #include <gst/glib-compat-private.h>
48 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
50 #include <gst/allocators/gsttizenmemory.h>
52 #define TIZEN_BUFFER_DUMP_PATH "/tmp/v4l2_output.raw"
53 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
55 GST_DEBUG_CATEGORY_STATIC (v4l2bufferpool_debug);
56 GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE);
57 #define GST_CAT_DEFAULT v4l2bufferpool_debug
59 #define GST_V4L2_IMPORT_QUARK gst_v4l2_buffer_pool_import_quark ()
64 #define gst_v4l2_buffer_pool_parent_class parent_class
65 G_DEFINE_TYPE (GstV4l2BufferPool, gst_v4l2_buffer_pool, GST_TYPE_BUFFER_POOL);
67 enum _GstV4l2BufferPoolAcquireFlags
69 GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT =
70 GST_BUFFER_POOL_ACQUIRE_FLAG_LAST,
71 GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_LAST
74 /* Buffer state flags */
75 enum _GstV4l2BufferState
77 /* Buffer is free (either on the GstBufferPool free queue, or no GstBuffer has
78 * been allocated yet) */
79 BUFFER_STATE_FREE = 0,
81 /* Buffer had outstanding external users */
82 BUFFER_STATE_OUTSTANDING = 1,
84 /* Buffer is on one of the kernel queues */
85 BUFFER_STATE_QUEUED = 2,
88 static void gst_v4l2_buffer_pool_complete_release_buffer (GstBufferPool * bpool,
89 GstBuffer * buffer, gboolean queued);
91 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
92 static void gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool,
95 typedef struct _GstV4l2TizenBuffer GstV4l2TizenBuffer;
96 struct _GstV4l2TizenBuffer {
98 GstBuffer *gst_buffer;
99 GstBuffer *v4l2_buffer;
100 GstV4l2BufferPool *v4l2_pool;
104 gst_v4l2_tizen_buffer_finalize (GstV4l2TizenBuffer *tizen_buffer)
106 GstV4l2BufferPool *pool = NULL;
109 GST_ERROR ("NULL buffer");
113 pool = tizen_buffer->v4l2_pool;
115 gst_v4l2_buffer_pool_release_buffer (GST_BUFFER_POOL_CAST (pool), tizen_buffer->v4l2_buffer);
117 g_mutex_lock (&pool->buffer_lock);
119 pool->live_buffer_count--;
121 GST_DEBUG_OBJECT (pool, "release buffer[%d][tizen:%p,v4l2:%p,gst:%p], live[%d]",
122 tizen_buffer->index, tizen_buffer, tizen_buffer->v4l2_buffer,
123 tizen_buffer->gst_buffer, pool->live_buffer_count);
125 g_cond_signal (&pool->buffer_cond);
127 g_mutex_unlock (&pool->buffer_lock);
129 gst_object_unref (pool);
131 g_free(tizen_buffer);
134 static GstV4l2TizenBuffer *
135 gst_v4l2_tizen_buffer_new (GstBuffer *v4l2_buffer, int index, GstV4l2BufferPool *v4l2_pool)
137 GstV4l2TizenBuffer *tizen_buffer = NULL;
138 GstMemory *memory = NULL;
140 tizen_buffer = g_new0 (GstV4l2TizenBuffer, 1);
141 tizen_buffer->index = index;
142 tizen_buffer->v4l2_buffer = v4l2_buffer;
143 tizen_buffer->gst_buffer = gst_buffer_new ();
144 tizen_buffer->v4l2_pool = gst_object_ref (v4l2_pool);
146 memory = gst_tizen_allocator_alloc_surface (v4l2_pool->tallocator,
147 &v4l2_pool->obj->info, v4l2_pool->vallocator->groups[index]->surface, (gpointer)tizen_buffer,
148 (GDestroyNotify)gst_v4l2_tizen_buffer_finalize);
150 gst_buffer_append_memory (tizen_buffer->gst_buffer, memory);
151 gst_buffer_set_size (tizen_buffer->gst_buffer, v4l2_pool->vallocator->s_info.size);
153 g_mutex_lock (&v4l2_pool->buffer_lock);
155 v4l2_pool->live_buffer_count++;
157 GST_DEBUG_OBJECT (v4l2_pool, "new buffer[tizen:%p,v4l2:%p,gst:%p], size[%d], live[%d]",
158 tizen_buffer, v4l2_buffer, tizen_buffer->gst_buffer,
159 v4l2_pool->vallocator->s_info.size, v4l2_pool->live_buffer_count);
161 g_mutex_unlock (&v4l2_pool->buffer_lock);
167 gst_v4l2_tizen_buffer_dump (tbm_surface_h surface)
171 tbm_surface_info_s sinfo;
174 GST_WARNING ("NULL surface");
178 memset (&sinfo, 0x0, sizeof(tbm_surface_info_s));
180 if (tbm_surface_get_info (surface, &sinfo) != TBM_ERROR_NONE) {
181 GST_ERROR ("get tbm surface[%p] info failed", surface);
185 fp = fopen (TIZEN_BUFFER_DUMP_PATH, "a");
187 GST_ERROR ("file open failed[%s], errno[%d]", TIZEN_BUFFER_DUMP_PATH, errno);
191 for (i = 0 ; i < sinfo.num_planes ; i++) {
192 GST_DEBUG ("[%d] %ux%u, stride[%u], size[%u], offset[%u]",
193 i, sinfo.width, sinfo.height, sinfo.planes[i].stride,
194 sinfo.planes[i].size, sinfo.planes[i].offset);
195 fwrite (sinfo.planes[i].ptr, 1, sinfo.planes[i].size, fp);
200 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
203 gst_v4l2_is_buffer_valid (GstBuffer * buffer, GstV4l2MemoryGroup ** out_group)
205 GstMemory *mem = gst_buffer_peek_memory (buffer, 0);
206 gboolean valid = FALSE;
208 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY))
211 if (gst_is_dmabuf_memory (mem))
212 mem = gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
213 GST_V4L2_MEMORY_QUARK);
215 if (mem && gst_is_v4l2_memory (mem)) {
216 GstV4l2Memory *vmem = (GstV4l2Memory *) mem;
217 GstV4l2MemoryGroup *group = vmem->group;
220 if (group->n_mem != gst_buffer_n_memory (buffer))
223 for (i = 0; i < group->n_mem; i++) {
224 if (group->mem[i] != gst_buffer_peek_memory (buffer, i))
227 if (!gst_memory_is_writable (group->mem[i]))
241 gst_v4l2_buffer_pool_resize_buffer (GstBufferPool * bpool, GstBuffer * buffer)
243 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
244 GstV4l2MemoryGroup *group;
246 if (gst_v4l2_is_buffer_valid (buffer, &group)) {
247 gst_v4l2_allocator_reset_group (pool->vallocator, group);
249 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
254 gst_v4l2_buffer_pool_copy_buffer (GstV4l2BufferPool * pool, GstBuffer * dest,
257 const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
259 GST_LOG_OBJECT (pool, "copying buffer");
261 if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
262 finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
263 GstVideoFrame src_frame, dest_frame;
265 GST_DEBUG_OBJECT (pool, "copy video frame");
267 /* we have raw video, use videoframe copy to get strides right */
268 if (!gst_video_frame_map (&src_frame, &pool->caps_info, src, GST_MAP_READ))
271 if (!gst_video_frame_map (&dest_frame, &pool->caps_info, dest,
273 gst_video_frame_unmap (&src_frame);
277 gst_video_frame_copy (&dest_frame, &src_frame);
279 gst_video_frame_unmap (&src_frame);
280 gst_video_frame_unmap (&dest_frame);
284 GST_DEBUG_OBJECT (pool, "copy raw bytes");
286 if (!gst_buffer_map (src, &map, GST_MAP_READ))
289 gst_buffer_fill (dest, 0, map.data, gst_buffer_get_size (src));
291 gst_buffer_unmap (src, &map);
292 gst_buffer_resize (dest, 0, gst_buffer_get_size (src));
295 gst_buffer_copy_into (dest, src,
296 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
298 GST_CAT_LOG_OBJECT (CAT_PERFORMANCE, pool, "slow copy into buffer %p", dest);
304 GST_ERROR_OBJECT (pool, "could not map buffer");
305 return GST_FLOW_ERROR;
318 gst_v4l2_buffer_pool_import_quark (void)
320 static GQuark quark = 0;
323 quark = g_quark_from_string ("GstV4l2BufferPoolUsePtrData");
329 _unmap_userptr_frame (struct UserPtrData *data)
332 gst_video_frame_unmap (&data->frame);
334 gst_buffer_unmap (data->buffer, &data->map);
337 gst_buffer_unref (data->buffer);
339 g_slice_free (struct UserPtrData, data);
343 gst_v4l2_buffer_pool_import_userptr (GstV4l2BufferPool * pool,
344 GstBuffer * dest, GstBuffer * src)
346 GstFlowReturn ret = GST_FLOW_OK;
347 GstV4l2MemoryGroup *group = NULL;
349 const GstVideoFormatInfo *finfo = pool->caps_info.finfo;
350 struct UserPtrData *data = NULL;
352 GST_LOG_OBJECT (pool, "importing userptr");
355 if (!gst_v4l2_is_buffer_valid (dest, &group))
358 if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
359 flags = GST_MAP_READ;
361 flags = GST_MAP_WRITE;
363 data = g_slice_new0 (struct UserPtrData);
365 if (finfo && (finfo->format != GST_VIDEO_FORMAT_UNKNOWN &&
366 finfo->format != GST_VIDEO_FORMAT_ENCODED)) {
367 gsize size[GST_VIDEO_MAX_PLANES] = { 0, };
370 data->is_frame = TRUE;
372 if (!gst_video_frame_map (&data->frame, &pool->caps_info, src, flags))
375 for (i = 0; i < GST_VIDEO_FORMAT_INFO_N_PLANES (finfo); i++) {
376 if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
377 gint tinfo = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i);
378 size[i] = GST_VIDEO_TILE_X_TILES (tinfo) *
379 GST_VIDEO_TILE_Y_TILES (tinfo) *
380 GST_VIDEO_FORMAT_INFO_TILE_SIZE (finfo, i);
382 size[i] = GST_VIDEO_FRAME_PLANE_STRIDE (&data->frame, i) *
383 GST_VIDEO_FRAME_COMP_HEIGHT (&data->frame, i);
387 /* In the single planar API, planes must be contiguous in memory and
388 * therefore they must have expected size. ie: no padding.
389 * To check these conditions, we check that plane 'i' start address
390 * + plane 'i' size equals to plane 'i+1' start address */
391 if (!V4L2_TYPE_IS_MULTIPLANAR (pool->obj->type)) {
392 for (i = 0; i < (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) - 1); i++) {
393 const struct v4l2_pix_format *pix_fmt = &pool->obj->format.fmt.pix;
395 gint estride = gst_video_format_info_extrapolate_stride (finfo, i,
396 pix_fmt->bytesperline);
397 guint eheight = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i,
400 tmp = ((guint8 *) data->frame.data[i]) + estride * eheight;
401 if (tmp != data->frame.data[i + 1])
402 goto non_contiguous_mem;
406 if (!gst_v4l2_allocator_import_userptr (pool->vallocator, group,
407 data->frame.info.size, finfo->n_planes, data->frame.data, size))
413 data->is_frame = FALSE;
415 if (!gst_buffer_map (src, &data->map, flags))
418 ptr[0] = data->map.data;
419 size[0] = data->map.size;
421 if (!gst_v4l2_allocator_import_userptr (pool->vallocator, group,
422 data->map.size, 1, ptr, size))
426 data->buffer = gst_buffer_ref (src);
428 gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
429 data, (GDestroyNotify) _unmap_userptr_frame);
431 gst_buffer_copy_into (dest, src,
432 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
438 GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
439 return GST_FLOW_ERROR;
443 GST_ERROR_OBJECT (pool, "could not map buffer");
444 g_slice_free (struct UserPtrData, data);
445 return GST_FLOW_ERROR;
449 GST_ERROR_OBJECT (pool, "memory is not contiguous or plane size mismatch");
450 _unmap_userptr_frame (data);
451 return GST_FLOW_ERROR;
455 GST_ERROR_OBJECT (pool, "failed to import data");
456 _unmap_userptr_frame (data);
457 return GST_FLOW_ERROR;
462 gst_v4l2_buffer_pool_import_dmabuf (GstV4l2BufferPool * pool,
463 GstBuffer * dest, GstBuffer * src)
465 GstV4l2MemoryGroup *group = NULL;
466 GstMemory *dma_mem[GST_VIDEO_MAX_PLANES] = { 0 };
467 guint n_mem = gst_buffer_n_memory (src);
470 GST_LOG_OBJECT (pool, "importing dmabuf");
472 if (!gst_v4l2_is_buffer_valid (dest, &group))
475 if (n_mem > GST_VIDEO_MAX_PLANES)
478 for (i = 0; i < n_mem; i++)
479 dma_mem[i] = gst_buffer_peek_memory (src, i);
481 if (!gst_v4l2_allocator_import_dmabuf (pool->vallocator, group, n_mem,
485 gst_mini_object_set_qdata (GST_MINI_OBJECT (dest), GST_V4L2_IMPORT_QUARK,
486 gst_buffer_ref (src), (GDestroyNotify) gst_buffer_unref);
488 gst_buffer_copy_into (dest, src,
489 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
495 GST_ERROR_OBJECT (pool, "destination buffer invalid or not from our pool");
496 return GST_FLOW_ERROR;
500 GST_ERROR_OBJECT (pool, "could not map buffer");
501 return GST_FLOW_ERROR;
505 GST_ERROR_OBJECT (pool, "failed to import dmabuf");
506 return GST_FLOW_ERROR;
511 gst_v4l2_buffer_pool_prepare_buffer (GstV4l2BufferPool * pool,
512 GstBuffer * dest, GstBuffer * src)
514 GstFlowReturn ret = GST_FLOW_OK;
515 gboolean own_src = FALSE;
518 if (pool->other_pool == NULL) {
519 GST_ERROR_OBJECT (pool, "can't prepare buffer, source buffer missing");
520 return GST_FLOW_ERROR;
523 ret = gst_buffer_pool_acquire_buffer (pool->other_pool, &src, NULL);
524 if (ret != GST_FLOW_OK) {
525 GST_ERROR_OBJECT (pool, "failed to acquire buffer from downstream pool");
532 switch (pool->obj->mode) {
533 case GST_V4L2_IO_MMAP:
534 case GST_V4L2_IO_DMABUF:
535 ret = gst_v4l2_buffer_pool_copy_buffer (pool, dest, src);
537 case GST_V4L2_IO_USERPTR:
538 ret = gst_v4l2_buffer_pool_import_userptr (pool, dest, src);
540 case GST_V4L2_IO_DMABUF_IMPORT:
541 ret = gst_v4l2_buffer_pool_import_dmabuf (pool, dest, src);
548 gst_buffer_unref (src);
555 gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
556 GstBufferPoolAcquireParams * params)
558 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
559 GstV4l2MemoryGroup *group = NULL;
560 GstBuffer *newbuf = NULL;
570 gst_buffer_new_allocate (pool->allocator, pool->size, &pool->params);
572 case GST_V4L2_IO_MMAP:
573 group = gst_v4l2_allocator_alloc_mmap (pool->vallocator);
575 case GST_V4L2_IO_DMABUF:
576 group = gst_v4l2_allocator_alloc_dmabuf (pool->vallocator,
579 case GST_V4L2_IO_USERPTR:
580 group = gst_v4l2_allocator_alloc_userptr (pool->vallocator);
582 case GST_V4L2_IO_DMABUF_IMPORT:
583 group = gst_v4l2_allocator_alloc_dmabufin (pool->vallocator);
587 g_assert_not_reached ();
593 newbuf = gst_buffer_new ();
595 for (i = 0; i < group->n_mem; i++)
596 gst_buffer_append_memory (newbuf, group->mem[i]);
598 if (g_atomic_int_get (&pool->buffer_state[group->buffer.index])) {
599 GST_WARNING_OBJECT (pool, "newly allocated buffer %u is not free",
600 group->buffer.index);
602 } else if (newbuf == NULL) {
603 goto allocation_failed;
606 /* add metadata to raw video buffers */
607 if (pool->add_videometa) {
608 GstVideoMeta *videometa =
609 gst_buffer_add_video_meta_full (newbuf, GST_VIDEO_FRAME_FLAG_NONE,
610 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
611 GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
612 info->offset, info->stride);
614 gst_video_meta_set_alignment (videometa, obj->align);
624 GST_ERROR_OBJECT (pool, "failed to allocate buffer");
625 return GST_FLOW_ERROR;
630 gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
632 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
633 GstV4l2Object *obj = pool->obj;
635 guint size, min_buffers, max_buffers;
636 GstAllocator *allocator;
637 GstAllocationParams params;
638 gboolean can_allocate = FALSE;
639 gboolean updated = FALSE;
642 pool->add_videometa =
643 gst_buffer_pool_config_has_option (config,
644 GST_BUFFER_POOL_OPTION_VIDEO_META);
646 /* parse the config and keep around */
647 if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
651 if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
654 GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
657 gst_object_unref (pool->allocator);
658 pool->allocator = NULL;
661 case GST_V4L2_IO_DMABUF:
662 pool->allocator = gst_dmabuf_allocator_new ();
663 can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
665 case GST_V4L2_IO_MMAP:
666 can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
668 case GST_V4L2_IO_USERPTR:
670 GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
672 case GST_V4L2_IO_DMABUF_IMPORT:
673 can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
677 pool->allocator = g_object_ref (allocator);
678 pool->params = params;
679 /* No need to change the configuration */
683 g_assert_not_reached ();
687 /* libv4l2 conversion code does not handle CREATE_BUFS, and may lead to
688 * instability and crash, disable it for now */
689 if (can_allocate && obj->fmtdesc->flags & V4L2_FMT_FLAG_EMULATED) {
690 GST_WARNING_OBJECT (pool,
691 "libv4l2 converter detected, disabling CREATE_BUFS");
692 can_allocate = FALSE;
693 GST_OBJECT_FLAG_UNSET (pool->vallocator,
694 GST_V4L2_ALLOCATOR_FLAG_MMAP_CREATE_BUFS
695 | GST_V4L2_ALLOCATOR_FLAG_USERPTR_CREATE_BUFS
696 | GST_V4L2_ALLOCATOR_FLAG_DMABUF_CREATE_BUFS);
699 if (min_buffers < GST_V4L2_MIN_BUFFERS (obj)) {
701 min_buffers = GST_V4L2_MIN_BUFFERS (obj);
702 GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
705 /* respect driver requirements */
706 if (min_buffers < obj->min_buffers) {
708 min_buffers = obj->min_buffers;
709 GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
712 if (max_buffers > VIDEO_MAX_FRAME || max_buffers == 0) {
714 max_buffers = VIDEO_MAX_FRAME;
715 GST_INFO_OBJECT (pool, "reducing maximum buffers to %u", max_buffers);
718 if (min_buffers > max_buffers) {
720 min_buffers = max_buffers;
721 GST_INFO_OBJECT (pool, "reducing minimum buffers to %u", min_buffers);
722 } else if (min_buffers != max_buffers) {
725 max_buffers = min_buffers;
726 GST_INFO_OBJECT (pool, "can't allocate, setting maximum to minimum");
730 if (!pool->add_videometa && obj->need_video_meta) {
731 GST_INFO_OBJECT (pool, "adding needed video meta");
733 gst_buffer_pool_config_add_option (config,
734 GST_BUFFER_POOL_OPTION_VIDEO_META);
737 /* Always update the config to ensure the configured size matches */
738 gst_buffer_pool_config_set_params (config, caps, obj->info.size, min_buffers,
741 /* keep a GstVideoInfo with defaults for the when we need to copy */
742 gst_video_info_from_caps (&pool->caps_info, caps);
745 ret = GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
747 /* If anything was changed documentation recommend to return FALSE */
748 return !updated && ret;
753 GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
759 gst_v4l2_buffer_pool_resurrect_buffer (GstV4l2BufferPool * pool)
761 GstBufferPoolAcquireParams params = { 0 };
762 GstBuffer *buffer = NULL;
765 GST_DEBUG_OBJECT (pool, "A buffer was lost, reallocating it");
767 /* block recursive calls to this function */
768 g_signal_handler_block (pool->vallocator, pool->group_released_handler);
771 (GstBufferPoolAcquireFlags) GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT |
772 GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
774 gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (pool), &buffer, ¶ms);
776 if (ret == GST_FLOW_OK)
777 gst_buffer_unref (buffer);
779 g_signal_handler_unblock (pool->vallocator, pool->group_released_handler);
785 gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
787 GstV4l2Object *obj = pool->obj;
793 case GST_V4L2_IO_MMAP:
794 case GST_V4L2_IO_USERPTR:
795 case GST_V4L2_IO_DMABUF:
796 case GST_V4L2_IO_DMABUF_IMPORT:
797 if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) {
801 GST_OBJECT_LOCK (pool);
802 num_queued = g_atomic_int_get (&pool->num_queued);
803 if (num_queued < pool->num_allocated)
804 n = pool->num_allocated - num_queued;
805 GST_OBJECT_UNLOCK (pool);
807 /* For captures, we need to enqueue buffers before we start streaming,
808 * so the driver don't underflow immediately. As we have put then back
809 * into the base class queue, resurrect them, then releasing will queue
811 for (i = 0; i < n; i++)
812 gst_v4l2_buffer_pool_resurrect_buffer (pool);
815 if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
816 goto streamon_failed;
818 pool->streaming = TRUE;
820 GST_DEBUG_OBJECT (pool, "Started streaming");
830 GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
836 /* Call with streamlock held, or when streaming threads are down */
838 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
839 gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool, gboolean is_locked)
841 gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
844 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
845 GstV4l2Object *obj = pool->obj;
847 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
849 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
851 if (!pool->streaming)
854 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
855 if (obj->tbm_output && !V4L2_TYPE_IS_OUTPUT(pool->obj->type)) {
856 g_mutex_lock (&pool->buffer_lock);
858 GST_INFO_OBJECT (pool, "live buffer[%d], is_locked[%d]",
859 pool->live_buffer_count, is_locked);
861 if (pool->live_buffer_count > 0) {
862 end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
865 GST_OBJECT_UNLOCK (pool);
868 GST_WARNING_OBJECT (pool, "wait for live buffer[%d]", pool->live_buffer_count);
870 if (!g_cond_wait_until (&pool->buffer_cond, &pool->buffer_lock, end_time)) {
871 GST_ERROR_OBJECT (pool, "failed to wait live buffer[%d]", pool->live_buffer_count);
875 GST_WARNING_OBJECT (pool, "signal received, check again : live count[%d]",
876 pool->live_buffer_count);
877 } while (pool->live_buffer_count > 0);
880 GST_OBJECT_LOCK (pool);
883 g_mutex_unlock (&pool->buffer_lock);
885 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
887 case GST_V4L2_IO_MMAP:
888 case GST_V4L2_IO_USERPTR:
889 case GST_V4L2_IO_DMABUF:
890 case GST_V4L2_IO_DMABUF_IMPORT:
892 if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
893 GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
894 errno, g_strerror (errno));
896 pool->streaming = FALSE;
898 GST_DEBUG_OBJECT (pool, "Stopped streaming");
900 if (pool->vallocator)
901 gst_v4l2_allocator_flush (pool->vallocator);
907 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
908 gint old_buffer_state =
909 g_atomic_int_and (&pool->buffer_state[i], ~BUFFER_STATE_QUEUED);
910 if ((old_buffer_state & BUFFER_STATE_QUEUED) && pool->buffers[i]) {
911 GstBuffer *buffer = pool->buffers[i];
912 GstBufferPool *bpool = GST_BUFFER_POOL (pool);
914 pool->buffers[i] = NULL;
916 if (!(old_buffer_state & BUFFER_STATE_OUTSTANDING)) {
917 if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
918 gst_v4l2_buffer_pool_complete_release_buffer (bpool, buffer, FALSE);
920 else /* Don't re-enqueue capture buffer on stop */
921 pclass->release_buffer (bpool, buffer);
924 g_atomic_int_add (&pool->num_queued, -1);
930 gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
932 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
933 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
934 GstV4l2Object *obj = pool->obj;
935 GstStructure *config;
937 guint size, min_buffers, max_buffers;
938 guint max_latency, min_latency, copy_threshold = 0;
939 gboolean can_allocate = FALSE, ret = TRUE;
941 GST_DEBUG_OBJECT (pool, "activating pool");
943 if (pool->other_pool) {
946 if (!gst_buffer_pool_set_active (pool->other_pool, TRUE))
947 goto other_pool_failed;
949 if (gst_buffer_pool_acquire_buffer (pool->other_pool, &buffer, NULL) !=
951 goto other_pool_failed;
953 if (!gst_v4l2_object_try_import (obj, buffer)) {
954 gst_buffer_unref (buffer);
957 gst_buffer_unref (buffer);
960 config = gst_buffer_pool_get_config (bpool);
961 if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
965 min_latency = MAX (GST_V4L2_MIN_BUFFERS (obj), obj->min_buffers);
971 /* This workaround a unfixable bug in libv4l2 when RW is emulated on top
972 * of MMAP. In this case, the first read initialize the queues, but the
973 * poll before that will always fail. Doing an empty read, forces the
974 * queue to be initialized now. We only do this if we have a streaming
976 if (obj->device_caps & V4L2_CAP_STREAMING)
977 obj->read (obj->video_fd, NULL, 0);
980 case GST_V4L2_IO_DMABUF:
981 case GST_V4L2_IO_MMAP:
985 can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP);
987 /* first, lets request buffers, and see how many we can get: */
988 GST_DEBUG_OBJECT (pool, "requesting %d MMAP buffers", min_buffers);
990 count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
992 pool->num_allocated = count;
994 if (count < GST_V4L2_MIN_BUFFERS (obj)) {
999 /* V4L2 buffer pool are often very limited in the amount of buffers it
1000 * can offer. The copy_threshold will workaround this limitation by
1001 * falling back to copy if the pipeline needed more buffers. This also
1002 * prevent having to do REQBUFS(N)/REQBUFS(0) every time configure is
1004 if (count != min_buffers || pool->enable_copy_threshold) {
1005 GST_WARNING_OBJECT (pool,
1006 "Uncertain or not enough buffers, enabling copy threshold");
1007 min_buffers = count;
1008 copy_threshold = min_latency;
1013 case GST_V4L2_IO_USERPTR:
1018 GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR);
1020 GST_DEBUG_OBJECT (pool, "requesting %d USERPTR buffers", min_buffers);
1022 count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
1023 V4L2_MEMORY_USERPTR);
1024 pool->num_allocated = count;
1026 /* There is no rational to not get what we asked */
1027 if (count < min_buffers) {
1028 min_buffers = count;
1032 min_buffers = count;
1035 case GST_V4L2_IO_DMABUF_IMPORT:
1039 can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF);
1041 GST_DEBUG_OBJECT (pool, "requesting %d DMABUF buffers", min_buffers);
1043 count = gst_v4l2_allocator_start (pool->vallocator, min_buffers,
1044 V4L2_MEMORY_DMABUF);
1045 pool->num_allocated = count;
1047 /* There is no rational to not get what we asked */
1048 if (count < min_buffers) {
1049 min_buffers = count;
1053 min_buffers = count;
1059 g_assert_not_reached ();
1064 max_latency = max_buffers;
1066 max_latency = min_buffers;
1069 pool->copy_threshold = copy_threshold;
1070 pool->max_latency = max_latency;
1071 pool->min_latency = min_latency;
1072 pool->num_queued = 0;
1074 if (max_buffers != 0 && max_buffers < min_buffers)
1075 max_buffers = min_buffers;
1077 gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
1079 pclass->set_config (bpool, config);
1080 gst_structure_free (config);
1082 /* now, allocate the buffers: */
1083 if (!pclass->start (bpool))
1086 if (!V4L2_TYPE_IS_OUTPUT (obj->type)) {
1087 if (g_atomic_int_get (&pool->num_queued) < pool->num_allocated)
1090 pool->group_released_handler =
1091 g_signal_connect_swapped (pool->vallocator, "group-released",
1092 G_CALLBACK (gst_v4l2_buffer_pool_resurrect_buffer), pool);
1093 ret = gst_v4l2_buffer_pool_streamon (pool);
1101 GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
1102 gst_structure_free (config);
1107 GST_ERROR_OBJECT (pool,
1108 "we received %d buffer from device '%s', we want at least %d",
1109 min_buffers, obj->videodev, GST_V4L2_MIN_BUFFERS (obj));
1110 gst_structure_free (config);
1115 GST_ERROR_OBJECT (pool, "allocate failed");
1120 GST_ERROR_OBJECT (pool, "failed to activate the other pool %"
1121 GST_PTR_FORMAT, pool->other_pool);
1126 GST_ERROR_OBJECT (pool, "failed to queue buffers into the capture queue");
1131 GST_ERROR_OBJECT (pool, "cannot import buffers from downstream pool");
1137 gst_v4l2_buffer_pool_vallocator_stop (GstV4l2BufferPool * pool)
1141 if (!pool->vallocator)
1144 vret = gst_v4l2_allocator_stop (pool->vallocator);
1146 if (vret == GST_V4L2_BUSY)
1147 GST_WARNING_OBJECT (pool, "some buffers are still outstanding");
1149 return (vret == GST_V4L2_OK);
1153 gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
1155 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1158 GST_DEBUG_OBJECT (pool, "stopping pool");
1160 if (pool->group_released_handler > 0) {
1161 g_signal_handler_disconnect (pool->vallocator,
1162 pool->group_released_handler);
1163 pool->group_released_handler = 0;
1166 if (pool->other_pool) {
1167 gst_buffer_pool_set_active (pool->other_pool, FALSE);
1168 gst_object_unref (pool->other_pool);
1169 pool->other_pool = NULL;
1172 if (!pool->orphaned)
1173 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1174 gst_v4l2_buffer_pool_streamoff (pool, FALSE);
1176 gst_v4l2_buffer_pool_streamoff (pool);
1179 ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
1182 ret = gst_v4l2_buffer_pool_vallocator_stop (pool);
1188 gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object)
1190 GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
1191 GstV4l2BufferPool *pool;
1194 /* Nothing to do if there is no pool */
1198 pool = GST_V4L2_BUFFER_POOL (bpool);
1200 if (pool->orphaned != FALSE
1201 || !GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (pool->vallocator)
1202 || g_getenv ("GST_V4L2_FORCE_DRAIN")) {
1203 gst_object_unref (bpool);
1207 GST_DEBUG_OBJECT (pool, "orphaning pool");
1208 gst_buffer_pool_set_active (bpool, FALSE);
1210 /* We lock to prevent racing with a return buffer in QBuf, and has a
1211 * workaround of not being able to use the pool hidden activation lock. */
1212 GST_OBJECT_LOCK (pool);
1214 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1215 gst_v4l2_buffer_pool_streamoff (pool, TRUE);
1217 gst_v4l2_buffer_pool_streamoff (pool);
1219 ret = gst_v4l2_allocator_orphan (pool->vallocator);
1221 pool->orphaned = TRUE;
1223 GST_OBJECT_UNLOCK (pool);
1226 GstBufferPool *old_pool;
1227 GST_OBJECT_LOCK (v4l2object->element);
1228 old_pool = v4l2object->pool;
1229 v4l2object->pool = NULL;
1230 GST_OBJECT_UNLOCK (v4l2object->element);
1232 gst_object_unref (old_pool);
1235 gst_object_unref (bpool);
1241 gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
1243 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1245 GST_DEBUG_OBJECT (pool, "start flushing");
1247 gst_poll_set_flushing (pool->obj->poll, TRUE);
1249 GST_OBJECT_LOCK (pool);
1250 pool->empty = FALSE;
1251 g_cond_broadcast (&pool->empty_cond);
1252 GST_OBJECT_UNLOCK (pool);
1254 if (pool->other_pool && gst_buffer_pool_is_active (pool->other_pool))
1255 gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
1259 gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool)
1261 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1263 GST_DEBUG_OBJECT (pool, "stop flushing");
1265 if (pool->other_pool && gst_buffer_pool_is_active (pool->other_pool))
1266 gst_buffer_pool_set_flushing (pool->other_pool, FALSE);
1268 gst_poll_set_flushing (pool->obj->poll, FALSE);
1271 static GstFlowReturn
1272 gst_v4l2_buffer_pool_poll (GstV4l2BufferPool * pool, gboolean wait)
1274 GstClockTime timeout;
1277 timeout = GST_CLOCK_TIME_NONE;
1281 /* In RW mode there is no queue, hence no need to wait while the queue is
1283 if (pool->obj->mode != GST_V4L2_IO_RW) {
1284 GST_OBJECT_LOCK (pool);
1286 if (!wait && pool->empty) {
1287 GST_OBJECT_UNLOCK (pool);
1288 return GST_V4L2_FLOW_LAST_BUFFER;
1292 g_cond_wait (&pool->empty_cond, GST_OBJECT_GET_LOCK (pool));
1294 GST_OBJECT_UNLOCK (pool);
1297 if (!pool->obj->can_poll_device) {
1301 return GST_V4L2_FLOW_LAST_BUFFER;
1304 return gst_v4l2_object_poll (pool->obj, timeout);
1307 static GstFlowReturn
1308 gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
1309 GstV4l2MemoryGroup * group, guint32 * frame_number)
1311 const GstV4l2Object *obj = pool->obj;
1312 gint old_buffer_state;
1315 GST_OBJECT_LOCK (pool);
1317 index = group->buffer.index;
1320 g_atomic_int_or (&pool->buffer_state[index], BUFFER_STATE_QUEUED);
1321 if (old_buffer_state & BUFFER_STATE_QUEUED)
1322 goto already_queued;
1324 GST_LOG_OBJECT (pool, "queuing buffer %i, previous-state = %i", index,
1327 if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
1328 enum v4l2_field field;
1330 /* Buffer field is the same as the one defined in format */
1331 if (V4L2_TYPE_IS_MULTIPLANAR (obj->type))
1332 field = obj->format.fmt.pix_mp.field;
1334 field = obj->format.fmt.pix.field;
1336 group->buffer.field = field;
1340 group->buffer.timestamp.tv_sec = *frame_number;
1341 group->buffer.timestamp.tv_usec = 0;
1343 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1344 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buf);
1345 GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp);
1347 group->buffer.timestamp.tv_sec = -1;
1348 group->buffer.timestamp.tv_usec = -1;
1352 /* If the pool was orphaned, don't try to queue any returned buffers.
1353 * This is done with the objet lock in order to synchronize with
1358 g_atomic_int_inc (&pool->num_queued);
1359 pool->buffers[index] = buf;
1361 if (!gst_v4l2_allocator_qbuf (pool->vallocator, group))
1364 pool->empty = FALSE;
1365 g_cond_signal (&pool->empty_cond);
1366 GST_OBJECT_UNLOCK (pool);
1372 GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
1373 GST_OBJECT_UNLOCK (pool);
1374 return GST_FLOW_ERROR;
1378 GST_DEBUG_OBJECT (pool, "pool was orphaned, not queuing back buffer.");
1379 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY);
1380 g_atomic_int_and (&pool->buffer_state[index], ~BUFFER_STATE_QUEUED);
1381 GST_OBJECT_UNLOCK (pool);
1382 return GST_FLOW_FLUSHING;
1386 GST_ERROR_OBJECT (pool, "could not queue a buffer %i", index);
1387 /* Mark broken buffer to the allocator */
1388 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY);
1389 g_atomic_int_add (&pool->num_queued, -1);
1390 pool->buffers[index] = NULL;
1391 g_atomic_int_and (&pool->buffer_state[index], ~BUFFER_STATE_QUEUED);
1392 GST_OBJECT_UNLOCK (pool);
1393 return GST_FLOW_ERROR;
1397 static GstFlowReturn
1398 gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
1399 gboolean * outstanding, gboolean wait)
1402 GstBuffer *outbuf = NULL;
1403 GstV4l2Object *obj = pool->obj;
1404 GstClockTime timestamp;
1405 GstV4l2MemoryGroup *group;
1406 const GstVideoInfo *info = &obj->info;
1408 gint old_buffer_state;
1409 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1410 GstV4l2TizenBuffer *tizen_buffer = NULL;
1411 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1413 if ((res = gst_v4l2_buffer_pool_poll (pool, wait)) < GST_FLOW_OK)
1416 if (res == GST_V4L2_FLOW_LAST_BUFFER) {
1417 GST_LOG_OBJECT (pool, "nothing to dequeue");
1421 if (res == GST_V4L2_FLOW_RESOLUTION_CHANGE) {
1422 GST_INFO_OBJECT (pool, "Resolution change detected.");
1426 GST_LOG_OBJECT (pool, "dequeueing a buffer");
1428 res = gst_v4l2_allocator_dqbuf (pool->vallocator, &group);
1429 if (res == GST_V4L2_FLOW_LAST_BUFFER)
1431 if (res != GST_FLOW_OK)
1435 g_atomic_int_and (&pool->buffer_state[group->buffer.index],
1436 ~BUFFER_STATE_QUEUED);
1437 if (!(old_buffer_state & BUFFER_STATE_QUEUED))
1441 *outstanding = (old_buffer_state & BUFFER_STATE_OUTSTANDING) != 0;
1442 } else if (old_buffer_state & BUFFER_STATE_OUTSTANDING) {
1443 GST_WARNING_OBJECT (pool, "unexpected outstanding buffer %u",
1444 group->buffer.index);
1447 if (group->buffer.flags & V4L2_BUF_FLAG_LAST &&
1448 group->planes[0].bytesused == 0) {
1449 GST_DEBUG_OBJECT (pool, "Empty last buffer, signalling eos.");
1453 outbuf = pool->buffers[group->buffer.index];
1457 pool->buffers[group->buffer.index] = NULL;
1458 if (g_atomic_int_dec_and_test (&pool->num_queued)) {
1459 GST_OBJECT_LOCK (pool);
1461 GST_OBJECT_UNLOCK (pool);
1464 timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
1466 for (i = 0; i < group->n_mem; i++) {
1467 const GstVideoFormatInfo *finfo = info->finfo;
1469 GST_LOG_OBJECT (pool,
1470 "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %"
1471 GST_TIME_FORMAT ", pool-queued=%d, buffer=%p, previous-state=%i",
1472 outbuf, group->buffer.sequence, group->buffer.index, group->mem[i],
1473 group->planes[i].bytesused, i, group->buffer.flags,
1474 GST_TIME_ARGS (timestamp), pool->num_queued, outbuf, old_buffer_state);
1476 if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) == GST_VIDEO_FORMAT_ENCODED)
1479 /* Ensure our offset matches the expected plane size, or image size if
1480 * there is only one memory */
1481 if (group->n_mem == 1) {
1482 gst_memory_resize (group->mem[0], 0, info->size + info->offset[0]);
1486 if (!GST_VIDEO_FORMAT_INFO_IS_TILED (finfo))
1487 gst_memory_resize (group->mem[i], 0, obj->plane_size[i]);
1490 /* Ignore timestamp and field for OUTPUT device */
1491 if (V4L2_TYPE_IS_OUTPUT (obj->type))
1494 /* Check for driver bug in reporting feild */
1495 if (group->buffer.field == V4L2_FIELD_ANY) {
1496 /* Only warn once to avoid the spamming */
1497 #ifndef GST_DISABLE_GST_DEBUG
1498 if (!pool->has_warned_on_buggy_field) {
1499 pool->has_warned_on_buggy_field = TRUE;
1500 GST_WARNING_OBJECT (pool,
1501 "Driver should never set v4l2_buffer.field to ANY");
1505 /* Use the value from the format (works for UVC bug) */
1506 group->buffer.field = obj->format.fmt.pix.field;
1508 /* If driver also has buggy S_FMT, assume progressive */
1509 if (group->buffer.field == V4L2_FIELD_ANY) {
1510 #ifndef GST_DISABLE_GST_DEBUG
1511 if (!pool->has_warned_on_buggy_field) {
1512 pool->has_warned_on_buggy_field = TRUE;
1513 GST_WARNING_OBJECT (pool,
1514 "Driver should never set v4l2_format.pix.field to ANY");
1518 group->buffer.field = V4L2_FIELD_NONE;
1522 /* set top/bottom field first if v4l2_buffer has the information */
1523 switch (group->buffer.field) {
1524 case V4L2_FIELD_NONE:
1525 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1526 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1528 case V4L2_FIELD_TOP:
1529 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1530 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TOP_FIELD);
1532 case V4L2_FIELD_BOTTOM:
1533 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1534 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_BOTTOM_FIELD);
1536 case V4L2_FIELD_INTERLACED_TB:
1537 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1538 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1540 case V4L2_FIELD_INTERLACED_BT:
1541 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1542 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1544 case V4L2_FIELD_INTERLACED:
1545 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1546 if (obj->tv_norm == V4L2_STD_NTSC_M ||
1547 obj->tv_norm == V4L2_STD_NTSC_M_JP ||
1548 obj->tv_norm == V4L2_STD_NTSC_M_KR) {
1549 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1551 GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1555 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1556 GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
1557 GST_FIXME_OBJECT (pool,
1558 "Unhandled enum v4l2_field %d - treating as progressive",
1559 group->buffer.field);
1563 if (!gst_v4l2_object_is_raw (obj)) {
1564 if ((group->buffer.flags & V4L2_BUF_FLAG_KEYFRAME) ||
1565 GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_MJPEG ||
1566 GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_JPEG ||
1567 GST_V4L2_PIXELFORMAT (obj) == V4L2_PIX_FMT_PJPG)
1568 GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1570 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1573 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1574 if (group->surface) {
1575 tizen_buffer = gst_v4l2_tizen_buffer_new (outbuf, group->buffer.index, pool);
1576 if (!tizen_buffer) {
1577 GST_ERROR_OBJECT (pool, "tizen buffer failed for index[%d]", group->buffer.index);
1580 outbuf = tizen_buffer->gst_buffer;
1582 if (pool->tbm_output_dump)
1583 gst_v4l2_tizen_buffer_dump (group->surface);
1585 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1587 if (group->buffer.flags & V4L2_BUF_FLAG_ERROR)
1588 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_CORRUPTED);
1590 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1591 GST_BUFFER_OFFSET (outbuf) = group->buffer.sequence;
1592 GST_BUFFER_OFFSET_END (outbuf) = group->buffer.sequence + 1;
1602 GST_DEBUG_OBJECT (pool, "poll error %s", gst_flow_get_name (res));
1607 return GST_V4L2_FLOW_LAST_BUFFER;
1611 return GST_FLOW_ERROR;
1615 GST_ERROR_OBJECT (pool, "No free buffer found in the pool at index %d.",
1616 group->buffer.index);
1617 return GST_FLOW_ERROR;
1621 static GstFlowReturn
1622 gst_v4l2_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
1623 GstBufferPoolAcquireParams * params)
1626 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1627 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1628 GstV4l2Object *obj = pool->obj;
1630 GST_DEBUG_OBJECT (pool, "acquire");
1632 /* If this is being called to resurrect a lost buffer */
1633 if (params && params->flags & GST_V4L2_BUFFER_POOL_ACQUIRE_FLAG_RESURRECT) {
1634 ret = pclass->acquire_buffer (bpool, buffer, params);
1638 switch (obj->type) {
1639 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1640 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1641 /* capture, This function should return a buffer with new captured data */
1642 switch (obj->mode) {
1643 case GST_V4L2_IO_RW:
1645 /* take empty buffer from the pool */
1646 ret = pclass->acquire_buffer (bpool, buffer, params);
1649 case GST_V4L2_IO_DMABUF:
1650 case GST_V4L2_IO_MMAP:
1651 case GST_V4L2_IO_USERPTR:
1652 case GST_V4L2_IO_DMABUF_IMPORT:
1654 /* just dequeue a buffer, we basically use the queue of v4l2 as the
1655 * storage for our buffers. This function does poll first so we can
1656 * interrupt it fine. */
1657 ret = gst_v4l2_buffer_pool_dqbuf (pool, buffer, NULL, TRUE);
1661 ret = GST_FLOW_ERROR;
1662 g_assert_not_reached ();
1668 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1669 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1670 /* playback, This function should return an empty buffer */
1671 switch (obj->mode) {
1672 case GST_V4L2_IO_RW:
1673 /* get an empty buffer */
1674 ret = pclass->acquire_buffer (bpool, buffer, params);
1677 case GST_V4L2_IO_MMAP:
1678 case GST_V4L2_IO_DMABUF:
1679 case GST_V4L2_IO_USERPTR:
1680 case GST_V4L2_IO_DMABUF_IMPORT:
1681 /* get a free unqueued buffer */
1682 ret = pclass->acquire_buffer (bpool, buffer, params);
1686 ret = GST_FLOW_ERROR;
1687 g_assert_not_reached ();
1693 ret = GST_FLOW_ERROR;
1694 g_assert_not_reached ();
1698 /* Mark buffer as outstanding */
1699 if (ret == GST_FLOW_OK) {
1700 GstV4l2MemoryGroup *group;
1701 if (gst_v4l2_is_buffer_valid (*buffer, &group)) {
1702 GST_LOG_OBJECT (pool, "mark buffer %u outstanding", group->buffer.index);
1703 g_atomic_int_or (&pool->buffer_state[group->buffer.index],
1704 BUFFER_STATE_OUTSTANDING);
1712 * Completes a release buffer operation
1714 * Before calling this function:
1715 * - The buffer state (if applicable) must have already been updated.
1716 * - The buffer must not be outstanding.
1717 * - The "queued" argument contains whether the buffer is currently queued.
1720 gst_v4l2_buffer_pool_complete_release_buffer (GstBufferPool * bpool,
1721 GstBuffer * buffer, gboolean queued)
1723 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1724 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
1725 GstV4l2Object *obj = pool->obj;
1727 GST_DEBUG_OBJECT (pool, "complete release buffer %p (queued = %s)", buffer,
1728 queued ? "yes" : "no");
1730 /* If the buffer's pool has been orphaned, dispose of it so that
1731 * the pool resources can be freed */
1732 if (pool->orphaned) {
1733 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1734 pclass->release_buffer (bpool, buffer);
1738 switch (obj->type) {
1739 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1740 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1741 /* capture, put the buffer back in the queue so that we can refill it
1744 GST_WARNING_OBJECT (pool,
1745 "capture buffer %p was release while still queued", buffer);
1748 switch (obj->mode) {
1749 case GST_V4L2_IO_RW:
1750 /* release back in the pool */
1751 pclass->release_buffer (bpool, buffer);
1754 case GST_V4L2_IO_DMABUF:
1755 case GST_V4L2_IO_MMAP:
1756 case GST_V4L2_IO_USERPTR:
1757 case GST_V4L2_IO_DMABUF_IMPORT:
1759 GstV4l2MemoryGroup *group;
1760 if (gst_v4l2_is_buffer_valid (buffer, &group)) {
1761 GstFlowReturn ret = GST_FLOW_OK;
1763 gst_v4l2_allocator_reset_group (pool->vallocator, group);
1764 /* queue back in the device */
1765 if (pool->other_pool)
1766 ret = gst_v4l2_buffer_pool_prepare_buffer (pool, buffer, NULL);
1767 if (ret != GST_FLOW_OK ||
1768 gst_v4l2_buffer_pool_qbuf (pool, buffer, group,
1769 NULL) != GST_FLOW_OK)
1770 pclass->release_buffer (bpool, buffer);
1772 /* Simply release invalid/modified buffer, the allocator will
1773 * give it back later */
1774 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1775 pclass->release_buffer (bpool, buffer);
1780 g_assert_not_reached ();
1785 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1786 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1787 switch (obj->mode) {
1788 case GST_V4L2_IO_RW:
1789 /* release back in the pool */
1790 pclass->release_buffer (bpool, buffer);
1793 case GST_V4L2_IO_MMAP:
1794 case GST_V4L2_IO_DMABUF:
1795 case GST_V4L2_IO_USERPTR:
1796 case GST_V4L2_IO_DMABUF_IMPORT:
1798 GstV4l2MemoryGroup *group;
1801 if (!gst_v4l2_is_buffer_valid (buffer, &group)) {
1802 /* Simply release invalid/modified buffer, the allocator will
1803 * give it back later */
1804 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
1805 pclass->release_buffer (bpool, buffer);
1809 index = group->buffer.index;
1812 GST_LOG_OBJECT (pool, "buffer %u not queued, putting on free list",
1815 /* Remove qdata, this will unmap any map data in userptr */
1816 gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
1817 GST_V4L2_IMPORT_QUARK, NULL, NULL);
1819 /* reset to default size */
1820 gst_v4l2_allocator_reset_group (pool->vallocator, group);
1822 /* playback, put the buffer back in the queue to refill later. */
1823 pclass->release_buffer (bpool, buffer);
1825 /* the buffer is queued in the device but maybe not played yet. We just
1826 * leave it there and not make it available for future calls to acquire
1827 * for now. The buffer will be dequeued and reused later. */
1828 GST_LOG_OBJECT (pool, "buffer %u is queued", index);
1834 g_assert_not_reached ();
1840 g_assert_not_reached ();
1846 gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
1848 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
1849 GstV4l2MemoryGroup *group;
1850 gboolean queued = FALSE;
1852 if (gst_v4l2_is_buffer_valid (buffer, &group)) {
1853 gint old_buffer_state =
1854 g_atomic_int_and (&pool->buffer_state[group->buffer.index],
1855 ~BUFFER_STATE_OUTSTANDING);
1856 queued = (old_buffer_state & BUFFER_STATE_QUEUED) != 0;
1857 GST_LOG_OBJECT (pool, "mark buffer %u not outstanding",
1858 group->buffer.index);
1861 gst_v4l2_buffer_pool_complete_release_buffer (bpool, buffer, queued);
1865 gst_v4l2_buffer_pool_dispose (GObject * object)
1867 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1869 if (pool->vallocator)
1870 gst_object_unref (pool->vallocator);
1871 pool->vallocator = NULL;
1873 if (pool->allocator)
1874 gst_object_unref (pool->allocator);
1875 pool->allocator = NULL;
1877 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1878 g_cond_clear (&pool->buffer_cond);
1879 g_mutex_clear (&pool->buffer_lock);
1881 if (pool->tallocator)
1882 gst_object_unref (pool->tallocator);
1883 pool->tallocator = NULL;
1884 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1885 if (pool->other_pool)
1886 gst_object_unref (pool->other_pool);
1887 pool->other_pool = NULL;
1889 G_OBJECT_CLASS (parent_class)->dispose (object);
1893 gst_v4l2_buffer_pool_finalize (GObject * object)
1895 GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (object);
1897 if (pool->video_fd >= 0)
1898 pool->obj->close (pool->video_fd);
1900 /* This can't be done in dispose method because we must not set pointer
1901 * to NULL as it is part of the v4l2object and dispose could be called
1903 gst_object_unref (pool->obj->element);
1905 g_cond_clear (&pool->empty_cond);
1907 /* FIXME have we done enough here ? */
1909 G_OBJECT_CLASS (parent_class)->finalize (object);
1913 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
1915 g_cond_init (&pool->empty_cond);
1917 pool->orphaned = FALSE;
1918 for (gint i = 0; i < VIDEO_MAX_FRAME; i++)
1919 g_atomic_int_set (&pool->buffer_state[i], BUFFER_STATE_FREE);
1923 gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
1925 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1926 GstBufferPoolClass *bufferpool_class = GST_BUFFER_POOL_CLASS (klass);
1928 object_class->dispose = gst_v4l2_buffer_pool_dispose;
1929 object_class->finalize = gst_v4l2_buffer_pool_finalize;
1931 bufferpool_class->start = gst_v4l2_buffer_pool_start;
1932 bufferpool_class->stop = gst_v4l2_buffer_pool_stop;
1933 bufferpool_class->set_config = gst_v4l2_buffer_pool_set_config;
1934 bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
1935 bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
1936 bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
1937 bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
1938 bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
1940 GST_DEBUG_CATEGORY_INIT (v4l2bufferpool_debug, "v4l2bufferpool", 0,
1941 "V4L2 Buffer Pool");
1942 GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
1946 * gst_v4l2_buffer_pool_new:
1947 * @obj: the v4l2 object owning the pool
1949 * Construct a new buffer pool.
1951 * Returns: the new pool, use gst_object_unref() to free resources
1954 gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
1956 GstV4l2BufferPool *pool;
1957 GstStructure *config;
1958 gchar *name, *parent_name;
1961 fd = obj->dup (obj->video_fd);
1965 /* setting a significant unique name */
1966 parent_name = gst_object_get_name (GST_OBJECT (obj->element));
1967 name = g_strdup_printf ("%s:pool%u:%s",
1968 parent_name, obj->pool_seq++,
1969 V4L2_TYPE_IS_OUTPUT (obj->type) ? "sink" : "src");
1970 g_free (parent_name);
1972 pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL,
1973 "name", name, NULL);
1974 g_object_ref_sink (pool);
1977 pool->video_fd = fd;
1980 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
1981 pool->tallocator = gst_tizen_allocator_new ();
1982 if (pool->tallocator == NULL)
1983 goto allocator_failed;
1985 g_mutex_init (&pool->buffer_lock);
1986 g_cond_init (&pool->buffer_cond);
1988 pool->tbm_output_dump = obj->tbm_output_dump;
1990 GST_INFO ("tbm output dump [%d]", pool->tbm_output_dump);
1991 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
1992 pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj);
1993 if (pool->vallocator == NULL)
1994 goto allocator_failed;
1996 gst_object_ref (obj->element);
1998 config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
1999 gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
2000 /* This will simply set a default config, but will not configure the pool
2001 * because min and max are not valid */
2002 gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
2004 return GST_BUFFER_POOL (pool);
2009 GST_ERROR ("failed to dup fd %d (%s)", errno, g_strerror (errno));
2014 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
2015 if (pool->tallocator) {
2016 gst_object_unref (pool->tallocator);
2017 pool->tallocator = NULL;
2019 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
2020 GST_ERROR_OBJECT (pool, "Failed to create V4L2 allocator");
2021 gst_object_unref (pool);
2026 static GstFlowReturn
2027 gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
2030 GstV4l2Object *obj = pool->obj;
2035 toread = obj->info.size;
2037 GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);
2039 gst_buffer_map (buf, &map, GST_MAP_WRITE);
2042 if ((res = gst_v4l2_buffer_pool_poll (pool, TRUE)) != GST_FLOW_OK)
2045 amount = obj->read (obj->video_fd, map.data, toread);
2047 if (amount == toread) {
2049 } else if (amount == -1) {
2050 if (errno == EAGAIN || errno == EINTR) {
2055 /* short reads can happen if a signal interrupts the read */
2060 GST_LOG_OBJECT (pool, "read %d bytes", amount);
2061 gst_buffer_unmap (buf, &map);
2062 gst_buffer_resize (buf, 0, amount);
2069 GST_DEBUG ("poll error %s", gst_flow_get_name (res));
2074 GST_ELEMENT_ERROR (obj->element, RESOURCE, READ,
2075 (_("Error reading %d bytes from device '%s'."),
2076 toread, obj->videodev), GST_ERROR_SYSTEM);
2077 res = GST_FLOW_ERROR;
2082 gst_buffer_unmap (buf, &map);
2083 gst_buffer_resize (buf, 0, 0);
2089 * gst_v4l2_buffer_pool_process:
2090 * @bpool: a #GstBufferPool
2091 * @buf: a #GstBuffer, maybe be replaced
2092 * @frame_number: 32 bit frame number or %NULL
2094 * Process @buf in @bpool. For capture devices, this functions fills @buf with
2095 * data from the device. For output devices, this functions send the contents of
2096 * @buf to the device for playback.
2098 * If non-%NULL and an output device, @frame_number is stored inside the timestamp for output devices and read
2099 * back from the timestamp for capture devices.
2101 * Returns: %GST_FLOW_OK on success.
2104 gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf,
2105 guint32 * frame_number)
2107 GstFlowReturn ret = GST_FLOW_OK;
2108 GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool);
2109 GstV4l2Object *obj = pool->obj;
2111 GST_DEBUG_OBJECT (pool, "process buffer %p", *buf);
2113 if (GST_BUFFER_POOL_IS_FLUSHING (pool))
2114 return GST_FLOW_FLUSHING;
2116 switch (obj->type) {
2117 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2118 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
2120 switch (obj->mode) {
2121 case GST_V4L2_IO_RW:
2122 /* capture into the buffer */
2123 ret = gst_v4l2_do_read (pool, *buf);
2126 case GST_V4L2_IO_MMAP:
2127 case GST_V4L2_IO_DMABUF:
2131 if ((*buf)->pool == bpool) {
2133 gsize size = gst_buffer_get_size (*buf);
2135 /* Legacy M2M devices return empty buffer when drained */
2136 if (size == 0 && GST_V4L2_IS_M2M (obj->device_caps)) {
2137 gst_v4l2_buffer_pool_resize_buffer (bpool, *buf);
2141 if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) !=
2142 GST_VIDEO_FORMAT_ENCODED && size < pool->size)
2143 goto buffer_truncated;
2145 num_queued = g_atomic_int_get (&pool->num_queued);
2146 GST_TRACE_OBJECT (pool, "Only %i buffer left in the capture queue.",
2149 /* If we have no more buffer, and can allocate it time to do so */
2150 if (num_queued == 0) {
2151 if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
2152 GST_DEBUG_OBJECT (pool, "Resurrect for empty queue");
2153 ret = gst_v4l2_buffer_pool_resurrect_buffer (pool);
2154 if (ret == GST_FLOW_OK || ret == GST_FLOW_FLUSHING)
2159 /* start copying buffers when we are running low on buffers */
2160 if (num_queued < pool->copy_threshold) {
2163 if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
2164 GST_DEBUG_OBJECT (pool, "Resurrect for threshold");
2165 ret = gst_v4l2_buffer_pool_resurrect_buffer (pool);
2166 if (ret == GST_FLOW_OK || ret == GST_FLOW_FLUSHING)
2170 /* copy the buffer */
2171 copy = gst_buffer_copy_region (*buf,
2172 GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1);
2173 GST_LOG_OBJECT (pool, "copy buffer %p->%p", *buf, copy);
2175 /* and requeue so that we can continue capturing */
2176 gst_buffer_unref (*buf);
2181 /* nothing, data was inside the buffer when we did _acquire() */
2185 /* buffer not from our pool, grab a frame and copy it into the target */
2186 if ((ret = gst_v4l2_buffer_pool_dqbuf (pool, &tmp, NULL, TRUE))
2190 /* An empty buffer on capture indicates the end of stream */
2191 if (gst_buffer_get_size (tmp) == 0) {
2192 gst_v4l2_buffer_pool_complete_release_buffer (bpool, tmp, FALSE);
2194 /* Legacy M2M devices return empty buffer when drained */
2195 if (GST_V4L2_IS_M2M (obj->device_caps)) {
2196 gst_v4l2_buffer_pool_resize_buffer (bpool, *buf);
2200 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
2201 if (pool->obj->tbm_output && pool->obj->mode == GST_V4L2_IO_DMABUF) {
2202 gst_buffer_unref (*buf);
2205 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
2206 ret = gst_v4l2_buffer_pool_copy_buffer (pool, *buf, tmp);
2208 /* an queue the buffer again after the copy */
2209 gst_v4l2_buffer_pool_complete_release_buffer (bpool, tmp, FALSE);
2210 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
2212 #endif /* TIZEN_FEATURE_V4L2_TBM_SUPPORT */
2213 if (ret != GST_FLOW_OK)
2218 case GST_V4L2_IO_USERPTR:
2220 struct UserPtrData *data;
2223 /* Replace our buffer with downstream allocated buffer */
2224 data = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2225 GST_V4L2_IMPORT_QUARK);
2226 tmp = gst_buffer_ref (data->buffer);
2227 _unmap_userptr_frame (data);
2229 /* Now tmp is writable, copy the flags and timestamp */
2230 gst_buffer_copy_into (tmp, *buf,
2231 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2233 gst_buffer_replace (buf, tmp);
2234 gst_buffer_unref (tmp);
2238 case GST_V4L2_IO_DMABUF_IMPORT:
2242 /* Replace our buffer with downstream allocated buffer */
2243 tmp = gst_mini_object_steal_qdata (GST_MINI_OBJECT (*buf),
2244 GST_V4L2_IMPORT_QUARK);
2246 gst_buffer_copy_into (tmp, *buf,
2247 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
2249 gst_buffer_replace (buf, tmp);
2250 gst_buffer_unref (tmp);
2255 g_assert_not_reached ();
2260 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2261 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2263 switch (obj->mode) {
2264 case GST_V4L2_IO_RW:
2265 /* FIXME, do write() */
2266 GST_WARNING_OBJECT (pool, "implement write()");
2269 case GST_V4L2_IO_USERPTR:
2270 case GST_V4L2_IO_DMABUF_IMPORT:
2271 case GST_V4L2_IO_DMABUF:
2272 case GST_V4L2_IO_MMAP:
2274 GstBuffer *to_queue = NULL;
2276 GstV4l2MemoryGroup *group;
2278 gboolean outstanding;
2280 if ((*buf)->pool != bpool)
2283 if (!gst_v4l2_is_buffer_valid (*buf, &group))
2286 index = group->buffer.index;
2288 GST_LOG_OBJECT (pool, "processing buffer %i from our pool", index);
2290 if (g_atomic_int_get (&pool->buffer_state[index]) &
2291 BUFFER_STATE_QUEUED) {
2292 GST_LOG_OBJECT (pool, "buffer %i already queued, copying", index);
2296 /* we can queue directly */
2297 to_queue = gst_buffer_ref (*buf);
2300 if (to_queue == NULL) {
2301 GstBufferPoolAcquireParams params = { 0 };
2303 GST_LOG_OBJECT (pool, "alloc buffer from our pool");
2305 /* this can return EOS if all buffers are outstanding which would
2306 * be strange because we would expect the upstream element to have
2307 * allocated them and returned to us.. */
2308 params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
2309 ret = gst_buffer_pool_acquire_buffer (bpool, &to_queue, ¶ms);
2310 if (ret != GST_FLOW_OK)
2311 goto acquire_failed;
2313 ret = gst_v4l2_buffer_pool_prepare_buffer (pool, to_queue, *buf);
2314 if (ret != GST_FLOW_OK) {
2315 gst_buffer_unref (to_queue);
2316 goto prepare_failed;
2319 /* retrieve the group */
2320 gst_v4l2_is_buffer_valid (to_queue, &group);
2324 gst_v4l2_buffer_pool_qbuf (pool, to_queue, group,
2329 /* if we are not streaming yet (this is the first buffer, start
2331 if (!gst_v4l2_buffer_pool_streamon (pool)) {
2332 /* don't check return value because qbuf would have failed */
2333 gst_v4l2_is_buffer_valid (to_queue, &group);
2335 /* qbuf has stored to_queue buffer but we are not in
2336 * streaming state, so the flush logic won't be performed.
2337 * To avoid leaks, flush the allocator and restore the queued
2338 * buffer as non-queued */
2339 gst_v4l2_allocator_flush (pool->vallocator);
2341 pool->buffers[group->buffer.index] = NULL;
2342 g_atomic_int_and (&pool->buffer_state[group->buffer.index],
2343 ~BUFFER_STATE_QUEUED);
2345 gst_mini_object_set_qdata (GST_MINI_OBJECT (to_queue),
2346 GST_V4L2_IMPORT_QUARK, NULL, NULL);
2347 gst_buffer_unref (to_queue);
2348 g_atomic_int_add (&pool->num_queued, -1);
2352 /* Remove our ref, we will still hold this buffer in acquire as needed,
2353 * otherwise the pool will think it is outstanding and will refuse to stop. */
2354 gst_buffer_unref (to_queue);
2356 /* release as many buffer as possible */
2357 while (gst_v4l2_buffer_pool_dqbuf (pool, &buffer, &outstanding,
2358 FALSE) == GST_FLOW_OK) {
2360 gst_v4l2_buffer_pool_complete_release_buffer (bpool, buffer,
2364 if (g_atomic_int_get (&pool->num_queued) >= pool->min_latency) {
2365 /* all buffers are queued, try to dequeue one and release it back
2366 * into the pool so that _acquire can get to it again. */
2368 gst_v4l2_buffer_pool_dqbuf (pool, &buffer, &outstanding, TRUE);
2369 if (ret == GST_FLOW_OK && !outstanding)
2370 /* release the rendered buffer back into the pool. This wakes up any
2371 * thread waiting for a buffer in _acquire(). */
2372 gst_v4l2_buffer_pool_complete_release_buffer (bpool, buffer,
2378 g_assert_not_reached ();
2383 g_assert_not_reached ();
2392 GST_ERROR_OBJECT (pool, "failed to copy buffer");
2397 GST_WARNING_OBJECT (pool,
2398 "Dropping truncated buffer, this is likely a driver bug.");
2399 gst_buffer_unref (*buf);
2401 return GST_V4L2_FLOW_CORRUPTED_BUFFER;
2405 GST_DEBUG_OBJECT (pool, "end of sequence reached");
2406 gst_buffer_unref (*buf);
2408 return GST_V4L2_FLOW_LAST_BUFFER;
2412 if (ret == GST_FLOW_FLUSHING)
2413 GST_DEBUG_OBJECT (pool, "flushing");
2415 GST_WARNING_OBJECT (pool, "failed to acquire a buffer: %s",
2416 gst_flow_get_name (ret));
2421 GST_ERROR_OBJECT (pool, "failed to prepare data");
2426 GST_ERROR_OBJECT (pool, "failed to queue buffer");
2431 GST_ERROR_OBJECT (pool, "failed to start streaming");
2432 return GST_FLOW_ERROR;
2437 gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
2438 GstBufferPool * other_pool)
2440 g_return_if_fail (!gst_buffer_pool_is_active (GST_BUFFER_POOL (pool)));
2442 if (pool->other_pool)
2443 gst_object_unref (pool->other_pool);
2444 pool->other_pool = gst_object_ref (other_pool);
2448 gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool, gboolean copy)
2450 GST_OBJECT_LOCK (pool);
2451 pool->enable_copy_threshold = copy;
2452 GST_OBJECT_UNLOCK (pool);
2455 static GstFlowReturn
2456 gst_v4l2_buffer_pool_flush_events (GstV4l2Object * v4l2object)
2458 GstFlowReturn ret = GST_FLOW_OK;
2459 gboolean event_found;
2461 /* FIXME simplify this when we drop legacy support for driver without poll()
2462 * support. When we do, we can switch the video_fd to non blocking, and just
2463 * pop the events directly. */
2466 struct v4l2_event event = { 0, };
2469 event_found = FALSE;
2471 gst_poll_set_flushing (v4l2object->poll, FALSE);
2474 /* GstPoll don't have 0ns timeout, but 1 will do */
2475 poll_ret = gst_poll_wait (v4l2object->poll, 1);
2476 } while (poll_ret == EAGAIN || poll_ret == EINTR);
2478 if (gst_poll_fd_has_pri (v4l2object->poll, &v4l2object->pollfd)) {
2479 if (!gst_v4l2_dequeue_event (v4l2object, &event))
2480 return GST_FLOW_ERROR;
2484 if (event.type == V4L2_EVENT_SOURCE_CHANGE &&
2485 (event.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION)) {
2486 GST_DEBUG_OBJECT (v4l2object->dbg_obj,
2487 "Can't streamon capture as the resolution have changed.");
2488 ret = GST_V4L2_FLOW_RESOLUTION_CHANGE;
2491 } while (event_found);
2497 gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
2499 GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
2500 GstV4l2BufferPool *pool;
2501 GstFlowReturn ret = GST_FLOW_OK;
2504 return GST_FLOW_ERROR;
2506 pool = GST_V4L2_BUFFER_POOL (bpool);
2508 GST_OBJECT_LOCK (pool);
2509 #ifdef TIZEN_FEATURE_V4L2_TBM_SUPPORT
2510 gst_v4l2_buffer_pool_streamoff (pool, FALSE);
2512 gst_v4l2_buffer_pool_streamoff (pool);
2514 GST_OBJECT_UNLOCK (pool);
2516 if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) {
2517 ret = gst_v4l2_buffer_pool_flush_events (v4l2object);
2519 /* If the format haven't change, avoid reallocation to go back to
2521 if (ret == GST_FLOW_OK)
2522 ret = gst_v4l2_buffer_pool_streamon (pool);
2525 gst_object_unref (bpool);
2530 * gst_v4l2_buffer_pool_enable_resolution_change:
2531 * @pool: a #GstBufferPool
2533 * When this is called, the pool will subscribe to the
2534 * %V4L2_EVENT_SOURCE_CHANGE. Upon receiving this event, it will notify
2535 * the element acquiring buffer with the special flow return
2536 * %GST_V4L2_FLOW_RESOLUTION_CHANGE.
2539 gst_v4l2_buffer_pool_enable_resolution_change (GstV4l2BufferPool * pool)
2541 gst_v4l2_object_subscribe_event (pool->obj, V4L2_EVENT_SOURCE_CHANGE);