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
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
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
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 reflects changes in Google's policy on JavaScript license
headers, which should be smaller to avoid increasing the size of the
binary unnecessarily.
This also updates the company name from "Google, Inc" to "Google LLC".
Change-Id: I3f8b9ed3700b6351f43173d50c94d35c333e82b4
An empty list is still truthy, so the if statement should check for a
non-empty list instead. This ensures we don't try to append captions
when we play audio-only content.
Fixes#2187
Change-Id: I589a5508878ab28ad1ac69211f331ea829fa8b28
These are intermittently used and cannot be verified. Most of our
methods can throw a shaka.util.Error, so having it doesn't really add
anything. Plus, if we change a function to throw, we'd need to update
all their callers to ensure they have an accurate description of what
they throw; otherwise we can't trust the directive.
Change-Id: I520bd0fc4c33443e967bf5b103ca5aa9e3274884
This changes the network API to use BufferSource instead of ArrayBuffer,
which allows plugins to return a "view" on a buffer instead of the
whole buffer. This also adds some utilities for changing between
views and buffers.
Lastly this forbids the use of the "buffer" property of TypedArrays
since it doesn't work with partial "views". This audits and fixes the
usages of the "buffer" property to ensure correct usage.
It should be noted that both MSE and EME accept a BufferSource as input,
so we don't need to convert a "view" into an ArrayBuffer before passing
to it.
Change-Id: Iaa417773f8ce5304424e43c7372ce10ebf540d2a
Chrome has fixed their behavior involving endOfStream(), but both Tizen
and IE11 have the same broken behavior. Unfortunately these platforms
will likely never be fixed, so we need to keep this forever.
Fixes#1357
Change-Id: Id540170f8c8cb6e0ddf3a30bde5035016fa61df1
MediaSource throws if endOfStream() is called when
its readyState is equal to 'ended.' This happens if
endOfStream() has already been called.
This change ensures that we don't try to call endOfStream
on the MediaSource that has already marked as 'ended.'
Closes#2050.
Change-Id: I2672b297f0ebb7fd67afcf72ee52df6d5bacf761
This changes several classes to use the Destroyer class to handle
destroy(). This also changes the behavior to not ignore destruction
and instead throw a new error. This is more clear for callers and
ensures we propagate errors.
Change-Id: I756c085639558509c22e5c43d69ddf4acd28d46f
A recent refactoring caused a test failure on Chrome due to a Promise
getting rejected without a "catch" block and getting an unexpected
rejection error. This adds the expectation first so we don't get that
error.
This also removes the empty "catch" blocks since we use async/await,
which introduces another Promise, so the "catch" block won't suppress
the unhandled rejections like we want.
Change-Id: Ib217b4b374668d800a0eeb1a9b8069269bccf261
This sets a TextDisplayer to the native text displayer if native
controls were desired, or a custom UI text displayer otherwise.
This required adding methods to the player to switch out the current
text displayer if a new factory is provided, and a method to streaming
engine to reload the current text stream.
Change-Id: I85595e9ac9db0b60464ee7f20fa35855efb26424
This is a fully automated change. The linter will fail because the
extra indentation caused line-length errors. These won't be fixed
automatically. They are fixed in a follow-up to make this one fully
automated.
Change-Id: I4d8cf9c998985add2bcd24a81c8d65495668c4f3
With the new style rule, we cannot have two statements on the same line.
So we can no longer have an "if" on a single line and we cannot have
an arrow function with a body on the same line as when it is used.
This is mostly a manual change.
Change-Id: I2285202dd5ecbad764308bc725e6d317ff2ee7f0
This is an automated change to convert use of "function" functions
to arrow functions. This doesn't change all uses of bind() that
could be converted. This also doesn't remove all "function" functions.
Change-Id: I40ac7d086bcef947a1be083359c8fd1d4499a9c3
A coming update to the Google eslint config will require using "const"
over "let". This makes that one change to isolate the big changes.
Change-Id: I7d0974c3ae15c53cc45a6b07bf9f6586e2d34aca
Now iOS is supported for HLS through src=, so isBrowserSupported
needs to reflect that. This makes MediaSource optional for any
browser with src= playback of HLS.
This also fixes probeSupport() to reflect the capabilities of non-MSE
platforms such as iOS, which is critical for our demo app to be able
to show the correct set of playable assets.
Issue #997Closes#1857
Change-Id: Ic6e18587db90fff2b097a2038c16cc928e2b9438
This CL creates the "loaded with src=" node and its initial
implementation. Adding this node required some changed to the routing
logic as a new destination was created.
We will use src= when given mp4 content or media source is unavailable.
We detect mp4 content via the mimeType in |load| and/or the file
extension. When media source is not available on a platform, we fall
back to using src=. To do this, we check if media source is available
whenever |load| is called, and will route to the src= branch if media
source is not found.
To avoid pre-initializing media source (when it is not available) we
modify the |initializeMediaSource| flag in |attach| and |unload| when
media source is not available.
Doing this showed that we had inconsistent behaviour between |attach|
and |unload|. |attach| would default to initializing media source
whereas |unload| would not. This has been fixed.
Issue #816
Issue #997
Change-Id: I00599832b49c9079e273e65a4b827fee736479cc
To make the getBufferedInfo method simpler for when we have three
different ways of responding (not loaded, loaded with media source, and
loaded with src=), this changes media source to fill-in a buffered info
object rather than return one.
Issue #816
Issue #997
Change-Id: If9e4558ca324808a1b94e3c235f4bfb42a5df8ce
React Native introduces its own polyfill for window.URL.createObjectURL which is not compatible with Shaka. Encapsulating a reference to the original function inside of the MediaSourceEngine circumvents this issue.
Closes#1842
When CEA captions are extracted from video segments, the
presentationTimeOffset of the video segment should be applied to the
extracted captions, as well.
Fixes b/70902665
Change-Id: I446333a14b8b6374786ab594a579b6e18bc73ac1
Before, media source engine could be created with no text displayer.
However, player would always create media source engine with a
text displayer.
Just like with closed captions, this appeared to be a good time
to change it to be passed in the constructor and have media source
engine own it.
This now means that media source engine is responsible for destroying
it - lessening player's responsibilities.
Change-Id: I71cd1c28a3c22d3c765a3892fe74ae3f9abd1914
We often use the IDestroyable interface to provide us with a standardized
way to break internal references and tear-down objects, however many
objects don't need this to be async. Once using IDestroyable, everyone
must assume that you must be async.
This change introduces IReleasable, a sibling to IDestryable, which
provides the |release| method. IReleasable is the synchronous version of
IDestroyable.
This change converts EventManager from IDestroyable to IReleasable as
the first of many conversions.
Change-Id: Ic3e90e594abc1c7326eccbe2521eb71676b74a09
When we create a media source engine instance, we pass in
a closed captions parser. However a key subtlety was missing
from the parameter description; media source engine is taking
ownership over the parser.
Change-Id: Id49483ccac4cc1812c31ead9e82c09390ce2ed37
Instead of requiring media source engine to create its own closed
caption parser and then allow tests to override it, have it be
passed into the constructor.
This allows us to easily use the fake one in all our tests and
removes the need for a test only method on media source engine.
Change-Id: Ia1d4f0bb988dca30699b30ccaf4522126f357f90
Similar to Transmuxer, adding a Caption Parser class as a wrapper of
mux.js's Caption Parser, and move all relevant operations from Media
Source Engine to Caption Parser wrapper class.
Issue: #1404
Change-Id: Iaafa22a963b53315e1f7ae52a5fe17a4cd3f2bde
Refactor the closed captions support for HLS, using the same approach as
the closed captions support for Dash.
If closed captions are signaled in the manifest, player will create a
text stream for to represent the closed captions, and text engine will
store and append them. We don't need to set 'useEmbeddedText' value for
closed captions any longer.
Issue #1404
Change-Id: I9a5bf4df7e29d6e6982f29fd5e2df07bc78071d7
Removing a few hacks from player and streaming engine, so that now
closed captions streams are treated almost the same way as usual text streams.
Fixed the issue where toggling the closed captions doesn't work.
Fixed the delay of showing closed captions when we seek to a buffered
stream.
Issue #1404
Change-Id: I28a739f3033f30b53b3adf8fa1a181e3d4592f6f
Adding support for CEA closed captions embedded in video streams for
Dash.
1. Dash parser reads and parses closed captions' channel and language
information.
2. Player creates text streams for the closed captions.
3. Media Source Engine calls mux.js Caption Parser API to get the closed
captions embedded in the video streams.
4. Text Engine stores the closed captions, and text displayer shows the
captions.
TODO:
1. Add test cases, will send out another CL.
2. Change closed captions support for hls to the similar way we handle
dash closed captions, will send out another CL.
3. Handle dash content that's missing language indication from the manifest.
Issue: #1404
Change-Id: Ibae8f69623c13561415ec860107d7f5bc86e19e9
First, we cannot destroy the EventListener in MediaSourceEngine until
the in-progress tasks are done so we can get the 'updateend' event.
Second, we shouldn't detach MediaSource until the tasks are done to
ensure the media stack is still working.
As part of that, we need to delay the destruction of DrmEngine to
ensure it happens after MediaSourceEngine.
Fixes: 118148113
Change-Id: I2c77d72556eb0b1b6ef4a3f7a092f182b94e9156
A new WIP test accidentally destroyed MediaSourceEngine twice, which
should not result in an exception. This fixes the exception.
Change-Id: I199e3072a3e7994083844c2013ac9c8f76406a63
This replaces almost every instance of indexOf on both String and
Array. There are very few places where we really wanted an index.
Mostly, indexOf was used to check for inclusion.
Change-Id: I08e299768b6ffdb4bfc30b39b5d82a058c6d1b56
This reverts commit c38d4dd8d3, which
actually broke text range calculations in v2.3.10, and v2.4.2-v2.4.4.
The original commit was meant to account for the period start, but
resulted in a double-accounting of presentationTimeOffset.
The start and ends times passed into TextEngine's appendBuffer were
period-relative, so timestampOffset had already been applied. To
avoid further confusion and to fix the original issue the reverted
commit tried to address, these have been changed to
presentation-relative timestamps. Now the period start and all
offsets have been accounted for before the metadata reaches
MediaSourceEngine and TextEngine.
The tests added in the bad commit have been modified to test for the
opposite: that we do not erroneously account for timestamp offset when
calculating the buffered ranges for text.
Closes#1562
Change-Id: I9fa7a3f59906c4f3e623f411e48551f86f5c2ff7
When the video is looping and there's a small gap between the playhead
and buffer start, we should jump the gap instead of clear the buffer and
download it again later.
Change-Id: Ieead1462ac8c1cfcc957c391a61890396b870d40
Closes: #1459.
https://goo.gl is being turned-down, so we can't use it for new URLS.
So we have consistent short links, this converts them to be
https://bit.ly.
Change-Id: I07a86cba807b67157664893341f648023918d0de
MediaCapabilities only recognized the new vp09.... strings, even for
WebM. So we should start checking for that when we look at browser
codec support.
The AV1 codec string has not been finalized as far as I know, so that
should not be in there yet.
Change-Id: Ia7cb51bf712d8875ff439a9574a181da13acee27