Commit Graph

1410 Commits

Author SHA1 Message Date
Andy(김규회) c3d82bea1d feat(ABR): Monitor dropped frames to influence decisions (#9918)
Close https://github.com/shaka-project/shaka-player/issues/745

The ratio is checked periodically, and when the threshold is exceeded,
the current stream is 'disableStream' if possible, and a new decission
is taken

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
Co-authored-by: Matthias Van Parijs <matvp91@gmail.com>
2026-04-09 11:37:13 +02:00
Álvaro Velad Galván ccb4b1472e feat(net): Add commonAccessTokenHeaderName config (#9949)
Both CTA-5007-A and CTA-5007-B now specifies that the default header
name should be "cta-common-access-token", but it also provides a path
for using a custom header name.

Close https://github.com/shaka-project/shaka-player/issues/9948
2026-04-09 11:24:21 +02:00
Wojciech Tyczyński e2cf6a1724 chore: Replace PublicPromise with Promise.withResolvers (#9925)
Stop using `shaka.util.PublicPromise` and replace it with modern
`Promise.withResolvers()` API, that is [widely implemented
already](https://caniuse.com/wf-promise-withresolvers).

Polyfill is already included by Closure Compiler:
https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/js/es6/promise/withResolvers.js

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-04-07 16:11:29 +02:00
Álvaro Velad Galván 4706d5f286 feat: Add subtitleDelay config for manual subtitle timing offset (#9939) 2026-04-07 12:15:21 +02:00
Álvaro Velad Galván 0522d0b1dc feat(MSF): Make subscribe filter type configurable (#9941) 2026-04-07 10:47:23 +02:00
Álvaro Velad Galván 83cc35161e feat(MSF): Add authorizationToken support (#9916) 2026-04-07 09:54:45 +02:00
Wojciech Tyczyński 2d2228bbd8 chore: Remove DelayedTick (#9927)
DelayedTick in reality was used directly only in StreamingEngine for no
particular reason. Move this functionality directly to Timer class.
2026-04-02 18:45:26 +02:00
Wojciech Tyczyński 6509d9b7ac chore: Remove rarely used Functional methods (#9928) 2026-04-02 18:43:37 +02:00
Sakura501 586ce0636e chore(Demo): demo assetBase64 prototype pollution to DOM XSS (#9906)
## Summary

This PR fixes a demo asset parsing and configuration merge vulnerability
where a
malicious `assetBase64` payload could abuse `__proto__`, `constructor`,
or
`prototype` keys to pollute object prototypes and later reach DOM XSS
gadgets in
Shaka Player Demo.

## Vulnerability details

The vulnerable path was:

1. `demo/main.js` reads attacker-controlled `assetBase64` from the URL
hash.
2. `demo/common/asset.js` copies `extraConfig` into a player config
object with
   `for..in`, which allows dangerous magic keys to be applied.
3. `lib/util/config_utils.js` merges config objects with another
`for..in`
   traversal and no explicit rejection of `__proto__`, `constructor`, or
   `prototype`.
4. The resulting prototype pollution can be turned into DOM XSS when
later demo
   UI rebuild paths consume inherited properties.

## Fix approach

This change hardens both the demo entry point and the shared merge
utility:

- `demo/common/asset.js`
  - filter dangerous keys when copying `extraConfig`
  - restrict `toJSON()` and `fromJSON()` to own properties only
- prevent dangerous keys from being serialized into or restored from
saved demo
    assets
- `lib/util/config_utils.js`
  - switch config merging from `for..in` to `Object.keys()`
  - explicitly reject `__proto__`, `constructor`, and `prototype`

## Regression coverage

Added tests that verify:

- dangerous `extraConfig` keys do not alter the generated player config
- inherited demo asset properties are not serialized into JSON
- dangerous keys are ignored when parsing saved assets back into demo
objects
- inherited magic keys are not traversed during config merges

## Verification

- `python3 build/test.py --quick --filter 'Demo|ConfigUtils' --browsers
ChromeHeadless`
- `python3 build/check.py`
2026-03-30 10:40:10 +02:00
Ivan 2c8cfd20f3 perf(TS): Eliminate per-PES wrapper array allocations in parse loop (#9883)
This PR reduces GC pressure during MPEG-TS segment parsing - it replaces
nested PES packet arrays with a flat array plus a PES-start index,
eliminating per-PES inner array allocations and avoiding spread-operator
overhead when concatenating packets - reduces allocations, hence reduces
GC pressure on low-end devices during long livestreams
2026-03-26 10:03:32 +01:00
Álvaro Velad Galván 76d655bed6 perf(MSF): Improve compatibility with the draft-14 (#9895)
More types of messages are now supported than before. 
SubscribeError handling has been improved.
A new error has been added when no catalog.
Existing messages have been reviewed to eliminate inconsistencies in the
migration from draft-11 to draft-14 support.
Fix log levels
2026-03-26 09:46:40 +01:00
Ivan c86ce869c3 perf(media): replace filter calls in SegmentIndex with binary search (#9880)
This PR replaces `Array.filter` calls in
`SegmentIndex.merge()`,`mergeAndEvict()`, and `evict()` with more
efficient alternatives. The key addition is `binarySearch` helper: it
repeatedly checks the midpoint and discards half the array each time.
The idea is the same as `Array.findIndex` but exploiting the sorted
order to skip most of the work. `merge()` and `evict()` use this to find
their truncation/expiry boundary; `mergeAndEvict()` uses a simple
forward scan that stops at the first valid reference since stale refs
are always bunched at the front. This is done to reduce iteration during
playback (especially livestream with DVR)

- no big new array creations by default - we don't create one when for
example there is nothing to evict
- fewer comparisons — binary search finds the cutoff without scanning
the whole array
- slice just copies the kept elements and that's it
2026-03-25 10:00:52 +01:00
gmamzn dd5b2dab21 fix(HLS): Add support for DTS and DTS-HD audio codec variants (#9863)
Add DTS (dts), DTS-HD (dtsh), DTS Digital Surround (dtsc), DTS Express
(dtse), and DTS:X (dtsx) to AUDIO_CODEC_REGEXPS using a single merged
regex /^dts[cehx]?$/.

Include regression tests for all new codec variants.
2026-03-20 16:01:02 +01:00
Ivan c9f8057f9a perf(DASH): loop over adaptation sets using the partition method (#9862) 2026-03-20 15:45:57 +01:00
gmamzn d15a0702ac fix(util): Add support for MPEG-2 video codec (#9860)
Add /^mp2v/ regex to VIDEO_CODEC_REGEXPS so that guessCodecsSafe
correctly recognizes MPEG-2 video codec strings. Without this, manifests
containing mp2v codec identifiers would fail codec detection, preventing
playback of MPEG-2 video content.

Includes regression tests verifying mp2v is recognized as a video codec
and not misidentified as audio.
2026-03-20 14:09:43 +01:00
Álvaro Velad Galván b9abb399bb fix(LCEVC): Fix multi-period VOD support (#9837)
A new integration test has been added.
The use of `stream` within `stream` in `periods.js` has been refactored
to simplify management and avoid duplicates.

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-03-19 10:07:14 +01:00
Álvaro Velad Galván 0c0a47c8d6 fix(MSF): Use bigint natively (#9826)
Many relays use large numbers and with the current implementation it
doesn't always work.

See Closure's limitations here:
https://github.com/google/closure-compiler/wiki/BigInt-support
2026-03-14 10:51:09 +01:00
Álvaro Velad Galván c92c3bddba feat(DASH): Add json format support (#9788)
This initial support is complete but not efficient, as it involves
conversion to XML and normal processing. It should only be used for
testing purposes. Improved support will be added in the future.

Tested with https://github.com/Dash-Industry-Forum/dash-json-schema

Note: This is only added to the experimental build.
2026-03-09 09:52:06 +01:00
vlazh 2e732b5392 feat: Add clampAppendWindowToDuration option (#9699)
Fixes #9674
2026-03-06 11:04:00 +01:00
Álvaro Velad Galván ac010c4159 perf: Improve performance of TsParser (#9783) 2026-03-04 12:47:11 +01:00
Álvaro Velad Galván cca8f504c2 fix: prevent negative times in Stats (#9784) 2026-03-04 10:51:45 +01:00
Álvaro Velad Galván 9575e2ae63 perf: Eliminate DataViewReader allocation and use native clz32 in ExpGolomb (#9779) 2026-03-03 11:06:32 +01:00
gmamzn 5b81f70eb0 fix(tXml): Return default value for a missing attribute (#9734)
If the attribute does NOT exist, getAttribute(name) on an element return
an empty string. Empty string '' is not equivalent to 'null'. As a
result 'defaultValue' is not returned, which leads to playback related
issues.
2026-03-02 10:54:20 -08:00
Álvaro Velad Galván e3781c493b feat(DASH): Enable automatic XLink processing with fast detection and performance improvements (#9764)
This PR modernizes and optimizes XLink handling in the DASH parser by
removing the legacy flag-based behavior and replacing it with a
standards‑aligned, fast, and deterministic workflow. The changes improve
performance on large MPDs, simplify configuration, and ensure correct
XLink expansion according to DASH/XLink rules.

XLink processing is now automatically enabled only when needed. If the
MPD contains no XLinks, the parser skips processXlinks entirely.
2026-02-26 14:05:32 +01:00
Andy(김규회) c7368024ae feat: Select default track by a list of preferences (#9542)
I went ahead and implemented the full structured preference system that
was discussed in
https://github.com/shaka-project/shaka-player/issues/1591.
Instead of just expanding languages to arrays, I replaced all 14
individual preference fields with 3 structured arrays:

```tsx
  preferredAudio (language, role, label, channelCount, codec, spatialAudio)
  preferredText (language, role, format, forced)
  preferredVideo (label, role, codec, hdrLevel, layout)
```

Each array entry works as an AND filter - so you can say things like "I
want Korean with 5.1 surround, but if not available, English is fine
too":

```tsx
player.configure('preferredAudio', [
  {language: 'ko', channelCount: 6},
  {language: 'ko'},
  {language: 'en'},
]);
```

<img width="1728" height="965" alt="image"
src="https://github.com/user-attachments/assets/7b088150-139b-475e-bdba-5bc77dd4e524"
/>

**Config** - Replaced the 14 individual fields with 3 arrays of typed
preference objects (AudioPreference, TextPreference, VideoPreference).
The old fields still work at runtime with a deprecation warning, so
existing apps won't break immediately.

**Demo** - The demo config UI now shows inline expandable preference
lists instead of flat text inputs. You can add/remove entries and
configure each field per entry. URL hash serialization was updated to
use JSON format, with legacy param fallbacks preserved.
2026-02-20 10:12:08 +01:00
Álvaro Velad Galván f8abc76dcf docs: Fix NO_VIDEO_ELEMENT doc on v5 (#9697) 2026-02-11 13:16:48 +01:00
Andy(김규회) d98169bc25 feat(EME): Add retryLicensing() and failureCallback for manual license retry (#9638)
So basically, when a license request fails (eg. network Error, server
down whatever), apps can now retry from scratch by calling
`player.retryLicensing()`. This was tricky to implement because of EME
spec limitations: `generateRequest()` can only be called once per
session. So if it fails, it would be stuck.

So I close the old session and create a brand new one with the same
`initData`

> Will Video element throw an error during this process?

we were worried that closing the session would leave the video without
keys for a brief moment, potentially triggering errors. But in practice,
the transition is fast enough( I added a 0.1s delay for CDM clean up)
and the video element handles it gracefully

> Will new encrypted event fire? If not, will it limit this feature?

The encrypted event only fires when the browser first encounters
encrypted content. When we close and recreate a session, the content is
already loaded, so no new event

Solutions: In `CreateSession()` metadata store `initData` and
`initDataType` in the session metadata when the session is first
created. So when `retryLicensing()`is called, we just grab the stored
data and pass it to `generateRequest()` on the new session. No need to
wait for an `encrypted` event at all.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-02-05 14:12:30 +01:00
Álvaro Velad Galván c200219fa2 test: Fix UI tests on SmartTVs (#9660)
Tests fixed:

```
  UI Customization
    ✗ big buttons only created when configured [Safari 3.0 (Tizen 3.0)]
	Error: Expected 1 to be 0.
	    at <Jasmine>
	    at Function.confirmElementMissing (test/test/util/ui_utils.js:70:29 <- test/test/util/ui_utils.js:139:31)
	    at _callee6$ (test/ui/ui_customization_unit.js:86:13 <- test/ui/ui_customization_unit.js:152:21)
	    at tryCatch (node_modules/@babel/polyfill/dist/polyfill.js:6473:40)
  UI
    controls
      controls-button-panel
        ✗ has default elements [Safari 3.0 (Tizen 3.0)]
	Error: Expected 1 to be 0.
	    at <Jasmine>
	    at Function.confirmElementMissing (test/test/util/ui_utils.js:70:29 <- test/test/util/ui_utils.js:139:31)
	    at _callee15$ (test/ui/ui_unit.js:425:19 <- test/ui/ui_unit.js:506:27)
	    at tryCatch (node_modules/@babel/polyfill/dist/polyfill.js:6473:40)

```
2026-02-05 07:09:13 +01:00
Álvaro Velad Galván bd167c3744 feat: Add listenMulti and listenOnceMulti to shaka.util.EventManager (#9652)
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-02-03 21:49:35 +01:00
Álvaro Velad Galván 6fc70622eb chore: Change frameRate from string to number in shaka.media.SegmentUtils.BasicInfo (#9627)
Related to https://github.com/shaka-project/shaka-player/pull/9626
2026-01-29 17:13:20 +01:00
Álvaro Velad Galván 674e71d064 fix(Ads): Harden MediaTailorAdManager state and cuepoint handling (#9619)
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>
2026-01-29 12:39:14 +01:00
Álvaro Velad Galván 793749a6e2 perf: Minor performance optimizations in TXml text processing and root lookup (#9622)
- Avoid repeated split() when matching expected root element names
- Improve text content concatenation to reduce string allocations
- Remove unnecessary Array.from() usage when checking text-only children
2026-01-28 19:08:09 +01:00
Álvaro Velad Galván a1b5ffa510 chore: Remove unused params in shaka.util.Mp4BoxParsers (#9615) 2026-01-27 17:52:14 +01:00
Álvaro Velad Galván d452350d57 feat!: Remove shaka.util.XmlUtils (#9616)
It is removed because there is no longer any dependency on it anywhere
in the code.
2026-01-27 17:52:00 +01:00
Álvaro Velad Galván 71af24f82b feat: Only disallow SourceBuffer.changeType on PlayReady when using Edge browser (#9603)
More info in
https://chromium-review.googlesource.com/c/chromium/src/+/4577759 and
https://issues.chromium.org/issues/40261162

According to the source code and empirical testing, SMOOTH is supported
with clear content and Widevine, but not with PlayReady.
2026-01-26 12:12:53 +01:00
Andy(김규회) eac68c7ea0 feat(EME): Add manual and automatic license renewal API (#9589)
Widevine's CDM handles renewal automatically, but FairPlay and PlayReady
require manual
`session.update()` calls to renew licenses before they expire.
Previously, developers had to access internal APIs like
`getDrmEngine().activeSessions_` which only works in debug builds - not
ideal for production use.
Based on the discussion in #9505, this PR implements both Option A and
Option C:
**Option A - Manual renewal API:**
```js
player.renewLicense(); // all sessions
player.renewLicense(sessionId); // specific session
 ``` 
  **Option C - Automatic renewal with config:**
```js
player.configure({
drm: {
renewalIntervalSec: 600
}
});
player.addEventListener('licenserenewal', (event) => {
console.log('License renewed:', event.newSessionMetadata,
event.oldSessionMetadata);
  });
```
This way, developers can choose automatic renewal, manual control, or
both depending on their use case.
Under the hood, FairPlay sends a 'renew' message via session.update(),
while PlayReady re-creates the session. Widevine just dispatches the
event since the CDM already handles everything.
2026-01-26 11:49:26 +01:00
Wojciech Tyczyński 482117f6c8 fix(ContentWorkarounds): Insert PSSH boxes for fake init encryption (#9600)
Related to #8048

Some platforms (i.e. NOS STB) are not able to play encrypted content
without PSSH boxes in init segments. This PR addresses it by adding PSSH
boxes with actual data if we have it.
2026-01-26 10:15:39 +01:00
Wojciech Tyczyński 5c05132772 feat!: Use shared logic for MediaError details (#9594) 2026-01-22 20:50:32 +01:00
Álvaro Velad Galván 4c945af650 feat(MSF): Add support for custom namespaces via config (#9586) 2026-01-22 14:00:12 +01:00
Álvaro Velad Galván 5ee77799f5 chore: Remove unused code (#9584) 2026-01-21 14:08:36 +01:00
Woody Hill 66b0c74a01 fix: parseHDLR for Apple QuickTime hdlr box compatibility (#9577)
Apple QuickTime places a manufacturer field ('appl') immediately after
the handler type ('soun'), causing readTerminatedString() to incorrectly
read 'sounappl' instead of 'soun'. This breaks Opus fMP4 audio playback
for content packaged with Apple tools.

Replace null-terminated string parsing with fixed-length byte reading to
extract exactly 4 bytes for the handler type.

Closes #9576

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-01-20 12:59:31 +01:00
Wojciech Tyczyński 9af54837c7 chore: Mp4Generator - make segmentInfos array optional (#9569) 2026-01-17 04:44:03 +01:00
Álvaro Velad Galván e96442c409 feat: Add new config to allow stop fetching new segments on pause (#9567)
Close https://github.com/shaka-project/shaka-player/issues/9386
2026-01-16 07:37:08 +01:00
Álvaro Velad Galván e5d9471fa5 feat(HLS): Add AES-256-GCM support (#9562)
More info in:
https://datatracker.ietf.org/doc/draft-pantos-hls-rfc8216bis/19/ and
https://mailarchive.ietf.org/arch/msg/hls-interest/85CoeMS9O2zRoMff_Xx_WgCukJg/
2026-01-15 14:18:02 +01:00
Álvaro Velad Galván bdfd028088 feat(HLS): Support chapters on Live and custom config to add it (#9561)
Co-authored-by: Theodore Abshire <TheodoreAbshire@Gmail.com>
2026-01-15 09:47:11 +01:00
Álvaro Velad Galván ef361ed039 feat: Add MoQT draft-14 + WARP/MSF draft-1 experimental support (#9409)
Spec: https://datatracker.ietf.org/doc/draft-ietf-moq-transport/14/
Spec: https://datatracker.ietf.org/doc/draft-ietf-moq-warp/01/

Note: this is experimental and not included in the default builds

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-01-14 09:27:10 +01:00
Andy(김규회) 05b09728c7 perf: Use Map.getOrInsert/getOrInsertComputed native methods (#9546)
Added polyfills for `Map.getOrInsert()` and
`Map.getOrInsertComputed()` from the TC39 upsert proposal and refactor
the codebase to use them.
These methods replace the common "check if key exists, then set default"
pattern with a single atomic operation. This improves code readability
and eliminates redundant map lookups throughout the player.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-01-13 10:57:25 +01:00
Wojciech Tyczyński 1c18dea798 chore: Remove encrypted property from StreamInfo (#9547)
Simplify interface a bit
2026-01-07 15:03:11 +01:00
Álvaro Velad Galván 909655f4eb feat: Add configurationchanged event (#9531) 2025-12-19 16:35:35 +01:00
Álvaro Velad Galván c6e6082bc2 feat: Allow override subtitle position (#9522)
Close https://github.com/shaka-project/shaka-player/issues/9521

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2025-12-19 13:38:33 +01:00