mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
hlsdemux2: Fix position searching
The scanning is done in a reverse order, the proper full checks to do are therefore: * If the position is beyond half a "segment duration", it's in the following segment * If the position is within the first half of a segment, it's in that one * If the segment is the first one and the position is within half a duration backwards, we consider the position as being within that first segment Also handle the case where a "partial only" segment doesn't have a reliable duration, and therefore use the playlist target duration instead. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3883>
This commit is contained in:
parent
1c6364673d
commit
5935c8049a
1 changed files with 44 additions and 18 deletions
|
@ -1490,16 +1490,17 @@ gst_hls_media_playlist_find_partial_position (GstHLSMediaPlaylist * playlist,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* gst_hls_media_playlist_find_position() is used
|
||||
* when finding the segment or partial segment that corresponds
|
||||
* to our current playback position.
|
||||
/* gst_hls_media_playlist_find_position() is used when finding the segment or
|
||||
* partial segment that corresponds to our current playback position.
|
||||
*
|
||||
* If we're "playing partial segments", we want to find the partial segment
|
||||
whose stream_time matches the target position most closely (or fail
|
||||
if there's no partial segment, since the target partial segment was
|
||||
removed from the playlist and we lost sync.
|
||||
* If not currently playing partial segment, find the segment with a
|
||||
* stream_time that matches, or the partial segment exactly at the start
|
||||
* of the 'partial_only' segment.
|
||||
* whose stream_time matches the target position most closely (or fail if
|
||||
* there's no partial segment, since the target partial segment was removed from
|
||||
* the playlist and we lost sync.
|
||||
*
|
||||
* If not currently playing partial segment, find the segment with a stream_time
|
||||
* that matches, or the partial segment exactly at the start of the
|
||||
* 'partial_only' segment.
|
||||
*/
|
||||
gboolean
|
||||
gst_hls_media_playlist_find_position (GstHLSMediaPlaylist * playlist,
|
||||
|
@ -1507,7 +1508,7 @@ gst_hls_media_playlist_find_position (GstHLSMediaPlaylist * playlist,
|
|||
GstM3U8SeekResult * seek_result)
|
||||
{
|
||||
guint i;
|
||||
GstM3U8MediaSegment *seg = NULL;
|
||||
GstM3U8MediaSegment *seg = NULL, *following = NULL;
|
||||
|
||||
GST_DEBUG ("ts:%" GST_STIME_FORMAT
|
||||
" in_partial_segments %d (live %d) playlist uri: %s", GST_STIME_ARGS (ts),
|
||||
|
@ -1579,19 +1580,44 @@ gst_hls_media_playlist_find_position (GstHLSMediaPlaylist * playlist,
|
|||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we're doing a full segment match so check that the timestamp is
|
||||
* within half a segment duration of this segment stream_time. The maximum
|
||||
* of the current segment or target duration is used, because the partial-only
|
||||
* last segment might be quite small (as it's still being created), which
|
||||
* can cause a missed match otherwise */
|
||||
/* Otherwise, we're doing a full segment match so check that the timestamp
|
||||
* is within half a segment duration of this segment stream_time.
|
||||
*
|
||||
* If the final segment has partial fragments, the target duration is used
|
||||
* instead, because the partial-only last segment might be quite small (as
|
||||
* it's still being created), which can cause a missed match otherwise */
|
||||
GstClockTimeDiff match_threshold =
|
||||
MAX (cand->duration, playlist->targetduration) / 2;
|
||||
if (cand->stream_time + match_threshold >= ts
|
||||
&& cand->stream_time <= ts + match_threshold) {
|
||||
(cand->partial_only ? playlist->targetduration : cand->duration) / 2;
|
||||
|
||||
/* If the requesting position is beyond the halfway point of this segment,
|
||||
* we should return the following segment, which is closer to the requested
|
||||
* position. Note that it can be NULL */
|
||||
if (ts > cand->stream_time + match_threshold) {
|
||||
if (following)
|
||||
GST_DEBUG ("choosing following segment %d", seg_idx + 1);
|
||||
else
|
||||
GST_DEBUG ("After last segment");
|
||||
seg = following;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Else if the requested position is within the first half we are sure it's
|
||||
* this segment */
|
||||
if (ts >= cand->stream_time) {
|
||||
GST_DEBUG ("choosing segment %d", seg_idx);
|
||||
seg = cand;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Last check for the very first segment in the playlist */
|
||||
if (i == 1 && cand->stream_time <= ts + match_threshold) {
|
||||
GST_DEBUG ("choosing first segment");
|
||||
seg = cand;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We are scanning backwards, remember this as the following segment */
|
||||
following = cand;
|
||||
}
|
||||
|
||||
if (seg == NULL) {
|
||||
|
|
Loading…
Reference in a new issue