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
There are some platforms (e.g. iPad) which can be rotated,
but do not support the screen.orientation API. This is relevant
because iPad now supports requestFullscreen, which it did not
before.
Found while investigating #2653
Change-Id: Iacc93433aa1fb50a25d968203dc9fd4f7f16b4ae
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
In particular:
- New ad events were added
- It's now possible to get original IMA ad and ad manager
objects through Shaka
Change-Id: I2ffdc08befc11011673ebba5fb2fdb5e485977f5
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
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
@exportInterface is used by the extern generator, but ignored by the
compiler. @export should be used for shaka.util.FairPlayUtils and
shaka.util.BufferUtils.
Closes#2626 and #2627
Since createSegments_() is asynchronous, and we are updating all the streams
in parallel, the global playlistStartTime_ value may get changed when we update
other playlists, rather than the current playlist. This caused the references'
start and end times discontinuous in a stream.
Closes#2605
Change-Id: Ib2dd1161f4075486f79b0122b98e558ea7d05aaa
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
1. We get the start time for either the first segment in the playlist,
or a segment after discontinuity. The logic for getting the start time
in both places is almost the same.
Moving the dupliate code to getStartTime_() function.
2. We create a temporary SegmentReference to get the start time.
Moving creating the SegmentReference into getStartTime_() function.
3. Moving the logic of getting timestampOffset for a discontinuity
segment into a seperate function.
createSegments_() is now 20+ lines shorter.
Change-Id: If484aab56aa169d4a0f9166813d696724230b919
The current implementation of pixelAspectRatio in DASH is wrong. `@par` in DASH is "picture aspect ratio" so the correct is populate this field with `@sar`.
There is not a separate message for skip forward or skip backward, and
we already support seek. So there's no obvious reason to claim we
can't support skip forward and skip backward.
Related to #2606
Change-Id: If9a931afa2d6a0d323b561ed9f6500f79fb0d1bd
The docs for the Cast messages say that duration is optional, so it
seems better to omit it for live content, rather than send back an
absurdly-large number.
Note that this does not seem to affect seeking in live streams.
Seeking in live streams seems to be disallowed by the Google Home app
either way.
Related to #2606
Change-Id: Id7d3911b410489b56643afaaee12102b5d6929a1
When we get a GET_STATUS request, we are supposed to send back media
info. That field is only optional for other requests.
This fixes the scrubber in the Google Home app for VOD content.
Issue #2606
Change-Id: Iceec95f18cf15325b7ee2350a0f30f31edc90560
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
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
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