/* must be called with the lock */ static gboolean do_start (GstBufferPool * pool) { GstBufferPoolPrivate *priv = pool->priv; if (!priv->started) { GstBufferPoolClass *pclass; pclass = GST_BUFFER_POOL_GET_CLASS (pool); GST_LOG_OBJECT (pool, "starting"); /* start the pool, subclasses should allocate buffers and put them * in the queue */ if (G_LIKELY (pclass->start)) { if (!pclass->start (pool)) return FALSE; } priv->started = TRUE; } return TRUE; }
static gboolean gst_v4l2_buffer_pool_start (GstBufferPool * bpool) { GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool); GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class); GstV4l2Object *obj = pool->obj; GstStructure *config; GstCaps *caps; guint size, min_buffers, max_buffers; guint max_latency, min_latency, copy_threshold = 0; gboolean can_allocate = FALSE; GST_DEBUG_OBJECT (pool, "activating pool"); config = gst_buffer_pool_get_config (bpool); if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) goto wrong_config; min_latency = MAX (GST_V4L2_MIN_BUFFERS, obj->min_buffers); switch (obj->mode) { case GST_V4L2_IO_RW: can_allocate = TRUE; break; case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_MMAP: { guint count; can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP); /* first, lets request buffers, and see how many we can get: */ GST_DEBUG_OBJECT (pool, "requesting %d MMAP buffers", min_buffers); count = gst_v4l2_allocator_start (pool->vallocator, min_buffers, V4L2_MEMORY_MMAP); if (count < GST_V4L2_MIN_BUFFERS) { min_buffers = count; goto no_buffers; } /* V4L2 buffer pool are often very limited in the amount of buffers it * can offer. The copy_threshold will workaround this limitation by * falling back to copy if the pipeline needed more buffers. This also * prevent having to do REQBUFS(N)/REQBUFS(0) everytime configure is * called. */ if (count != min_buffers) { GST_WARNING_OBJECT (pool, "using %u buffers instead of %u", count, min_buffers); min_buffers = count; copy_threshold = min_latency; /* The initial minimum could be provide either by GstBufferPool or * driver needs. */ min_buffers = count; } break; } case GST_V4L2_IO_USERPTR: { guint count; can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, USERPTR); GST_DEBUG_OBJECT (pool, "requesting %d USERPTR buffers", min_buffers); count = gst_v4l2_allocator_start (pool->vallocator, min_buffers, V4L2_MEMORY_USERPTR); /* There is no rational to not get what we asked */ if (count < min_buffers) { min_buffers = count; goto no_buffers; } min_buffers = count; break; } case GST_V4L2_IO_DMABUF_IMPORT: { guint count; can_allocate = GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, DMABUF); GST_DEBUG_OBJECT (pool, "requesting %d DMABUF buffers", min_buffers); count = gst_v4l2_allocator_start (pool->vallocator, min_buffers, V4L2_MEMORY_DMABUF); /* There is no rational to not get what we asked */ if (count < min_buffers) { min_buffers = count; goto no_buffers; } min_buffers = count; break; } default: min_buffers = 0; copy_threshold = 0; g_assert_not_reached (); break; } if (can_allocate) max_latency = max_buffers; else max_latency = min_buffers; pool->size = size; pool->copy_threshold = copy_threshold; pool->max_latency = max_latency; pool->min_latency = min_latency; pool->num_queued = 0; if (max_buffers < min_buffers) max_buffers = min_buffers; gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); pclass->set_config (bpool, config); gst_structure_free (config); if (pool->other_pool) if (!gst_buffer_pool_set_active (pool->other_pool, TRUE)) goto other_pool_failed; /* now, allocate the buffers: */ if (!pclass->start (bpool)) goto start_failed; if (!V4L2_TYPE_IS_OUTPUT (obj->type)) pool->group_released_handler = g_signal_connect_swapped (pool->vallocator, "group-released", G_CALLBACK (gst_v4l2_buffer_pool_group_released), pool); return TRUE; /* ERRORS */ wrong_config: { GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config); gst_structure_free (config); return FALSE; } no_buffers: { GST_ERROR_OBJECT (pool, "we received %d buffer from device '%s', we want at least %d", min_buffers, obj->videodev, GST_V4L2_MIN_BUFFERS); gst_structure_free (config); return FALSE; } start_failed: { GST_ERROR_OBJECT (pool, "failed to start streaming"); return FALSE; } other_pool_failed: { GST_ERROR_OBJECT (pool, "failed to active the other pool %" GST_PTR_FORMAT, pool->other_pool); return FALSE; } }