diff options
author | George Kiagiadakis <george.kiagiadakis@collabora.com> | 2018-02-19 11:48:01 +0200 |
---|---|---|
committer | George Kiagiadakis <george.kiagiadakis@collabora.com> | 2018-08-03 13:20:09 +0300 |
commit | 0591bc934a227d1c269b406c365178f77a8434f0 (patch) | |
tree | d2ce59520c7f08913d363ad8c6136df863631c52 | |
parent | 9cf58eb3e4621ea8261e1443bda496b6da9f8833 (diff) | |
download | gstreamer-plugins-bad-0591bc934a227d1c269b406c365178f77a8434f0.tar.gz |
GstPlanarAudioAdapter: copy pts, dts and offset tracking from GstAdapter
https://bugzilla.gnome.org/show_bug.cgi?id=793605
-rw-r--r-- | gst-libs/gst/audio/gstplanaraudioadapter.c | 291 | ||||
-rw-r--r-- | gst-libs/gst/audio/gstplanaraudioadapter.h | 23 |
2 files changed, 293 insertions, 21 deletions
diff --git a/gst-libs/gst/audio/gstplanaraudioadapter.c b/gst-libs/gst/audio/gstplanaraudioadapter.c index c476980bf..87a4f128b 100644 --- a/gst-libs/gst/audio/gstplanaraudioadapter.c +++ b/gst-libs/gst/audio/gstplanaraudioadapter.c @@ -43,6 +43,19 @@ struct _GstPlanarAudioAdapter gsize samples; gsize skip; guint count; + + GstClockTime pts; + guint64 pts_distance; + GstClockTime dts; + guint64 dts_distance; + guint64 offset; + guint64 offset_distance; + + GstClockTime pts_at_discont; + GstClockTime dts_at_discont; + guint64 offset_at_discont; + + guint64 distance_from_discont; }; struct _GstPlanarAudioAdapterClass @@ -70,6 +83,16 @@ gst_planar_audio_adapter_class_init (GstPlanarAudioAdapterClass * klass) static void gst_planar_audio_adapter_init (GstPlanarAudioAdapter * adapter) { + adapter->pts = GST_CLOCK_TIME_NONE; + adapter->pts_distance = 0; + adapter->dts = GST_CLOCK_TIME_NONE; + adapter->dts_distance = 0; + adapter->offset = GST_BUFFER_OFFSET_NONE; + adapter->offset_distance = 0; + adapter->pts_at_discont = GST_CLOCK_TIME_NONE; + adapter->dts_at_discont = GST_CLOCK_TIME_NONE; + adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE; + adapter->distance_from_discont = 0; } static void @@ -134,6 +157,51 @@ gst_planar_audio_adapter_clear (GstPlanarAudioAdapter * adapter) adapter->count = 0; adapter->samples = 0; adapter->skip = 0; + + adapter->pts = GST_CLOCK_TIME_NONE; + adapter->pts_distance = 0; + adapter->dts = GST_CLOCK_TIME_NONE; + adapter->dts_distance = 0; + adapter->offset = GST_BUFFER_OFFSET_NONE; + adapter->offset_distance = 0; + adapter->pts_at_discont = GST_CLOCK_TIME_NONE; + adapter->dts_at_discont = GST_CLOCK_TIME_NONE; + adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE; + adapter->distance_from_discont = 0; +} + +static inline void +update_timestamps_and_offset (GstPlanarAudioAdapter * adapter, GstBuffer * buf) +{ + GstClockTime pts, dts; + guint64 offset; + + 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->pts = pts; + adapter->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->dts = dts; + adapter->dts_distance = 0; + } + offset = GST_BUFFER_OFFSET (buf); + if (offset != GST_BUFFER_OFFSET_NONE) { + GST_LOG_OBJECT (adapter, "new offset %" G_GUINT64_FORMAT, offset); + adapter->offset = offset; + adapter->offset_distance = 0; + } + + if (GST_BUFFER_IS_DISCONT (buf)) { + /* Take values as-is (might be NONE) */ + adapter->pts_at_discont = pts; + adapter->dts_at_discont = dts; + adapter->offset_at_discont = offset; + adapter->distance_from_discont = 0; + } } /** @@ -165,6 +233,7 @@ gst_planar_audio_adapter_push (GstPlanarAudioAdapter * adapter, GstBuffer * buf) GST_LOG_OBJECT (adapter, "pushing %p first %" G_GSIZE_FORMAT " samples", buf, samples); adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf); + update_timestamps_and_offset (adapter, buf); } else { /* Otherwise append to the end, and advance our end pointer */ GST_LOG_OBJECT (adapter, "pushing %p %" G_GSIZE_FORMAT " samples at end, " @@ -179,31 +248,51 @@ static void gst_planar_audio_adapter_flush_unchecked (GstPlanarAudioAdapter * adapter, gsize to_flush) { - GSList *cur = adapter->buflist; + GSList *g = adapter->buflist; gsize cur_samples; - while (to_flush > 0) { - cur_samples = gst_buffer_get_audio_meta (cur->data)->samples; - cur_samples -= adapter->skip; - - if (to_flush >= cur_samples) { - gst_buffer_unref (cur->data); - cur = g_slist_remove_link (cur, cur); - - to_flush -= cur_samples; - adapter->samples -= cur_samples; - adapter->skip = 0; - --adapter->count; - } else { - adapter->samples -= to_flush; - adapter->skip += to_flush; - to_flush = 0; + /* clear state */ + adapter->samples -= to_flush; + + /* take skip into account */ + to_flush += adapter->skip; + /* distance is always at least the amount of skipped samples */ + adapter->pts_distance -= adapter->skip; + adapter->dts_distance -= adapter->skip; + adapter->offset_distance -= adapter->skip; + adapter->distance_from_discont -= adapter->skip; + + g = adapter->buflist; + cur_samples = gst_buffer_get_audio_meta (g->data)->samples; + while (to_flush >= cur_samples) { + /* can skip whole buffer */ + GST_LOG_OBJECT (adapter, "flushing out head buffer"); + adapter->pts_distance += cur_samples; + adapter->dts_distance += cur_samples; + adapter->offset_distance += cur_samples; + adapter->distance_from_discont += cur_samples; + to_flush -= cur_samples; + + gst_buffer_unref (g->data); + g = g_slist_delete_link (g, g); + --adapter->count; + + if (G_UNLIKELY (g == NULL)) { + GST_LOG_OBJECT (adapter, "adapter empty now"); + adapter->buflist_end = NULL; + break; } + /* there is a new head buffer, update the timestamps */ + update_timestamps_and_offset (adapter, g->data); + cur_samples = gst_buffer_get_audio_meta (g->data)->samples; } - - adapter->buflist = cur; - if (!adapter->buflist) - adapter->buflist_end = NULL; + adapter->buflist = g; + /* account for the remaining bytes */ + adapter->skip = to_flush; + adapter->pts_distance += to_flush; + adapter->dts_distance += to_flush; + adapter->offset_distance += to_flush; + adapter->distance_from_discont += to_flush; } /** @@ -389,3 +478,163 @@ gst_planar_audio_adapter_available (GstPlanarAudioAdapter * adapter) return adapter->samples; } + +/** + * gst_planar_audio_adapter_get_distance_from_discont: + * @adapter: a #GstPlanarAudioAdapter + * + * Get the distance in samples since the last buffer with the + * %GST_BUFFER_FLAG_DISCONT flag. + * + * The distance will be reset to 0 for all buffers with + * %GST_BUFFER_FLAG_DISCONT on them, and then calculated for all other + * following buffers based on their size. + * + * Returns: The offset. Can be %GST_BUFFER_OFFSET_NONE. + */ +guint64 +gst_planar_audio_adapter_distance_from_discont (GstPlanarAudioAdapter * adapter) +{ + return adapter->distance_from_discont; +} + +/** + * gst_planar_audio_adapter_offset_at_discont: + * @adapter: a #GstPlanarAudioAdapter + * + * Get the offset that was on the last buffer with the GST_BUFFER_FLAG_DISCONT + * flag, or GST_BUFFER_OFFSET_NONE. + * + * Returns: The offset at the last discont or GST_BUFFER_OFFSET_NONE. + */ +guint64 +gst_planar_audio_adapter_offset_at_discont (GstPlanarAudioAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_PLANAR_AUDIO_ADAPTER (adapter), + GST_BUFFER_OFFSET_NONE); + + return adapter->offset_at_discont; +} + +/** + * gst_planar_audio_adapter_pts_at_discont: + * @adapter: a #GstPlanarAudioAdapter + * + * Get the PTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT + * flag, or GST_CLOCK_TIME_NONE. + * + * Returns: The PTS at the last discont or GST_CLOCK_TIME_NONE. + */ +GstClockTime +gst_planar_audio_adapter_pts_at_discont (GstPlanarAudioAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_PLANAR_AUDIO_ADAPTER (adapter), + GST_CLOCK_TIME_NONE); + + return adapter->pts_at_discont; +} + +/** + * gst_planar_audio_adapter_dts_at_discont: + * @adapter: a #GstPlanarAudioAdapter + * + * Get the DTS that was on the last buffer with the GST_BUFFER_FLAG_DISCONT + * flag, or GST_CLOCK_TIME_NONE. + * + * Returns: The DTS at the last discont or GST_CLOCK_TIME_NONE. + */ +GstClockTime +gst_planar_audio_adapter_dts_at_discont (GstPlanarAudioAdapter * adapter) +{ + g_return_val_if_fail (GST_IS_PLANAR_AUDIO_ADAPTER (adapter), + GST_CLOCK_TIME_NONE); + + return adapter->dts_at_discont; +} + +/** + * gst_planar_audio_adapter_prev_offset: + * @adapter: a #GstPlanarAudioAdapter + * @distance: (out) (allow-none): pointer to a location for distance, or %NULL + * + * Get the offset that was before the current sample in the adapter. When + * @distance is given, the amount of samples between the offset and the current + * position is returned. + * + * The offset is reset to GST_BUFFER_OFFSET_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 sample with an offset is removed from the adapter, the + * offset and distance returned are GST_BUFFER_OFFSET_NONE and 0 respectively. + * + * Returns: The previous seen offset. + */ +guint64 +gst_planar_audio_adapter_prev_offset (GstPlanarAudioAdapter * adapter, + guint64 * distance) +{ + g_return_val_if_fail (GST_IS_PLANAR_AUDIO_ADAPTER (adapter), + GST_BUFFER_OFFSET_NONE); + + if (distance) + *distance = adapter->offset_distance; + + return adapter->offset; +} + +/** + * gst_planar_audio_adapter_prev_pts: + * @adapter: a #GstPlanarAudioAdapter + * @distance: (out) (allow-none): pointer to location for distance, or %NULL + * + * Get the pts that was before the current sample in the adapter. When + * @distance is given, the amount of samples between the pts and the current + * position is returned. + * + * 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 sample 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 pts. + */ +GstClockTime +gst_planar_audio_adapter_prev_pts (GstPlanarAudioAdapter * adapter, + guint64 * distance) +{ + g_return_val_if_fail (GST_IS_PLANAR_AUDIO_ADAPTER (adapter), + GST_CLOCK_TIME_NONE); + + if (distance) + *distance = adapter->pts_distance; + + return adapter->pts; +} + +/** + * gst_planar_audio_adapter_prev_dts: + * @adapter: a #GstPlanarAudioAdapter + * @distance: (out) (allow-none): pointer to location for distance, or %NULL + * + * Get the dts that was before the current sample in the adapter. When + * @distance is given, the amount of bytes between the dts and the current + * position is returned. + * + * 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 sample 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_planar_audio_adapter_prev_dts (GstPlanarAudioAdapter * adapter, + guint64 * distance) +{ + g_return_val_if_fail (GST_IS_PLANAR_AUDIO_ADAPTER (adapter), + GST_CLOCK_TIME_NONE); + + if (distance) + *distance = adapter->dts_distance; + + return adapter->dts; +} diff --git a/gst-libs/gst/audio/gstplanaraudioadapter.h b/gst-libs/gst/audio/gstplanaraudioadapter.h index 85b6380c1..5ddb098c9 100644 --- a/gst-libs/gst/audio/gstplanaraudioadapter.h +++ b/gst-libs/gst/audio/gstplanaraudioadapter.h @@ -85,6 +85,29 @@ GstBuffer * gst_planar_audio_adapter_take_buffer (GstPlanarAudioAdapter * adapte GST_AUDIO_BAD_API gsize gst_planar_audio_adapter_available (GstPlanarAudioAdapter * adapter); +GST_AUDIO_BAD_API +guint64 gst_planar_audio_adapter_distance_from_discont (GstPlanarAudioAdapter * adapter); + +GST_AUDIO_BAD_API +guint64 gst_planar_audio_adapter_offset_at_discont (GstPlanarAudioAdapter * adapter); + +GST_AUDIO_BAD_API +GstClockTime gst_planar_audio_adapter_pts_at_discont (GstPlanarAudioAdapter * adapter); + +GST_AUDIO_BAD_API +GstClockTime gst_planar_audio_adapter_dts_at_discont (GstPlanarAudioAdapter * adapter); + +GST_AUDIO_BAD_API +guint64 gst_planar_audio_adapter_prev_offset (GstPlanarAudioAdapter * adapter, + guint64 * distance); + +GST_AUDIO_BAD_API +GstClockTime gst_planar_audio_adapter_prev_pts (GstPlanarAudioAdapter * adapter, + guint64 * distance); + +GST_AUDIO_BAD_API +GstClockTime gst_planar_audio_adapter_prev_dts (GstPlanarAudioAdapter * adapter, + guint64 * distance); #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstPlanarAudioAdapter, gst_object_unref) |