/**
 * 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;
  }
}
예제 #2
0
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;
  }
}