Beispiel #1
0
/**
 * gst_adapter_take:
 * @adapter: a #GstAdapter
 * @nbytes: the number of bytes to take
 *
 * Returns a freshly allocated buffer containing the first @nbytes bytes of the
 * @adapter. The returned bytes will be flushed from the adapter.
 *
 * Caller owns returned value. g_free after usage.
 *
 * Returns: oven-fresh hot data, or #NULL if @nbytes bytes are not available
 */
guint8 *
gst_adapter_take (GstAdapter * adapter, guint nbytes)
{
  guint8 *data;

  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
  g_return_val_if_fail (nbytes > 0, NULL);

  /* we don't have enough data, return NULL. This is unlikely
   * as one usually does an _available() first instead of peeking a
   * random size. */
  if (G_UNLIKELY (nbytes > adapter->size))
    return NULL;

  /* we have enough assembled data, take from there */
  if (adapter->assembled_len >= nbytes) {
    GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
    data = adapter->assembled_data;
    /* allocate new data, assembled_len will be set to 0 in the flush below */
    adapter->assembled_data = g_malloc (adapter->assembled_size);
  } else {
    /* we need to allocate and copy. We could potentially copy bytes from the
     * assembled data before doing the copy_into */
    GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
    data = g_malloc (nbytes);
    copy_into_unchecked (adapter, data, adapter->skip, nbytes);
  }

  gst_adapter_flush_unchecked (adapter, nbytes);

  return data;
}
Beispiel #2
0
/**
 * gst_adapter_take_buffer:
 * @adapter: a #GstAdapter
 * @nbytes: the number of bytes to take
 *
 * Returns a #GstBuffer containing the first @nbytes bytes of the
 * @adapter. The returned bytes will be flushed from the adapter.
 * This function is potentially more performant than gst_adapter_take()
 * since it can reuse the memory in pushed buffers by subbuffering
 * or merging.
 *
 * Caller owns returned value. gst_buffer_unref() after usage.
 *
 * Since: 0.10.6
 *
 * Returns: a #GstBuffer containing the first @nbytes of the adapter,
 * or #NULL if @nbytes bytes are not available
 */
GstBuffer *
gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
{
    GstBuffer *buffer;
    GstBuffer *cur;
    guint hsize, skip;
    guint8 *data;

    g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
    g_return_val_if_fail (nbytes > 0, NULL);

    GST_LOG_OBJECT (adapter, "taking buffer of %u bytes", nbytes);

    /* we don't have enough data, return NULL. This is unlikely
     * as one usually does an _available() first instead of grabbing a
     * random size. */
    if (G_UNLIKELY (nbytes > adapter->size))
        return NULL;

    cur = adapter->buflist->data;
    skip = adapter->skip;
    hsize = GST_BUFFER_SIZE (cur);

    /* our head buffer has enough data left, return it */
    if (skip == 0 && hsize == nbytes) {
        GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
                        nbytes);
        buffer = gst_buffer_ref (cur);
        goto done;
    } else if (hsize >= nbytes + skip) {
        GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
                        nbytes);
        buffer = gst_buffer_create_sub (cur, skip, nbytes);
        goto done;
    }

    if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
        /* Merged something, let's try again for sub-buffering */
        cur = adapter->buflist->data;
        if (GST_BUFFER_SIZE (cur) >= nbytes + skip) {
            GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
                            nbytes);
            buffer = gst_buffer_create_sub (cur, skip, nbytes);
            goto done;
        }
    }

    data = gst_adapter_take_internal (adapter, nbytes);

    buffer = gst_buffer_new ();
    GST_BUFFER_SIZE (buffer) = nbytes;
    GST_BUFFER_DATA (buffer) = data;
    GST_BUFFER_MALLOCDATA (buffer) = data;

done:
    gst_adapter_flush_unchecked (adapter, nbytes);

    return buffer;
}
Beispiel #3
0
/**
 * gst_adapter_take_buffer:
 * @adapter: a #GstAdapter
 * @nbytes: the number of bytes to take
 *
 * Returns a #GstBuffer containing the first @nbytes bytes of the
 * @adapter. The returned bytes will be flushed from the adapter.
 * This function is potentially more performant than gst_adapter_take()
 * since it can reuse the memory in pushed buffers by subbuffering
 * or merging.
 *
 * Note that no assumptions should be made as to whether certain buffer
 * flags such as the DISCONT flag are set on the returned buffer, or not.
 * The caller needs to explicitly set or unset flags that should be set or
 * unset.
 *
 * Caller owns a reference to the returned buffer. gst_buffer_unref() after
 * usage.
 *
 * Free-function: gst_buffer_unref
 *
 * Returns: (transfer full): a #GstBuffer containing the first @nbytes of
 *     the adapter, or #NULL if @nbytes bytes are not available.
 *     gst_buffer_unref() when no longer needed.
 */
GstBuffer *
gst_adapter_take_buffer (GstAdapter * adapter, gsize nbytes)
{
  GstBuffer *buffer;
  GstBuffer *cur;
  gsize hsize, skip;
  guint8 *data;

  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
  g_return_val_if_fail (nbytes > 0, NULL);

  GST_LOG_OBJECT (adapter, "taking buffer of %" G_GSIZE_FORMAT " bytes",
      nbytes);

  /* we don't have enough data, return NULL. This is unlikely
   * as one usually does an _available() first instead of grabbing a
   * random size. */
  if (G_UNLIKELY (nbytes > adapter->size))
    return NULL;

  cur = adapter->buflist->data;
  skip = adapter->skip;
  hsize = gst_buffer_get_size (cur);

  /* our head buffer has enough data left, return it */
  if (skip == 0 && hsize == nbytes) {
    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
        " as head buffer", nbytes);
    buffer = gst_buffer_ref (cur);
    goto done;
  } else if (hsize >= nbytes + skip) {
    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
        " via region copy", nbytes);
    buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes);
    goto done;
  }
#if 0
  if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
    /* Merged something, let's try again for sub-buffering */
    cur = adapter->buflist->data;
    skip = adapter->skip;
    if (gst_buffer_get_size (cur) >= nbytes + skip) {
      GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
          " via sub-buffer", nbytes);
      buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes);
      goto done;
    }
  }
#endif

  data = gst_adapter_take_internal (adapter, nbytes);

  buffer = gst_buffer_new_wrapped (data, nbytes);

done:
  gst_adapter_flush_unchecked (adapter, nbytes);

  return buffer;
}
Beispiel #4
0
void
gst_adapter_flush (GstAdapter * adapter, guint flush)
{
    g_return_if_fail (GST_IS_ADAPTER (adapter));
    g_return_if_fail (flush <= adapter->size);

    /* flushing out 0 bytes will do nothing */
    if (G_UNLIKELY (flush == 0))
        return;

    gst_adapter_flush_unchecked (adapter, flush);
}
Beispiel #5
0
GstBuffer *
gst_adapter_take_buffer_fast (GstAdapter * adapter, gsize nbytes)
{
  GstBuffer *buffer = NULL;
  GstBuffer *cur;
  GSList *item;
  gsize skip;
  gsize left = nbytes;

  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
  g_return_val_if_fail (nbytes > 0, NULL);

  GST_LOG_OBJECT (adapter, "taking buffer of %" G_GSIZE_FORMAT " bytes",
      nbytes);

  /* we don't have enough data, return NULL. This is unlikely
   * as one usually does an _available() first instead of grabbing a
   * random size. */
  if (G_UNLIKELY (nbytes > adapter->size))
    return NULL;

  skip = adapter->skip;
  cur = adapter->buflist->data;

  if (skip == 0 && gst_buffer_get_size (cur) == nbytes) {
    GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
        " as head buffer", nbytes);
    buffer = gst_buffer_ref (cur);
    goto done;
  }

  for (item = adapter->buflist; item && left > 0; item = item->next) {
    gsize size;

    cur = item->data;
    size = MIN (gst_buffer_get_size (cur) - skip, left);

    GST_LOG_OBJECT (adapter, "appending %" G_GSIZE_FORMAT " bytes"
        " via region copy", size);
    if (buffer)
      gst_buffer_copy_into (buffer, cur, GST_BUFFER_COPY_MEMORY, skip, size);
    else
      buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, size);
    skip = 0;
    left -= size;
  }

done:
  gst_adapter_flush_unchecked (adapter, nbytes);

  return buffer;
}
Beispiel #6
0
/**
 * gst_adapter_take_buffer_fast:
 * @adapter:  a #GstAdapter
 * @nbytes: the number of bytes to take
 *
 * Returns a #GstBuffer containing the first @nbytes of the @adapter.
 * The returned bytes will be flushed from the adapter.  This function
 * is potentially more performant than gst_adapter_take_buffer() since
 * it can reuse the memory in pushed buffers by subbuffering or
 * merging. Unlike gst_adapter_take_buffer(), the returned buffer may
 * be composed of multiple non-contiguous #GstMemory objects, no
 * copies are made.
 *
 * Note that no assumptions should be made as to whether certain buffer
 * flags such as the DISCONT flag are set on the returned buffer, or not.
 * The caller needs to explicitly set or unset flags that should be set or
 * unset.
 *
 * This will also copy over all GstMeta of the input buffers except
 * for meta with the %GST_META_FLAG_POOLED flag or with the "memory" tag.
 *
 * This function can return buffer up to the return value of
 * gst_adapter_available() without making copies if possible.
 *
 * Caller owns a reference to the returned buffer. gst_buffer_unref() after
 * usage.
 *
 * Free-function: gst_buffer_unref
 *
 * Returns: (transfer full) (nullable): a #GstBuffer containing the first
 *     @nbytes of the adapter, or %NULL if @nbytes bytes are not available.
 *     gst_buffer_unref() when no longer needed.
 *
 * Since: 1.2
 */
GstBuffer *
gst_adapter_take_buffer_fast (GstAdapter * adapter, gsize nbytes)
{
  GstBuffer *buffer;

  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
  g_return_val_if_fail (nbytes > 0, NULL);

  buffer = gst_adapter_get_buffer_fast (adapter, nbytes);
  if (buffer)
    gst_adapter_flush_unchecked (adapter, nbytes);

  return buffer;
}
Beispiel #7
0
/**
 * gst_adapter_take:
 * @adapter: a #GstAdapter
 * @nbytes: the number of bytes to take
 *
 * Returns a freshly allocated buffer containing the first @nbytes bytes of the
 * @adapter. The returned bytes will be flushed from the adapter.
 *
 * Caller owns returned value. g_free after usage.
 *
 * Returns: oven-fresh hot data, or #NULL if @nbytes bytes are not available
 */
guint8 *
gst_adapter_take (GstAdapter * adapter, guint nbytes)
{
    guint8 *data;

    g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
    g_return_val_if_fail (nbytes > 0, NULL);

    /* we don't have enough data, return NULL. This is unlikely
     * as one usually does an _available() first instead of peeking a
     * random size. */
    if (G_UNLIKELY (nbytes > adapter->size))
        return NULL;

    data = gst_adapter_take_internal (adapter, nbytes);

    gst_adapter_flush_unchecked (adapter, nbytes);

    return data;
}
Beispiel #8
0
/**
 * gst_adapter_take_buffer:
 * @adapter: a #GstAdapter
 * @nbytes: the number of bytes to take
 *
 * Returns a #GstBuffer containing the first @nbytes bytes of the
 * @adapter. The returned bytes will be flushed from the adapter.
 * This function is potentially more performant than gst_adapter_take()
 * since it can reuse the memory in pushed buffers by subbuffering
 * or merging.
 *
 * Caller owns returned value. gst_buffer_unref() after usage.
 *
 * Since: 0.10.6
 *
 * Returns: a #GstBuffer containing the first @nbytes of the adapter,
 * or #NULL if @nbytes bytes are not available
 */
GstBuffer *
gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
{
  GstBuffer *buffer;
  GstBuffer *cur;
  guint hsize, skip;

  g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
  g_return_val_if_fail (nbytes > 0, NULL);

  GST_LOG_OBJECT (adapter, "taking buffer of %u bytes", nbytes);

  /* we don't have enough data, return NULL. This is unlikely
   * as one usually does an _available() first instead of grabbing a
   * random size. */
  if (G_UNLIKELY (nbytes > adapter->size))
    return NULL;

  cur = adapter->buflist->data;
  skip = adapter->skip;
  hsize = GST_BUFFER_SIZE (cur);

  /* our head buffer has enough data left, return it */
  if (skip == 0 && hsize == nbytes) {
    GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer",
        nbytes);
    buffer = gst_buffer_ref (cur);
    goto done;
  } else if (hsize >= nbytes + skip) {
    GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
        nbytes);
    buffer = gst_buffer_create_sub (cur, skip, nbytes);
    goto done;
  }

  if (gst_adapter_try_to_merge_up (adapter, nbytes)) {
    /* Merged something, let's try again for sub-buffering */
    cur = adapter->buflist->data;
    if (GST_BUFFER_SIZE (cur) >= nbytes + skip) {
      GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
          nbytes);
      buffer = gst_buffer_create_sub (cur, skip, nbytes);
      goto done;
    }
  }

  /* we have enough assembled data, copy from there */
  if (adapter->assembled_len >= nbytes) {
    GST_LOG_OBJECT (adapter, "taking %u bytes already assembled", nbytes);
    buffer = gst_buffer_new ();
    GST_BUFFER_SIZE (buffer) = nbytes;
    GST_BUFFER_DATA (buffer) = adapter->assembled_data;
    GST_BUFFER_MALLOCDATA (buffer) = adapter->assembled_data;
    /* flush will set the assembled_len to 0 */
    adapter->assembled_data = g_malloc (adapter->assembled_size);
  } else {
    /* we need to allocate and copy. We could potentially copy bytes from the
     * assembled data before doing the copy_into */
    buffer = gst_buffer_new_and_alloc (nbytes);
    GST_LOG_OBJECT (adapter, "taking %u bytes by collection", nbytes);
    copy_into_unchecked (adapter, GST_BUFFER_DATA (buffer), skip, nbytes);
  }

done:
  gst_adapter_flush_unchecked (adapter, nbytes);

  return buffer;
}