EventStreams in DASH generate TimelineRegionInfo objects, which are
then stored in the RegionTimeline and RegionObserver classes. But
DashParser would add all regions to RegionTimeline, even if they would
be quickly removed again, and RegionObserver would cache some regions
from the timeline without ever removing them.
This fixes the issue from both of those directions. DashParser will
now ignore regions that are outside the DVR window (and therefore
would soon be removed from RegionTimeline), and RegionObserver listens
to an event on RegionTimeline to clean up its own storage when regions
fall outside the DVR window during playback.
Closes#3949 (memory leak in DASH live streams with inband EventStream)
This adds code to allow Shaka Player to play media in sequence
mode, an alternate playback mode that makes the browser ignore
media timestamps, when playing HLS media.
This is important for containerless media formats, as they do not
contain such timestamps.
Changing HLS to not require timestamps also means that we no
longer need to fetch media segments in order to get the start
time, which should lower bandwidth usage and startup delay.
In initial tests, on a simulated 3G network, load latency went down
from an average 3.16s to 2.61s on the HLS version of "Big Buck Bunny:
the Dark Truths of a Video Dev Cartoon"; an improvement of about 17%.
Issue #2337
Change-Id: I507898d74ae30ddfb1bddf8dce643780949fbd9b
Now we parse value of descriptor for urn:mpeg:mpegB:cicp:TransferCharacteristics in AdaptationSet to indicate hdr property on shaka.extern.Stream which seems equivalent to HLS definition given in VIDEO-RANGE attribute within EXT-X-STREAM-INF.
This is done by reading the supplemental / essential property in the parsing of AdaptationSet, then mutating the hdr property on shaka.extern.Stream if no hdr exists after parseRepresentation_.
The alternative considered was to parse all essential / supplemental properties on any shaka.dash.DashParser.InheritanceFrame and then carrying that through to the parseRepresentaiton_ function; this can be seen here. The problem with the alternative approach was that the essential property in the adaptation set would have had to have been "let through" on the assumption that we would parse it within the parseRepresentation_ method... But this to me seemed somewhat risky to change, and also looks messy with the empty else if condition, plus was a much larger change (with more calls to XmlUtils, though not familiar with how that is implemented, so not sure if there was any penalty because of that).
* Test expectation for HDR signalling via property
The test sets the expectation that we should be able to extract the
information of the TransferCharacteristics from the DASH
AdaptationSet. This should then get converted to the nomenclature
used in HLS for the VIDEO-RANGE attribute on EXT-X-STREAM-INF.
* Implement signalling of HDR capability through property descriptor
According to DASH-IF IOP v4.3 6.2.5.1. the transfer characteristics
can be declared at the AdaptationSet level via a supplemental or
essential property. In HLS the transfer characteristics are used to
determine the value of the VIDEO-RANGE attribute on the
EXT-X-STREAM-INF attribute, which is already used to indicate the
hdr property on the shaka.extern.Stream object. Therefore for
consistency we also add the same identification to the DASH parser.
* Added entry in AUTHORS and CONTRIBUTORS
Fixes#3726
Add support for including Common Media Client Data (CMCD) in outgoing requests.
Fixes#3619
NOTE: The following fields have not been implemented: rtp, nrr, nor, dl
Co-authored-by: Dan Sparacio <daniel.sparacio@cbsinteractive.com>
This is a step prior to the closeSegmentIndex implementation.
In the DashParser, use a map of context id to stream instead of
context id to segment index when parsing SegmentList.
For Dash live content, every time we parse a manifest update, we
create a new Stream object, leaving the old stream with its old
segment index.
If we close the segment index and create it later again, we need
update the stream's segment index.
Change-Id: I7a3af3666ddb4e26362c40eeb82c3d050fafe3ee
This is for fixing a case in geo-redundant streams failover:
1. ShakaPlayer identifies DASH period based on period id
2. Period ids generated by two synchronized packager could be inconsistent temporarily in some negative scenarios
3. After the scenario the packagers resync at the live edge, but the inconsistency is preserved in the manifest for the length of the DVR window
4. When ShakaPlayer receives a new mpd with inconsistent period ids (i.e. jumping between mpds from two packagers), it might result in
- Wrong presentation time
- Wrong buffer ahead estimation
- Old segment references added into segment index
5. Consequently, playback gets stalled and requires end-user to refresh the player (i.e. VPF)
When caption languages are not present in the manifest (such as
"CC2=;CC3="), use "und", the language code for "undetermined".
Bug: 187442669
Change-Id: Ia129815efb2ae6b0ac6b655ac02398a7b1f70e68
Added support for efficient preprocessing of DASH manifest after they have been parsed into an XMLDocument
This is configured with the new manifest.dash.manifestPreprocessor setting.
This is need to efficiently repair manifests that are not compatible with Shaka Player.
Closes#3339
In DASH with SegmentTemplate and a fixed duration, indexes would
continue to grow so long as they had not ended. However, this was
based on a callback which captured an end time variable that could
become out-of-date in a multi-period live stream.
This prevents indexes from continuing to grow indefinitely by always
using the most up-to-date end time for the period.
This also fixes eviction of segments in the same scenario, which
fixes SegmentIterator access and related assertions later.
Issue #3354 (partial fix)
b/186457868
Change-Id: I2b34ee52dd12b59e1c1237258050b50e3189bee3
This was broken accidentally during MediaCapabilities refactoring.
This does not affect any release version.
The filtering step does two things: it applys the "restrictions"
config to the streams in the manifest, and it sends DRM init data to
DrmEngine for all streams in case new sessions need to be created.
For key rotation, it is critical to create new sessions in DrmEngine.
The init datas for new periods are added to existing streams when the
new period's streams are stitched onto the old ones.
The restrictions config should also be applied on manifest update,
since the update could have created some new streams with
characteristics outside of the current restrictions config.
Closes#3169
Change-Id: I716c2978c7394d7bb56227aa1854392a10eae058
In #3169, we discovered failing assertions for some multi-Period DASH
live streams. The failing assertion was meant to ensure that our
eviction logic was correct, and that our assumptions are maintained
properly.
Though the assertion failed, nothing was actually wrong with playback.
But the assertion itself should only fail if there is actually
something wrong.
With the choice between removing the assertion (since playback is
fine) or "fixing" the assertion (to avoid this false negative), I
chose to fix the assertion to retain the value of it to catch actual
bugs in our logic in the future.
The assertion specifies that you should not see evicted segments after
non-evicted segments. But eviction was only done when merging a
segment index with an old version of the same index (same
Representation and Period). When an update drops a Period from the
manifest, this means everything in that Period should be evicted. But
the eviction call wouldn't happen, because we had no new version of
the segment index to update the old one.
An extra call to evict() on each manifest update can fix the state
of the system so that our assertions pass.
The assertion message appeared identically in two different
assertions, so this change also rewrites the assertion messages to
differentiate them and to clarify their meanings.
Issue #3169
Change-Id: Ifeb7a1a8f48af704b028a22d987349209d7ee485
Make the DASH keySystems configurable, so that any developer could chose to opt-in for recommendation based on DASH DRM UUID.
Example:
player.configure({
dash: {
keySystemsByURI: {
'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95': 'com.microsoft.playready.recommendation',
}
}
});
Previously, we fill in the variants' drmInfos with the drm
configurations of |clearKeys|, |servers| and |advanced| during
initializing the DrmEngine, before we query the media keys.
Now we need to call |MediaCapabilities.decodingInfo()| to get the
mediaKeySystemAccess of the variants after the DrmEngine is
created and configured, and the drm values are filled in for the
variants, and before |DrmEngine.queryMediaKey_()|.
The steps would be:
0. StreamUtils.setDecodingInfo() should not be called before
DrmEngine is initialized and configured.
1. Create and configure DrmEngine.
2. Fill in drm values for the variants with configurations.
3. Call StreamUtils.setDecodingInfo() to get the decodingInfo of
the variants.
4. Use the decodingInfo results to set up the Drm mediaKeys in
DrmEngine.
5. When StreamUtils.filterManifest() is called, we can reuse the
decodingInfo results instead of calling decodingInfo again.
Previously we call filterManifest() when parsing the manifest, to
filter out the unsupported streams.
Now decodingInfo can tell us if a variant is supported and its
MediaKeys at once. When initializing the DrmEngine, we get the
decodingInfo results of the variants, and only use the supported
streams to set up the MediaKeys. After that, we filter the manifest
right after DrmEngine is initialized.
Thus, we can skip filterManifest() in manifest parsers.
Using decodingInfo to get media keys will be in the next CL.
Issue #1391
Change-Id: Ieb401a1e4dfbcc958f7a14fa96df546237b0f446
In DASH, a trick mode track can be associated with multiple regular tracks.
This fixes the parser to respect the whitespace-separated list of IDs instead of assuming just one ID.
Resolves#2978
With "lowLatencyMode" enabled, "rebufferingGoal" is set to 0.001, and inaccurateManifestTolerance is set to 0 by default. However, in some cases longer rebufferingGoal helps to avoid new rebuffering.
Besides "lowLatencyMode", this code change adds the "autoLowLatencyMode" config. When "lowLatencyMode" config is disabled and "autoLowLatencyMode" config is enabled, and the manifest provides low latency features, we automatically activate the lowLatencyMode.
If "lowLatencyMode" is enabled, "autoLowLatencyMode" has no effect.
Issue #1525
If an HLS playlist contains partials segments, or a Dash playlist
has availabilityTimeOffset value, we check whether lowLatencyMode
is enabled. If not, we show a warning to remind the developer to
set the configuration.
Issue #1525
Change-Id: If7b851c32c325203870c33d868668e1a3dd3c8bf
This pertains to #2648 (although this is a new feature, not a replacement) and #1404. A CEA-708 decoder that follows the CEA-708-E standard, decodes closed caption data from User Data Registered by Rec. ITU-T T.35 SEI messages, and returns them as cues in Shaka's internal cue format. Furthermore, this pull request fixes and cements some of the logic surrounding CEA-608 and CEA-708 tag parsing on the Dash Manifest Parser.
Format:
Similar to the CEA-608 decoder, cues are emitted in Shaka's internal format (lib/text/cue.js). This decoder makes use of nested cues. The top level cue is always a blank cue with no text, and each nested cue inside it contains text, as well as a specific style, or linebreak cues to facilitate line breaks. This also allows for inline style (color, italics, underline) changes.
Details:
- ASCII (G0), Latin-1 (G1), and CEA-708 specific charsets (G2 and G3) all supported.
- Underlines, colors, and Italics supported, set as a property on each nested cue.
- Positioning of text is supported. (Exception: In CEA-708 the default positioning is left, in this decoder it is centered.)
- Positioning of windows not supported, but relevant fields that could be used to support this are extracted and left as a TODO.
Previously, on manifest updates, embedded captions would vanish in
single-period live DASH streams. The problem was based on the
specific point in the load order that we added dummy text streams
to indicate the presence of embedded captions.
This modifies the PlayerInterface for manifest parsers to add a
new method passed in, makeTextStreamsForClosedCaptions, which
must be called by manifest parsers for new video streams.
This also completes an unfinished feature, where new video streams
which add new closed captions would not get corresponding
text streams.
Closes#2811
Change-Id: Iee7499ec950b363cf6839765cc2bd2d01743467d
1. Move the config field from ManifestConfiguration to StreamingConfiguration, since StreamingEngine will need it.
2. In manifest parsers, we get the value of lowLatencyMode config from the StreamingConfiguration.
Issue #1525
Change-Id: Iaa961b4e6799ecc1fcf3147b2fb992e86d4b043d
availabilityTimeOffset indicates that a segment is available for
download earlier than its availability start time.
1. This attribute can be on Period, Adaptation set, and Representation
level. The availabilityTimeOffset value of a segment should be the sum
of the values on different levels that apply to the segment.
2. We pick the minimum of the availabilityTimeOffset value among the
representations, reduce the distance from live edge by this value.
3. The availability window should be:
timeShiftBufferDepth + availabilityTimeOffset.
Doc: https://dashif-documents.azurewebsites.net/Guidelines-TimingModel/master/Guidelines-TimingModel.html
Tested with demo page, and the live latency got reduced by the availabilityTimeOffset value.
Issue #1525
Change-Id: Ibe87b0293b31e594f38f98c7caa9f5aeb134e40b
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
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`.
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
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
Live stream tests call stop() on their manifest parsers, but nobody
was calling release() on the SegmentIndex objects. This meant they
could continue to generate SegmentReference objects indefinitely.
In production, the Player releases all SegmentIndex objects. But if
some Variants had been removed due to filtering, they would never be
stopped.
By having DashParser release all SegmentIndexes it generated, we can
ensure that there are no timers running after the parser is stopped.
This bug was introduced in the master branch and has not appeared in
any release.
Change-Id: If885e828b4761528e40abdbc601a11cf13849a1e