Before, when using SegmentTemplate or SegmentList, we would tell
the presentation timeline about new segments only when we saw a
new period or representation. This meant that, in live streams,
if new content was being added to the SegmentTemplate or SegmentList,
the presentation timeline was not being kept abreast of the changes.
Thus, if that stream were to then transition to VOD, the presentation
timeline would suddenly start to report that the current time was
beyond the end of the seek range, which caused playback to stop.
Closes#3675
Change-Id: I77ef00c5a86de9ebcb86f18f792084ed70f94e8d
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
Thumbnail segments may be structured for a certain grid size and
duration, but the segment references may have their duration truncated
due to the end of a period or the end of the presentation. This was
causing us to calculate the wrong duration for those individual
thumbnails, and therefore return the wrong
thumbnail.
We also did not have any way to indicate to an application how long a
thumbnail should be shown.
This fixes the duration calculation by retaining the original,
untruncated duration in SegmentReference. This also exposes startTime
and duration information on the Thumbnail object, so that applications
know when/where and how long to show a given thumbnail.
Closes#3517
Change-Id: I84aa7705a19691fc6ae68eee9944fecbd7067fe0
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
In live streams, we can evict segments outside the availability window
faster than they disappear from the manifest. If that happens, we used
to evict them several times (add them back in and then evict again).
This caused the eviction counter to increase beyond what it should be
and we had trouble finding segments afterwards.
Closes#3139.
Change-Id: Iafebfaf8e1e9ebb09a64cdf7e09a882115fd8eb6
When a Period has segments outside the Period, we evict them during
manifest parsing. However, this eviction shouldn't affect the position
of segments since these never existed.
Fixes#3230
Change-Id: I0494d9c38b51857967ed4b572475ddcc37f815a0
When a multi-period DASH manifest contains periods which are in the
future (described in the manifest, but with all segments past the
current end time of the segment availability window), the segments
generated for SegmentTemplate were invalid. Not all DASH multi-period
content describes unavailable future periods, so many providers using
DASH would not see this issue. This bug affected v3.0.0 - v3.0.7.
To fix this, we change the "next position" calculation for updates to
clamp to the minimum valid position. This avoids creating segment
references with negative position numbers for these future periods.
When the segment availability window moves to include this period, we
will then start generating segments for it (starting at position 0 or
whatever the startNumber attribute is for this period).
However, the contract for updateEvery() in SegmentIndex was such that
the timer would stop if the list of references was every empty. This
was meant to handle the case in which all segments were evicted, but
it could be triggered instantly on these "future" periods, for which
no segments exist yet in the availability window. To resolve this,
the contract was changed so that the updateEvery() callback must
explicitly signal a stop by returning null instead of an array of
segment references.
Bug: 179025415
Change-Id: I56a2826fd3aea3f69da7b8bf4fa7629562d63506
We found the issue within our app with the latest Chromecast CAF receiver update (November 22, 2020) that use Shaka 3.0.x. With our live stream containing 90 minutes of buffer, we notice high level of buffering issue with our customer.
It seems that the createUris callback was holding onto a parsing context in each reference.
Closes#3038
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 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
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
As part of Period-flattening, I'm trying to remove our dependence on
the "position" field of SegmentReference. With that eliminated, we
can more easily concatenate Arrays of SegmentReferences without
modifying them.
- Make SegmentIndex iterable
- Add specialized seek() and current() methods to SegmentIterator
- Remove position from SegmentReference
- Make positions in SegmentIndex API stable without field in
reference
- Remove brittle hard-coded positions in tests (except SegmentIndex
tests, where they would be hard to avoid in testing methods
separately)
- Use SegmentIterator in StreamingEngine to track the next segment
between switches
Issue #892 (refactor StreamingEngine)
Issue #1339 (period flattening)
Change-Id: I666cc21249c34ee6cbc138a59109d9f1159fa127
The recent DASH refactor broke the details of multi-period segment
references for SegmentTemplate+duration.
This change introduces a corrected universal model for generating
segment references for fixed-duration SegmentTemplate content. It has
been tested with a variety of streams from third-parties, most notably
the DASH-IF's live simulator.
Issue #1339 (flatten periods)
Issue #892 (refactor StreamingEngine)
Closes#2111
Bug: 28087927
Change-Id: Ife4e9ae2bb726e24e97dfe153882dabba4c03f2d
In an in-progress DASH stream (in which the content is static, but not
fully available yet), we will need to produce additional segment
references as time progresses. This was broken recently during
refactors for period flattening, when SegmentTemplate with a fixed
duration was changed to use a SegmentIndex instead of generating
references on-demand.
Issue #1339 (flatten periods)
Issue #892 (refactor StreamingEngine)
Change-Id: I0239335fa7c569063f06f4416982fc5ca7d5873d
This changes the eslint rule to enforce a strict pattern for the
argument comments. The comment must appear before the argument and
must be /* foo= */. This still ignores line comments.
Change-Id: I3afb01c65e1088eda13facb3aeeaa7595a2f5aee
This is a step along the way to flattening periods, and also
simplifies a few small things in StreamingEngine and tests.
Issue #1339 (flatten periods)
Issue #892 (refactor StreamingEngine)
Change-Id: Ie17cd5e15ed6ec9290a918c3a69c05c74581e0fc
SegmentReference used to have presentationTimeOffset, which,
subtracted from the period start time, was then _added_ to the
timestamps in the segment by MediaSource.
Now, SegmentReference has a timestampOffset field, which is exactly
what MediaSource's timestampOffset field is set to on the SourceBuffer
before this segment is appended. For DASH, this is periodStart minus
presentationTimeOffset.
This also adds append window start & end times to the
SegmentReference. Now segments can be appended to SourceBuffers
without reference to the period.
Note that start & end times of the SegmentReference in each segment
index are still relative to the period. This will change in a
follow-up.
Issue #1339 (flatten periods)
Issue #892 (refactor StreamingEngine)
Change-Id: I9d54eb2b529ec643c9475b8e9d218c3e2e826a26
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
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
To prepare for flattening out the manifest structure to remove
periods, this change moves initSegmentReference and
presentationTimeOffset fields into the SegmentReference object. This
way, the segments on either side of a period transition or HLS
discontinuity can have different offsets or init segments, eventually
allowing us to create a single array of SegmentReferences for
multi-period content.
Issue #1339
Change-Id: Ic7eff0483789644881247ecf8044c5fb6a48f0e6
In a recent refactor that made some internals of DASH parsing async for the first time, we broke the creation of SegmentReferences by having createUris close around values that changed later. This fixes the bug and adds a regression test.
This replaces find/get callbacks in Stream with a SegmentIndex. With
the exception of DASH's SegmentTemplate+duration, all manifests were
already backed by SegmentIndex. Now, all manifests are backed by
SegmentIndex. This will simplify Period-flattening, in which all
tracks will be represented by a list of segments, some of which come
from different Periods.
The SegmentIndex in Stream will not be created until
createSegmentIndex is called. Prior to this change, the find/get
callbacks could be invoked without createSegmentIndex() in some cases
(excluding DASH's SegmentBase), which some lazy tests took advantage
of. Now that find/get are methods on SegmentIndex, createSegmentIndex
must be called in all cases. The tests have been updated accordingly.
Making SegmentIndex generation async in all cases exposed some issues
with the parser context being modified in-place between one
Representation and the next. So the parser now makes a shallow copy
of the context before it is bound into an async callback.
To facilitate updating the SegmentIndex for SegmentTemplate+duration
content, SegmentIndex now has a method to update its list on a timer.
Once per segment duration, the index will be updated to add and remove
SegmentReferences.
The initial expansion of SegmentTemplate+duration will be limited to a
relatively small number of segments, to avoid excessive CPU or memory
consumption. This defaults to 1000 segments, but is configurable.
Issue #1339
Change-Id: I99c007b1096c3b396d04a729750cd7b743cb899d
This is a helper to aid in iterating over items. This returns a list
of objects that contain:
- "item": The current value.
- "prev": The previous value in the list.
- "next": The next value in the list.
- "i": The zero-based index in the list.
Issue #1518
Change-Id: Id18ab977e3ae45dfbfd2b4137a1bffb6e53c6bce
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
Before, segment timestamps were used in PresentationTimeline without
regard for the period start. This means they were not truly relative
to the presentation, but to the period.
The "isFirstPeriod" argument was also broken. It was meant to be true
for segments from the first period *ever*, but was passed true for the
first period *in the latest manifest update*. So data calculated from
that was bogus for live streams.
Now, notifySegments() is supplied with a period start time, so that
segment references can be combined with the period start to give
presentation timestamps. This fixes a major issue with the original
fix for #999.
Closes#999
Change-Id: Id0fe450f3ce4f90a2387d7103c75eb88f0c69c72
When we try to merge two SegmentIndex objects, we check to make sure
that they are sequential. Then, after merging the various SegmentIndexes,
they are fit.
This causes problems when trying to merge two identical periods together,
an operation that could potentially happen in a live stream.
SegmentIndex.merge was comparing the post-fit version of one SegmentIndex
with the pre-fit version of another, causing it to believe that the two
SegmentIndex had different end times when really they were identical.
This change causes SegmentTemplate.createStream to perform an extra fit
operation before merging, to avoid that problem.
Closes#1448
Change-Id: If2e9a9a91de344b7ab8cd9004da0553b324cb599
Google style guide requires adding curly braces to all block statements
even if it is only has one line. This fixes it by using eslint's
--fix flag followed by running clang-format to reformat the change.
Change-Id: Idc086c2aa8c02df5ef8b2140a11bfb9128eeb4bd
Rather than using the availability window, Playhead should use the
seek range to restrict the playhead's position.
Closes#1224
Change-Id: I8612bfafb53bbb214e32aae2d71af52d748a3aee
This is part of a change to convert all usages of 'var' with either
'let' or 'const'. This takes a conservative approach for 'const' where
it will only be used for aliases and storing the "original" values in
tests.
Change-Id: Iebba756b5d0e68c41292ecabda89503682d8d434
We incorrectly added the presentationTimeOffset to the segment times as
a fix for #1164. The correct fix is to use the include the PTO in the
time structure passed to the text parsers. This is a partial revert
of 207505.
Issue #1164Closes#1232
Change-Id: I1f2805e0dbdc44be71e2160b3d37a73732c97a4f
When calculating segment references, the end time should be capped at
the period's end, except when the period has no end.
Closes#1204
Change-Id: Ia608452706bbc3fd847a645197e8a0cb57d7aaec
We were not previously applying presentationTimeOffset in
SegmentTemplate w/ the duration attribute. This fixes the DASH parser
to correctly apply the offset in this case.
This also fixes an issue in which segment times could stretch past the
end of the period or even past the end of the presentation, causing
StreamingEngine to fail period transitions afterward.
Closes#1164Closes#1163 (PR to address 1164)
Change-Id: Ib16fc2b65117557a4ad9a05adc4a07f8bc90fd3c
In DASH SegmentBase, we were not dividing presentationTimeOffset by
the timescale. In all other instances of presentationTimeOffset in
DASH, we were handling it correctly.
This bug was present in all v2 releases until now.
The solution is not only to divide by timescale, but to rename all
internal uses of presentationTimeOffset to either unscaled or scaled,
to differentiate between those in timescale units and those in
seconds. I believe inconsistent naming and units were a contributing
factor to the creation of the bug.
Closes#1099
Change-Id: Id561f8eb1f5bc011c606e1925c12f0d8183fd51a
This reverts commit 478fb1a473
("Detect and attempt to correct timeline sync issues") and commit
4334b6ea90 ("Add mediaSegmentReferences
to shakaExtern.Stream").
Timeline correction only addresses one class of broken live content,
while actually making it more difficult to diagnose other classes of
broken live content.
Issue #933
Change-Id: Ie71b8a45600ed0994626f53268fb90e336c3c62b
This will allow us, in many cases, to detect time sync issues in
content by comparing the media segment references to the presentation
timeline. If the references are outside the timeline, it may indicate
a common form of bad content, and we may be able to attempt to correct
it.
In some cases, the references are not available upfront. We can't
detect time sync issues in DASH with SegmentTemplate+duration, because
the references are not explicitly described by the manifest. We can't
detect time sync issues in DASH with SegmentBase, because the segment
index requires additional fetching and parsing. (SegmentBase is not
used with live content, so this should be a non-issue.)
This only introduces the new data, but does not use it for detection
or correction yet.
Issue #933
Change-Id: If70b1bdbd3b08a7c8b7ae296da209737492dfe17
The bulk of the logic for gap jumping is handled in Playhead. It
tracks the current buffered ranges and jumps over any gaps that appear.
It listens for a special browser event ('waiting') for when the video
element runs out of playable frames.
This change also removes the logic for jumping gaps at the beginning
of the timeline. This is handled by the more general gap jumping
logic and works cross-browser.
Finally, this updates the buffering logic to only count the amount of
content buffered (i.e. ignoring the gaps). This fixes some bugs where
gaps in the content can result in StreamingEngine buffering forever
since it thinks only a little is buffered.
This includes full implementation of the logic, but this doesn't close
the issue since there aren't any integration tests yet. Those will
be added next.
Issue #555
Change-Id: Id99eb9fe469e8cf2c7464a3d70c3733791e806e0
This adds a severity field to Error objects. This can be used to
detect whether an error is recoverable. All the same errors are still
reported so the field can be ignored.
There are two possible values:
* RECOVERABLE means that the Player will try to recover from the error
* CRITICAL means the Player will be unable to continue and must call
load() again
Closes#564
Change-Id: Ie2c5468340c13e7a288b99690ab65b7ecc0a6b29
This fixes an infinite loop when storing SegmentTemplate-based VOD
content. In shaka.offline.Storage.prototype.createStream_, we loop
over all segment references to feed the download manager. Those
references should stop at the period duration.
Closes#739
Change-Id: Ia16e89968b3bd8fc554b71ac857f8d9ae890cde1
We usually fit segment references to the Period for VOD content. This
ensures that a gap in the manifest at the end of the Period doesn't
cause problems. We don't do this for live because we may get more
segments. However, for multi-Period live, we should still fit the
references for all Periods except the last one.
This also removes the error about duplicate Representation IDs for
VOD content since the problem only occurs for live.
Issue #694
b/35849085
Change-Id: Ib195dc51982ca58b8d5613b37817216980b8d366