hlsdemux2: Do a full playlist reload if delta fails

If we do a delta playlist request but then can't merge the result with the
existing playlist, retry with a full playlist request.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3883>
This commit is contained in:
Jan Schmidt 2022-11-25 01:14:12 +11:00 committed by GStreamer Marge Bot
parent 874b665710
commit 55f6cd9243
3 changed files with 53 additions and 32 deletions

View file

@ -1240,8 +1240,9 @@ apply_directives_to_uri (GstHLSDemuxStream * stream,
if (dl_params->flags & PLAYLIST_DOWNLOAD_FLAG_BLOCKING_REQUEST
&& dl_params->next_msn != -1) {
GST_LOG_OBJECT (stream,
"Doing HLS blocking request with MSN %" G_GINT64_FORMAT " part %"
G_GINT64_FORMAT, dl_params->next_msn, dl_params->next_part);
"Doing HLS blocking request for URI %s with MSN %" G_GINT64_FORMAT
" part %" G_GINT64_FORMAT, playlist_uri, dl_params->next_msn,
dl_params->next_part);
gchar *next_msn_str =
g_strdup_printf ("%" G_GINT64_FORMAT, dl_params->next_msn);
@ -1265,43 +1266,45 @@ apply_directives_to_uri (GstHLSDemuxStream * stream,
}
static GstHLSMediaPlaylist *
download_media_playlist (GstHLSDemuxStream * stream, gchar * uri,
download_media_playlist (GstHLSDemuxStream * stream, gchar * orig_uri,
GError ** err, GstHLSMediaPlaylist * current)
{
const gchar *main_uri;
DownloadRequest *download;
GstBuffer *buf;
gchar *playlist_data;
GstHLSMediaPlaylist *playlist = NULL;
gchar *base_uri;
gboolean playlist_uri_change = FALSE;
struct PlaylistDownloadParams dl_params = { 0, };
gboolean allow_skip = TRUE;
GstAdaptiveDemux2Stream *base_stream = GST_ADAPTIVE_DEMUX2_STREAM (stream);
GstAdaptiveDemux *demux = base_stream->demux;
const gchar *main_uri = gst_adaptive_demux_get_manifest_ref_uri (demux);
main_uri = gst_adaptive_demux_get_manifest_ref_uri (demux);
retry:
struct PlaylistDownloadParams dl_params = { 0, };
/* If there's no previous playlist, or the URI changed this
* is not a refresh/update but a switch to a new playlist */
playlist_uri_change = (current == NULL || g_strcmp0 (uri, current->uri) != 0);
gboolean playlist_uri_change = (current == NULL
|| g_strcmp0 (orig_uri, current->uri) != 0);
if (!playlist_uri_change) {
GST_LOG_OBJECT (stream, "Updating the playlist");
/* See if we can do a delta playlist update (if the playlist age is less than
* one half of the Skip Boundary */
GstClockTime now = gst_adaptive_demux2_get_monotonic_time (demux);
GstClockTimeDiff playlist_age = GST_CLOCK_DIFF (current->playlist_ts, now);
if (GST_CLOCK_TIME_IS_VALID (current->skip_boundary) && allow_skip) {
GstClockTime now = gst_adaptive_demux2_get_monotonic_time (demux);
GstClockTimeDiff playlist_age =
GST_CLOCK_DIFF (current->playlist_ts, now);
if (GST_CLOCK_TIME_IS_VALID (current->playlist_ts) &&
GST_CLOCK_TIME_IS_VALID (current->skip_boundary) &&
playlist_age <= current->skip_boundary / 2) {
if (current->can_skip_dateranges) {
dl_params.flags |= PLAYLIST_DOWNLOAD_FLAG_SKIP_V2;
} else {
dl_params.flags |= PLAYLIST_DOWNLOAD_FLAG_SKIP_V1;
if (GST_CLOCK_TIME_IS_VALID (current->playlist_ts) &&
playlist_age <= current->skip_boundary / 2) {
if (current->can_skip_dateranges) {
dl_params.flags |= PLAYLIST_DOWNLOAD_FLAG_SKIP_V2;
} else {
dl_params.flags |= PLAYLIST_DOWNLOAD_FLAG_SKIP_V1;
}
}
} else if (GST_CLOCK_TIME_IS_VALID (current->skip_boundary)) {
GST_DEBUG_OBJECT (stream,
"Doing full playlist update after failed delta request");
}
}
@ -1318,10 +1321,9 @@ download_media_playlist (GstHLSDemuxStream * stream, gchar * uri,
}
}
gchar *target_uri = apply_directives_to_uri (stream, uri, &dl_params);
gchar *target_uri = apply_directives_to_uri (stream, orig_uri, &dl_params);
download =
downloadhelper_fetch_uri (demux->download_helper,
DownloadRequest *download = downloadhelper_fetch_uri (demux->download_helper,
target_uri, main_uri,
DOWNLOAD_FLAG_COMPRESS | DOWNLOAD_FLAG_FORCE_REFRESH, err);
@ -1333,6 +1335,9 @@ download_media_playlist (GstHLSDemuxStream * stream, gchar * uri,
/* If we got a permanent redirect, use that as the new
* playlist URI, otherwise set the base URI of the playlist
* to the redirect target if any (NULL if there was no redirect) */
GstHLSMediaPlaylist *playlist = NULL;
gchar *base_uri, *uri;
if (download->redirect_permanent && download->redirect_uri) {
uri = g_strdup (download->redirect_uri);
base_uri = NULL;
@ -1357,13 +1362,13 @@ download_media_playlist (GstHLSDemuxStream * stream, gchar * uri,
MAX (0, GST_CLOCK_DIFF (download_request_get_age (download),
download->download_start_time));
buf = download_request_take_buffer (download);
GstBuffer *buf = download_request_take_buffer (download);
download_request_unref (download);
/* there should be a buf if there wasn't an error (handled above) */
g_assert (buf);
playlist_data = gst_hls_buf_to_utf8_text (buf);
gchar *playlist_data = gst_hls_buf_to_utf8_text (buf);
gst_buffer_unref (buf);
if (playlist_data == NULL) {
@ -1396,7 +1401,18 @@ download_media_playlist (GstHLSDemuxStream * stream, gchar * uri,
* we did a delta playlist update */
if (!playlist_uri_change && current && playlist
&& playlist->skipped_segments > 0) {
gst_hls_media_playlist_sync_skipped_segments (playlist, current);
if (!gst_hls_media_playlist_sync_skipped_segments (playlist, current)) {
GST_DEBUG_OBJECT (stream,
"Could not merge delta update to playlist. Retrying with full request");
/* Delta playlist update failed. Load a full playlist */
allow_skip = FALSE;
gst_hls_media_playlist_unref (playlist);
g_free (uri);
g_free (base_uri);
goto retry;
}
}
out:

View file

@ -1908,12 +1908,13 @@ find_segment_in_playlist (GstHLSMediaPlaylist * playlist,
/* Match up the first segment in a delta playlist against the reference and transfer
* over preceding segments if we can */
void
gboolean
gst_hls_media_playlist_sync_skipped_segments (GstHLSMediaPlaylist * m3u8,
GstHLSMediaPlaylist * reference)
{
/* Trivially there might be nothing to do (not a delta playlist) */
if (m3u8->skipped_segments < 1 || m3u8->segments->len < 1)
return;
return TRUE;
/* find the first non-skipped segment from this playlist
* in the reference playlist, then transfer over as many
@ -1936,11 +1937,13 @@ gst_hls_media_playlist_sync_skipped_segments (GstHLSMediaPlaylist * m3u8,
}
if (!found_ref_seg)
return; /* Couldn't match the segment */
return FALSE; /* Couldn't match the segment */
/* Found the first segment of this playlist in the reference. Transfer over
* as many skipped segments as we can */
guint segs_avail = MIN (ref_idx, m3u8->skipped_segments);
if (segs_avail < 1)
return FALSE;
GST_DEBUG
("Transferring %u skipped segments from reference playlist starting at index %u",
@ -1957,6 +1960,8 @@ gst_hls_media_playlist_sync_skipped_segments (GstHLSMediaPlaylist * m3u8,
g_ptr_array_insert (m3u8->segments, 0,
gst_m3u8_media_segment_ref (segment));
}
return TRUE;
}
/* Given a media segment (potentially from another media playlist), find the

View file

@ -283,7 +283,7 @@ gst_hls_media_playlist_parse (gchar * data,
const gchar * uri,
const gchar * base_uri);
void
gboolean
gst_hls_media_playlist_sync_skipped_segments (GstHLSMediaPlaylist * m3u8,
GstHLSMediaPlaylist * reference);