LL-HLS hints a resource that is needed to playback in the upcoming
update. It's available for request, and may not be available for
download yet.
A preload hinted resource is either a partial segment, or an init
segment. If it's an init segment, treat it the same way as the Map tag
in ManifestTextParser.
A preload hinted segment contains no duration information, so its
start time and end time are the same. It will be replaced by a partial
segment in the next update.
We should fetch and append the preload hinted segment the same way as a
partial segment.
Issue #1525
Change-Id: I1e30f216ecdc843c3cd01681629a8886383d0b22
Changed SegmentIndex and SegmentIterator to iterate through regular and
Partial SegmentReferences.
SegmentIndex:
merge(): Find all the old segments after the first new segment's start
time, and replace the old ones with new segments.
SegmentIterator:
Use the currentPosition and currentPartialPosition pointers to iterate
through the two-layer arrays.
current(): Get the current SegmentReference, and get its current Partial
SegmentReference if it has a Partial Segment list. Move to the next
regular segment if we reached the end of the current segment's partial
list.
next():
If the regular segment has a partial list, go to the next Partial
Segment. If reached the end of the current partial list, move to the
next regular segment.
If the regular segment doesn't have a partial list, move to the next
regular segment.
Issue #1525
Change-Id: Icb7f49e50314f15ea40bf3a74d008191ed1a9a6c
This is an MP4 Parser which extracts CEA-708 packets from Fragmented MP4 streams.
The Closed Caption Parser (shaka.media.ClosedCaptionParser) will own this MP4 Parser, and will initialize it and call it as shown. As data comes in, the parser will parse this data, and the caption packets data then be returned in a callback (on708Data), as shown. Here, a theoretical decoder (future pull request, mentioned as a Todo comment) will decode and extract the parsed captions from these packets.
Issue #2648
When the subtitles are turned off, unloadTextStream() on streaming engine is called, but currentTextStream is never set to null. When the captions are turned back on, a check in player.js sees that the current text stream is not null, so it assumes it exists, and is ready to go. Thus captions are never loaded.
Clearing (setting to null) the current stream on unloadTextStream ensures the text stream is properly initialized the next time it is called, and in a state so that captions can resume being parsed.
After further investigation, it seems that the unit tests are written in a way that assumes that the text stream is nulled when unloadTextStream is called. So this fix is definitely something that we assume already happens.
Closes#2671
During video playback, if the user switches the caption stream (e.g. CC1 to CC3 which changes languages), the first caption in the next fragment is missing.
In fragmented MP4s, the end time of a caption is determined by the start time of the next caption. Thus for the last caption in a fragment, the end time cannot be determined until the next fragment is parsed.
Before this fix: the clearing of the caption stream was being called from a chain of function calls originating from clearBuffer_() on the Media source engine. But clearing a buffer and resetting a caption stream are two independent operations. As a result, the caption parser was being reset (its buffer cleared) during video seeks, and during stream switches. This makes sense for video seeks, because the end time of the last caption in the fragment can't be determined if the entire presentation timestamp changes. However for stream switches, resetting the parser doesn't make sense. Clearing the caption parser during a stream switch would actually get rid of the last caption in that fragment (which wasn't emitted since its end time wasn't determined yet), and we would lose the data, causing the problem.
The fix is to reset (and hence clear) the caption parser during seeks, but not during stream switches.
Issue #2648
If a segment has partial segment tags, create a SegmentReference for
each partial tag, and add the list of partial SegmentReferences to the
parent SegmentReference as an attribute.
If the parent segment contains the segment tag(EXTINF tag), use the
duration information from EXTINF tag to create the SegmentReference.
Otherwise, calculate the parent segment's duration based on the partial
segments' durations.
Issue #1525
Change-Id: I946cc007aad2ff911b69bf1c6a46df145452bfaa
In our Google-internal build systems, with the strictest compiler
settings, we were seeing errors related to these two issues:
1. A missing require
2. Incomplete type info
This fixes the errors in that environment.
Change-Id: I9c4c482ed6ef8f669e113263a70958b53138c4ee
This fixes all the license headers in the main library, which corrects
the appearance of the main license in the compiled output.
It seems that the `!` in the header forces the compiler to keep it in
the output. I believe older compiler releases did this purely based
on `@license`.
Issue #2638
Change-Id: I7f0e918caad10c9af689c9d07672b7fe9be7b2f3
When we get a playlist update, we replace the list of SegmentReferences
in the SegmentIndex. However, the position pointer in the
SegmentIterator of the SegmentIndex is not updated, and still points to
the index of the old SegmentReference list. Thus, the current
SegmentReference may be null.
We should merge the new SegmentReference list with the old list, and
mark the offset of the list.
Closes#2605
Change-Id: Ia6740e1173ac48467e7b141257cc9c6148e30a0c
Since we are getting strict about semantic versioning, we can't remove
features in v3.1. Any backward compatibility we offer will be
maintained until v4.0.
The exception is explicit IE 11 support, which will still be removed
in v3.1.
To help us follow the rules for removal, the Deprecate utility no
longer accepts a minor version argument.
Change-Id: I4dd94a6084e4ed72eeec410eb9aa0ad974d8dac8
In getSegmentReferenceNeeded_(), we get a SegmentReference base on
(presentationTime - maxDrift) time. If no SegmentReference is avaiable,
we wait until next update.
For live edge, if the SegmentReference with the drifted time is always
out of the segment availability start/end time window, we don't append
any segments.
If we can't find a valid segment with the drifted time, we should seek
with the presentation time.
Fixes#2589
Change-Id: I3fedc002ffc5c99f9dd1d1bf9525aca141b9a2be
We have decided to bump the major version number instead of the minor
number, based primarily on the fact that this release breaks
compatibility with our previous manifest structure.
Change-Id: I67e4c8267c6e103cfc7278e09daac186ae5cbbc6
The destroy method on SegmentIndex is needed for backward
compatiblity, so it should definitely be exported in v2.6, as it was
for v2.5.
Change-Id: Id29faea5ae1719f1ea9201808aa9ce674574afc7
1. When the video hasn't started playing and is buffering, display
playback rate as 1x.
2. When the video is buffering and the playback rate gets updated,
display the newly selected playback rate.
Closes#2526.
Change-Id: I2e8764cfabdcc675a94e26bd9cd18cbc056a35f9
We changed SegmentIndex from IDestroyable to IReleasable since v2.5.x,
so this adds compatibility for the v2.6 release to avoid breaking
existing apps.
Change-Id: I3a12eec98c9af58fe08f0aec7e499266b70e9b48
We used to alias static utility methods by assigning the method itself
to a local variable. This is not allowed by the new Closure Compiler
release that we are adopting, and for good reason.
The old compiler did not understand the use of "this" in static
methods, but the new one does. And it turns out that when we start
using "this" in static methods (see #2532), aliasing the method itself
can break everything.
When you refer to "this" in a static method, it refers to the class.
This is really useful in utility classes that have private static
methods they use to perform common tasks. However, just as it ruins
the value of "this" to alias an instance method, the same is true of
an ES6 class's static method.
The fix is to always alias the class instead of the method. The new
compiler will simply not let us get away with the old way any more, so
regressions after this are unlikely.
Issue #2528 (compiler upgrade)
Issue #2532 (static "this")
Change-Id: Id800d466e639c7cbcf4aa6fbb05114c772a2229f
The old compiler would let us export a static method on a class
without exporting the whole class and its constructor. The new
compiler silently ignores `@export` for any methods of a non-exported
class.
This means that for the latest Closure Compiler, we must export any
class with exported static methods. In some cases, these are
non-utility classes with constructors we'd rather not export, but the
constructor is implicitly exported by exporting the class itself.
This was initially caught by the integration tests. The error wasn't
especially helpful, so I added a try/catch to loadShaka that makes the
error more apparent:
TypeError: Cannot read property 'registerParserByMime' of undefined
To make sure we do not make this mistake again, I've added a check to
the extern generator, which was already able to detect these types of
classes. I don't know a compiler-based way to do it, since the
compiler silently ignores the export annotations in these cases.
Issue #2528
Change-Id: I797c75a8098b0bb3cf837588569f878253dec2cf
Various issues with the nullability of number types led to various
fixes, including:
- defaulting a nullable number to 0 to avoid propagating a null value
through calculations
- adding an assertion or runtime check that something is not null
- moving an existing null check to before the calculation
- returning early on null during an iteration
- changing a nullable number to non-nullable
- defaulting to NaN instead of null
These issues were caught by a compiler upgrade.
Issue #2528
Change-Id: I86d516c74a42ee3624c33d7513d2d4c76d3ea589
In many places, we check error codes on shaka.util.Error. But the
compiler doesn't know that what is caught in "catch" is that type, so
we add type assertions.
In some cases, we know that other types may also be thrown, so there
are also some runtime checks. Some of these had to be refactored to
allow the compiler to correctly infer types.
Change-Id: I053bd7e96213c689aae3889315052dd402124690
In many places, the implicit type info was insufficient. For example,
document.createElement returns Element, but the actual return is
always a subclass of Element. In many cases, we need the compiler to
know that a specific subclass is in use, so that it can correctly
check our use of subclass-specific properties. Another common pattern
is confusion between Node and Element (which is a subclass of Node).
Almost all of the changes in the demo and UI are Element-related.
In some places, we referred to HTMLMediaElement, used in the Player
API, instead of the more specific HTMLVideoElement in use in our demo.
Since the demo uses video-specific properties, we must use the more
specific type.
Another case is the use of document.createEvent, which returns Event
according to the compiler, but in reality always returns a subclass,
like CustomEvent.
In one case in NetworkingEngine, correcting the type of an
AbortableOperation led to the discovery that we had been incorrectly
accessing a private method of that type.
In goog.Uri, there were several instances of "*" for a type, which the
newer compiler won't accept. These have all been corrected.
Finally, in some places, we had the wrong nullability on a type.
These were all caught by a compiler upgrade.
Issue #2528
Change-Id: I7f2d070e3da32fe9ff5f444315649f3cbdb5a4a5
This adds an annotation to suppress a bogus compiler error in
StreamingEngine. In this method, we set updateTimer to null, then
await some async operation, then check to see if it's still null. The
latest Closure Compiler thinks this is a useless check, but we know
better. The updateTimer could have been created while the async
operation was in progress.
Issue #2528
Change-Id: I9a28b7dac1d7cb8bcfd836847507454030af52c6
DrmEngine is adding an extra property to MediaKeySystemConfiguration
objects, knowing that EME will ignore it. The latest Closure Compiler
won't allow this.
In the future, we should refactor DrmEngine and consider tracking this
in some other way. For now, this changes the dot to square brackets.
Issue #2528
Change-Id: I544c93dfa2534e9d62ac5ea47e20a6dc3cb79e3a
For webOS TV 2020 platform, like for Tizen, key IDs should not be
transformed to big-endian UUIDs, it causes `4012
RESTRICTIONS_CANNOT_BE_MET` error.
Closes#2512
This exception was thrown when we attempted to set up a
SegmentIterator on CEA tracks. Because they do not have their own
segments, this is not possible. The fix is to exclude CEA tracks from
this step.
Discovered while debugging #2395, but seems to be unrelated.
This bug does not affect any release versions.
Change-Id: I534b19139d88cc7ad2d6167611c04f400308a71b
This creates a new utility used by DashParser and old offline DB
formats to combine Streams across Periods. This allows multi-Period
DASH content to be played without period-specific structures in the
manifest format, StreamingEngine, or Player. This also makes the
Tracks stable across Periods.
Closes#1339 (flatten periods)
Closes#1698 (rapid period transitions issue)
Closes#856 (audio change causes bitrate change)
Change-Id: Icb04c8e47e36eacf7ac024a5063130d85a115e54
When period-flattening combines Streams, key ID arrays would get very
long with duplicates.
This changes keyIds in the manifest and offline structures from Array
to Set.
Issue #1339
Change-Id: I003d23e567efafa771ecd2ad597900181604ad18
Period-flattening will concatenate Stream objects, so this information
should be available per-Stream instead of at the Variant level.
Issue #1339
Change-Id: I96195fea48cab1e4a349b2ab0b16064a443e928a
This removes periods from the internal manifest structure and cleans
up code and tests accordingly. This leaves us unable to play
multi-period DASH & offline streams until the main period-flattening
algorithm is completed in shaka.util.Periods.
Three test cases have been disabled for the moment.
Multi-period playback will be restored in a smaller, more focused
follow-up commit, with disabled tests re-enabled.
Issue #1339 (flatten periods)
Issue #1698 (rapid period transitions issue)
Issue #856 (audio change causes bitrate change)
Closes#892 (refactor StreamingEngine)
Change-Id: I0cbf3b56bfdb51add15229df323b902f0b2e643a
mediaElement.buffered can never be null. If nothing is buffered,
buffered.length will be 0.
The bug has been in this file since it was created in January 2019.
This affects all v2.5.x releases up to v2.5.10.
Hopefully this will address some seeking issues on Chromecast, though
that has not yet been confirmed.
Closes#1809
Change-Id: Iccc49d299cdac9fccdafdfc2d35e5b2376cff644
The 'webkitkeyneeded' and 'encrypted' events send similar data, but
they were incompatible with each other and our transform handling.
This makes our polyfill produce the same format as the browser for
cases where the browser may only fire the old event. This also makes
our utilities work with the new format.
The 'webkitkeyneeded' event was a length-prefixed UTF-16 string while
the 'encrypted' event was just a UTF-8 string.
This also makes a breaking change in the transform callback to pass the
init data type. This shouldn't break anyone that only uses the first
argument; the second argument was mainly added so we could have the
default transform work without knowing anything.
This change could also break people who use custom transform functions.
The init data format is changing, which could break people who read
it directly. If they follow the tutorial and use our utilities, it
shouldn't break. This also updates the tutorial to match the new format
and be more clear about the format.
Fixes#2214
Change-Id: I006382028e828e31e20e085114fd7fd85c0e1eaa
Playing content in our demo with my WiFi acting CRAZY, I found an
exception in StreamingEngine. The bad connection seems to have
exacerbated and exposed a race condition that can be triggered when
the active stream is switched during an async appendBuffer() call.
The fix is to be careful not to assume that the mediaState object is
the same as it was after the async call. If mediaState.stream has
changed, we should not manipulate mediaState.segmentIterator, which
may refer to a different Stream or may be null.
This bug does not affect any release versions.
Change-Id: I3d00009e78978cae95b47bb9f862fca4294b7b20
After evicting segments from a SegmentIndex, SegmentIterator should no
longer start at 0. So instead of starting at 0, start at the earliest
position, which is returned by find(0).
Change-Id: I512ffb10a7f09f52930c5afbd783db063e9ebd66
querySelector isn't available in Shaka Player Embedded. Since we only
use it to find nodes with a specific tag name, we can usually use
getElementsByTagName.
Issue google/shaka-player-embedded#113
Change-Id: Ia225e5d1f7598b13bd05db868fe2ea566dca4493
SegmentIndex has had a destroy() method for a long time, but it has
never been called. Now that SegmentIndex has a timer which adds new
references for DASH SegmentTemplate live streams, it is more important
than ever to properly stop this active part of SegmentIndex.
This change replaces async destroy() with synchronous release() and
calls it from Player when the manifest is being disposed of. This
will ensure that SegmentIndexes don't grow out of control after
content is unloaded.
This would not have affected v2.5, since we didn't have this
timer-driven growth of DASH SegmentTemplate live streams in that
release branch.
Related to #1339 (fixes issues introduced for period flattening)
Change-Id: I419a06a62eaa507d92132e20d4cc2d6e45c83ff2
As part of Period-flattening, I'm trying to remove our dependence on
the "position" field of SegmentReference. With that eliminated, we
can more easily concatenate Arrays of SegmentReferences without
modifying them.
- Make SegmentIndex iterable
- Add specialized seek() and current() methods to SegmentIterator
- Remove position from SegmentReference
- Make positions in SegmentIndex API stable without field in
reference
- Remove brittle hard-coded positions in tests (except SegmentIndex
tests, where they would be hard to avoid in testing methods
separately)
- Use SegmentIterator in StreamingEngine to track the next segment
between switches
Issue #892 (refactor StreamingEngine)
Issue #1339 (period flattening)
Change-Id: I666cc21249c34ee6cbc138a59109d9f1159fa127
This reverts commit 235e4e11ad.
The effort to remove SegmentReference's position field will be handled
in a different way.
Issue #892 (refactor StreamingEngine)
Issue #1339 (period flattening)
Change-Id: I62b115137abc89f498b30467e574b0401dcad05d
`'webkitneedkey'` events are fired with the same `event.initData` for the video and audio tracks, and a new session is needed for each.
Closes#813 (duplicate sessions required on Tizen)
Closes#2447 (polyfills broken on Tizen)
Closes#2448 (PlayReady broken on Tizen)
As part of Period-flattening, I'm trying to reduce our dependence on
the "position" field of SegmentReference. If it can be eliminated, we
can more easily concatenate Arrays of SegmentReferences without
modifying them.
SegmentIndex can now track the last reference you asked for and
iterate through the list of references. This means we don't need the
"position" field of SegmentReference, which means we don't need to
know positions in advance or globally. StreamingEngine will no longer
use position to request segments.
The old methods find(time):position and get(position):SegmentReference
have been replaced with seek(time), current(), and next(), all of
which return a SegmentReference and maintain an internal pointer to
the "current" reference. Care has been taken to maintain that pointer
during the evict() and fit() operations. Recent changes to merge()
made sure that the pointer does not need to change during that
operation.
All test updates are related to the SegmentIndex API change, not
changing expectations or behavior.
Issue #892 (refactor StreamingEngine)
Issue #1339 (period flattening)
Change-Id: I1682dcc2dd625c6e390711538e46d31e6eb6cea8
As part of Period-flattening, I'm trying to reduce our dependence on
the "position" field of SegmentReference. If it can be eliminated, we
can more easily concatenate Arrays of SegmentReferences without
modifying them.
There has long been a comment at the top of SegmentIndex's merge
method stating that we only ever extend the references, but never
interleave them. The code, however, is structured in such a way that
it could interleave them. This could cause the offset of a given
SegmentReference in the Array to change, which would be counter to the
comment about only ever extending the list.
This change simplifies merge() so that it can only ever extend the
array of SegmentReferences. This will guarantee that their offset
within the Array will not change during the merge operation. This, in
turn, enables further SegmentIndex changes to move "next" segment
tracking out of StreamingEngine (where it is based on the "position"
field of SegmentReference) and into SegmentIndex (where it could be
based on offset into the Array of references).
It removes one test related to PR #838. This test was about our
ability to update the position of the final segment in a list. This
doesn't seem to make a lot of sense, and we're going to stop relying
on segment position anyway.
Issue #1339 (period-flattening)
Change-Id: I2067e2266cf2d02c0e6350d6b57d74f9ed1b27d3
That alias was confusing the closure compiler, and causing it to
produce invalid output when making release versions.
Closes#2438
Change-Id: Ic232ce4f29222543b13c2cc725ffefaedea29e3a