diff options
Diffstat (limited to 'libs/gst/base/gstadapter.c')
-rw-r--r-- | libs/gst/base/gstadapter.c | 212 |
1 files changed, 123 insertions, 89 deletions
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c index 75944a902a..94fbabf9cd 100644 --- a/libs/gst/base/gstadapter.c +++ b/libs/gst/base/gstadapter.c @@ -33,11 +33,12 @@ * * The theory of operation is like this: All buffers received are put * into the adapter using gst_adapter_push() and the data is then read back - * in chunks of the desired size using gst_adapter_peek(). After the data is - * processed, it is freed using gst_adapter_flush(). + * in chunks of the desired size using gst_adapter_map()/gst_adapter_unmap() + * and/or gst_adapter_copy(). After the data has been processed, it is freed + * using gst_adapter_unmap(). * * Other methods such as gst_adapter_take() and gst_adapter_take_buffer() - * combine gst_adapter_peek() and gst_adapter_flush() in one method and are + * combine gst_adapter_map() and gst_adapter_unmap() in one method and are * potentially more convenient for some use cases. * * For example, a sink pad's chain function that needs to pass data to a library @@ -58,9 +59,10 @@ * gst_adapter_push (adapter, buffer); * // while we can read out 512 bytes, process them * while (gst_adapter_available (adapter) >= 512 && ret == GST_FLOW_OK) { + * const guint8 *data = gst_adapter_map (adapter, 512); * // use flowreturn as an error value - * ret = my_library_foo (gst_adapter_peek (adapter, 512)); - * gst_adapter_flush (adapter, 512); + * ret = my_library_foo (data); + * gst_adapter_unmap (adapter, 512); * } * * gst_object_unref (this); @@ -116,6 +118,8 @@ /* default size for the assembled data buffer */ #define DEFAULT_SIZE 4096 +static void gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush); + GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug); #define GST_CAT_DEFAULT gst_adapter_debug @@ -127,25 +131,22 @@ struct _GstAdapterPrivate GstClockTime timestamp; guint64 distance; - guint scan_offset; + gsize scan_offset; GSList *scan_entry; + + gpointer cdata; + gsize csize; }; -#define _do_init(thing) \ +#define _do_init \ GST_DEBUG_CATEGORY_INIT (gst_adapter_debug, "adapter", 0, "object to splice and merge buffers to desired size") -GST_BOILERPLATE_FULL (GstAdapter, gst_adapter, GObject, G_TYPE_OBJECT, - _do_init); +#define gst_adapter_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstAdapter, gst_adapter, G_TYPE_OBJECT, _do_init); static void gst_adapter_dispose (GObject * object); static void gst_adapter_finalize (GObject * object); static void -gst_adapter_base_init (gpointer g_class) -{ - /* nop */ -} - -static void gst_adapter_class_init (GstAdapterClass * klass) { GObjectClass *object = G_OBJECT_CLASS (klass); @@ -157,7 +158,7 @@ gst_adapter_class_init (GstAdapterClass * klass) } static void -gst_adapter_init (GstAdapter * adapter, GstAdapterClass * g_class) +gst_adapter_init (GstAdapter * adapter) { adapter->priv = GST_ADAPTER_GET_PRIVATE (adapter); adapter->assembled_data = g_malloc (DEFAULT_SIZE); @@ -239,12 +240,12 @@ update_timestamp (GstAdapter * adapter, GstBuffer * buf) /* copy data into @dest, skipping @skip bytes from the head buffers */ static void -copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip, - guint size) +copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip, + gsize size) { GSList *g; GstBuffer *buf; - guint bsize, csize; + gsize bsize, csize; /* first step, do skipping */ /* we might well be copying where we were scanning */ @@ -255,16 +256,17 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip, g = adapter->buflist; } buf = g->data; - bsize = GST_BUFFER_SIZE (buf); + bsize = gst_buffer_get_size (buf); while (G_UNLIKELY (skip >= bsize)) { skip -= bsize; g = g_slist_next (g); buf = g->data; - bsize = GST_BUFFER_SIZE (buf); + bsize = gst_buffer_get_size (buf); } /* copy partial buffer */ csize = MIN (bsize - skip, size); - memcpy (dest, GST_BUFFER_DATA (buf) + skip, csize); + GST_DEBUG ("%u %u %u", bsize, skip, csize); + gst_buffer_extract (buf, skip, dest, csize); size -= csize; dest += csize; @@ -272,10 +274,10 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip, while (size > 0) { g = g_slist_next (g); buf = g->data; - bsize = GST_BUFFER_SIZE (buf); + bsize = gst_buffer_get_size (buf); if (G_LIKELY (bsize > 0)) { csize = MIN (bsize, size); - memcpy (dest, GST_BUFFER_DATA (buf), csize); + gst_buffer_extract (buf, 0, dest, csize); size -= csize; dest += csize; } @@ -293,12 +295,12 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, guint skip, void gst_adapter_push (GstAdapter * adapter, GstBuffer * buf) { - guint size; + gsize size; g_return_if_fail (GST_IS_ADAPTER (adapter)); g_return_if_fail (GST_IS_BUFFER (buf)); - size = GST_BUFFER_SIZE (buf); + size = gst_buffer_get_size (buf); adapter->size += size; /* Note: merging buffers at this point is premature. */ @@ -322,11 +324,12 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf) * Returns TRUE if it managed to merge anything. */ static gboolean -gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size) +gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size) { GstBuffer *cur, *head; GSList *g; gboolean ret = FALSE; + gsize hsize; g = adapter->buflist; if (g == NULL) @@ -338,8 +341,9 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size) /* How large do we want our head buffer? The requested size, plus whatever's * been skipped already */ size += adapter->skip; + hsize = gst_buffer_get_size (head); - while (g != NULL && GST_BUFFER_SIZE (head) < size) { + while (g != NULL && hsize < size) { cur = g->data; if (!gst_buffer_is_span_fast (head, cur)) return ret; @@ -347,9 +351,10 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size) /* Merge the head buffer and the next in line */ GST_LOG_OBJECT (adapter, "Merging buffers of size %u & %u in search of target %u", - GST_BUFFER_SIZE (head), GST_BUFFER_SIZE (cur), size); + hsize, gst_buffer_get_size (cur), size); head = gst_buffer_join (head, cur); + hsize = gst_buffer_get_size (head); ret = TRUE; /* Delete the front list item, and store our new buffer in the 2nd list @@ -368,9 +373,9 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size) } /** - * gst_adapter_peek: + * gst_adapter_map: * @adapter: a #GstAdapter - * @size: the number of bytes to peek + * @size: the number of bytes to map/peek * * Gets the first @size bytes stored in the @adapter. The returned pointer is * valid until the next function is called on the adapter. @@ -390,11 +395,11 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, guint size) * @size bytes of data, or NULL */ const guint8 * -gst_adapter_peek (GstAdapter * adapter, guint size) +gst_adapter_map (GstAdapter * adapter, gsize size) { GstBuffer *cur; - guint skip; - guint toreuse, tocopy; + gsize skip, csize; + gsize toreuse, tocopy; guint8 *data; g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); @@ -410,20 +415,20 @@ gst_adapter_peek (GstAdapter * adapter, guint size) if (adapter->assembled_len >= size) return adapter->assembled_data; - /* our head buffer has enough data left, return it */ - cur = adapter->buflist->data; - skip = adapter->skip; - if (GST_BUFFER_SIZE (cur) >= size + skip) - return GST_BUFFER_DATA (cur) + skip; - - /* We may be able to efficiently merge buffers in our pool to - * gather a big enough chunk to return it from the head buffer directly */ - if (gst_adapter_try_to_merge_up (adapter, size)) { - /* Merged something! Check if there's enough avail now */ + do { cur = adapter->buflist->data; - if (GST_BUFFER_SIZE (cur) >= size + skip) - return GST_BUFFER_DATA (cur) + skip; - } + skip = adapter->skip; + + csize = gst_buffer_get_size (cur); + if (csize >= size + skip) { + data = gst_buffer_map (cur, &csize, NULL, GST_MAP_READ); + adapter->priv->cdata = data; + adapter->priv->csize = csize; + return data + skip; + } + /* We may be able to efficiently merge buffers in our pool to + * gather a big enough chunk to return it from the head buffer directly */ + } while (gst_adapter_try_to_merge_up (adapter, size)); /* see how much data we can reuse from the assembled memory and how much * we need to copy */ @@ -458,6 +463,29 @@ gst_adapter_peek (GstAdapter * adapter, guint size) } /** + * gst_adapter_unmap: + * @adapter: a #GstAdapter + * @flush: the amount of bytes to flush + * + * Releases the memory obtained with the last gst_adapter_map() and flushes + * @size bytes from the adapter. + */ +void +gst_adapter_unmap (GstAdapter * adapter, gsize flush) +{ + g_return_if_fail (GST_IS_ADAPTER (adapter)); + + if (adapter->priv->cdata) { + GstBuffer *cur = adapter->buflist->data; + gst_buffer_unmap (cur, adapter->priv->cdata, adapter->priv->csize); + adapter->priv->cdata = NULL; + } + + if (flush) + gst_adapter_flush_unchecked (adapter, flush); +} + +/** * gst_adapter_copy: * @adapter: a #GstAdapter * @dest: (out caller-allocates) (array length=size): the memory to copy into @@ -474,7 +502,7 @@ gst_adapter_peek (GstAdapter * adapter, guint size) * Since: 0.10.12 */ void -gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size) +gst_adapter_copy (GstAdapter * adapter, guint8 * dest, gsize offset, gsize size) { g_return_if_fail (GST_IS_ADAPTER (adapter)); g_return_if_fail (size > 0); @@ -491,13 +519,13 @@ gst_adapter_copy (GstAdapter * adapter, guint8 * dest, guint offset, guint size) * Flushes the first @flush bytes in the @adapter. The caller must ensure that * at least this many bytes are available. * - * See also: gst_adapter_peek(). + * See also: gst_adapter_map(), gst_adapter_unmap() */ static void -gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush) +gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) { GstBuffer *cur; - guint size; + gsize size; GstAdapterPrivate *priv; GSList *g; @@ -516,7 +544,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush) g = adapter->buflist; cur = g->data; - size = GST_BUFFER_SIZE (cur); + size = gst_buffer_get_size (cur); while (flush >= size) { /* can skip whole buffer */ GST_LOG_OBJECT (adapter, "flushing out head buffer"); @@ -534,7 +562,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush) /* there is a new head buffer, update the timestamp */ cur = g->data; update_timestamp (adapter, cur); - size = GST_BUFFER_SIZE (cur); + size = gst_buffer_get_size (cur); } adapter->buflist = g; /* account for the remaining bytes */ @@ -546,7 +574,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, guint flush) } void -gst_adapter_flush (GstAdapter * adapter, guint flush) +gst_adapter_flush (GstAdapter * adapter, gsize flush) { g_return_if_fail (GST_IS_ADAPTER (adapter)); g_return_if_fail (flush <= adapter->size); @@ -560,10 +588,10 @@ gst_adapter_flush (GstAdapter * adapter, guint flush) /* internal function, nbytes should be flushed after calling this function */ static guint8 * -gst_adapter_take_internal (GstAdapter * adapter, guint nbytes) +gst_adapter_take_internal (GstAdapter * adapter, gsize nbytes) { guint8 *data; - guint toreuse, tocopy; + gsize toreuse, tocopy; /* see how much data we can reuse from the assembled memory and how much * we need to copy */ @@ -592,7 +620,6 @@ gst_adapter_take_internal (GstAdapter * adapter, guint nbytes) } if (tocopy) { /* copy the remaining data */ - GST_LOG_OBJECT (adapter, "copying %u bytes", tocopy); copy_into_unchecked (adapter, toreuse + data, toreuse + adapter->skip, tocopy); } @@ -615,7 +642,7 @@ gst_adapter_take_internal (GstAdapter * adapter, guint nbytes) * #NULL if @nbytes bytes are not available */ guint8 * -gst_adapter_take (GstAdapter * adapter, guint nbytes) +gst_adapter_take (GstAdapter * adapter, gsize nbytes) { guint8 *data; @@ -656,11 +683,11 @@ gst_adapter_take (GstAdapter * adapter, guint nbytes) * Since: 0.10.6 */ GstBuffer * -gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes) +gst_adapter_take_buffer (GstAdapter * adapter, gsize nbytes) { GstBuffer *buffer; GstBuffer *cur; - guint hsize, skip; + gsize hsize, skip; guint8 *data; g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); @@ -676,7 +703,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes) cur = adapter->buflist->data; skip = adapter->skip; - hsize = GST_BUFFER_SIZE (cur); + hsize = gst_buffer_get_size (cur); /* our head buffer has enough data left, return it */ if (skip == 0 && hsize == nbytes) { @@ -685,19 +712,19 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint 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", + GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via region copy", nbytes); - buffer = gst_buffer_create_sub (cur, skip, nbytes); + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, 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) { + if (gst_buffer_get_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); + buffer = gst_buffer_copy_region (cur, GST_BUFFER_COPY_ALL, skip, nbytes); goto done; } } @@ -705,9 +732,8 @@ gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes) 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; + gst_buffer_take_memory (buffer, -1, + gst_memory_new_wrapped (0, data, g_free, nbytes, 0, nbytes)); done: gst_adapter_flush_unchecked (adapter, nbytes); @@ -735,11 +761,11 @@ done: * Since: 0.10.31 */ GList * -gst_adapter_take_list (GstAdapter * adapter, guint nbytes) +gst_adapter_take_list (GstAdapter * adapter, gsize nbytes) { GList *result = NULL, *tail = NULL; GstBuffer *cur; - guint hsize, skip; + gsize hsize, skip; g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); g_return_val_if_fail (nbytes <= adapter->size, NULL); @@ -749,7 +775,7 @@ gst_adapter_take_list (GstAdapter * adapter, guint nbytes) while (nbytes > 0) { cur = adapter->buflist->data; skip = adapter->skip; - hsize = MIN (nbytes, GST_BUFFER_SIZE (cur) - skip); + hsize = MIN (nbytes, gst_buffer_get_size (cur) - skip); cur = gst_adapter_take_buffer (adapter, hsize); @@ -769,12 +795,12 @@ gst_adapter_take_list (GstAdapter * adapter, guint nbytes) * @adapter: a #GstAdapter * * Gets the maximum amount of bytes available, that is it returns the maximum - * value that can be supplied to gst_adapter_peek() without that function + * value that can be supplied to gst_adapter_map() without that function * returning NULL. * * Returns: number of bytes available in @adapter */ -guint +gsize gst_adapter_available (GstAdapter * adapter) { g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0); @@ -793,11 +819,11 @@ gst_adapter_available (GstAdapter * adapter) * Returns: number of bytes that are available in @adapter without expensive * operations */ -guint +gsize gst_adapter_available_fast (GstAdapter * adapter) { GstBuffer *cur; - guint size; + gsize size; GSList *g; g_return_val_if_fail (GST_IS_ADAPTER (adapter), 0); @@ -814,7 +840,7 @@ gst_adapter_available_fast (GstAdapter * adapter) g = adapter->buflist; while (TRUE) { cur = g->data; - size = GST_BUFFER_SIZE (cur); + size = gst_buffer_get_size (cur); if (size != 0) break; g = g_slist_next (g); @@ -878,14 +904,14 @@ gst_adapter_prev_timestamp (GstAdapter * adapter, guint64 * distance) * * Since: 0.10.30 */ -guint +gsize gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, - guint32 pattern, guint offset, guint size, guint32 * value) + guint32 pattern, gsize offset, gsize size, guint32 * value) { GSList *g; - guint skip, bsize, i; + gsize skip, bsize, osize, i; guint32 state; - guint8 *bdata; + guint8 *bdata, *odata; GstBuffer *buf; g_return_val_if_fail (size > 0, -1); @@ -909,18 +935,20 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, adapter->priv->scan_entry = NULL; } buf = g->data; - bsize = GST_BUFFER_SIZE (buf); + bsize = gst_buffer_get_size (buf); while (G_UNLIKELY (skip >= bsize)) { skip -= bsize; g = g_slist_next (g); adapter->priv->scan_offset += bsize; adapter->priv->scan_entry = g; buf = g->data; - bsize = GST_BUFFER_SIZE (buf); + bsize = gst_buffer_get_size (buf); } /* get the data now */ - bsize -= skip; - bdata = GST_BUFFER_DATA (buf) + skip; + odata = gst_buffer_map (buf, &osize, NULL, GST_MAP_READ); + + bdata = odata + skip; + bsize = osize - skip; skip = 0; /* set the state to something that does not match */ @@ -937,6 +965,7 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, if (G_LIKELY (skip + i >= 3)) { if (G_LIKELY (value)) *value = state; + gst_buffer_unmap (buf, odata, osize); return offset + skip + i - 3; } } @@ -948,13 +977,18 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, /* nothing found yet, go to next buffer */ skip += bsize; g = g_slist_next (g); - adapter->priv->scan_offset += GST_BUFFER_SIZE (buf); + adapter->priv->scan_offset += osize; adapter->priv->scan_entry = g; + gst_buffer_unmap (buf, odata, osize); buf = g->data; - bsize = GST_BUFFER_SIZE (buf); - bdata = GST_BUFFER_DATA (buf); + + odata = gst_buffer_map (buf, &osize, NULL, GST_MAP_READ); + bsize = osize; + bdata = odata; } while (TRUE); + gst_buffer_unmap (buf, odata, osize); + /* nothing found */ return -1; } @@ -1005,9 +1039,9 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, * * Since: 0.10.24 */ -guint +gsize gst_adapter_masked_scan_uint32 (GstAdapter * adapter, guint32 mask, - guint32 pattern, guint offset, guint size) + guint32 pattern, gsize offset, gsize size) { return gst_adapter_masked_scan_uint32_peek (adapter, mask, pattern, offset, size, NULL); |