diff --git a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json index a110f533fc..550568f317 100644 --- a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json +++ b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json @@ -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", diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c index 0594da2be4..cfcb3bcd83 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c @@ -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; diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c index 28bdb4a07b..f4ff4d5f74 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c @@ -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)); diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h index ea4a473146..186e21d1b2 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h @@ -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; }; /** diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c index eebafdcded..9e5f8682d5 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/gsthlsdemux.c @@ -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; diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.c index 3a68d16b54..511ce43d7b 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.c @@ -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) { diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.h b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.h index c6a22a91f3..63238fdb72 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.h +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/hls/m3u8.h @@ -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,