TTML nested cues are meant to be displayed horizontally as inline
elements. This fixes the rendering of these nested cues in both
SimpleTextDisplayer and UITextDisplayer.
In UITextDisplayer, the styles have been adjusted to lay out the
nested cues horizontally rather than vertically.
In SimpleTextDisplayer, the nested cues were being displayed as if
they were top-level cues. This change concatenates the nested cues
into a single cue displayed in the browser.
This also improves comments on the poorly-named "spacer" property,
which represents a line break in TTML.
This fixes the rendering of "spacer" in SimpleTextDisplayer by
inserting an actual newline character into the collapsed nested cues.
Finally, this fixes and clarifies names used internally in
UITextDisplayer. For example, there is a difference between a nested
cue and leaf cue. A nested cue and a top-level cue without nested
cues are both "leaf" cues, but a top-level cue is never a "nested"
cue, since it is at the top level. The conflation of these names
before this fix made it difficult to understand and fix the code in
the first place.
Closes#2760
Change-Id: I89633761d12704e253371d17e2e786c5b2ed67a7
One of the cast tests which load sintel-enc had license server info,
and the other did not. This adds the missing license server info.
Change-Id: Ibfd6f3af7a6e418f7b58deaebe5a8926bc4f07a5
This test was only set up for Widevine, which is fine for Chrome.
Adding license server configs for PlayReady and FairPlay makes it the
test pass on all supported platforms.
Issue #2741
Change-Id: I2aa60a6970de07516d07591342c0fba30e7ac9fc
The high playbackRate test seems to trigger a Tizen 3 platform bug in
which the decoders fail when the playback rate is above 2x. We can't
control this as far as I can tell, so this change skips the test on
Tizen.
Found while investigating #2620.
Change-Id: I5b72005c9539c3945dad2cdd7eced8649d7a9cb6
There is a new bug that is preventing the DRM engine from
shutting down, for Widevine assets. Or, at least, new to us.
It happens if session.generateRequest is called, but
session.update is never called (e.g. if the network request fails).
In this case, session.close will never resolve.
This re-adds the old workaround we used to use, where we
would timeout after a while, if the session fails to close.
This also adds a regression test.
Issue #2741
Change-Id: Ieb6a64b762473edb9a3209580a84aee870e21fb5
Tizen 3 has the NetworkInformation API, but not the downlink
attribute. This led to NaN as a bandwidth estimate. Now we screen
for the presence of this attribute as well as the API overall.
Futhermore, we now disable this API in unit tests to better control
the fake estimates used during the tests.
Found while investigating #2620. Introduced in PR #2663, and has not
affected any release versions.
Change-Id: Iaa1486545825ceee536ecbe5ea617f92de4fbc2d
If the last segment in the media playlist contains only partial
segments, its init segment was not set, causing playback failing to
start, with 'Append: stream parsing failed' error.
Issue #1525
Change-Id: I0dab967fe55c9d792f102f4d49dda7f9437d8897
At some point, a refactor of the demo app broke the use of
--test-custom-license-server, which is rarely used, but is being used
now in debugging #2620.
Change-Id: I6376bbf7a0ef9ce650e846cf8df5a6b3bebbfcf8
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
Player can request delta updates to reduce the transfer cost.
Client: sends a request for playlist update with '_HLS_skip=YES'
parameter.
Server: replaces the older segments in the media playlist with
'EXT-X-SKIP' tag.
Issue #1525
Change-Id: I3643641d0cb97444ba1c00f06d9e113acba7b824
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
For LL-HLS, use the value of 'PART-HOLD-BACK' in the Server Control tag
as the default presentation delay.
'PART-HOLD-BACK' is the server suggested min distance from the live
edge, and must be >= 3 * partial segment target duration.
It's always available when the playlist contains partial segments.
Issue #1525
Change-Id: I176188dbd39be0d038eee938d3e8358e54b8a3a8
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
The Android device in our lab exploded and had to be replaced, and in
the meantime, new screenshots were added to the repo. This adds the
missing screenshots so that the layout tests can pass on Android.
Change-Id: If82042d6b5d5c425108337d22fce938f339f2311
In low latency streaming mode, EXT-X-PART-INF tag provides the target
duration of Partial Segments. It's required if the playlist contains
Partial Segments.
1. Get a playlist update every Partial Segment target duration.
2. Set the distance from live edge as 3 * Partial Segment target
duration, if not configured.
Issue: #1525
Change-Id: I8770f2be30f510ec143672411da0624801d48f4e
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
The period-flattening algorithm is run even on single-period content
if the manifest is dynamic, because we don't know if another period
will be added later.
As a failsafe, we should create one output per input for single-period
content, and we can ensure that no streams are unused by marking an
input stream as the "best match" for an output if they share the same
ID. That way, even if all other characteristics for two inputs are
the same, the input-to-output mapping for single-period content will
always be sane.
That ID-based logic was missing for text streams. This change
corrects that.
Closes#2646
Change-Id: I28c6c63d92bcf710ae0072783911f9e66ed78228
Low Latency HLS uses 'EXT-X-PART' tag for Partial Segments.
ManifestTextParser will parse the Partial Segment tags, and add them to
the regular segment after them.
If a list of Partial Segment tags is being published and doesn't have a
regular segment Uri following it yet, create a segment object to wrap
the Partial Segment tags list.
Issue #1525
Change-Id: Ie04ed70ae15c88416d677d67b721f76bc2f5b486
This works around an apparent compiler bug that caused the invocation
of our progress callbacks to be removed from the compiled output. To
test for this, the existing progress tests now use the compiled
library.
Closes#2652
Change-Id: I5698cfe0a833696e9cd5c8f8851698e1e66ef901
The prefer-spread rule to prevent use of apply() was disabled, but we
had another custom rule that also prevented the use of apply(). This
re-enables the standard rule.
Issue #2639
Change-Id: Ic3778d7267deb6cd5ed49282ea43bb84ad076060
When Representations have different BaseURLs, segment URLs generated
for SegmentTimeline were always using the BaseURL of the last
Representation because the wrong parsing context was being used. This
fixes the issue and adds a regression test.
This only affected v3.0.0.
Closes#2650
Change-Id: I04df950b5d3205e102f9c74f52ece9773ce92282
This upgrades the compiler to the latest release and fixes some type
errors in the tests found by the new compiler.
Change-Id: I3a555cbdfc94c51fb0683f8397c6adb8ea43f120
This corrects/normalizes license headers in misc. files, such as
config files, docs, build tools, tests, and externs. This does not
affect the compiled output, and is only done for consistency.
Issue #2638
Change-Id: I9d8da2de55243b08d7df2b743aac73c6f15e858a
One of the src= playback tests was failing on Chromecast with an
estimated rate of about 20% when the src= tests are run alone. The
timeout for playback to start was found to be too short on that
resource-limited embedded device. This increases the playback timeout
in the test.
Fixes: 157702575
Change-Id: Ib8d5a0d961bc0e99e77c16b93ca63569f3a2cc31
This change adds the following methods on CastReceiver:
- setContentMetadata(metadata)
- clearContentMetadata()
- setContentTitle(title)
- setContentImage(imageUrl)
- setContentArtist(artist)
These should be called from the CastReceiver's app data callback.
The title, image, and artist methods cover all the Cast content
metadata fields that have an effect in the Google Home App as of June
2020, and setContentMetadata can be used to set one of several object
formats with many more fields defined in the Cast SDK docs.
See https://developers.google.com/cast/docs/reference/messages and the
definitions of GenericMediaMetadata, MovieMediaMetadata,
TvShowMediaMetadata, and MusicTrackMediaMetadata for details.
This also uses these methods from our cast receiver demo, so our demo
will now set all possible metadata when casting our content library.
Closes#2606
Change-Id: I6386276449dbddd2501cd6e3e52206f7fb30b8fd
The fix for Google Home scrubber in 8c3775ce (Change-Id
Iceec95f18cf15325b7ee2350a0f30f31edc90560) did not come with a
regression test. This change covers that fix with an automated test.
I have confirmed that the test fails without the fix.
Issue #2606
Change-Id: I13a2bcfb2fcca059db4e909d7c27fb68b0bfb409
Details of the cleanup:
- Don't replace the load() spy with a non-spy
- Fix an out-of-date comment on an explicit delay in a test
- Hoist expectMediaInfo helper to make it available for all tests
- Simulate loading content before the "generic controls messages" to allow the
use of expectMediaInfo
- Don't do a substring comparison on a JSON blob, which is inherently
unreliable, and compare the parsed object structure instead
Related to #2606
Change-Id: Ifb46e223ba800c0e10cbdfa6cb847faa8424cd3d
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
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
Changes to the load() promise resolution on iOS for #2483 accidentally
broke language preferences in src= mode, and the regression test for
this revealed subtleties in how and when tracks may be selected with
Apple's native HLS.
By waiting for a "change" event on video.textTracks, we can make sure
Apple is ready to accept our own text track selection.
This should now work correctly on all platforms.
Closes#2593
Change-Id: Iec59b89001fbec3779a0f7087ce11efe1be003ef
I'm not sure what caused the change, but after some other changes
merged, screenshots on Linux were off slightly and needed an update.
Screenshots in Safari were way off, and a workaround in the screenshot
utility needed to be removed.
Change-Id: Ic28d83dddcd6272b4cbb83aa7a3dcdb5c8fcdad9
This adds our first screenshot-based layout tests and the
infrastructure to use WebDriver for screenshots through Karma.
This new kind of test will be skipped in any non-WebDriver context.
There are many pieces to this system.
First, we update the Karma WebDriver launcher to a newly-released
version that lets us access the client spec object from the launcher.
Second, we build a Karma middleware plugin to respond to HTTP requests
from the tests. We handle /screenshot/isSupported and return a bool
so tests can be skipped on non-WebDriver launchers. We also handle
/screenshot/diff to take the screenshot and compare it to a known-good
version.
The screenshot is a full-page screenshot, since element screenshots
don't work consistently across all the browsers in our test lab. The
screenshot is then cropped to a rectangle specified in the request.
This rectangle is measured to match a specific element, so in
practice, we are screenshotting just one element.
Browsers use sub-pixel rendering, effectively rendering at a scale
larger than the "pixels" seen by JS. The screenshot comes in at this
scale, so the requested cropping rectangle is scaled to match, then
the cropped screenshot is scaled down to the JS-measured size.
Because of sub-pixel rendering, element offsets can be non-integer
numbers. Normally, Karma puts the tests in a iframe, above which is a
variable-height banner showing which devices are connected to Karma
and what state they are in. So this variation and the lack of integer
offsets means we can run into stability issues due to rounding errors.
To make offsets consistent and improve stability of the screenshots,
this banner is now disabled in our Karma config.
The cropping, scaling, and diffing of images is handled Karma-side by
a node module called Jimp.
Before we start the layout tests for UITextDisplayer, we use a node
module in the browser called fontfaceonload to wait for our web fonts
to be fully loaded. This module is a polyfill that polls on IE and
uses a standard API in modern browsers to wait for our font to load.
This is all wrapped into a new test util called waitForFont.
Screenshots are stored in test/test/assets/screenshots/ and are
organized into folders by platform and browser and named according to
an identifier specified by each test case. The new screenshot is
written to disk with the suffix "-new", and a diff image is written
with the suffix "-diff". When a test fails, we can review the changes
in a browser with test/test/assets/screenshots/review.html. The
known-good screenshots can be updated with the new tool
build/updateScreenshots.py.
Change-Id: Ib477fd3c459de466c6dc91e9a60d3e2579164b12
These issues were mostly introduced in "Don't preload data on iOS",
and were not detectable in Chrome. They came up during a full test
pass in our test lab on all browsers.
Change-Id: Ife6e157a18df84ea30b840615f6d06a22e340a44
Instead of calling video.load() and waiting for loadeddata for src=,
wait for loadedmetadata. This should be a safe event to use in most
cases, and calling video.load() causes native HLS to start preloading
an uncontrollable amount of content.
The exception is if the app sets preload='none' on the video element.
If this happens, we will detect it, log a warning, and avoid the
loadedmetadata event which may never fire. This is not a scenario we
will officially support, but at least we can prevent a hang in
player.load().
Closes#2483
Change-Id: Id64c8f23cb8fa82bb5c301abafb51f2d9d8730f7
The timestamp parser in our HLS parser should not fail on null TS
packets. These are indicates by a packet ID of 8191 (0x1fff), and
according to the spec, should be skipped by any receiver.
We will not skip such packets and continue through the segment to find
a PES packet with a timestamp.
In addition to the comments in #2546, I found this document helpful:
https://www.mikrocontroller.net/attachment/27265/mpeg2ts.pdfCloses#2546
Change-Id: Id9dc16160bbde03969199150ca50122f12de77f4