/** * 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; }
/** * 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; }
/** * 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; }
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); }
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; }
/** * 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; }
/** * 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; }
/** * 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; }