audiobuffersplit: Perform discont tracking on running time

Otherwise we would have to drain on every segment event. Like this we
can handle segment events that don't cause a discontinuity in running
time to be handled without draining.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1254>
This commit is contained in:
Sebastian Dröge 2020-05-08 22:36:01 +03:00 committed by GStreamer Merge Bot
parent 20756e3387
commit 79e65951a9
2 changed files with 80 additions and 53 deletions

View file

@ -361,9 +361,9 @@ gst_audio_buffer_split_output (GstAudioBufferSplit * self, gboolean force,
{
gint size, avail;
GstFlowReturn ret = GST_FLOW_OK;
GstClockTime resync_time;
GstClockTime resync_pts;
resync_time = self->resync_time;
resync_pts = self->resync_pts;
size = samples_per_buffer * bpf;
/* If we accumulated enough error for one sample, include one
@ -387,21 +387,21 @@ gst_audio_buffer_split_output (GstAudioBufferSplit * self, gboolean force,
resync_time_diff =
gst_util_uint64_scale (self->current_offset, GST_SECOND, rate);
if (self->out_segment.rate < 0.0) {
if (resync_time > resync_time_diff)
GST_BUFFER_TIMESTAMP (buffer) = resync_time - resync_time_diff;
if (resync_pts > resync_time_diff)
GST_BUFFER_PTS (buffer) = resync_pts - resync_time_diff;
else
GST_BUFFER_TIMESTAMP (buffer) = 0;
GST_BUFFER_PTS (buffer) = 0;
GST_BUFFER_DURATION (buffer) =
gst_util_uint64_scale (size / bpf, GST_SECOND, rate);
self->current_offset += size / bpf;
} else {
GST_BUFFER_TIMESTAMP (buffer) = resync_time + resync_time_diff;
GST_BUFFER_PTS (buffer) = resync_pts + resync_time_diff;
self->current_offset += size / bpf;
resync_time_diff =
gst_util_uint64_scale (self->current_offset, GST_SECOND, rate);
GST_BUFFER_DURATION (buffer) =
resync_time_diff - (GST_BUFFER_TIMESTAMP (buffer) - resync_time);
resync_time_diff - (GST_BUFFER_PTS (buffer) - resync_pts);
}
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
@ -412,9 +412,12 @@ gst_audio_buffer_split_output (GstAudioBufferSplit * self, gboolean force,
self->error_per_buffer) % self->output_buffer_duration_d;
GST_LOG_OBJECT (self,
"Outputting buffer at timestamp %" GST_TIME_FORMAT " with duration %"
GST_TIME_FORMAT " (%u samples)",
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
"Outputting buffer at running time %" GST_TIME_FORMAT
" with timestamp %" GST_TIME_FORMAT " with duration %" GST_TIME_FORMAT
" (%u samples)",
GST_TIME_ARGS (gst_segment_to_running_time (&self->out_segment,
GST_FORMAT_TIME, GST_BUFFER_PTS (buffer))),
GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), size / bpf);
ret = gst_pad_push (self->srcpad, buffer);
@ -442,16 +445,35 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self,
guint avail = gst_adapter_available (self->adapter);
guint avail_samples = avail / bpf;
guint64 new_offset;
GstClockTime current_timestamp;
GstClockTime current_timestamp_end;
GstClockTime input_rt, current_rt;
GstClockTime input_duration;
GstClockTime current_rt_end;
input_rt =
gst_segment_to_running_time (&self->in_segment, GST_FORMAT_TIME,
GST_BUFFER_PTS (buffer));
input_duration =
(gst_buffer_get_size (buffer) / bpf) / ABS (self->in_segment.rate);
GST_OBJECT_LOCK (self);
if (self->in_segment.rate < 0) {
discont = FALSE;
} else {
discont = GST_BUFFER_IS_DISCONT (buffer)
|| GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_RESYNC);
}
/* If the segment rate is changing this is a discontinuity */
discont = discont || (self->out_segment.format != GST_FORMAT_UNDEFINED
&& self->in_segment.rate != self->out_segment.rate);
/* If this is the very first buffer we also have a discontinuity */
discont = discont || self->current_offset == -1;
discont =
gst_audio_stream_align_process (self->stream_align,
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);
discont, input_rt, input_duration, NULL, NULL, NULL);
GST_OBJECT_UNLOCK (self);
if (!discont)
@ -461,45 +483,39 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self,
self->drop_samples = 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);
current_timestamp_end =
self->resync_time - gst_util_uint64_scale (self->current_offset,
GST_SECOND, rate);
current_rt =
self->resync_rt - gst_util_uint64_scale (self->current_offset +
avail_samples, GST_SECOND, rate * ABS (self->in_segment.rate));
current_rt_end =
self->resync_rt - gst_util_uint64_scale (self->current_offset,
GST_SECOND, rate * ABS (self->in_segment.rate));
} else {
current_timestamp =
self->resync_time + gst_util_uint64_scale (self->current_offset,
GST_SECOND, rate);
current_timestamp_end =
self->resync_time + gst_util_uint64_scale (self->current_offset +
avail_samples, GST_SECOND, rate);
current_rt =
self->resync_rt + gst_util_uint64_scale (self->current_offset,
GST_SECOND, rate * self->in_segment.rate);
current_rt_end =
self->resync_rt + gst_util_uint64_scale (self->current_offset +
avail_samples, GST_SECOND, rate * self->in_segment.rate);
}
if (self->gapless) {
if (self->current_offset == -1) {
/* We only set resync time on the very first buffer */
self->current_offset = 0;
self->resync_time = GST_BUFFER_PTS (buffer);
discont = FALSE;
} else {
if (self->current_offset != -1) {
GST_DEBUG_OBJECT (self,
"Got discont in gapless mode: Current timestamp %" GST_TIME_FORMAT
", current end timestamp %" GST_TIME_FORMAT
", timestamp after discont %" GST_TIME_FORMAT,
GST_TIME_ARGS (current_timestamp),
GST_TIME_ARGS (current_timestamp_end),
GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
"Got discont in gapless mode: Current running time %" GST_TIME_FORMAT
", current end running time %" GST_TIME_FORMAT
", running time after discont %" GST_TIME_FORMAT,
GST_TIME_ARGS (current_rt),
GST_TIME_ARGS (current_rt_end), GST_TIME_ARGS (input_rt));
new_offset =
gst_util_uint64_scale (GST_BUFFER_PTS (buffer) - self->resync_time,
rate, GST_SECOND);
if (GST_BUFFER_PTS (buffer) < self->resync_time) {
gst_util_uint64_scale (current_rt - self->resync_rt,
rate * ABS (self->in_segment.rate), GST_SECOND);
if (current_rt < self->resync_rt) {
guint64 drop_samples;
new_offset =
gst_util_uint64_scale (self->resync_time -
GST_BUFFER_PTS (buffer), rate, GST_SECOND);
gst_util_uint64_scale (self->resync_rt -
current_rt, rate * ABS (self->in_segment.rate), GST_SECOND);
drop_samples = self->current_offset + avail_samples + new_offset;
GST_DEBUG_OBJECT (self,
@ -567,12 +583,12 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self,
/* We might end up in here also in gapless mode, if the above code decided
* that no silence is to be inserted, because e.g. the gap is too big */
GST_DEBUG_OBJECT (self,
"Got discont: Current timestamp %" GST_TIME_FORMAT
", current end timestamp %" GST_TIME_FORMAT
", timestamp after discont %" GST_TIME_FORMAT,
GST_TIME_ARGS (current_timestamp),
GST_TIME_ARGS (current_timestamp_end),
GST_TIME_ARGS (GST_BUFFER_PTS (buffer)));
"Got %s: Current running time %" GST_TIME_FORMAT
", current end running time %" GST_TIME_FORMAT
", running time after discont %" GST_TIME_FORMAT,
self->current_offset == -1 ? "first buffer" : "discont",
GST_TIME_ARGS (current_rt),
GST_TIME_ARGS (current_rt_end), GST_TIME_ARGS (input_rt));
if (self->strict_buffer_size) {
gst_adapter_clear (self->adapter);
@ -585,7 +601,8 @@ gst_audio_buffer_split_handle_discont (GstAudioBufferSplit * self,
self->current_offset = 0;
self->accumulated_error = 0;
self->resync_time = GST_BUFFER_PTS (buffer);
self->resync_pts = GST_BUFFER_PTS (buffer);
self->resync_rt = input_rt;
if (self->segment_pending) {
GstEvent *event;
@ -663,6 +680,16 @@ gst_audio_buffer_split_sink_chain (GstPad * pad, GstObject * parent,
samples_per_buffer = self->samples_per_buffer;
GST_OBJECT_UNLOCK (self);
GST_LOG_OBJECT (self,
"Processing buffer at running time %" GST_TIME_FORMAT
" with timestamp %" GST_TIME_FORMAT " with duration %" GST_TIME_FORMAT
" (%u samples)",
GST_TIME_ARGS (gst_segment_to_running_time (&self->in_segment,
GST_FORMAT_TIME, GST_BUFFER_PTS (buffer))),
GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)),
(guint) (gst_buffer_get_size (buffer) / bpf));
if (format == GST_AUDIO_FORMAT_UNKNOWN || samples_per_buffer == 0) {
gst_buffer_unref (buffer);
return GST_FLOW_NOT_NEGOTIATED;

View file

@ -55,7 +55,7 @@ struct _GstAudioBufferSplit {
GstAdapter *adapter;
GstAudioStreamAlign *stream_align;
GstClockTime resync_time;
GstClockTime resync_pts, resync_rt;
guint64 current_offset; /* offset from start time in samples */
guint64 drop_samples; /* number of samples to drop in gapless mode */