From 20756e3387f0d1ed5df2ea3245133c987526bac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 8 May 2020 21:36:44 +0300 Subject: [PATCH] audiobuffersplit: Keep incoming and outgoing segments separate We might have to drain already queued input based on the old segment before forwarding the new segment event. The new segment is only forwarded after a discont as otherwise we might cause unnecessary timestamp jumps as we output buffers timestamped based on sample counts. Part-of: --- gst/audiobuffersplit/gstaudiobuffersplit.c | 42 ++++++++++++++++------ gst/audiobuffersplit/gstaudiobuffersplit.h | 4 ++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/gst/audiobuffersplit/gstaudiobuffersplit.c b/gst/audiobuffersplit/gstaudiobuffersplit.c index 8d7767a65f..ac1c3bddbe 100644 --- a/gst/audiobuffersplit/gstaudiobuffersplit.c +++ b/gst/audiobuffersplit/gstaudiobuffersplit.c @@ -321,7 +321,9 @@ gst_audio_buffer_split_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_audio_info_init (&self->info); - gst_segment_init (&self->segment, GST_FORMAT_TIME); + gst_segment_init (&self->in_segment, GST_FORMAT_TIME); + gst_segment_init (&self->out_segment, GST_FORMAT_UNDEFINED); + self->segment_pending = FALSE; GST_OBJECT_LOCK (self); gst_audio_stream_align_mark_discont (self->stream_align); GST_OBJECT_UNLOCK (self); @@ -384,7 +386,7 @@ gst_audio_buffer_split_output (GstAudioBufferSplit * self, gboolean force, resync_time_diff = gst_util_uint64_scale (self->current_offset, GST_SECOND, rate); - if (self->segment.rate < 0.0) { + if (self->out_segment.rate < 0.0) { if (resync_time > resync_time_diff) GST_BUFFER_TIMESTAMP (buffer) = resync_time - resync_time_diff; else @@ -446,7 +448,7 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self, GST_OBJECT_LOCK (self); discont = gst_audio_stream_align_process (self->stream_align, - self->segment.rate < 0 ? FALSE : GST_BUFFER_IS_DISCONT (buffer) + self->in_segment.rate < 0 ? FALSE : GST_BUFFER_IS_DISCONT (buffer) || GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_RESYNC), GST_BUFFER_PTS (buffer), gst_buffer_get_size (buffer) / bpf, NULL, NULL, NULL); @@ -458,7 +460,7 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self, /* Reset */ self->drop_samples = 0; - if (self->segment.rate < 0.0) { + if (self->in_segment.rate < 0.0) { current_timestamp = self->resync_time - gst_util_uint64_scale (self->current_offset + avail_samples, GST_SECOND, rate); @@ -584,6 +586,18 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self, self->current_offset = 0; self->accumulated_error = 0; self->resync_time = GST_BUFFER_PTS (buffer); + + if (self->segment_pending) { + GstEvent *event; + + self->out_segment = self->in_segment; + GST_DEBUG_OBJECT (self, "Updating output segment %" GST_SEGMENT_FORMAT, + &self->out_segment); + event = gst_event_new_segment (&self->out_segment); + gst_event_set_seqnum (event, self->segment_seqnum); + gst_pad_push_event (self->srcpad, event); + self->segment_pending = FALSE; + } } return ret; @@ -616,7 +630,7 @@ gst_audio_buffer_split_clip_buffer_start_for_gapless (GstAudioBufferSplit * return NULL; } - if (self->segment.rate < 0.0) { + if (self->out_segment.rate < 0.0) { buffer = gst_audio_buffer_truncate (buffer, bpf, 0, nsamples - self->drop_samples); @@ -655,7 +669,7 @@ gst_audio_buffer_split_sink_chain (GstPad * pad, GstObject * parent, } buffer = - gst_audio_buffer_split_clip_buffer (self, buffer, &self->segment, rate, + gst_audio_buffer_split_clip_buffer (self, buffer, &self->in_segment, rate, bpf); if (!buffer) return GST_FLOW_OK; @@ -736,7 +750,9 @@ gst_audio_buffer_split_sink_event (GstPad * pad, GstObject * parent, break; } case GST_EVENT_FLUSH_STOP: - gst_segment_init (&self->segment, GST_FORMAT_TIME); + gst_segment_init (&self->in_segment, GST_FORMAT_TIME); + gst_segment_init (&self->out_segment, GST_FORMAT_UNDEFINED); + self->segment_pending = FALSE; GST_OBJECT_LOCK (self); gst_audio_stream_align_mark_discont (self->stream_align); GST_OBJECT_UNLOCK (self); @@ -746,12 +762,18 @@ gst_audio_buffer_split_sink_event (GstPad * pad, GstObject * parent, ret = gst_pad_event_default (pad, parent, event); break; case GST_EVENT_SEGMENT: - gst_event_copy_segment (event, &self->segment); - if (self->segment.format != GST_FORMAT_TIME) { + gst_event_copy_segment (event, &self->in_segment); + if (self->in_segment.format != GST_FORMAT_TIME) { gst_event_unref (event); ret = FALSE; } else { - ret = gst_pad_event_default (pad, parent, event); + GST_DEBUG_OBJECT (self, + "Received new input segment %" GST_SEGMENT_FORMAT, + &self->in_segment); + self->segment_pending = TRUE; + self->segment_seqnum = gst_event_get_seqnum (event); + gst_event_unref (event); + ret = TRUE; } break; case GST_EVENT_EOS: diff --git a/gst/audiobuffersplit/gstaudiobuffersplit.h b/gst/audiobuffersplit/gstaudiobuffersplit.h index 8625df8ca3..d22eba682a 100644 --- a/gst/audiobuffersplit/gstaudiobuffersplit.h +++ b/gst/audiobuffersplit/gstaudiobuffersplit.h @@ -47,7 +47,9 @@ struct _GstAudioBufferSplit { gint output_buffer_duration_d; /* State */ - GstSegment segment; + GstSegment in_segment, out_segment; + guint32 segment_seqnum; + gboolean segment_pending; GstAudioInfo info; GstAdapter *adapter;