A realtime clock is used in many places, such as deciding which
fragment to select at start up and deciding how long to sleep
before a fragment becomes available. For example dashdemux needs
sample the client's estimate of UTC when selecting where to start
in a live DASH stream.
The problem with dashdemux calculating the client's idea of UTC is
that it makes it difficult to create unit tests, because the passage
of time is a factor in the test.
This commit changes dashdemux and adaptivedemux to use the
GstSystemClock, so that a unit test can replace the system clock when
it needs to be able to control the clock.
This commit makes no change to the behaviour under normal usage, as
GstSystemClock is based upon the system time.
https://bugzilla.gnome.org/show_bug.cgi?id=762147
The code in the gst_dash_demux_parse_http_xsdate() was trying to
handle the case where the string is not null terminated by resizing
the buffer and appending a zero byte. This does not work if the buffer
is exactly the length of the string because the gst_buffer_resize()
function does not re-allocate the buffer, it just changes its size.
If a buffer is passed to gst_dash_demux_parse_http_xsdate() that is
exactly the length of the string, the function fails with an assert
failure in gst_buffer_resize().
https://bugzilla.gnome.org/show_bug.cgi?id=762148
The function actually returns the segment availability start time (as defined by the standard).
That is at the end of the segment, but it is called availability start time.
Availability end time is something else (the time when the segment is no longer
available on the server). The function name was misleading.
https://bugzilla.gnome.org/show_bug.cgi?id=757655
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
For a live mpd, if availabilityStartTime is missing, adaptive demux asserts
with: Unexpected critical/warning: gst_date_time_to_g_date_time: assertion
'datetime != NULL' failed.
This patch improves the error message to:
Unexpected critical/warning: gst_mpd_client_seek_to_time: assertion
'client->mpd_node->availabilityStartTime != NULL' failed
https://bugzilla.gnome.org/show_bug.cgi?id=757602
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
gst_mpdparser_parse_utctiming_node does not validate the parsed values completely. The following scenarios are incorrectly accepted:
- elements with no schemeIdUri property should be rejected
- elements with unrecognized UTCTiming scheme should be rejected
- elements with empty values should be rejected
The last one triggers a division by 0 in gst_dash_demux_poll_clock_drift:
clock_drift->selected_url = clock_drift->selected_url % g_strv_length (urls);
because it urls is a valid pointer to an empty array.
https://bugzilla.gnome.org/show_bug.cgi?id=759547
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
The stream->cur_seg_template is set to the lowest available segment
template (representation or adaptation or period, in this order).
Because the template elements are inherited, the lowest template will
have all the elements the parents had, so there is no need to check the
parent for an element that is not found in the child (eg initialisation
or index).
https://bugzilla.gnome.org/show_bug.cgi?id=752714
The standard does not seem to make any particular explicit not
implicit reference to the signedness of durations, and the code
does not rely on such, nor on the negativity of the -1 value
that's used as a placeholder when a duration property is not
present in the XML.
https://bugzilla.gnome.org/show_bug.cgi?id=750847
According to the standard:
"SegmentBase, SegmentTemplate and SegmentList shall inherit
attributes and elements from the same element on a higher level.
If the same attribute or element is present on both levels,
the one on the lower level shall take precedence over the one
on the higher level."
gst_mpdparser_parse_segment_list_node will now discard any inherited
segment URLs if the parsed element defines some too.
https://bugzilla.gnome.org/show_bug.cgi?id=751832
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").
Corrected the parsing of a segment template string.
Added unit tests to test the segment template parsing.
All reported problems are now correctly handled.
https://bugzilla.gnome.org/show_bug.cgi?id=751735
When building the media segment list using a SegmentList node, the
gst_mpd_client_setup_representation function will iterate through the
list of S nodes and will expect to find a matching SegmentUrl node. If
one does not exist, the code made an illegal memory access.
https://bugzilla.gnome.org/show_bug.cgi?id=752496
These are used to apply restrictions on what the MPD file may
use, so no profile means no restrictions.
Besides, nothing actually uses the profiles (yet) anyway.
https://bugzilla.gnome.org/show_bug.cgi?id=750869
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
The same has to be done for AdaptationSet and SegmentList nodes still.
Also this does not correctly implement the semantics: by default Period (and
other nodes) should only be loaded when needed, not in the very beginning. We
need to implement lazy loading for them, which means adjusting
gst_mpd_client_setup_media_presentation().
https://bugzilla.gnome.org/show_bug.cgi?id=752230
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
The spec defines these as signed in 5.3.9.6.1.
Since we don't support this behavior, warn and default to 0
(non repeating), which is the spec's default when the value
is not present.
https://bugzilla.gnome.org/show_bug.cgi?id=752480
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
This reverts commit 626a8f0a74.
This allows us to get the plain presentation offset and the period start time
separately. We have to adjust the timestamp by the presentation offset, but
the period start time should only adjust the stream time and running time.
https://bugzilla.gnome.org/show_bug.cgi?id=752409
This reverts commit e671ad25a9.
The timestamps should restart at 0 again for each period, but we have to
adjust the segment to map those timestamps to the actual stream time and
running time of that period.
Otherwise we would have timestamps that conflict with the ones from the tfdt
inside the MP4 container, which are restarting at 0 for each period.
https://bugzilla.gnome.org/show_bug.cgi?id=752409
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.
This GstStreamPeriod start value is expressed in nanoseconds,
and the glib time addition function expects microseconds.
There seems to have been a confusion with GstPeriodNode's start
field, which is expressed in milliseconds.
Additionally, add a warning if the timestamp modification did
not succeed, and NULL was returned.
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
Previous patch did not handle the case where an encoding (e.g. UTF-8) is
specified in the <xml ?> element. Added an extra test for with and without
encoding.
https://bugzilla.gnome.org/show_bug.cgi?id=753813
When running on an STB, the function
gst_mpdparser_get_xml_node_as_string causes a segmentation fault. This
code works correctly on a Linux desktop.
Looking at the libxml documentation, the xmlNodeDump is deprecated.
Replacing the use of xmlNodeDump with xmlNodeDumpOutput fixes the
segfault on the STB and removes the use of the deprecated function.
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
Only copy the values from the parent if the current node doesn't
have that value, they were being copied from the parent and
then overwriten by the child node, leaking the parent's copy
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
Moved gst_mpd_client_get_next_segment_availability_end_time and
gst_mpd_client_add_time_difference functions to be grouped with
functions from the same category.
https://bugzilla.gnome.org/show_bug.cgi?id=752027
Corrected the initialisation of mimeType in
gst_mpdparser_get_list_and_nb_of_audio_language: the variable is used
in a loop, so it must be set to NULL at the beginning of each iteration.
https://bugzilla.gnome.org/show_bug.cgi?id=751911
Before returning the next fragment duration value, the
gst_mpd_client_get_next_fragment_duration function tries to validate it.
But the condition was incorrect.
https://bugzilla.gnome.org/show_bug.cgi?id=751539
We're interested in the offset between the period start timestamp and the
actual media timestamp so that we can properly correct for it. The absolute
presentation offset to timestamp 0 is useless as the only thing we really
care about is the offset between the current fragment timestamp and the
media timestamp.
Otherwise we will look for segments after the period usually. The seek
timestamp is relative to the start of the first period and we have to
select a segment relative to the current period's start.
We didn't do this for fragments that are generated on demand from a template,
only for the other cases when they were all generated upfront. This caused
fragment timestamps to start from 0 again for each new period.
If not set, the timeShiftBufferDepth has a default value of -1.
The standard says that this should be interpreted as infinite.
The gst_mpd_client_check_time_position function incorrectly compares
timeShiftBufferDepth with 0 instead of -1 to determine if it was set.
https://bugzilla.gnome.org/show_bug.cgi?id=751500
The last parameter of gst_mpd_client_add_media_segment function is a
duration. But when called from gst_mpd_client_setup_representation, the
last argument was wrongly set to PeriodEnd
https://bugzilla.gnome.org/show_bug.cgi?id=751449
The period start information, calculated in gst_mpd_client_setup_media_presentation
function is stored in stream_period->start. The information read from
xml file and stored in stream_period->period->start is not changed.
If the xml file does not contain the period start information,
stream_period->period->start will be -1.
The function gst_mpd_client_get_next_segment_availability_end_time wants to
use period start time, but incorrectly uses stream_period->period->start
(value from xml file, which could be -1) instead of stream_period->start
(computed value)
https://bugzilla.gnome.org/show_bug.cgi?id=751465
According to ISO/IEC 23009-1:2014(E), chapter 5.3.2.1
"The Period extends until the PeriodStart of the next Period, or until
the end of the Media Presentation in the case of the last Period."
This means that a configured value for optional attribute period duration
should be ignored if the next period contains a start attribute or it is
the last period and the MPD contains a mediaPresentationDuration attribute.
https://bugzilla.gnome.org/show_bug.cgi?id=750797
Added some warning messages in gst_mpd_client_setup_streaming to help
debug situations when the function will return FALSE.
Renamed a wrongly spelled variable.
https://bugzilla.gnome.org/show_bug.cgi?id=751149
Corrected some comments in gstmpdparser.h file.
Moved gst_mpd_client_get_adaptation_sets function to be grouped with
other functions from AdaptationSet group
https://bugzilla.gnome.org/show_bug.cgi?id=751149
The gst_mpdparser_get_rep_idx_with_max_bandwidth function assumes
representations are ordered by bandwidth and incorrectly returns the
first one when wanting the one with minimum bandwidth.
Corrected gst_mpdparser_get_rep_idx_with_max_bandwidth function to get the
correct representation in case max_bandwidth parameter is 0.
https://bugzilla.gnome.org/show_bug.cgi?id=751153
Added a check for a_node->ns before accessing a_node->ns->href in
gst_mpdparser_get_xml_node_namespace. This could happen if the xml
is missing the default namespace.
https://bugzilla.gnome.org/show_bug.cgi?id=750866
If the presentationTimeOffset attribute of a DASH manifest contains
a value that is larger than 2^32, gstmpdparser incorrectly calculates
the stream's presentation time offset. This is due to two bugs:
1: Using gst_mpdparser_get_xml_prop_unsigned_integer rather than
gst_mpdparser_get_xml_prop_unsigned_integer_64 to parse the
attribute
2: gst_mpd_client_setup_representation multiplying the value by
GST_SECOND and then dividing by timescale
https://bugzilla.gnome.org/show_bug.cgi?id=750804
This reverts commit 37011e5198.
This change was actually completely unnecessary, the streams in question are
marked as static and are not considered live anyway.
Otherwise we'll only get half of its bits printed on 32 bit architectures.
For this, promote the %d-style format strings to something that accepts
64 bit integers with G_GINT64_MODIFIER.
Using format strings from an untrusted source without validation is
calling for problems, and at least allows to remotely crash your application.
If not worse.
The functions to get the next fragment, next fragment timestamp and to advance
to the next fragment need to work differently when stream->segments is NULL.
Use logic similar to that introduced by commit 2105a310 to perform these
functions.
https://bugzilla.gnome.org/show_bug.cgi?id=749684
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.
These functions of directly getting and setting segment indexes
are no longer useful as now we need 2 indexes: repeat and segment
index.
The only operations needed are advance_segment, going back to the
first one or seeking for a timestamp.
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.
Use a single segment to represent it internally to avoid using too
much memory. This has the drawback of issuing a linear search to
find the correct segment to play but this can be fixed by using
binary searches or caching the current position and just looking
for the next one.
https://bugzilla.gnome.org/show_bug.cgi?id=748369
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 segment start time is calculated as the offset into the current segment.
The old condition to detect the end of period (i.e. segment start time >
period start + period duration) failed when the period start was not 0 since
the segment start time does not take the period start time into account.
Fix this detection by only comparing the segment start to the period duration.
https://bugzilla.gnome.org/show_bug.cgi?id=733369
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