Some streams in the wild have empty segments at the beginning and
hlsdemux2 use to stall forever while we can handle it by processing
the following ones. The gap handling mechanism in adaptivedemux2
works properly and pushes the required gaps.
Update validate medias so the hls stream is present.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6034>
By setting the earliest time to timestamp + 2 * diff there would be a difference
of 1 * diff between the current clock time and the earliest time the element
would let through in the future. If e.g. a frame is arriving 30s late at the
sink, then not just all frames up to that point would be dropped but also 30s of
frames after the current clock time.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7459>
The initial goal was to support the case where we are paused watching a live
stream, and when we resume we can no longer resume from the previously
downloaded position. In that case we internally do a flushing seek back to the
"current live head position". This was also extended since to be able to
handle (utterly broken) servers when we can't really figure out where we are
anymore and therefore trigger that lost sync so we can try to get back on our
feet.
This does fix the issue... but results in spurious FLUSH_{START|STOP} events
being sent downstream. While that's fine for regular playback scenarios, it's a
bit of a wild scenario since a lot of pipelines/applications don't expect such
events when it wasn't triggered by downstream/application.
Fixes#3605
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7005>
Some servers might not provide 100% matching PDT when doing updates, or accross
variants. This would cause the code matching segments using PDT to fail if the
segment PDT was 1 microsecond (or whatever small value) before the candidate
segment. And would pick the (wrong) following segment as the matching one.
In order to be more tolerant when matching, we instead check whether the
candidate segment is within the first segment of the segment we are trying to
match.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6610>
If we end up with a segment with an internal time that varies from the supposed
one, this could be for two reasons:
* We guess-timated the wrong segment to go to when advancing or switching
variants. In that case we try to find the actual segment to go to (just before
this change).
* There was a complete playlist change (for whatever reason) and we can't find a
replacement. In that case we want to carry on playback from this position but
need to remember that we moved (by setting the stream to DISCONT, and
resetting the new mapping).
Fixes playback on several broken stream
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6610>
Since the default value of `m3u8->discont_sequence` (before parsing of the
playlist data) was 0 .. we would never properly detect the presence of that
field if it was present with a value of 0.
This would later on cause havoc in playlist synchronization where we would
assume it didn't have a discontinuity sequence specified (whereas it did, and it
was 0).
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6610>
A lot of streams will do a poor job of estimating proper duration of fragments
in the playlist, but over several fragments have it correct.
Instead of constantly trying to realign the estimated stream time, allow for a
more realistic tolerance of 3-4 video frames
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6610>
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/6610>
When dealing with live streams, the function was assuming that all segments of
the playlist had valid stream_time. But that isn't TRUE, for example in the case
of failing to synchronize playlists.
Fixes losing sync due to not being able to match playlist on updates
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6610>
Set as much information as possible on the slot (including the associated
track) *before* the associated source pad is added to the element.
We need this so that incoming event/queries can be replied to if they are
received when adding the pad
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6690>
The tags and caps were leaked for unknown streams, I'm not sure they'd be valid
in that case, but better safe than sorry.
The tags ownership is transfered when calling `gst_adaptive_demux_track_new()`
so unreffing those afterwards was a mistake.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5714>
There is a race condition where transfer has not been submitted yet while the
request is cancelled which leads to the transfer state going back to
`DOWNLOAD_REQUEST_STATE_OPEN` and the user of the request to get signalled about
its completion (and the task actually happening after it was cancelled) leading
to assertions and misbehaviours.
To ensure that this race can't happen, we start differentiating between the
UNSENT and CANCELLED states as in the normal case, when entering `submit_request`
the state is UNSENT and at that point we need to know that it is not because
the request has been cancelled.
In practice this case lead to an assertion in
`gst_adaptive_demux2_stream_begin_download_uri` because in a previous call to
`gst_adaptive_demux2_stream_stop_default` we cancelled the previous request and
setup a new one while it had not been submitted yet and then got a `on_download_complete`
callback called from that previous cancelled request and then we tried to do
`download_request_set_uri` on a request that was still `in_use`, leading to
something like:
```
#0: 0x0000000186655ec8 g_assert (request->in_use == FALSE)assert.c:0
#1: 0x00000001127236b8 libgstadaptivedemux2.dylib`download_request_set_uri(request=0x000060000017cc00, uri="https://XXX/chunk-stream1-00002.webm", range_start=0, range_end=-1) at downloadrequest.c:361
#2: 0x000000011271cee8 libgstadaptivedemux2.dylib`gst_adaptive_demux2_stream_begin_download_uri(stream=0x00000001330f1800, uri="https://XXX/chunk-stream1-00002.webm", start=0, end=-1) at gstadaptivedemux-stream.c:1447
#3: 0x0000000112719898 libgstadaptivedemux2.dylib`gst_adaptive_demux2_stream_load_a_fragment [inlined] gst_adaptive_demux2_stream_download_fragment(stream=0x00000001330f1800) at gstadaptivedemux-stream.c:0
#4: 0x00000001127197f8 libgstadaptivedemux2.dylib`gst_adaptive_demux2_stream_load_a_fragment(stream=0x00000001330f1800) at gstadaptivedemux-stream.c:1969
#5: 0x000000011271c2a4 libgstadaptivedemux2.dylib`gst_adaptive_demux2_stream_next_download(stream=0x00000001330f1800) at gstadaptivedemux-stream.c:2112
```
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5435>
Is a seek is done on stream-collection post, there are no selected streams
yet. Therefore none would be chosen to adjust the key-unit seek.
If no streams are selected, fallback to a default stream (i.e. one which has
track(s) with GST_STREAM_FLAG_SELECT).
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3914>
When seeking is handled by the collection posting thread, there is a possibility
that some leftover data will be pushed by the stream thread.
Properly detect and reject those early segments (and buffers) by comparing it to
the main segment seqnum
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3914>