Adaptive demuxers need to start downloading from specific positions
(fragments) for every stream, this means that all streams can snap-seek
to a different position when requested. Snap seeking in this case will
be done in 2 steps:
1) do the snap seeking on the pad that received the seek event and
get the final position
2) use this position to do a regular seek on the other streams to
make sure they all start from the same position
More arguments were added to the stream_seek function, allowing better control
of how seeking is done. Knowing the flags and the playback direction allows
subclasses to handle snap-seeking.
And also adds a new return parameter to inform of the final
selected seeking position that is used to align the other streams.
https://bugzilla.gnome.org/show_bug.cgi?id=759158
Handling the ghostpad and its internal pad was causing more issues
than helping because of their coupled activation/deactivation
actions.
As we have to install custom chain,event and query functions it is
better to use a floating sink pad internally in the demuxer and just
use those pad functions to push through a standard pad in the demuxer
https://bugzilla.gnome.org/show_bug.cgi?id=757951
Dashdemux has set the width and height information from MPD manifest.
Some embedded devices which are not insufficient H/W resources need more information such as framerate
to assign H/W resources. So I suggested that dashdemux also needs to set the framerate information from MDP manifest.
https://bugzilla.gnome.org/show_bug.cgi?id=758515
If MPD@suggestedPresentationDelay is not present in the manifest,
dashdemux selects the fragment closest to the most recently generated
fragment. This causes a playback issue because this choice does not allow
the DASH client to build up any buffer of downloaded fragments without
pausing playback. This is because by definition new fragments appear on
the server in real-time (e.g. if segment duration is 4 seconds, a new
fragment will appear on the server every 4 seconds). If the starting
playback position was n*segmentDuration seconds behind "now", the DASH
client could download up to 'n' fragments faster than realtime before it
reached the point where it needed to wait for fragments to appear on the
server.
The MPD@suggestedPresentationDelay attribute allows a content publisher
to provide a suggested starting position that is behind the current
"live" position.
If the MPD@suggestedPresentationDelay attribute is not present, provide
a suitable default value as a property of the dashdemux element. To
allow the default presentation delay to be specified either using
fragments or seconds, the property is a string that contains a number
and a unit (e.g. "10 seconds", "4 fragments", "2500ms").
Create src pads for Representations that contain timed-text subtitles,
both when the subtitles are encapsulated in ISO BMFF (i.e., the
Representation has mimeType "application/mp4") and when they are
unencapsulated (i.e., the Representation has mimeType
"application/ttml+xml").
https://bugzilla.gnome.org/show_bug.cgi?id=747774
gst_uri_join_strings() will return the second parameter if it is an absolute
URI. No need to do a (wrong) check if the URI is absolute or not beforehand.
https://bugzilla.gnome.org/show_bug.cgi?id=755134
Even if it doesn't actually advance the subfragment in the default way
for streams that have subfragments, it can help the base class to return
EOS when there is no more fragments instead of signaling it that it should
continue downloading.
https://bugzilla.gnome.org/show_bug.cgi?id=755042
In dash isombff profile the fragment is split into subframents where
bitrate switching is possible. Also take that into consideration
when checking if a stream has next fragments.
Fix some very dubious code. The class methods should always
be set, and the instance-specific check should then be done
inside the method. For data_received that's there already, for
finish_fragment we need to add it.
https://bugzilla.gnome.org/show_bug.cgi?id=753937
When seeking to the last second of a mpd it would reject the seek
because the comparison was < instead of <=
This fails the important use case of seeking to the end of a file
to play it back in reverse from the end
The urn:mpeg:dash:utc:http-head:2014 method of time synchronisation
uses an HTTP HEAD request to a specified URL and then parses the
Date: HTTP response header.
This commit adds support to dashdemux for this method of time
synchronisation by making a HEAD request and then parsing the Date:
response.
This commit adds support to gstfragment to return the HTTP headers
and to uridownloader to support HEAD requests. To avoid creating a
new API, the RANGE get function is re-used (abused?) with start=-1
and end=-1 to indicate a HEAD request.
https://bugzilla.gnome.org/show_bug.cgi?id=752413
This commit addresses the following items from the code review:
use a portable way to define NTP_TO_UNIX_EPOCH,
fix memory leak on error, and
add documentation to UTCTiming parse functions
Using LL is not portable, so the G_GUINT64_CONSTANT needs to be instead.
If an error occurs during DNS resolution, the GError was not being
released, causing a memory leak.
https://bugzilla.gnome.org/show_bug.cgi?id=752413
Unless the DASH client can compensate for the difference between its
clock and the clock used by the server, the client might request
fragments that either not yet on the server or fragments that have
already been expired from the server. This is an issue because these
requests can propagate all the way back to the origin
ISO/IEC 23009-1:2014/Amd 1 [PDAM1] defines a new UTCTiming element to allow
a DASH client to track the clock used by the server generating the
DASH stream. Multiple UTCTiming elements might be present, to indicate
support for multiple methods of UTC time gathering. Each element can
contain a white space separated list of URLs that can be contacted
to discover the UTC time from the server's perspective.
This commit provides parsing of UTCTiming elements, unit tests of this
parsing and a function to poll a time server. This function
supports the following methods:
urn:mpeg:dash:utc:ntp:2014
urn:mpeg:dash:utc:http-xsdate:2014
urn:mpeg:dash:utc:http-iso:2014
urn:mpeg:dash:utc:http-ntp:2014
The manifest update task is used to poll the clock time server,
to save having to create a new thread.
When choosing the starting fragment number and when waiting for a
fragment to become available, the difference between the server's idea
of UTC and the client's idea of UTC is taken into account. For example,
if the server's time is behind the client's idea of UTC, we wait for
longer before requesting a fragment
[PDAM1]: http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=66068
dashdemux: support NTP time servers in UTCTiming elements
Use the gst_ntp_clock to support the use of an NTP server.
https://bugzilla.gnome.org/show_bug.cgi?id=752413
The gst_dash_demux_stream_update_fragment_info function could call
gst_dash_demux_stream_update_headers_info function twice. The
gst_dash_demux_stream_update_headers_info function will set header_uri and
index_uri to some newly allocated strings. The values set by the first call of
gst_dash_demux_stream_update_headers_info will leak when the function is
called for a second time.
The solution is to call gst_adaptive_demux_stream_fragment_clear before the
second call of gst_dash_demux_stream_update_headers_info
https://bugzilla.gnome.org/show_bug.cgi?id=753188
If a ContentProtection element is present in an AdaptationSet element,
send Protection events on the source pad, so that qtdemux can use this
information to correctly generate its source caps for DASH CENC
encrypted streams.
This allows qtdemux to support CENC encrypted DASH streams where the
content protection specific information is carried in the MPD file
rather than in pssh boxes in the initialisation segments.
This commit adds a new function to the adaptivedemux base class to allow
a GstEvent to be queued for a stream. The queue of events are sent the
next time a buffer is pushed for that stream.
https://bugzilla.gnome.org/show_bug.cgi?id=705991
When all fragments have already been downloaded on a live stream
dashdemux would busy loop as the default implementation of
has_next_fragment would return TRUE. Implement it to correctly
signal if adaptivedemux should wait for the manifest update before
trying to get new fragments.
When updating the manifest the timestamps on it might have changed a little
due to rounding and timescale conversions. If the change makes the timestamp
of the current segment to go up it makes dashdemux reposition to the previous
one causing one extra unnecessary download.
So when repositioning add an extra 10 microseconds to cover for that rounding
issues and increase the chance of falling in the same segment.
Additionally, also improve the time used when the client is already after the
last segment. Instead of using the last segment starting timestamp use the
final timestamp to make it reposition to the next one and not to the one that
has already been downloaded.
Segments are now stored with their repeat counts instead of spanding
them to multiple segments. This caused advancing to the next segment
using a single index to have to iterate over the whole list every time.
This commit addresses this by storing both the segment index as well
as the repeat index and makes advancing to next segment just an
increment of the repeat or the segment index.
There is a playback error when trying to play a content that
has 'application' mimeType. This commit prevents an exception from
setup text streams.
https://bugzilla.gnome.org/show_bug.cgi?id=747525
Bitrate-limit is already available in the baseclass and, even though
the bandwidth-usage name is better, hls and mss already used
bitrate-limit. This patch deprecates the bandwidth-usage and maps
it to the baseclass bitrate-limite.
By implementing get_live_seek_range.
As shown by :
gst-validate-1.0 playbin \
uri=http://dev-iplatforms.kw.bbc.co.uk/dash/news24-avc3/news24.php
This patch handles live seeking, by setting a live seek range
comprised between now - timeShiftBufferDepth and now.
The inteersting thing with this stream is that one can actually
ask fragments up to availabilityStartTime, but it seems quite clear
in the spec that content is only guaranteed to exist up to
timeShiftBufferDepth.
One can test live seeking this way :
gst-validate-1.0 playbin \
uri=http://dev-iplatforms.kw.bbc.co.uk/dash/news24-avc3/news24.php \
--set-scenario seek_back.scenario
with scenario being:
description, seek=true
seek, playback-time=position+5.0, start="position-600.0",
flags=accurate+flush
This example will play the stream, wait for five seconds, then seek back
to a position 10 minutes earlier.
https://bugzilla.gnome.org/show_bug.cgi?id=744362
Add more power to the chunk_received function (renamed to data_received)
and also to the fragment_finish function.
The data_received function must parse/decrypt the data if necessary and
also push it using the new push_buffer function that is exposed now. The
default implementation gets data from the stream adapter (all available)
and pushes it.
The fragment_finish function must also advance the fragment. The default
implementation only advances the fragment.
This allows the subsegment handling in dashdemux to continuously download
the same file from the server instead of stopping at every subsegment
boundary and starting a new request
gstdashdemux.c:1330:13: error: implicit conversion from enumeration type 'enum _GstAdaptiveDemuxFlowReturn' to different enumeration type
'GstFlowReturn' [-Werror,-Wenum-conversion]
ret = GST_ADAPTIVE_DEMUX_FLOW_SUBSEGMENT_END;
~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ISOBMFF profile allows definind subsegments in a segment. At those
subsegment boundaries the client can switch from one representation to
another as they have aligned indexes.
To handle those the 'sidx' index is parsed from the stream and the
entries point to pts/offset of the samples in the stream. Knowing that
the entries are aligned in the different representation allows the client
to switch mid fragment. In this profile a single fragment is used per
representation and the subsegments are contained in this fragment.
To notify the superclass about the subsegment boundary the chunk_received
function returns a special flow return that indicates that. In this case,
the super class will check if a more suitable bitrate is available and will
change to the same subsegment in this new representation.
It also requires special handling of the position in the stream as the
fragment advancing is now done by incrementing the index of the subsegment.
It will only advance to the next fragment once all subsegments have been
downloaded.
https://bugzilla.gnome.org/show_bug.cgi?id=741248
If EOS or ERROR happens before the download loop thread has reached its
g_cond_wait() call, then the g_cond_signal doesn't have any effect and
the download loop thread stucks later.
https://bugzilla.gnome.org/show_bug.cgi?id=735663
The internal pad still keeps its EOS flag and event as it can be assigned
after the flush-start/stop pair is sent. The EOS is assigned from the streaming
thread so this is racy.
To be sure to clear it, it has to be done after setting the source to READY to
be sure that its streaming thread isn't running.
https://bugzilla.gnome.org/show_bug.cgi?id=736012
If the language is not specified in the AdaptationSet, use the ContentComponent
node to get it. We only get it if there is only a single ContentComponent as
it doesn't seem clear on what to do if there are multiple entries
https://bugzilla.gnome.org/show_bug.cgi?id=732237
When a seek with a negative rate is requested, find the target
segment where gstsegment.stop belongs in and then download from
this segment backwards until the first segment.
This allows proper reverse playback.
When flushing, this will prevent dashdemux from trying to download more
fragments or more chunks of the same fragment before stopping.
Also improves the error handling to not transform everything non-ok into
an error.
https://bugzilla.gnome.org/show_bug.cgi?id=734014
Set up a message handling function to be able to catch errors
from the source element and signal the cond to allow the download
loop to retry the download.
Instead, use a source element linked to a ghostpad to provide
smaller buffers and more granular control for downstream
buffering elements while also reducing startup latency
Incorrect time scaling in gst_dash_demux_wait_for_fragment_to_be_available()
means that media segments are fetched before their availablity time. This
patch fixes this.
https://bugzilla.gnome.org/show_bug.cgi?id=724875
demux->last_manifest_update is not initialised at startup, with the
effect that live manifests are reloaded immediately after the download
loop begins. This patch fixes this.
https://bugzilla.gnome.org/show_bug.cgi?id=724790
Remove the dashdemux seeking function to use the one implemented
in mpdparser as it is more complete. This also makes dashdemux not
crash when seeking on streams that use segment templates.
Download and push from the same task, makes code a lot simpler
to maintain. Also pushing from separate threads avoids deadlocking
when gst_pad_push blocks due to downstream queues being full.
Use a single lock for all streams instead of having separate locks.
This makes maintenance easier and at most points we would need
a single lock before iterating on all streams data. So not much
is gained from individual locks.
Make dash playlists with multiple periods work again by waiting
to switch the periods when all streams have reached the end of
the current period. The stream_loop is responsible for advancing
the period, but the download loops will already start downloading
data for the next period as soon as possible.
Handle multiple languages by using the not-linked return to stop
the download task for that stream. It can be reactivated when
a reconfigure event is received. Stopping the unused streams is
relevant to save network bandwidth
Instead of having a single download task for all streams, this
commit makes each stream have its own download loop, allowing
parallel download of fragments.
always expose all streams instead of only exposing one of each type.
This is more aligned with gstreamer's way of working. Allows the user
to select the stream that it wants to use by linking its pad and leaving
the unused ones as unlinked.
Fixed up the error-handling code when downloading fragments.
Modifed the error-handling code to use positive logic when
testing for cancellation of the download loop.
https://bugzilla.gnome.org/show_bug.cgi?id=701404
There is an issue for live streams where download_loop will keep
downloading segments until it gets a 404 error for a segment
that has not yet been published. This is a problem because this
request for a segment that doesn't exist will propagate all the
way back to the origin server(s). This means that dashdemux causes
extra load on the origin server(s) for segments that aren't yet
available.
This patch uses availabilityStartTime, period
and the host's idea of UTC to decide if a fragment is available to
be requested from an HTTP server and filter out requests for fragments
that are not yet available.
https://bugzilla.gnome.org/show_bug.cgi?id=701404
gstdashdemux.c:1753: warning: format '%llu' expects type 'long long unsigned int', but argument 8 has type 'long unsigned int'
gstdashdemux.c:2224: warning: format '%llu' expects type 'long long unsigned int', but argument 9 has type 'guint64'
gstdashdemux.c:2224: warning: format '%llu' expects type 'long long unsigned int', but argument 10 has type 'guint64'
This prevents deadlocks on startup on files that have only a very
large buffer for a stream and the queue is filled and will lock on
the eos event that is pushed after the buffer. As no buffers have yet
been pushed to other streams, the pipeline locks on preroll
During a live stream it is possible for dashdemux to lag behind on a
slow connection or to rush ahead of the connection os too fast.
For the first case it is necessary to jump some segments ahead to be able to
continue playback as old segments are usually deleted from the server.
For the later, dashdemux should wait a little before attempting another
download do give time to the server to produce a new segment
Replaces the 2 likely larger lists with more appropriate structures
to improve performance.
Replaces S nodes GList for a GQueue, this reduces latency to startup
because of traversing the list just append an element.
Replaces the processed media segments GList for a GPtrArray as it is
constantly acessed by index during playback.
When dashdemux selects its first fragment, it always selects the
first fragment listed in the manifest. For on-demand content,
this is the correct behaviour. However for live content, this
behaviour is undesirable because the first fragment listed in the
manifest might be some considerable time behind "now".
The commit uses the host's idea of UTC and tries to find the
oldest fragment that contains samples for this time of day.
https://bugzilla.gnome.org/show_bug.cgi?id=701509
It was not properly divided by GST_SECONDS. Also fix issue with
max-buffering-time being multiplied by GST_SECONDS every time the
property is retrieved.
https://bugzilla.gnome.org/show_bug.cgi?id=700487
We only want to adjust the timestamps so that they start from 0 for live
streams. Non-live streams already start from 0 and after a seek we actually want
to timestamp to be the position we seek to.
Non-live streams should timestamp buffers with a running-time starting from
0. Since we already push a 0 -> -1 segment, bring the timestamps to 0
by subtracting the initial timestamp.
Manifest updates should be done periodically for live streams,
this patch makes the demuxer create a new manifest client for
the new version and transfers the stream position to the new
one, discarding the old one afterwards.