mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 14:56:36 +00:00
adaptivedemux2: Improve minimum buffering threshold
Previously the minimum buffering threshold was hardcoded to a specific value (10s). This is suboptimal this an actual value will depend on the actual stream being played. This commit sets the low watermark threshold in time to 0, which is an automatic mode. Subclasses can provide a stream `recommended_buffering_threshold` when update_stream_info() is called. Currently implemented for HLS, where we recommended 1.5 average segment duration. This will result in buffering being at 100% when the 2nd segment has been downloaded (minus a bit already being consumed downstream) Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3240>
This commit is contained in:
parent
d8bdd9429b
commit
33db765f45
7 changed files with 60 additions and 7 deletions
|
@ -1349,12 +1349,12 @@
|
|||
"writable": true
|
||||
},
|
||||
"low-watermark-time": {
|
||||
"blurb": "Low watermark for parsed data below which downloads are resumed (in ns, 0=disable)",
|
||||
"blurb": "Low watermark for parsed data below which downloads are resumed (in ns, 0=automatic)",
|
||||
"conditionally-available": false,
|
||||
"construct": false,
|
||||
"construct-only": false,
|
||||
"controllable": false,
|
||||
"default": "10000000000",
|
||||
"default": "0",
|
||||
"max": "18446744073709551615",
|
||||
"min": "0",
|
||||
"mutable": "playing",
|
||||
|
|
|
@ -149,6 +149,19 @@ gst_adaptive_demux2_stream_add_track (GstAdaptiveDemux2Stream * stream,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (stream->demux->buffering_low_watermark_time)
|
||||
track->buffering_threshold = stream->demux->buffering_low_watermark_time;
|
||||
else if (GST_CLOCK_TIME_IS_VALID (stream->recommended_buffering_threshold))
|
||||
track->buffering_threshold =
|
||||
MIN (10 * GST_SECOND, stream->recommended_buffering_threshold);
|
||||
else {
|
||||
/* Using a starting default, can be overriden later in
|
||||
* ::update_stream_info() */
|
||||
GST_DEBUG_OBJECT (stream,
|
||||
"Setting default 10s buffering threshold on new track");
|
||||
track->buffering_threshold = 10 * GST_SECOND;
|
||||
}
|
||||
|
||||
stream->tracks =
|
||||
g_list_append (stream->tracks, gst_adaptive_demux_track_ref (track));
|
||||
if (stream->demux) {
|
||||
|
@ -762,6 +775,7 @@ gst_adaptive_demux2_stream_parse_buffer (GstAdaptiveDemux2Stream * stream,
|
|||
*/
|
||||
static void
|
||||
calculate_track_thresholds (GstAdaptiveDemux * demux,
|
||||
GstAdaptiveDemux2Stream * stream,
|
||||
GstClockTime fragment_duration, GstClockTime * low_threshold,
|
||||
GstClockTime * high_threshold)
|
||||
{
|
||||
|
@ -773,6 +787,15 @@ calculate_track_thresholds (GstAdaptiveDemux * demux,
|
|||
*low_threshold = demux->buffering_low_watermark_time;
|
||||
}
|
||||
|
||||
if (*low_threshold == 0) {
|
||||
/* This implies both low level properties were 0, the default is 10s unless
|
||||
* the subclass has specified a recommended buffering threshold */
|
||||
*low_threshold = 10 * GST_SECOND;
|
||||
if (GST_CLOCK_TIME_IS_VALID (stream->recommended_buffering_threshold))
|
||||
*low_threshold =
|
||||
MIN (stream->recommended_buffering_threshold, *low_threshold);
|
||||
}
|
||||
|
||||
*high_threshold =
|
||||
demux->buffering_high_watermark_fragments * fragment_duration;
|
||||
if (*high_threshold == 0 || (demux->buffering_high_watermark_time != 0
|
||||
|
@ -800,9 +823,11 @@ calculate_track_thresholds (GstAdaptiveDemux * demux,
|
|||
(*low_threshold != 0 && *low_threshold > *high_threshold)) {
|
||||
*high_threshold = *low_threshold;
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (demux);
|
||||
}
|
||||
|
||||
#define ABSDIFF(a,b) ((a) < (b) ? (b) - (a) : (a) - (b))
|
||||
static gboolean
|
||||
gst_adaptive_demux2_stream_wait_for_output_space (GstAdaptiveDemux * demux,
|
||||
GstAdaptiveDemux2Stream * stream, GstClockTime fragment_duration)
|
||||
|
@ -816,8 +841,13 @@ gst_adaptive_demux2_stream_wait_for_output_space (GstAdaptiveDemux * demux,
|
|||
GstClockTime low_threshold = 0, high_threshold = 0;
|
||||
GList *iter;
|
||||
|
||||
calculate_track_thresholds (demux, fragment_duration,
|
||||
calculate_track_thresholds (demux, stream, fragment_duration,
|
||||
&low_threshold, &high_threshold);
|
||||
GST_DEBUG_OBJECT (stream,
|
||||
"Thresholds low:%" GST_TIME_FORMAT " high:%" GST_TIME_FORMAT
|
||||
" recommended:%" GST_TIME_FORMAT, GST_TIME_ARGS (low_threshold),
|
||||
GST_TIME_ARGS (high_threshold),
|
||||
GST_TIME_ARGS (stream->recommended_buffering_threshold));
|
||||
|
||||
/* If there are no tracks at all, don't wait. If there are no active
|
||||
* tracks, keep filling until at least one track is full. If there
|
||||
|
@ -826,8 +856,9 @@ gst_adaptive_demux2_stream_wait_for_output_space (GstAdaptiveDemux * demux,
|
|||
for (iter = stream->tracks; iter; iter = iter->next) {
|
||||
GstAdaptiveDemuxTrack *track = (GstAdaptiveDemuxTrack *) iter->data;
|
||||
|
||||
/* Update the buffering threshold */
|
||||
if (low_threshold != track->buffering_threshold) {
|
||||
/* Update the buffering threshold if it changed by more than a second */
|
||||
if (ABSDIFF (low_threshold, track->buffering_threshold) > GST_SECOND) {
|
||||
GST_DEBUG_OBJECT (stream, "Updating threshold");
|
||||
/* The buffering threshold for this track changed, make sure to
|
||||
* re-check buffering status */
|
||||
update_buffering = TRUE;
|
||||
|
|
|
@ -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 (10 * GST_SECOND)
|
||||
#define DEFAULT_BUFFERING_LOW_WATERMARK_TIME 0 /* Automatic */
|
||||
#define DEFAULT_BUFFERING_HIGH_WATERMARK_FRAGMENTS 0.0
|
||||
#define DEFAULT_BUFFERING_LOW_WATERMARK_FRAGMENTS 0.0
|
||||
|
||||
|
@ -486,7 +486,7 @@ gst_adaptive_demux_class_init (GstAdaptiveDemuxClass * klass)
|
|||
PROP_BUFFERING_LOW_WATERMARK_TIME,
|
||||
g_param_spec_uint64 ("low-watermark-time",
|
||||
"Low buffering watermark size (ns)",
|
||||
"Low watermark for parsed data below which downloads are resumed (in ns, 0=disable)",
|
||||
"Low watermark for parsed data below which downloads are resumed (in ns, 0=automatic)",
|
||||
0, G_MAXUINT64, DEFAULT_BUFFERING_LOW_WATERMARK_TIME,
|
||||
G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
|
|
@ -359,6 +359,9 @@ struct _GstAdaptiveDemux2Stream
|
|||
|
||||
/* OR'd set of stream types in this stream */
|
||||
GstStreamType stream_type;
|
||||
|
||||
/* The buffering threshold recommended by the subclass */
|
||||
GstClockTime recommended_buffering_threshold;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -2425,6 +2425,10 @@ gst_hls_demux_update_fragment_info (GstAdaptiveDemux2Stream * stream)
|
|||
|
||||
stream->fragment.duration = file->duration;
|
||||
|
||||
stream->recommended_buffering_threshold =
|
||||
gst_hls_media_playlist_recommended_buffering_threshold
|
||||
(hlsdemux_stream->playlist);
|
||||
|
||||
if (discont)
|
||||
stream->discont = TRUE;
|
||||
|
||||
|
|
|
@ -1473,6 +1473,18 @@ gst_hls_media_playlist_get_seek_range (GstHLSMediaPlaylist * m3u8,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
GstClockTime
|
||||
gst_hls_media_playlist_recommended_buffering_threshold (GstHLSMediaPlaylist *
|
||||
playlist)
|
||||
{
|
||||
if (!playlist->duration || !GST_CLOCK_TIME_IS_VALID (playlist->duration)
|
||||
|| playlist->segments->len == 0)
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
|
||||
/* The recommended buffering threshold is 1.5 average segment duration */
|
||||
return 3 * (playlist->duration / playlist->segments->len) / 2;
|
||||
}
|
||||
|
||||
GstHLSRenditionStream *
|
||||
gst_hls_rendition_stream_ref (GstHLSRenditionStream * media)
|
||||
{
|
||||
|
|
|
@ -225,6 +225,9 @@ gst_hls_media_playlist_seek (GstHLSMediaPlaylist *playlist,
|
|||
void
|
||||
gst_hls_media_playlist_dump (GstHLSMediaPlaylist* self);
|
||||
|
||||
GstClockTime
|
||||
gst_hls_media_playlist_recommended_buffering_threshold (GstHLSMediaPlaylist *playlist);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_HLS_RENDITION_STREAM_TYPE_INVALID = -1,
|
||||
|
|
Loading…
Reference in a new issue