In reverse playback, we don't want to rely on the position of the current
keyframe to decide a stream is EOS: the last GOP we push will start with
a keyframe, which position is likely to be outside of the segment.
Instead, let the normal seek_to_previous_keyframe mechanism do its job,
it works just fine.
If a key unit seek is performed with a time position that matches
the offset of a keyframe, but not its actual PTS, we need to
adjust the segment nevertheless.
For example consider the following case:
* stream starts with a keyframe at 0 nanosecond, lasting 40 milliseconds
* user does a key unit seek at 20 milliseconds
* we don't adjust the segment as the time position is "over" a keyframe
* we push a segment that starts at 20 milliseconds
* we push a buffer with PTS == 0
* an element downstream (eg rtponviftimestamp) tries to calculate the
stream time of the buffer, fails to do so and drops it
When the seek event contains a (newly-added) trickmode interval,
and TRICKMODE_KEY_UNITS was requested, only let through keyframes
separated with the required interval
The time_position field of the stream is offset by the media_start
of its QtDemuxSegment compared to the start of the GstSegment of
the demuxer, take it into account when making comparisons.
mpegaudioparse suggests MP3 needs 10 or 30 frames of lead-in (depending on
mpegaudioversion, which we don't know here), thus provide at least 30 frames
lead-in for such cases as a followup to commit cbfa4531ee.
AAC and various other audio codecs need a couple frames of lead-in to
decode it properly. The parser elements like aacparse take care of it
via gst_base_parse_set_frame_rate, but when inside a container, the
demuxer is doing the seek segment handling and never gives lead-in
data downstream.
Handle this similar to going back to a keyframe with video, in the
same place. Without a lead-in, the start of the segment is silence,
when it shouldn't, which becomes especially evident in NLE use cases.
Need to respect return of gst_video_guess_framerate() to ensure
non-zero denominator.
This patch is to fix below error with an abnormal (but has valid frame) file.
(gst-play-1.0:17940): GStreamer-CRITICAL **: passed '0' as denominator for `GstFraction'
This problem was found in Test. 2 of the YouTube 2018 EME
tests[1]. The code was accidentally not finding an mp4a's esds atom in
the sample description table when the stream was encrypted. It assumed
that if the stream is protected, then only an enca atom will be found
here. What happens with YouTube is they often provide protected
content with a few seconds of clear content, and then switch to the
encrypted stream.
The failure case here was an incorrect codec_data field being sent
into aacparse. The advertisement of stereo audio @ 44.1kHz for the
mp4a (unprotected) stream was incorrect. As usual, the esds contained
the real values here which were mono at 22050 Hz.
Here's what the MP4 tree looks like for these types of files,
demonstrating why the code was making a wrong assumption (or maybe
YouTube is being unusual),
[ftyp] size=8+16
...
[moov] size=8+1571
...
[trak] size=8+559
...
[stsd] size=12+234
entry-count = 2
[enca] size=8+147
channel_count = 2
sample_size = 16
sample_rate = 44100
[esds] size=12+27
...
...
[mp4a] size=8+67
channel_count = 2
sample_size = 16
sample_rate = 44100
[esds] size=12+27
...
In addition to fixing this, the checks for esds atoms in mp4a and mp4v
have been made symmetrical. While I haven't seen a test case for video
with the same problem, it seemed better to make the same checks. This
also fixes a crash reported from another user[2], they also noted the
asymmetry with mp4v and mp4a.
[1] https://yt-dash-mse-test.commondatastorage.googleapis.com/unit-tests/2018.html?test_type=encryptedmedia-test
[2] https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/issues/398
EA608 closed caption tracks are a bit special in that each sample
can contain CCs for multiple frames, and CCs can be omitted and have to
be inferred from the duration of the sample then.
As such we take the framerate from the (first) video track here for
CEA608 as there must be one CC byte pair for every video frame
according to the spec.
For CEA708 all is fine and there is one sample per frame.
The duration field being a uint64, is stored in 8 bytes, not 4. So the offset of
the following field, language code, needs to be updated accordingly so that the
parsed language code is not garbage.
stream.segment should be updated with the values of the current edit
list, also when a new `moov` is received. Unfortunately this was not
being the case because of an early return.
As a consequence of this bugs, no end of movie clipping was being
performed on the new moov and no segment event was being emitted.
When performing stream switching (e.g. in MSE) the new moov may have a
different edit list. This is often the case when switching between
baseline H.264 (which lacks B-frames) and more demanding profiles. For
this reason it's important to emit a new segment in order to be able
to get matching stream times.
This patch moves the initialization of QtDemuxStream.segment from
gst_qtdemux_add_stream() to _create_stream(). This ensures the segment
is always initialized when the stream is created.
Otherwise the segment format is left as GST_FORMAT_UNDEFINED in the case
were a track is reparsed and qtdemux_reuse_and_configure_stream() is
called instead of gst_qtdemux_add_stream(). (See
qtdemux_expose_streams() in the non streams-aware case.)
If ctts (CompositionOffsetBox) has larger sample_offset
(offset between PTS and DTS) than (2 * duration) of the stream,
assume the ctts box to be corrupted and ignore the box.
https://bugzilla.gnome.org/show_bug.cgi?id=797262
... before the old streams is not exposed yet for MSS stream.
In case of DASH, newly configured streams will be exposed
whenever demux got moov without delay.
Meanwhile, since there is no moov box in MSS stream,
the caps will act like moov. Then, there is delay for exposing new pads
until demux got the first moof.
So, following scenario is possible only for MSS but not for DASH,
STREAM-START -> CAPS -> (configure stream but NOT EXPOSED YET)
-> STREAM-START-> CAPS (configure stream again).
In above scenario, we can reuse old stream without any stream reconfigure.
https://bugzilla.gnome.org/show_bug.cgi?id=797239
qtdemux_update_streams() is only ever called after checking
`qtdemux->streams_aware` is TRUE. There is no need to check for that
condition again.
`qtdemux->streams_aware` is only modified when the demuxer is
hard-resetted, which is mutually exclusive with demuxing, so it cannot
be modified during the call.
https://bugzilla.gnome.org/show_bug.cgi?id=797191
This patch clears the sample table whenever the demuxing of a new
fragment begins. This avoids increasing memory usage for long videos.
This behavior was already present when upstream_format_is_time; this
patch extends it to all push mode operation (e.g. Media Source
Extensions).
https://bugzilla.gnome.org/show_bug.cgi?id=796899
* When receiving a segment in TIME, use that seqnum
* Only reset the stored sequence number when doing HARD reset
(and not when we get a FLUSH event from upstream)
This patch aims at fixing the recent regressions in the adaptive test
suite.
All segment pushing in push mode is now done with
gst_qtdemux_check_send_pending_segment(), which is idempotent and
handles both edit lists cases and cases where the upstream TIME segments
have to be sent directly.
Fragmented files that start with a non-zero tfdt are also taken into
account, but their handling has been vastly simplified: now they are
handled as implicit default seeks so there is no need to extend the
GstSegment formulas as was being done before.
qtdemux->segment.duration is no longer modified when
upstream_format_is_time, respecting in this way the durations provided
by dashdemux and fixing bugs in reverse playback tests where mangled
durations appeared in the emitted segments.
https://bugzilla.gnome.org/show_bug.cgi?id=752603
Upstream driving elements such as dashdemux often do reverse playback by
feeding qtdemux with the fragments containing the requested playback
range in reverse order.
But the requested playback range stop may be somewhere in the
middle of a fragment. In that case, a naive pts >= segment.stop
condition may declare end of segment prematurely when demuxing this
first fragment.
This used not to happen because there were places in moov parsing where
segment.stop was overwritten to GST_CLOCK_TIME_NONE even if
upstream_format_is_time -- resulting in this case in a segment with rate
< 0 and stop == -1 and hence not triggering the EOS check, but that was
likely an accident.
This patch modifies the EOS check to take this case into account, not
sending EOS when upstream_format_is_time if rate < 0.
This fixes adaptive.dash.playback.seek_end_live.DASHIF_livestream_testpic_2s
https://bugzilla.gnome.org/show_bug.cgi?id=752603
Sample table based segment event (genereted by qtdemux) could break
presentation timeline. For example, qtdemux should not modify upstream
time format segment (e.g., adaptivedemux use case)
https://bugzilla.gnome.org/show_bug.cgi?id=796480
This field is actually only informatory and the user can potentially
choose something else. EME tests in WebKit testsuite actually doesn't
take it into and force another encryption system to be used, and expects
to be given the occasion to do so.
This basically also reverts 3e063703b3.
Instead of always keeping a safe segment (start=0) event from the beginning,
delay the creation of this event to when we really know the timestamp of the
first sample. This is important to properly start fragmented streams that
we might join in the middle or to play isolated fragment files that might
have an advanced tfdt.
https://bugzilla.gnome.org/show_bug.cgi?id=752603