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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1254>
This commit is contained in:
Sebastian Dröge 2020-05-08 21:36:44 +03:00 committed by GStreamer Merge Bot
parent 9937101e51
commit 20756e3387
2 changed files with 35 additions and 11 deletions

View file

@ -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:

View file

@ -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;