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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gst_hls_media_playlist_find_position() is used
|
/* gst_hls_media_playlist_find_position() is used when finding the segment or
|
||||||
* when finding the segment or partial segment that corresponds
|
* partial segment that corresponds to our current playback position.
|
||||||
* to our current playback position.
|
*
|
||||||
* If we're "playing partial segments", we want to find the partial segment
|
* If we're "playing partial segments", we want to find the partial segment
|
||||||
whose stream_time matches the target position most closely (or fail
|
* whose stream_time matches the target position most closely (or fail if
|
||||||
if there's no partial segment, since the target partial segment was
|
* there's no partial segment, since the target partial segment was removed from
|
||||||
removed from the playlist and we lost sync.
|
* 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
|
* If not currently playing partial segment, find the segment with a stream_time
|
||||||
* of the 'partial_only' segment.
|
* that matches, or the partial segment exactly at the start of the
|
||||||
|
* 'partial_only' segment.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_hls_media_playlist_find_position (GstHLSMediaPlaylist * playlist,
|
gst_hls_media_playlist_find_position (GstHLSMediaPlaylist * playlist,
|
||||||
|
@ -1507,7 +1508,7 @@ gst_hls_media_playlist_find_position (GstHLSMediaPlaylist * playlist,
|
||||||
GstM3U8SeekResult * seek_result)
|
GstM3U8SeekResult * seek_result)
|
||||||
{
|
{
|
||||||
guint i;
|
guint i;
|
||||||
GstM3U8MediaSegment *seg = NULL;
|
GstM3U8MediaSegment *seg = NULL, *following = NULL;
|
||||||
|
|
||||||
GST_DEBUG ("ts:%" GST_STIME_FORMAT
|
GST_DEBUG ("ts:%" GST_STIME_FORMAT
|
||||||
" in_partial_segments %d (live %d) playlist uri: %s", GST_STIME_ARGS (ts),
|
" 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
|
/* Otherwise, we're doing a full segment match so check that the timestamp
|
||||||
* within half a segment duration of this segment stream_time. The maximum
|
* is within half a segment duration of this segment stream_time.
|
||||||
* 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
|
* If the final segment has partial fragments, the target duration is used
|
||||||
* can cause a missed match otherwise */
|
* 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 =
|
GstClockTimeDiff match_threshold =
|
||||||
MAX (cand->duration, playlist->targetduration) / 2;
|
(cand->partial_only ? playlist->targetduration : cand->duration) / 2;
|
||||||
if (cand->stream_time + match_threshold >= ts
|
|
||||||
&& cand->stream_time <= ts + match_threshold) {
|
/* 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);
|
GST_DEBUG ("choosing segment %d", seg_idx);
|
||||||
seg = cand;
|
seg = cand;
|
||||||
break;
|
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) {
|
if (seg == NULL) {
|
||||||
|
|
Loading…
Reference in a new issue