diff options
Diffstat (limited to 'libs/gst/base/gstadapter.c')
-rw-r--r-- | libs/gst/base/gstadapter.c | 226 |
1 files changed, 140 insertions, 86 deletions
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c index 797eaaa..3342536 100644 --- a/libs/gst/base/gstadapter.c +++ b/libs/gst/base/gstadapter.c @@ -62,7 +62,8 @@ * const guint8 *data = gst_adapter_map (adapter, 512); * // use flowreturn as an error value * ret = my_library_foo (data); - * gst_adapter_unmap (adapter, 512); + * gst_adapter_unmap (adapter); + * gst_adapter_flush (adapter, 512); * } * * gst_object_unref (this); @@ -128,14 +129,15 @@ GST_DEBUG_CATEGORY_STATIC (gst_adapter_debug); struct _GstAdapterPrivate { - GstClockTime timestamp; - guint64 distance; + GstClockTime pts; + guint64 pts_distance; + GstClockTime dts; + guint64 dts_distance; gsize scan_offset; GSList *scan_entry; - gpointer cdata; - gsize csize; + GstMapInfo info; }; #define _do_init \ @@ -163,8 +165,10 @@ gst_adapter_init (GstAdapter * adapter) adapter->priv = GST_ADAPTER_GET_PRIVATE (adapter); adapter->assembled_data = g_malloc (DEFAULT_SIZE); adapter->assembled_size = DEFAULT_SIZE; - adapter->priv->timestamp = GST_CLOCK_TIME_NONE; - adapter->priv->distance = 0; + adapter->priv->pts = GST_CLOCK_TIME_NONE; + adapter->priv->pts_distance = 0; + adapter->priv->dts = GST_CLOCK_TIME_NONE; + adapter->priv->dts_distance = 0; } static void @@ -209,8 +213,15 @@ gst_adapter_new (void) void gst_adapter_clear (GstAdapter * adapter) { + GstAdapterPrivate *priv; + g_return_if_fail (GST_IS_ADAPTER (adapter)); + priv = adapter->priv; + + if (priv->info.memory) + gst_adapter_unmap (adapter); + g_slist_foreach (adapter->buflist, (GFunc) gst_mini_object_unref, NULL); g_slist_free (adapter->buflist); adapter->buflist = NULL; @@ -218,23 +229,30 @@ gst_adapter_clear (GstAdapter * adapter) adapter->size = 0; adapter->skip = 0; adapter->assembled_len = 0; - adapter->priv->timestamp = GST_CLOCK_TIME_NONE; - adapter->priv->distance = 0; - adapter->priv->scan_offset = 0; - adapter->priv->scan_entry = NULL; + priv->pts = GST_CLOCK_TIME_NONE; + priv->pts_distance = 0; + priv->dts = GST_CLOCK_TIME_NONE; + priv->dts_distance = 0; + priv->scan_offset = 0; + priv->scan_entry = NULL; } static inline void -update_timestamp (GstAdapter * adapter, GstBuffer * buf) +update_timestamps (GstAdapter * adapter, GstBuffer * buf) { - GstClockTime timestamp; - - timestamp = GST_BUFFER_TIMESTAMP (buf); - if (GST_CLOCK_TIME_IS_VALID (timestamp)) { - GST_LOG_OBJECT (adapter, "new timestamp %" GST_TIME_FORMAT, - GST_TIME_ARGS (timestamp)); - adapter->priv->timestamp = timestamp; - adapter->priv->distance = 0; + GstClockTime pts, dts; + + pts = GST_BUFFER_PTS (buf); + if (GST_CLOCK_TIME_IS_VALID (pts)) { + GST_LOG_OBJECT (adapter, "new pts %" GST_TIME_FORMAT, GST_TIME_ARGS (pts)); + adapter->priv->pts = pts; + adapter->priv->pts_distance = 0; + } + dts = GST_BUFFER_DTS (buf); + if (GST_CLOCK_TIME_IS_VALID (dts)) { + GST_LOG_OBJECT (adapter, "new dts %" GST_TIME_FORMAT, GST_TIME_ARGS (dts)); + adapter->priv->dts = dts; + adapter->priv->dts_distance = 0; } } @@ -267,6 +285,8 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip, csize = MIN (bsize - skip, size); GST_DEBUG ("bsize %" G_GSIZE_FORMAT ", skip %" G_GSIZE_FORMAT ", csize %" G_GSIZE_FORMAT, bsize, skip, csize); + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, "extract %" G_GSIZE_FORMAT + " bytes", csize); gst_buffer_extract (buf, skip, dest, csize); size -= csize; dest += csize; @@ -278,6 +298,8 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip, bsize = gst_buffer_get_size (buf); if (G_LIKELY (bsize > 0)) { csize = MIN (bsize, size); + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, + "extract %" G_GSIZE_FORMAT " bytes", csize); gst_buffer_extract (buf, 0, dest, csize); size -= csize; dest += csize; @@ -306,21 +328,21 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf) /* Note: merging buffers at this point is premature. */ if (G_UNLIKELY (adapter->buflist == NULL)) { - GST_LOG_OBJECT (adapter, "pushing first %" G_GSIZE_FORMAT " bytes", size); + GST_LOG_OBJECT (adapter, "pushing %p first %" G_GSIZE_FORMAT " bytes", + buf, size); adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf); - update_timestamp (adapter, buf); + update_timestamps (adapter, buf); } else { /* Otherwise append to the end, and advance our end pointer */ - GST_LOG_OBJECT (adapter, "pushing %" G_GSIZE_FORMAT " bytes at end, " - "size now %" G_GSIZE_FORMAT, size, adapter->size); + GST_LOG_OBJECT (adapter, "pushing %p %" G_GSIZE_FORMAT " bytes at end, " + "size now %" G_GSIZE_FORMAT, buf, size, adapter->size); adapter->buflist_end = g_slist_append (adapter->buflist_end, buf); adapter->buflist_end = g_slist_next (adapter->buflist_end); } } /* Internal method only. Tries to merge buffers at the head of the queue - * to form a single larger buffer of size 'size'. Only merges buffers that - * where 'gst_buffer_is_span_fast' returns TRUE. + * to form a single larger buffer of size 'size'. * * Returns TRUE if it managed to merge anything. */ @@ -346,15 +368,12 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size) while (g != NULL && hsize < size) { cur = g->data; - if (!gst_buffer_is_span_fast (head, cur)) - return ret; - /* Merge the head buffer and the next in line */ GST_LOG_OBJECT (adapter, "Merging buffers of size %" G_GSIZE_FORMAT " & %" G_GSIZE_FORMAT " in search of target %" G_GSIZE_FORMAT, hsize, gst_buffer_get_size (cur), size); - head = gst_buffer_join (head, cur); + head = gst_buffer_append (head, cur); hsize = gst_buffer_get_size (head); ret = TRUE; @@ -395,9 +414,10 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size) * Returns: (transfer none) (array length=size): a pointer to the first * @size bytes of data, or NULL */ -const guint8 * +gconstpointer gst_adapter_map (GstAdapter * adapter, gsize size) { + GstAdapterPrivate *priv; GstBuffer *cur; gsize skip, csize; gsize toreuse, tocopy; @@ -406,6 +426,11 @@ gst_adapter_map (GstAdapter * adapter, gsize size) g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); g_return_val_if_fail (size > 0, NULL); + priv = adapter->priv; + + if (priv->info.memory) + gst_adapter_unmap (adapter); + /* we don't have enough data, return NULL. This is unlikely * as one usually does an _available() first instead of peeking a * random size. */ @@ -422,10 +447,10 @@ gst_adapter_map (GstAdapter * adapter, gsize size) 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; + if (!gst_buffer_map (cur, &priv->info, GST_MAP_READ)) + return FALSE; + + return (guint8 *) priv->info.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 */ @@ -467,24 +492,24 @@ gst_adapter_map (GstAdapter * adapter, gsize 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. + * Releases the memory obtained with the last gst_adapter_map(). */ void -gst_adapter_unmap (GstAdapter * adapter, gsize flush) +gst_adapter_unmap (GstAdapter * adapter) { + GstAdapterPrivate *priv; + g_return_if_fail (GST_IS_ADAPTER (adapter)); - if (adapter->priv->cdata) { + priv = adapter->priv; + + if (priv->info.memory) { GstBuffer *cur = adapter->buflist->data; - gst_buffer_unmap (cur, adapter->priv->cdata, adapter->priv->csize); - adapter->priv->cdata = NULL; + GST_LOG_OBJECT (adapter, "unmap memory buffer %p", cur); + gst_buffer_unmap (cur, &priv->info); + priv->info.memory = NULL; } - - if (flush) - gst_adapter_flush_unchecked (adapter, flush); } /** @@ -504,7 +529,7 @@ gst_adapter_unmap (GstAdapter * adapter, gsize flush) * Since: 0.10.12 */ void -gst_adapter_copy (GstAdapter * adapter, guint8 * dest, gsize offset, gsize size) +gst_adapter_copy (GstAdapter * adapter, gpointer dest, gsize offset, gsize size) { g_return_if_fail (GST_IS_ADAPTER (adapter)); g_return_if_fail (size > 0); @@ -535,6 +560,9 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) priv = adapter->priv; + if (priv->info.memory) + gst_adapter_unmap (adapter); + /* clear state */ adapter->size -= flush; adapter->assembled_len = 0; @@ -542,7 +570,8 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) /* take skip into account */ flush += adapter->skip; /* distance is always at least the amount of skipped bytes */ - priv->distance -= adapter->skip; + priv->pts_distance -= adapter->skip; + priv->dts_distance -= adapter->skip; g = adapter->buflist; cur = g->data; @@ -550,7 +579,8 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) while (flush >= size) { /* can skip whole buffer */ GST_LOG_OBJECT (adapter, "flushing out head buffer"); - priv->distance += size; + priv->pts_distance += size; + priv->dts_distance += size; flush -= size; gst_buffer_unref (cur); @@ -561,15 +591,16 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) adapter->buflist_end = NULL; break; } - /* there is a new head buffer, update the timestamp */ + /* there is a new head buffer, update the timestamps */ cur = g->data; - update_timestamp (adapter, cur); + update_timestamps (adapter, cur); size = gst_buffer_get_size (cur); } adapter->buflist = g; /* account for the remaining bytes */ adapter->skip = flush; - adapter->priv->distance += flush; + adapter->priv->pts_distance += flush; + adapter->priv->dts_distance += flush; /* invalidate scan position */ priv->scan_offset = 0; priv->scan_entry = NULL; @@ -618,6 +649,8 @@ gst_adapter_take_internal (GstAdapter * adapter, gsize nbytes) /* reuse what we can from the already assembled data */ if (toreuse) { GST_LOG_OBJECT (adapter, "reusing %" G_GSIZE_FORMAT " bytes", toreuse); + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, adapter, + "memcpy %" G_GSIZE_FORMAT " bytes", toreuse); memcpy (data, adapter->assembled_data, toreuse); } } @@ -644,10 +677,10 @@ gst_adapter_take_internal (GstAdapter * adapter, gsize nbytes) * Returns: (transfer full) (array length=nbytes): oven-fresh hot data, or * #NULL if @nbytes bytes are not available */ -guint8 * +gpointer gst_adapter_take (GstAdapter * adapter, gsize nbytes) { - guint8 *data; + gpointer data; g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); g_return_val_if_fail (nbytes > 0, NULL); @@ -735,9 +768,7 @@ gst_adapter_take_buffer (GstAdapter * adapter, gsize nbytes) data = gst_adapter_take_internal (adapter, nbytes); - buffer = gst_buffer_new (); - gst_buffer_take_memory (buffer, -1, - gst_memory_new_wrapped (0, data, g_free, nbytes, 0, nbytes)); + buffer = gst_buffer_new_wrapped (data, nbytes); done: gst_adapter_flush_unchecked (adapter, nbytes); @@ -767,7 +798,7 @@ done: GList * gst_adapter_take_list (GstAdapter * adapter, gsize nbytes) { - GList *result = NULL, *tail = NULL; + GQueue queue = G_QUEUE_INIT; GstBuffer *cur; gsize hsize, skip; @@ -783,15 +814,11 @@ gst_adapter_take_list (GstAdapter * adapter, gsize nbytes) cur = gst_adapter_take_buffer (adapter, hsize); - if (result == NULL) { - result = tail = g_list_append (result, cur); - } else { - tail = g_list_append (tail, cur); - tail = g_list_next (tail); - } + g_queue_push_tail (&queue, cur); + nbytes -= hsize; } - return result; + return queue.head; } /** @@ -855,32 +882,57 @@ gst_adapter_available_fast (GstAdapter * adapter) } /** - * gst_adapter_prev_timestamp: + * gst_adapter_prev_pts: * @adapter: a #GstAdapter * @distance: (out) (allow-none): pointer to location for distance, or NULL * - * Get the timestamp that was before the current byte in the adapter. When - * @distance is given, the amount of bytes between the timestamp and the current + * Get the pts that was before the current byte in the adapter. When + * @distance is given, the amount of bytes between the pts and the current * position is returned. * - * The timestamp is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when + * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when * the adapter is first created or when it is cleared. This also means that before - * the first byte with a timestamp is removed from the adapter, the timestamp + * the first byte with a pts is removed from the adapter, the pts * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively. * - * Returns: The previously seen timestamp. + * Returns: The previously seen pts. + */ +GstClockTime +gst_adapter_prev_pts (GstAdapter * adapter, guint64 * distance) +{ + g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); + + if (distance) + *distance = adapter->priv->pts_distance; + + return adapter->priv->pts; +} + +/** + * gst_adapter_prev_dts: + * @adapter: a #GstAdapter + * @distance: (out) (allow-none): pointer to location for distance, or NULL + * + * Get the dts that was before the current byte in the adapter. When + * @distance is given, the amount of bytes between the dts and the current + * position is returned. * - * Since: 0.10.24 + * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when + * the adapter is first created or when it is cleared. This also means that before + * the first byte with a dts is removed from the adapter, the dts + * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively. + * + * Returns: The previously seen dts. */ GstClockTime -gst_adapter_prev_timestamp (GstAdapter * adapter, guint64 * distance) +gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance) { g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE); if (distance) - *distance = adapter->priv->distance; + *distance = adapter->priv->dts_distance; - return adapter->priv->timestamp; + return adapter->priv->dts; } /** @@ -913,9 +965,10 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, guint32 pattern, gsize offset, gsize size, guint32 * value) { GSList *g; - gsize skip, bsize, osize, i; + gsize skip, bsize, i; guint32 state; - guint8 *bdata, *odata; + GstMapInfo info; + guint8 *bdata; GstBuffer *buf; g_return_val_if_fail (size > 0, -1); @@ -949,10 +1002,11 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask, bsize = gst_buffer_get_size (buf); } /* get the data now */ - odata = gst_buffer_map (buf, &osize, NULL, GST_MAP_READ); + if (!gst_buffer_map (buf, &info, GST_MAP_READ)) + return -1; - bdata = odata + skip; - bsize = osize - skip; + bdata = (guint8 *) info.data + skip; + bsize = info.size - skip; skip = 0; /* set the state to something that does not match */ @@ -969,7 +1023,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); + gst_buffer_unmap (buf, &info); return offset + skip + i - 3; } } @@ -981,17 +1035,17 @@ 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 += osize; + adapter->priv->scan_offset += info.size; adapter->priv->scan_entry = g; - gst_buffer_unmap (buf, odata, osize); + gst_buffer_unmap (buf, &info); buf = g->data; - odata = gst_buffer_map (buf, &osize, NULL, GST_MAP_READ); - bsize = osize; - bdata = odata; + gst_buffer_map (buf, &info, GST_MAP_READ); + bsize = info.size; + bdata = info.data; } while (TRUE); - gst_buffer_unmap (buf, odata, osize); + gst_buffer_unmap (buf, &info); /* nothing found */ return -1; |