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
To keep people from thinking that the master branch contains v3.0,
bump the master branch version number in player.js to v3.1.0-pre
Change-Id: I15d1e24b6b431318f2e492901bcba8b5e468fb07
Playback stalls on Tizen can be corrected by pausing and playing
again. For Tizen and similar platforms, this is superior to the old
way of seeking to unstall playback, because seeking is expensive on
those platforms.
To facilitate pausing and playing again instead of seeking, a
stallSkip value of 0 will trigger the pause/play workaround instead of
the seeking workaround. Further, we will make this the default on
Tizen, WebOS, and Chromecast.
An internal detail which is changing is that GapJumpingController will
now call StallDetector first and inhibit gap jumping when the stall
detector has something to do, rather than the other way around. This
allows the StallDetector to be in charge of deciding what is buffered,
rather than having to pass GapJumpingController's interpretation of
buffered ranges first.
Fixes#2620
Change-Id: I5ad7aad42aa185b2837c830970e54218b4e55a21
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
src= playback on Tizen 3 was stalled at time 0, causing automated test
failures. These went unnoticed while our Tizen device in the lab was
offline.
The only workaround I was able to find was to call load(), which we
recently stopped doing for src= playback. This adds it back, but only
for Tizen.
Found while investigating #2620.
Change-Id: I4e071a6f1ccb18b9891dfc646a22dbb8c1711eb4
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
1. In low latency mode, the playback start time from live edge is about
3 times partial segment duration, 3s for example. The rebufferingGoal of
2s would result in infinite buffering.
2. In low latency mode, do not allow drift for seeking. Only seek with
the presentation time.
Change-Id: Iee92727bf17dab8b52fae070522a5a2ec1621ffc
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
On WebOS, objects are logged as 'Object' rather than the properties.
Convert buffered info to a string, so that the properties get printed
in the logs.
Change-Id: Ia6daab48122ed696e69ff7d15c551fdcb10bdb7e
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