/* the default implementation for preallocating the buffers
 * in the pool */
static gboolean
default_start (GstBufferPool * pool)
{
  guint i;
  GstBufferPoolPrivate *priv = pool->priv;
  GstBufferPoolClass *pclass;

  pclass = GST_BUFFER_POOL_GET_CLASS (pool);

  /* we need to prealloc buffers */
  for (i = 0; i < priv->min_buffers; i++) {
    GstBuffer *buffer;

    if (do_alloc_buffer (pool, &buffer, NULL) != GST_FLOW_OK)
      goto alloc_failed;

    /* release to the queue, we call the vmethod directly, we don't need to do
     * the other refcount handling right now. */
    if (G_LIKELY (pclass->release_buffer))
      pclass->release_buffer (pool, buffer);
  }
  return TRUE;

  /* ERRORS */
alloc_failed:
  {
    GST_WARNING_OBJECT (pool, "failed to allocate buffer");
    return FALSE;
  }
}
Beispiel #2
0
static GstFlowReturn
default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
    GstBufferPoolAcquireParams * params)
{
  GstFlowReturn result;
  GstBufferPoolPrivate *priv = pool->priv;

  while (TRUE) {
    if (G_UNLIKELY (GST_BUFFER_POOL_IS_FLUSHING (pool)))
      goto flushing;

    /* try to get a buffer from the queue */
    *buffer = gst_atomic_queue_pop (priv->queue);
    if (G_LIKELY (*buffer)) {
      gst_poll_read_control (priv->poll);
      result = GST_FLOW_OK;
      GST_LOG_OBJECT (pool, "acquired buffer %p", *buffer);
      break;
    }

    /* no buffer, try to allocate some more */
    GST_LOG_OBJECT (pool, "no buffer, trying to allocate");
    result = do_alloc_buffer (pool, buffer, NULL);
    if (G_LIKELY (result == GST_FLOW_OK))
      /* we have a buffer, return it */
      break;

    if (G_UNLIKELY (result != GST_FLOW_EOS))
      /* something went wrong, return error */
      break;

    /* check if we need to wait */
    if (params && (params->flags & GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT)) {
      GST_LOG_OBJECT (pool, "no more buffers");
      break;
    }

    /* now we release the control socket, we wait for a buffer release or
     * flushing */
    gst_poll_read_control (pool->priv->poll);
    GST_LOG_OBJECT (pool, "waiting for free buffers or flushing");
    gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE);
    gst_poll_write_control (pool->priv->poll);
  }

  return result;

  /* ERRORS */
flushing:
  {
    GST_DEBUG_OBJECT (pool, "we are flushing");
    return GST_FLOW_FLUSHING;
  }
}
static GstFlowReturn
default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
    GstBufferPoolAcquireParams * params)
{
  GstFlowReturn result;
  GstBufferPoolPrivate *priv = pool->priv;

  while (TRUE) {
    if (G_UNLIKELY (GST_BUFFER_POOL_IS_FLUSHING (pool)))
      goto flushing;

    /* try to get a buffer from the queue */
    *buffer = gst_atomic_queue_pop (priv->queue);
    if (G_LIKELY (*buffer)) {
      while (!gst_poll_read_control (priv->poll)) {
        if (errno == EWOULDBLOCK) {
          /* We put the buffer into the queue but did not finish writing control
           * yet, let's wait a bit and retry */
          g_thread_yield ();
          continue;
        } else {
          /* Critical error but GstPoll already complained */
          break;
        }
      }
      result = GST_FLOW_OK;
      GST_LOG_OBJECT (pool, "acquired buffer %p", *buffer);
      break;
    }

    /* no buffer, try to allocate some more */
    GST_LOG_OBJECT (pool, "no buffer, trying to allocate");
    result = do_alloc_buffer (pool, buffer, params);
    if (G_LIKELY (result == GST_FLOW_OK))
      /* we have a buffer, return it */
      break;

    if (G_UNLIKELY (result != GST_FLOW_EOS))
      /* something went wrong, return error */
      break;

    /* check if we need to wait */
    if (params && (params->flags & GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT)) {
      GST_LOG_OBJECT (pool, "no more buffers");
      break;
    }

    /* now we release the control socket, we wait for a buffer release or
     * flushing */
    if (!gst_poll_read_control (pool->priv->poll)) {
      if (errno == EWOULDBLOCK) {
        /* This means that we have two threads trying to allocate buffers
         * already, and the other one already got the wait token. This
         * means that we only have to wait for the poll now and not write the
         * token afterwards: we will be woken up once the other thread is
         * woken up and that one will write the wait token it removed */
        GST_LOG_OBJECT (pool, "waiting for free buffers or flushing");
        gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE);
      } else {
        /* This is a critical error, GstPoll already gave a warning */
        result = GST_FLOW_ERROR;
        break;
      }
    } else {
      /* We're the first thread waiting, we got the wait token and have to
       * write it again later 
       * OR
       * We're a second thread and just consumed the flush token and block all
       * other threads, in which case we must not wait and give it back
       * immediately */
      if (!GST_BUFFER_POOL_IS_FLUSHING (pool)) {
        GST_LOG_OBJECT (pool, "waiting for free buffers or flushing");
        gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE);
      }
      gst_poll_write_control (pool->priv->poll);
    }
  }

  return result;

  /* ERRORS */
flushing:
  {
    GST_DEBUG_OBJECT (pool, "we are flushing");
    return GST_FLOW_FLUSHING;
  }
}