/** * gst_buffer_pool_set_config: * @pool: a #GstBufferPool * @config: (transfer full): a #GstStructure * * Set the configuration of the pool. The pool must be inactive and all buffers * allocated form this pool must be returned or else this function will do * nothing and return FALSE. * * @config is a #GstStructure that contains the configuration parameters for * the pool. A default and mandatory set of parameters can be configured with * gst_buffer_pool_config_set_params(), gst_buffer_pool_config_set_allocator() * and gst_buffer_pool_config_add_option(). * * If the parameters in @config can not be set exactly, this function returns * FALSE and will try to update as much state as possible. The new state can * then be retrieved and refined with gst_buffer_pool_get_config(). * * This function takes ownership of @config. * * Returns: TRUE when the configuration could be set. */ gboolean gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { gboolean result; GstBufferPoolClass *pclass; GstBufferPoolPrivate *priv; g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE); g_return_val_if_fail (config != NULL, FALSE); priv = pool->priv; GST_BUFFER_POOL_LOCK (pool); /* can't change the settings when active */ if (priv->active) goto was_active; /* we can't change when outstanding buffers */ if (g_atomic_int_get (&priv->outstanding) != 0) goto have_outstanding; pclass = GST_BUFFER_POOL_GET_CLASS (pool); /* set the new config */ if (G_LIKELY (pclass->set_config)) result = pclass->set_config (pool, config); else result = FALSE; if (result) { if (priv->config) gst_structure_free (priv->config); priv->config = config; /* now we are configured */ priv->configured = TRUE; } else { gst_structure_free (config); } GST_BUFFER_POOL_UNLOCK (pool); return result; /* ERRORS */ was_active: { gst_structure_free (config); GST_WARNING_OBJECT (pool, "can't change config, we are active"); GST_BUFFER_POOL_UNLOCK (pool); return FALSE; } have_outstanding: { gst_structure_free (config); GST_WARNING_OBJECT (pool, "can't change config, have outstanding buffers"); GST_BUFFER_POOL_UNLOCK (pool); return FALSE; } }
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; } }
/** * gst_buffer_pool_set_config: * @pool: a #GstBufferPool * @config: (transfer full): a #GstStructure * * Set the configuration of the pool. If the pool is already configured, and * the configuration haven't change, this function will return %TRUE. If the * pool is active, this method will return %FALSE and active configuration * will remain. Buffers allocated form this pool must be returned or else this * function will do nothing and return %FALSE. * * @config is a #GstStructure that contains the configuration parameters for * the pool. A default and mandatory set of parameters can be configured with * gst_buffer_pool_config_set_params(), gst_buffer_pool_config_set_allocator() * and gst_buffer_pool_config_add_option(). * * If the parameters in @config can not be set exactly, this function returns * %FALSE and will try to update as much state as possible. The new state can * then be retrieved and refined with gst_buffer_pool_get_config(). * * This function takes ownership of @config. * * Returns: %TRUE when the configuration could be set. */ gboolean gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config) { gboolean result; GstBufferPoolClass *pclass; GstBufferPoolPrivate *priv; g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE); g_return_val_if_fail (config != NULL, FALSE); priv = pool->priv; GST_BUFFER_POOL_LOCK (pool); /* nothing to do if config is unchanged */ if (priv->configured && gst_structure_is_equal (config, priv->config)) goto config_unchanged; /* can't change the settings when active */ if (priv->active) goto was_active; /* we can't change when outstanding buffers */ if (g_atomic_int_get (&priv->outstanding) != 0) goto have_outstanding; pclass = GST_BUFFER_POOL_GET_CLASS (pool); /* set the new config */ if (G_LIKELY (pclass->set_config)) result = pclass->set_config (pool, config); else result = FALSE; /* save the config regardless of the result so user can read back the * modified config and evaluate if the changes are acceptable */ if (priv->config) gst_structure_free (priv->config); priv->config = config; if (result) { /* now we are configured */ priv->configured = TRUE; } GST_BUFFER_POOL_UNLOCK (pool); return result; config_unchanged: { gst_structure_free (config); GST_BUFFER_POOL_UNLOCK (pool); return TRUE; } /* ERRORS */ was_active: { gst_structure_free (config); GST_INFO_OBJECT (pool, "can't change config, we are active"); GST_BUFFER_POOL_UNLOCK (pool); return FALSE; } have_outstanding: { gst_structure_free (config); GST_WARNING_OBJECT (pool, "can't change config, have outstanding buffers"); GST_BUFFER_POOL_UNLOCK (pool); return FALSE; } }