This commit fixes the following assumptions with live seeking:
1) start was always valid and of type GST_SEEK_TYPE_SET
2) direction was always forward
3) stop should be offsetted when handling non-accurate seeks before
the range start position.
In order to handle more live seeking use-cases (including reverse playback),
only do non-accurate start/stop value clamping for GST_SEEK_TYPE_SET values.
Also add a bit more debugging lines for issues
https://bugzilla.gnome.org/show_bug.cgi?id=782330
When dealing with live streams, we can't rely on GstSegment calculation
since it uses the segment duration to calculate the absolute values.
But since we are dealing with live *and* we know the ranges, we can
compute the absolute seeking values using the range stop (i.e. "now")
as the END position.
Allows seeking back to "live" by using start_type:GST_SEEK_TYPE_END
and start:0
https://bugzilla.gnome.org/show_bug.cgi?id=782228
The allowed live seek ranges returned by subclasses are "inclusive", that is
to say that the "range_stop" value they return is the highest acceptable position
one can seek to (i.e. "now").
Allow seeking to exactly that value
Rationale is to allow the manifest update task to continue running while
seeks are occurring. Otherwise, if the user reliably performs a seek
before the manifest is updated, then as the manifest task is reset on
seeks (and thus the time to wait between manifest updates), the manifest
would never be updated.
This fix makes the manifest update task free-running and continously
update even during seeks.
Some actions (Qos, reconfigure, ...) might take place before we finish pushing out flush_start.
One problem would be that:
1) The QOS handling in adaptivedemux takes the MANIFEST LOCK
That QOS event comes from basesink with its PREROLL_LOCK taken
2) FLUSH_START is sent from adaptivedemux with the MANIFEST_LOCK taken and the basesink flushing handler needs to take the PREROLL_LOCK
=> deadlock
https://bugzilla.gnome.org/show_bug.cgi?id=781320
At the moment that demux is waiting manifest update, the target sequence
of fragment was advanced already. So, checking stream_has_next_fragment()
means looking for the next fragment of target fragment.
This might cause unexpected buffering if each fragment has
large duration and manifest is listing only limited number of fragments.
https://bugzilla.gnome.org/show_bug.cgi?id=780494
When there are new pads pending for a bitrate switch, don't allow
EOS through from the old streams. It will be sent when the new pads are
ready, just before the old streams are removed.
This fixes racy bitrate switching with hlsdemux in urisourcebin
where old pads EOS before new pads appear and the entire pipeline can
EOS if those propagate fast enough
For duration queries on live streams, adaptivedemux ignores the query.
The problem then is that the query is answered by the downstream
qtdemux element, with the duration of the currently passing fragment.
This commit changes the behaviour of adaptivedemux to answer the duration
queries for live streams, returning GST_CLOCK_TIME_NONE.
https://bugzilla.gnome.org/show_bug.cgi?id=753879
If we need to send EOS on a pad that hasn't prerolled, generate
an error on the bus instead, otherwise the app will have no idea.
Fixes the HLS testFragmentNotFound test, which is waiting
for either EOS or an error.
To ensure that pads have caps when they are exposed, do
the exposing when all pending streams have prerolled an
output buffer, and only then EOS and remove any old pads.
Improves the switching sequence by making caps available
as soon as a pad appears.
With fixes from Seungha Yang <sh.yang@lge.com>
https://bugzilla.gnome.org/show_bug.cgi?id=758257
send_event() of parent class (i.e., GstBinClass) iterates srcpads
to send SEEK event. And performing it per srcpad is inefficient.
So, let's drop duplicated SEEK event by checking seqnum
https://bugzilla.gnome.org/show_bug.cgi?id=776612
The reason we previously used queue2 was to calculate the download rate,
but that wasn't entirely correct and we therefore calculate it before
queue2. We therefore now just need a simple queue.
When a MSS server hosts a live stream the fragments listed in the
manifest usually don't have accurate timestamps and duration, except
for the first fragment, which additionally stores timing information
for the few upcoming fragments. In this scenario it is useless to
periodically fetch and update the manifest and the fragments list can
be incrementally built by parsing the first/current fragment.
https://bugzilla.gnome.org/show_bug.cgi?id=755036
This changes the failure case to require a consecutive number of
failures rather than being spread out over the entire stream.
Fixes the case where fetching the manifest was intermittent.
https://bugzilla.gnome.org/show_bug.cgi?id=774177
For formats that need to update the manifest to know about new
fragments as they're being written by the server would never receive an
updated fragment list after a seek event
https://bugzilla.gnome.org/show_bug.cgi?id=774177
With MSVC, this gives the following warning:
warning C4305: 'function': truncation from 'double' to 'gfloat'
Apparently, MSVC does not figure out what type to use for constants
based on the assignment. This warning is very spammy, so let's try to
fix it.
In order to calculate the *actual* bitrate for downloading a fragment
we need to take into account the time since we requested the fragment.
Without this, the bitrate calculations (previously reported by queue2)
would be biased since they wouldn't take into account the request latency
(that is the time between the moment we request a specific URI and the
moment we receive the first byte of that request).
Such examples were it would be biased would be high-bandwith but high-latency
networks. If you download 5MB in 500ms, but it takes 200ms to get the first
byte, queue2 would report 80Mbit/s (5Mb in 500ms) , but taking the request
into account it is only 57Mbit/s (5Mb in 700ms).
While this would not cause too much issues if the above fragment represented
a much longer duration (5s of content), it would cause issues with short
ones (say 1s, or when doing keyframe-only requests which are even shorter)
where the code would expect to be able to download up to 80Mbit/s ... whereas
if we take the request time into account it's much lower (and we would
therefore end up doing late requests).
Also calculate the request latency for debugging purposes and further
usage (it could allow us to figure out the maximum request rate for
example).
https://bugzilla.gnome.org/show_bug.cgi?id=733959https://bugzilla.gnome.org/show_bug.cgi?id=772330
And scale the bitrate with the absolute rate (if it's bigger than 1.0) to get
to the real bitrate due to faster playback.
This allowed in my tests to play a stream with 10x speed without buffering as
the lowest bitrate is chosen, instead of staying/selecting the highest bitrate
and then buffering all the time.
It was previously disabled for not very well specified reasons, which seem to
be not valid anymore nowadays.
Prevent the manifest update loop from looping endlessly
after a seek event, by clearing the variable that tells
the task function not to immediately exit.
The new streams should not be exposed until all streams are done with the
current fragment. The old code is incorrect and actually only checked the
current stream. Fix this by properly checking all streams.
Also, ignore the current stream. The code is only reached when the current
stream finished downloading and since
07f49f15b1 ("adaptivedemux: On EOS, handle it
before waking download loop") download_finished is set after
gst_adaptive_demux_stream_advance_fragment_unlocked() is called.
Without this HLS playback with multiple streams is broken, because the new
streams are never exposed.
https://bugzilla.gnome.org/show_bug.cgi?id=770075
This allows to gradually download part of a fragment when the final size is
not known and only a part of it should be downloaded. For example when only
the moof should be parsed and/or a single keyframe should be downloaded.
https://bugzilla.gnome.org/show_bug.cgi?id=741104
This helps catch those 404 server errors in live streams when
seeking to the very beginning, as the server will handle a
request with some delay, which can cause it to drop the fragment
before sending it.
https://bugzilla.gnome.org/show_bug.cgi?id=753751
To allow adaptivedemux to make retry decisions, it needs to know what
sort of HTTP error has occurred. For example, the retry logic for a
410 error is different from a 504 error.
https://bugzilla.gnome.org/show_bug.cgi?id=753751
Some derived classes (at least dashdemux) expose a seeking range
based on wall clock. This means that a subsequent seek to the start
of this range will be before the allowed range.
To solve this, seeks without the ACCURATE flag are allowed to seek
before the start for live streams, in which case the segment is
shifted to start at the start of the new seek range. If there is
an end position, is is shifted too, to keep the duration constant.
https://bugzilla.gnome.org/show_bug.cgi?id=753751
Make state changes of internal elements more reliable by locking
their state, and ensuring that they aren't blocked pushing data
downstream before trying to set their state.
Add a boolean to avoid starting tasks when the main
thread is busy trying to shut the element down.
Try harder to make switching pads work better by
making sure concurrent downloads are finished before exposing
a new set of pads.
Release the manifest lock when signalling no-more-pads, as
that can call back into adaptivedemux again
If other stream fragments are still downloading but new streams
have been scheduled, don't expose them yet - wait until the last
one finishes. Otherwise, we can cancel a partially downloaded
auxilliary stream and cause a gap.
Drop the manifest lock when performing actions that might
call back into adaptivedemux and trigger deadlocks, such
as adding/removing pads or sending in-band events (EOS).
Unlock the manifest lock when changing the child bin state to
NULL, as it might call back to acquire the manifest lock when
shutting down pads.
Drop the manifest lock while pushing events.
In the case of KEY_UNIT and TRICKMODE_KEY_UNITS seeks, we want to
"snap" to the closest fragment.
Without this, we end up pushing out a segment which does not match
the first fragment timestamp being pushed out, resulting in one or
more buffers being eventually dropped because they are out of segment.