mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
adaptivedemux2: reverse playback running times
Account for running time moving non-monotonically in reverse playback by tracking the highest running time seen at each point. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2510>
This commit is contained in:
parent
9df7a21ec9
commit
a4a805312d
4 changed files with 71 additions and 23 deletions
|
@ -1354,7 +1354,7 @@
|
|||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": false,
|
||||
"default": "3000000000",
|
||||
"default": "10000000000",
|
||||
"max": "18446744073709551615",
|
||||
"min": "0",
|
||||
"mutable": "playing",
|
||||
|
|
|
@ -204,6 +204,8 @@ typedef struct
|
|||
GstClockTimeDiff runningtime;
|
||||
/* GST_CLOCK_STIME_NONE for non-timed data */
|
||||
GstClockTimeDiff runningtime_end;
|
||||
/* running time of item for buffering tracking: GST_CLOCK_STIME_NONE for non-timed data */
|
||||
GstClockTimeDiff runningtime_buffering;
|
||||
} TrackQueueItem;
|
||||
|
||||
GstAdaptiveDemux2Stream *find_stream_for_track_locked (GstAdaptiveDemux *
|
||||
|
|
|
@ -51,7 +51,7 @@ gst_adaptive_demux_track_flush (GstAdaptiveDemuxTrack * track)
|
|||
gst_segment_init (&track->output_segment, GST_FORMAT_TIME);
|
||||
track->gap_position = track->gap_duration = GST_CLOCK_TIME_NONE;
|
||||
|
||||
track->output_time = 0;
|
||||
track->output_time = GST_CLOCK_STIME_NONE;
|
||||
track->next_position = GST_CLOCK_STIME_NONE;
|
||||
|
||||
track->level_bytes = 0;
|
||||
|
@ -123,6 +123,7 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
|||
gboolean is_pending_sticky = FALSE;
|
||||
GstEvent *event;
|
||||
GstClockTimeDiff running_time;
|
||||
GstClockTimeDiff running_time_buffering = GST_CLOCK_STIME_NONE;
|
||||
GstClockTimeDiff running_time_end;
|
||||
gsize item_size = 0;
|
||||
|
||||
|
@ -131,7 +132,8 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
|||
event = gst_event_store_get_next_pending (&track->sticky_events);
|
||||
if (event != NULL) {
|
||||
res = (GstMiniObject *) event;
|
||||
running_time = running_time_end = GST_CLOCK_STIME_NONE;
|
||||
running_time_buffering = running_time = running_time_end =
|
||||
GST_CLOCK_STIME_NONE;
|
||||
GST_DEBUG_OBJECT (demux,
|
||||
"track %s dequeued pending sticky event %" GST_PTR_FORMAT,
|
||||
track->stream_id, event);
|
||||
|
@ -160,9 +162,16 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
|||
}
|
||||
|
||||
res = (GstMiniObject *) gst_event_new_gap (pos, duration);
|
||||
if (track->output_segment.rate > 0.0) {
|
||||
running_time = my_segment_to_running_time (&track->output_segment, pos);
|
||||
running_time_end =
|
||||
running_time_buffering = running_time_end =
|
||||
my_segment_to_running_time (&track->output_segment, pos + duration);
|
||||
} else {
|
||||
running_time =
|
||||
my_segment_to_running_time (&track->output_segment, pos + duration);
|
||||
running_time_buffering = running_time_end =
|
||||
my_segment_to_running_time (&track->output_segment, pos);
|
||||
}
|
||||
item_size = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -174,6 +183,7 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
|||
res = item.item;
|
||||
running_time = item.runningtime;
|
||||
running_time_end = item.runningtime_end;
|
||||
running_time_buffering = item.runningtime_buffering;
|
||||
item_size = item.size;
|
||||
|
||||
/* Special case for a gap event, to drain them out little-by-little.
|
||||
|
@ -223,6 +233,18 @@ handle_event:
|
|||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEGMENT:
|
||||
gst_event_copy_segment (event, &track->output_segment);
|
||||
|
||||
if (!GST_CLOCK_STIME_IS_VALID (track->output_time)) {
|
||||
if (track->output_segment.rate > 0.0)
|
||||
track->output_time =
|
||||
my_segment_to_running_time (&track->output_segment,
|
||||
track->output_segment.start);
|
||||
else
|
||||
track->output_time =
|
||||
my_segment_to_running_time (&track->output_segment,
|
||||
track->output_segment.stop);
|
||||
}
|
||||
|
||||
if (track->update_next_segment) {
|
||||
GstClockTimeDiff global_output_position =
|
||||
demux->priv->global_output_position;
|
||||
|
@ -261,14 +283,21 @@ handle_event:
|
|||
}
|
||||
|
||||
/* Update track buffering levels */
|
||||
if (running_time != GST_CLOCK_STIME_NONE) {
|
||||
if (GST_CLOCK_STIME_IS_VALID (running_time_buffering)) {
|
||||
GstClockTimeDiff output_time;
|
||||
|
||||
track->output_time = running_time;
|
||||
if (running_time_end != GST_CLOCK_TIME_NONE)
|
||||
track->output_time = running_time_end;
|
||||
track->output_time = running_time_buffering;
|
||||
|
||||
GST_LOG_OBJECT (demux,
|
||||
"track %s buffering time:%" GST_STIME_FORMAT,
|
||||
track->stream_id, GST_STIME_ARGS (running_time_buffering));
|
||||
|
||||
if (GST_CLOCK_STIME_IS_VALID (track->output_time))
|
||||
output_time =
|
||||
MAX (track->output_time, demux->priv->global_output_position);
|
||||
else
|
||||
output_time = track->input_time;
|
||||
|
||||
output_time = MAX (track->output_time, demux->priv->global_output_position);
|
||||
if (track->input_time >= output_time)
|
||||
track->level_time = track->input_time - output_time;
|
||||
else
|
||||
|
@ -409,29 +438,46 @@ track_queue_data_locked (GstAdaptiveDemux * demux,
|
|||
item.size = size;
|
||||
item.runningtime = GST_CLOCK_STIME_NONE;
|
||||
item.runningtime_end = GST_CLOCK_STIME_NONE;
|
||||
item.runningtime_buffering = GST_CLOCK_STIME_NONE;
|
||||
|
||||
if (timestamp != GST_CLOCK_TIME_NONE) {
|
||||
GstClockTimeDiff output_time;
|
||||
GstClockTimeDiff output_time, input_time;
|
||||
|
||||
/* Set the running time of the item */
|
||||
item.runningtime =
|
||||
input_time = item.runningtime_end = item.runningtime =
|
||||
my_segment_to_running_time (&track->input_segment, timestamp);
|
||||
|
||||
/* Update segment position (include duration if valid) */
|
||||
track->input_segment.position = timestamp;
|
||||
if (GST_CLOCK_TIME_IS_VALID (duration)) {
|
||||
/* In backward playback, each buffer is played
|
||||
* 'backward', so the segment position should
|
||||
* only include duration in forward playback */
|
||||
if (track->input_segment.rate > 0.0) {
|
||||
track->input_segment.position += duration;
|
||||
item.runningtime_end =
|
||||
my_segment_to_running_time (&track->input_segment,
|
||||
input_time = my_segment_to_running_time (&track->input_segment,
|
||||
track->input_segment.position);
|
||||
} else {
|
||||
/* Otherwise, the end of the buffer has the smaller running time */
|
||||
item.runningtime = my_segment_to_running_time (&track->input_segment,
|
||||
timestamp + duration);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update track input time and level */
|
||||
track->input_time =
|
||||
my_segment_to_running_time (&track->input_segment,
|
||||
track->input_segment.position);
|
||||
if (input_time > track->input_time)
|
||||
track->input_time = input_time;
|
||||
|
||||
/* Store the maximum running time we've seen as
|
||||
* this item's "buffering running time" */
|
||||
item.runningtime_buffering = track->input_time;
|
||||
|
||||
if (GST_CLOCK_STIME_IS_VALID (track->output_time))
|
||||
output_time =
|
||||
MAX (track->output_time, demux->priv->global_output_position);
|
||||
else
|
||||
output_time = track->input_time;
|
||||
|
||||
output_time = MAX (track->output_time, demux->priv->global_output_position);
|
||||
if (track->input_time >= output_time)
|
||||
track->level_time = track->input_time - output_time;
|
||||
else
|
||||
|
@ -879,7 +925,7 @@ gst_adaptive_demux_track_new (GstAdaptiveDemux * demux,
|
|||
gst_segment_init (&track->output_segment, GST_FORMAT_TIME);
|
||||
track->gap_position = track->gap_duration = GST_CLOCK_TIME_NONE;
|
||||
|
||||
track->output_time = 0;
|
||||
track->output_time = GST_CLOCK_STIME_NONE;
|
||||
track->next_position = GST_CLOCK_STIME_NONE;
|
||||
|
||||
track->update_next_segment = FALSE;
|
||||
|
|
|
@ -122,7 +122,7 @@ GST_DEBUG_CATEGORY_EXTERN (adaptivedemux2_debug);
|
|||
#define DEFAULT_MAX_BUFFERING_TIME (30 * GST_SECOND)
|
||||
|
||||
#define DEFAULT_BUFFERING_HIGH_WATERMARK_TIME (30 * GST_SECOND)
|
||||
#define DEFAULT_BUFFERING_LOW_WATERMARK_TIME (3 * GST_SECOND)
|
||||
#define DEFAULT_BUFFERING_LOW_WATERMARK_TIME (10 * GST_SECOND)
|
||||
#define DEFAULT_BUFFERING_HIGH_WATERMARK_FRAGMENTS 0.0
|
||||
#define DEFAULT_BUFFERING_LOW_WATERMARK_FRAGMENTS 0.0
|
||||
|
||||
|
|
Loading…
Reference in a new issue