mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 13:11:06 +00:00
hlsdemux2: Fix handling of variant switching and playlist updates
When updating playlists, we want to know whether the updated playlist is continuous with the previous one. That is : if we advance, will the next fragment need to have the DISCONT buffer set on it or not. If that happens (because we switched variants, or the playlist all of a sudden changed) we remember that there is a pending discont for the next fragment. That will be used and resetted the next time we get the fragment information. Previously this was only partially done. And it was racy because it was set directly on `GstAdaptiveDemux2Stream->discont` when a playlist was updated, instead of when the next fragment was prepared. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6961>
This commit is contained in:
parent
726f2d8dc0
commit
dadf2ec56c
5 changed files with 66 additions and 32 deletions
|
@ -1291,12 +1291,13 @@ gst_hls_demux_stream_handle_playlist_update (GstHLSDemuxStream * stream,
|
||||||
const gchar * new_playlist_uri, GstHLSMediaPlaylist * new_playlist)
|
const gchar * new_playlist_uri, GstHLSMediaPlaylist * new_playlist)
|
||||||
{
|
{
|
||||||
GstHLSDemux *demux = GST_HLS_DEMUX_STREAM_GET_DEMUX (stream);
|
GstHLSDemux *demux = GST_HLS_DEMUX_STREAM_GET_DEMUX (stream);
|
||||||
|
gboolean found_segment_discont = FALSE;
|
||||||
|
|
||||||
/* Synchronize playlist with previous one. If we can't update the playlist
|
/* Synchronize playlist with previous one. If we can't update the playlist
|
||||||
* timing and inform the base class that we lost sync */
|
* timing and inform the base class that we lost sync */
|
||||||
if (stream->playlist
|
if (stream->playlist) {
|
||||||
&& !gst_hls_media_playlist_sync_to_playlist (new_playlist,
|
if (!gst_hls_media_playlist_sync_to_playlist (new_playlist,
|
||||||
stream->playlist)) {
|
stream->playlist, &found_segment_discont)) {
|
||||||
/* Failure to synchronize with the previous media playlist is only fatal for
|
/* Failure to synchronize with the previous media playlist is only fatal for
|
||||||
* variant streams. */
|
* variant streams. */
|
||||||
if (stream->is_variant) {
|
if (stream->is_variant) {
|
||||||
|
@ -1309,18 +1310,28 @@ gst_hls_demux_stream_handle_playlist_update (GstHLSDemuxStream * stream,
|
||||||
* variant playlist which is constantly updated */
|
* variant playlist which is constantly updated */
|
||||||
if (demux->main_stream->playlist
|
if (demux->main_stream->playlist
|
||||||
&& !gst_hls_media_playlist_sync_to_playlist (new_playlist,
|
&& !gst_hls_media_playlist_sync_to_playlist (new_playlist,
|
||||||
demux->main_stream->playlist)) {
|
demux->main_stream->playlist, &found_segment_discont)) {
|
||||||
GST_DEBUG_OBJECT (stream,
|
GST_DEBUG_OBJECT (stream,
|
||||||
"Could not do fallback synchronization of rendition stream to variant stream");
|
"Could not do fallback synchronization of rendition stream to variant stream");
|
||||||
goto lost_sync;
|
goto lost_sync;
|
||||||
}
|
}
|
||||||
} else if (!stream->is_variant && demux->main_stream->playlist) {
|
}
|
||||||
|
} else {
|
||||||
|
found_segment_discont = TRUE;
|
||||||
|
if (!stream->is_variant && demux->main_stream->playlist) {
|
||||||
/* For initial rendition media playlist, attempt to synchronize the playlist
|
/* For initial rendition media playlist, attempt to synchronize the playlist
|
||||||
* against the variant stream. This is non-fatal if it fails. */
|
* against the variant stream. This is non-fatal if it fails. */
|
||||||
GST_DEBUG_OBJECT (stream,
|
GST_DEBUG_OBJECT (stream,
|
||||||
"Attempting to synchronize initial rendition stream with variant stream");
|
"Attempting to synchronize initial rendition stream with variant stream");
|
||||||
gst_hls_media_playlist_sync_to_playlist (new_playlist,
|
gst_hls_media_playlist_sync_to_playlist (new_playlist,
|
||||||
demux->main_stream->playlist);
|
demux->main_stream->playlist, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (stream, "Synchronized playlist. Update is discont : %d",
|
||||||
|
found_segment_discont);
|
||||||
|
if (found_segment_discont) {
|
||||||
|
stream->pending_discont = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->current_segment) {
|
if (stream->current_segment) {
|
||||||
|
@ -1665,12 +1676,14 @@ gst_hls_demux_stream_update_fragment_info (GstAdaptiveDemux2Stream * stream)
|
||||||
hlsdemux_stream->part_idx, GST_STIME_ARGS (part->stream_time));
|
hlsdemux_stream->part_idx, GST_STIME_ARGS (part->stream_time));
|
||||||
discont = stream->discont;
|
discont = stream->discont;
|
||||||
/* Use the segment discont flag only on the first partial segment */
|
/* Use the segment discont flag only on the first partial segment */
|
||||||
if (file->discont && hlsdemux_stream->part_idx == 0)
|
if ((hlsdemux_stream->pending_discont || file->discont)
|
||||||
|
&& hlsdemux_stream->part_idx == 0)
|
||||||
discont = TRUE;
|
discont = TRUE;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (stream, "Current segment stream_time %" GST_STIME_FORMAT,
|
GST_DEBUG_OBJECT (stream, "Current segment stream_time %" GST_STIME_FORMAT,
|
||||||
GST_STIME_ARGS (file->stream_time));
|
GST_STIME_ARGS (file->stream_time));
|
||||||
discont = file->discont || stream->discont;
|
discont = file->discont || stream->discont
|
||||||
|
|| hlsdemux_stream->pending_discont;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean need_header = GST_ADAPTIVE_DEMUX2_STREAM_NEED_HEADER (stream);
|
gboolean need_header = GST_ADAPTIVE_DEMUX2_STREAM_NEED_HEADER (stream);
|
||||||
|
@ -1747,6 +1760,7 @@ gst_hls_demux_stream_update_fragment_info (GstAdaptiveDemux2Stream * stream)
|
||||||
|
|
||||||
if (discont)
|
if (discont)
|
||||||
stream->discont = TRUE;
|
stream->discont = TRUE;
|
||||||
|
hlsdemux_stream->pending_discont = FALSE;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,11 @@ struct _GstHLSDemuxStream
|
||||||
GstClockTime presentation_offset;
|
GstClockTime presentation_offset;
|
||||||
|
|
||||||
gboolean pdt_tag_sent;
|
gboolean pdt_tag_sent;
|
||||||
|
|
||||||
|
/* The next segment needs to have the discont flag set on it. This is set when
|
||||||
|
* a playlist update was detected as not being continuous/contiguous with the
|
||||||
|
* previous one. */
|
||||||
|
gboolean pending_discont;
|
||||||
};
|
};
|
||||||
|
|
||||||
GstFlowReturn
|
GstFlowReturn
|
||||||
|
|
|
@ -1108,8 +1108,7 @@ gst_hls_demux_handle_variant_playlist_update (GstHLSDemux * demux,
|
||||||
main_uri, "uri", G_TYPE_STRING,
|
main_uri, "uri", G_TYPE_STRING,
|
||||||
uri, "bitrate", G_TYPE_INT, new_bandwidth, NULL)));
|
uri, "bitrate", G_TYPE_INT, new_bandwidth, NULL)));
|
||||||
|
|
||||||
/* Mark discont on the next packet after switching variant */
|
GST_DEBUG_OBJECT (demux, "Changed variant");
|
||||||
GST_ADAPTIVE_DEMUX2_STREAM (demux->main_stream)->discont = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2189,10 +2189,15 @@ gst_hls_media_playlist_get_starting_segment (GstHLSMediaPlaylist * self,
|
||||||
* This should be used when a reference media segment couldn't be matched in the
|
* This should be used when a reference media segment couldn't be matched in the
|
||||||
* playlist, but we still want to carry over the information from a reference
|
* playlist, but we still want to carry over the information from a reference
|
||||||
* playlist to an updated one. This can happen with live playlists where the
|
* playlist to an updated one. This can happen with live playlists where the
|
||||||
* reference media segment is no longer present but the playlists intersect */
|
* reference media segment is no longer present but the playlists intersect
|
||||||
|
*
|
||||||
|
* If the sync is sucessfull, discont will be set to TRUE if it was a perfect
|
||||||
|
* URI fragment match, else it will be FALSE (ex: match was done on PDT or
|
||||||
|
* SN/DSN).
|
||||||
|
**/
|
||||||
gboolean
|
gboolean
|
||||||
gst_hls_media_playlist_sync_to_playlist (GstHLSMediaPlaylist * playlist,
|
gst_hls_media_playlist_sync_to_playlist (GstHLSMediaPlaylist * playlist,
|
||||||
GstHLSMediaPlaylist * reference)
|
GstHLSMediaPlaylist * reference, gboolean * discont)
|
||||||
{
|
{
|
||||||
GstM3U8MediaSegment *res = NULL;
|
GstM3U8MediaSegment *res = NULL;
|
||||||
GstM3U8MediaSegment *cand = NULL;
|
GstM3U8MediaSegment *cand = NULL;
|
||||||
|
@ -2200,6 +2205,9 @@ gst_hls_media_playlist_sync_to_playlist (GstHLSMediaPlaylist * playlist,
|
||||||
gboolean is_before;
|
gboolean is_before;
|
||||||
gboolean matched_pdt = FALSE;
|
gboolean matched_pdt = FALSE;
|
||||||
|
|
||||||
|
if (discont)
|
||||||
|
*discont = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (playlist && reference, FALSE);
|
g_return_val_if_fail (playlist && reference, FALSE);
|
||||||
|
|
||||||
retry_without_dsn:
|
retry_without_dsn:
|
||||||
|
@ -2229,6 +2237,13 @@ retry_without_dsn:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (discont) {
|
||||||
|
/* If not a perfect match, mark as such */
|
||||||
|
GST_DEBUG ("Checking match uri cand: %s", cand->uri);
|
||||||
|
GST_DEBUG ("Checking match uri res : %s", res->uri);
|
||||||
|
*discont = g_strcmp0 (res->uri, cand->uri) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Carry over reference stream time */
|
/* Carry over reference stream time */
|
||||||
if (res->stream_time == GST_CLOCK_STIME_NONE) {
|
if (res->stream_time == GST_CLOCK_STIME_NONE) {
|
||||||
GstClockTimeDiff stream_time_offset = 0;
|
GstClockTimeDiff stream_time_offset = 0;
|
||||||
|
|
|
@ -302,7 +302,8 @@ gst_hls_media_playlist_sync_to_segment (GstHLSMediaPlaylist * m3u8,
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_hls_media_playlist_sync_to_playlist (GstHLSMediaPlaylist * m3u8,
|
gst_hls_media_playlist_sync_to_playlist (GstHLSMediaPlaylist * m3u8,
|
||||||
GstHLSMediaPlaylist * reference);
|
GstHLSMediaPlaylist * reference,
|
||||||
|
gboolean *discont);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_hls_media_playlist_has_next_fragment (GstHLSMediaPlaylist * m3u8,
|
gst_hls_media_playlist_has_next_fragment (GstHLSMediaPlaylist * m3u8,
|
||||||
|
|
Loading…
Reference in a new issue