This change improves MediaTailor ad handling by:
- Deduplicating cue points to avoid repeated ad markers
- Guarding ad break listener setup to prevent event duplication
- Cleaning up ad state more defensively on stop/end
- Improving static resource caching and tracking robustness
These fixes prevent duplicate events, listener leaks, and inconsistent
ad playback during manifest updates and polling.
---------
Co-authored-by: Theodore Abshire <TheodoreAbshire@Gmail.com>
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
A test suite that overwrites the HLS parser needs to restore it afterward. To aid in debugging future parser issues, this adds the detected or specified MIME type to the error object for UNABLE_TO_GUESS_MANIFEST_TYPE.
Closes#5834
Adds a new player method, preload. This asynchronous method creates a PreloadManager object, which
will preload data for the given manifest, and which can be passed to the load method (in place of an asset URI)
in order to apply that preloaded data. This will allow for lower load latency; if you can predict what asset will
be loaded ahead of time (say, by preloading things the user is hovering their mouse over in a menu),
you can load the manifest before the user presses the load button.
Note that PreloadManagers are only meant to be used by the player instance that created them.
Closes#880
Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
We declare shaka.util.Error to extend the native Error, but only supplied a message field in uncompiled and debug modes. This broke the Jasmine test framework when it tried to extract error message information from a compiled-mode shaka.util.Error object.
Now we always supply a message object, and merely skip the fancy enum formatting in compiled mode.
Add capability to re-use persistent license sessions across sessions.
DrmEngine will now always:
- try to start stored persistent sessions before trying to fetch a
license, as-to be able to check if all needed keys are already loaded.
- ask for a new license when the persistent session doesn't have the
needed keys for playback,
Given the flag `persistentSessionOnlinePlayback` is true, DrmEngine:
- won't remove the persistent session from the device at the end of the
playback,
- won't throw an error when the persistent session isn't found on the
device,
For now, it needs Shaka's users to persist session information by
themselves (localStorage, IndexDB, ...) before giving it back for the
next session. Still, it lays foundation to develop the feature to fully
handling it on Shaka's side.
Related to #1956
This adds extra context to 3015 (MEDIA_SOURCE_OPERATION_THREW) errors, by attaching
the error on the media element. This is helpful because, in some situations, media source operations
can have very unhelpful exception strings like:
`Error: Failed to execute 'appendBuffer' on 'SourceBuffer': The HTMLMediaElement.error attribute is not null`
In some cases, indexedDB.open() can end up calling neither callback.
When this does happen, according to my initial testing, it happens
consistently when reloading the page, so it's not a one-off fluke but
presumably some sort of implementation or browser install problem. If
that does happen, the init promise of the storage muxer hangs forever,
potentially blocking other operations from happening. This adds a
timeout to the invocation of indexedDB.open(), after which the operation
fails with a new error.
Now that we support AES-128, some older AES-128 code paths in the HLS
parser have become obsolete. This cleans up those unneeded code paths
and adds a test to ensure that the correct failure handling is used
when AES-128 cannot be supported by the platform.
Now that #2337 has been implemented, the error code HLS_INTERNAL_SKIP_STREAM
is no longer used anywhere in the code.
This retires that error, and also cleans up the code that previously
was responsible for handling that error being fired.
Pre-work for #1936
addChaptersTrack() was already an async method, but it did not wait
for the chapter data to be loaded by the browser. The solution is to
wait for the `load` event on the `<track>` element we create.
To accomplish this, some cleanup and refactoring was done in how
tracks are managed. Summary of changes:
- The `addtrack` event, which triggered management of tracks in src=
playback, is now used for all types of playback. In src= mode, it
manages all tracks, and in MSE mode, it only manages chapters
tracks (which are added to the video element as in src= mode).
- `processChaptersTrack_()` has been renamed to
`activateChaptersTrack_()`, since its only job is to set the
track's mode field to make the browser load it.
- `activateChaptersTrack_()` is now only ever called via the
`addtrack` event.
- `activateChaptersTrack_()` no longer loops over all chapter tracks
on a timer, and instead only touches the single track it was
called for.
- `addSrcTrackElement_()` now returns the HTML `<track>` element it
creates.
- `addChaptersTrack()` now awaits a `load` or `error` event to
complete (or fail) the operation.
- Existing tests for addChaptersTrack had long delays to work around
this issue; these delays have simply been removed.
Fixes#4186
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
Add support for HLS com.apple.streamingkeydelivery through MSE/EME implementation.
Close#3346
## Tests
Tested on:
- Mac 11.6 Safari 15.2
- iOS 15.2 Safari 15.2
- Mac 11.6 Chrome 96 (for potential regressions on Widevine keySystem)
| Mode | DRM API | TS | CMAF (mono-key and multi-keys)
|---|---|---|---|
| file | EME | ✅ | ✅ |
| file | Legacy-prefixed | ✅ | ✅ |
| media-source | EME | **mux-js**: `encrypted` never fired<br />**real MSE**: `encrypted` event received, but with incorrect `sinf` initData (*1) | ✅ |
| media-source | Legacy-prefixed | **mux-js**: `webkitneedkey` never fired<br/>**real MSE**: TBD | 🔴 fails to append media segment to SourceBuffer (init segment ok) `(video:4) – "failed fetch and append: code=3015"` |
## Support table
| Mode | DRM API | TS | CMAF (mono-key and multi-keys)
|---|---|---|---|
| file | EME | ✅ | ✅ |
| file | Legacy-prefixed | ✅ | ✅ |
| media-source | EME | 🚫 `4040: HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED` | ✅ |
| media-source | Legacy-prefixed | 🚫 `4041: HLS_MSE_ENCRYPTED_LEGACY_APPLE_MEDIA_KEYS_NOT_SUPPORTED` |🚫 `4041: HLS_MSE_ENCRYPTED_LEGACY_APPLE_MEDIA_KEYS_NOT_SUPPORTED` |
⚠️ Use EME APIs with multi-keys CMAF makes the video stalling with the audio continuing alone after a short time (~3 minutes in the stream, could be shorter, could be longer). Didn't find an explanation to that yet. I've observed the same behaviour with hls.js code so I don't think this is a player issue.