hlsdemux2: Use partial segment for playlist update interval

When playing LL-HLS playlists in LL-HLS mode, update the playlist more often (on
the partial segment interval) or else we end up downloading them in bursts and
playing further from the live edge than intended.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3883>
This commit is contained in:
Jan Schmidt 2022-11-25 03:57:38 +11:00 committed by GStreamer Marge Bot
parent 55f6cd9243
commit 268a25b979
3 changed files with 60 additions and 16 deletions

View file

@ -1675,6 +1675,58 @@ lost_sync:
} }
} }
GstClockTime
gst_hls_demux_stream_get_playlist_reload_interval (GstHLSDemuxStream * stream)
{
GstHLSMediaPlaylist *playlist = stream->playlist;
if (playlist == NULL)
return GST_CLOCK_TIME_NONE; /* No playlist yet */
if (!gst_hls_media_playlist_is_live (playlist))
return GST_CLOCK_TIME_NONE; /* Not live playback */
/* Use the most recent segment (or part segment) duration, as per
* https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-11#section-6.3.4
*/
GstClockTime target_duration = GST_CLOCK_TIME_NONE;
GstClockTime min_reload_interval = playlist->targetduration / 2;
if (playlist->segments->len) {
GstM3U8MediaSegment *last_seg =
g_ptr_array_index (playlist->segments, playlist->segments->len - 1);
target_duration = last_seg->duration;
if (stream->llhls_enabled && last_seg->partial_segments) {
GstM3U8PartialSegment *last_part =
g_ptr_array_index (last_seg->partial_segments,
last_seg->partial_segments->len - 1);
target_duration = last_part->duration;
if (GST_CLOCK_TIME_IS_VALID (playlist->partial_targetduration)) {
min_reload_interval = playlist->partial_targetduration / 2;
} else {
min_reload_interval = target_duration / 2;
}
}
} else if (stream->llhls_enabled
&& GST_CLOCK_TIME_IS_VALID (playlist->partial_targetduration)) {
target_duration = playlist->partial_targetduration;
min_reload_interval = target_duration / 2;
} else if (playlist->version > 5) {
target_duration = playlist->targetduration;
}
if (playlist->reloaded && target_duration > min_reload_interval) {
GST_DEBUG_OBJECT (stream,
"Playlist didn't change previously, returning lower update interval");
target_duration = min_reload_interval;
}
return target_duration;
}
static GstFlowReturn static GstFlowReturn
gst_hls_demux_stream_update_rendition_playlist (GstHLSDemux * demux, gst_hls_demux_stream_update_rendition_playlist (GstHLSDemux * demux,
GstHLSDemuxStream * stream) GstHLSDemuxStream * stream)

View file

@ -165,6 +165,9 @@ gst_hls_demux_stream_seek (GstAdaptiveDemux2Stream * stream, gboolean forward,
GstFlowReturn GstFlowReturn
gst_hls_demux_stream_update_media_playlist (GstHLSDemuxStream * stream, gchar ** uri, GError ** err); gst_hls_demux_stream_update_media_playlist (GstHLSDemuxStream * stream, gchar ** uri, GError ** err);
GstClockTime
gst_hls_demux_stream_get_playlist_reload_interval (GstHLSDemuxStream * stream);
void void
gst_hls_demux_stream_clear_pending_data (GstHLSDemuxStream * hls_stream, gst_hls_demux_stream_clear_pending_data (GstHLSDemuxStream * hls_stream,
gboolean force); gboolean force);

View file

@ -745,7 +745,7 @@ gst_hls_demux_is_live (GstAdaptiveDemux * demux)
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux); GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
gboolean is_live = FALSE; gboolean is_live = FALSE;
if (hlsdemux->main_stream) if (hlsdemux->main_stream && hlsdemux->main_stream->playlist)
is_live = gst_hls_media_playlist_is_live (hlsdemux->main_stream->playlist); is_live = gst_hls_media_playlist_is_live (hlsdemux->main_stream->playlist);
return is_live; return is_live;
@ -1258,22 +1258,11 @@ gst_hls_demux_get_manifest_update_interval (GstAdaptiveDemux * demux)
{ {
GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux); GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
GstClockTime target_duration = 5 * GST_SECOND; GstClockTime target_duration = 5 * GST_SECOND;
GstHLSDemuxStream *main_stream = hlsdemux->main_stream;
if (hlsdemux->main_stream && hlsdemux->main_stream->playlist) { if (main_stream) {
GstHLSMediaPlaylist *playlist = hlsdemux->main_stream->playlist; target_duration =
gst_hls_demux_stream_get_playlist_reload_interval (main_stream);
if (playlist->version > 5) {
target_duration = hlsdemux->main_stream->playlist->targetduration;
} else if (playlist->segments->len) {
GstM3U8MediaSegment *last_seg =
g_ptr_array_index (playlist->segments, playlist->segments->len - 1);
target_duration = last_seg->duration;
}
if (playlist->reloaded && target_duration > (playlist->targetduration / 2)) {
GST_DEBUG_OBJECT (demux,
"Playlist didn't change previously, returning lower update interval");
target_duration /= 2;
}
} }
GST_DEBUG_OBJECT (demux, "Returning update interval of %" GST_TIME_FORMAT, GST_DEBUG_OBJECT (demux, "Returning update interval of %" GST_TIME_FORMAT,