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": false,
|
||||||
"construct-only": false,
|
"construct-only": false,
|
||||||
"controllable": false,
|
"controllable": false,
|
||||||
"default": "3000000000",
|
"default": "10000000000",
|
||||||
"max": "18446744073709551615",
|
"max": "18446744073709551615",
|
||||||
"min": "0",
|
"min": "0",
|
||||||
"mutable": "playing",
|
"mutable": "playing",
|
||||||
|
|
|
@ -204,6 +204,8 @@ typedef struct
|
||||||
GstClockTimeDiff runningtime;
|
GstClockTimeDiff runningtime;
|
||||||
/* GST_CLOCK_STIME_NONE for non-timed data */
|
/* GST_CLOCK_STIME_NONE for non-timed data */
|
||||||
GstClockTimeDiff runningtime_end;
|
GstClockTimeDiff runningtime_end;
|
||||||
|
/* running time of item for buffering tracking: GST_CLOCK_STIME_NONE for non-timed data */
|
||||||
|
GstClockTimeDiff runningtime_buffering;
|
||||||
} TrackQueueItem;
|
} TrackQueueItem;
|
||||||
|
|
||||||
GstAdaptiveDemux2Stream *find_stream_for_track_locked (GstAdaptiveDemux *
|
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);
|
gst_segment_init (&track->output_segment, GST_FORMAT_TIME);
|
||||||
track->gap_position = track->gap_duration = GST_CLOCK_TIME_NONE;
|
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->next_position = GST_CLOCK_STIME_NONE;
|
||||||
|
|
||||||
track->level_bytes = 0;
|
track->level_bytes = 0;
|
||||||
|
@ -123,6 +123,7 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
||||||
gboolean is_pending_sticky = FALSE;
|
gboolean is_pending_sticky = FALSE;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstClockTimeDiff running_time;
|
GstClockTimeDiff running_time;
|
||||||
|
GstClockTimeDiff running_time_buffering = GST_CLOCK_STIME_NONE;
|
||||||
GstClockTimeDiff running_time_end;
|
GstClockTimeDiff running_time_end;
|
||||||
gsize item_size = 0;
|
gsize item_size = 0;
|
||||||
|
|
||||||
|
@ -131,7 +132,8 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
||||||
event = gst_event_store_get_next_pending (&track->sticky_events);
|
event = gst_event_store_get_next_pending (&track->sticky_events);
|
||||||
if (event != NULL) {
|
if (event != NULL) {
|
||||||
res = (GstMiniObject *) event;
|
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,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"track %s dequeued pending sticky event %" GST_PTR_FORMAT,
|
"track %s dequeued pending sticky event %" GST_PTR_FORMAT,
|
||||||
track->stream_id, event);
|
track->stream_id, event);
|
||||||
|
@ -160,9 +162,16 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
||||||
}
|
}
|
||||||
|
|
||||||
res = (GstMiniObject *) gst_event_new_gap (pos, duration);
|
res = (GstMiniObject *) gst_event_new_gap (pos, duration);
|
||||||
running_time = my_segment_to_running_time (&track->output_segment, pos);
|
if (track->output_segment.rate > 0.0) {
|
||||||
running_time_end =
|
running_time = my_segment_to_running_time (&track->output_segment, pos);
|
||||||
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 + 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;
|
item_size = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -174,6 +183,7 @@ track_dequeue_data_locked (GstAdaptiveDemux * demux,
|
||||||
res = item.item;
|
res = item.item;
|
||||||
running_time = item.runningtime;
|
running_time = item.runningtime;
|
||||||
running_time_end = item.runningtime_end;
|
running_time_end = item.runningtime_end;
|
||||||
|
running_time_buffering = item.runningtime_buffering;
|
||||||
item_size = item.size;
|
item_size = item.size;
|
||||||
|
|
||||||
/* Special case for a gap event, to drain them out little-by-little.
|
/* Special case for a gap event, to drain them out little-by-little.
|
||||||
|
@ -223,6 +233,18 @@ handle_event:
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_SEGMENT:
|
case GST_EVENT_SEGMENT:
|
||||||
gst_event_copy_segment (event, &track->output_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) {
|
if (track->update_next_segment) {
|
||||||
GstClockTimeDiff global_output_position =
|
GstClockTimeDiff global_output_position =
|
||||||
demux->priv->global_output_position;
|
demux->priv->global_output_position;
|
||||||
|
@ -261,14 +283,21 @@ handle_event:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update track buffering levels */
|
/* Update track buffering levels */
|
||||||
if (running_time != GST_CLOCK_STIME_NONE) {
|
if (GST_CLOCK_STIME_IS_VALID (running_time_buffering)) {
|
||||||
GstClockTimeDiff output_time;
|
GstClockTimeDiff output_time;
|
||||||
|
|
||||||
track->output_time = running_time;
|
track->output_time = running_time_buffering;
|
||||||
if (running_time_end != GST_CLOCK_TIME_NONE)
|
|
||||||
track->output_time = running_time_end;
|
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)
|
if (track->input_time >= output_time)
|
||||||
track->level_time = track->input_time - output_time;
|
track->level_time = track->input_time - output_time;
|
||||||
else
|
else
|
||||||
|
@ -409,29 +438,46 @@ track_queue_data_locked (GstAdaptiveDemux * demux,
|
||||||
item.size = size;
|
item.size = size;
|
||||||
item.runningtime = GST_CLOCK_STIME_NONE;
|
item.runningtime = GST_CLOCK_STIME_NONE;
|
||||||
item.runningtime_end = GST_CLOCK_STIME_NONE;
|
item.runningtime_end = GST_CLOCK_STIME_NONE;
|
||||||
|
item.runningtime_buffering = GST_CLOCK_STIME_NONE;
|
||||||
|
|
||||||
if (timestamp != GST_CLOCK_TIME_NONE) {
|
if (timestamp != GST_CLOCK_TIME_NONE) {
|
||||||
GstClockTimeDiff output_time;
|
GstClockTimeDiff output_time, input_time;
|
||||||
|
|
||||||
/* Set the running time of the item */
|
/* 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);
|
my_segment_to_running_time (&track->input_segment, timestamp);
|
||||||
|
|
||||||
/* Update segment position (include duration if valid) */
|
/* Update segment position (include duration if valid) */
|
||||||
track->input_segment.position = timestamp;
|
track->input_segment.position = timestamp;
|
||||||
if (GST_CLOCK_TIME_IS_VALID (duration)) {
|
if (GST_CLOCK_TIME_IS_VALID (duration)) {
|
||||||
track->input_segment.position += duration;
|
/* In backward playback, each buffer is played
|
||||||
item.runningtime_end =
|
* 'backward', so the segment position should
|
||||||
my_segment_to_running_time (&track->input_segment,
|
* only include duration in forward playback */
|
||||||
track->input_segment.position);
|
if (track->input_segment.rate > 0.0) {
|
||||||
|
track->input_segment.position += duration;
|
||||||
|
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 */
|
/* Update track input time and level */
|
||||||
track->input_time =
|
if (input_time > track->input_time)
|
||||||
my_segment_to_running_time (&track->input_segment,
|
track->input_time = input_time;
|
||||||
track->input_segment.position);
|
|
||||||
|
/* 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)
|
if (track->input_time >= output_time)
|
||||||
track->level_time = track->input_time - output_time;
|
track->level_time = track->input_time - output_time;
|
||||||
else
|
else
|
||||||
|
@ -879,7 +925,7 @@ gst_adaptive_demux_track_new (GstAdaptiveDemux * demux,
|
||||||
gst_segment_init (&track->output_segment, GST_FORMAT_TIME);
|
gst_segment_init (&track->output_segment, GST_FORMAT_TIME);
|
||||||
track->gap_position = track->gap_duration = GST_CLOCK_TIME_NONE;
|
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->next_position = GST_CLOCK_STIME_NONE;
|
||||||
|
|
||||||
track->update_next_segment = FALSE;
|
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_MAX_BUFFERING_TIME (30 * GST_SECOND)
|
||||||
|
|
||||||
#define DEFAULT_BUFFERING_HIGH_WATERMARK_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_HIGH_WATERMARK_FRAGMENTS 0.0
|
||||||
#define DEFAULT_BUFFERING_LOW_WATERMARK_FRAGMENTS 0.0
|
#define DEFAULT_BUFFERING_LOW_WATERMARK_FRAGMENTS 0.0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue