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