Commit Graph

4942 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
Marc-Antoine 14821c30fb fix: Correctly extract file extension from URLs with dots in query params (#9946)
### Description

Fixes #9945 

The `getExtension` function (rewritten for performance in #9816) scans
the URI right-to-left, encountering dots in query parameter values (e.g.
hostnames like `app.example.com`, filenames like `en.vtt`) before
finding the `?` delimiter. This causes incorrect extension detection,
breaking MIME type resolution for URLs with signed parameters or other
query strings containing dots.

**Fix:** Split the single right-to-left scan into two passes:
1. **Left-to-right:** find the first `?` or `#` to establish the path
boundary
2. **Right-to-left:** scan backward within the path portion only,
looking for `.` or `/`

This preserves the lightweight character-scanning approach from #9816
without reintroducing the `goog.Uri` dependency.

**New test cases added:**
- Dots in query parameter values
(`?host=app.example.com&signature=abc.def`)
- Signed URLs with encoded paths and filenames in query strings
- Hostname-like values in query parameters (`?origin=cdn.example.co.uk`)
- No path extension with dotted query values (`/stream?file=video.mp4` →
`""`)
- Dots in fragment identifiers (`#t=1.5`)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:11:03 -07:00
Antonio Díaz Correa 93290d27a0 fix(StreamingEngine): correct variable reference in discardReferenceByBoundary_() (#9943)
## Description

fix: wrong variable reference in `discardReferenceByBoundary_()` causing
VIDEO_ERROR on HLS live streams
### What this fixes
`discardReferenceByBoundary_()` in `lib/media/streaming_engine.js` has a
wrong variable reference: when processing `newCodec` the code reads
`lastInitRef.mimeType` instead of `initRef.mimeType`.

This means `newCodec` is always identical to `oldCodec`, so the guard
that prevents unnecessary resets (`discard = false`) never fires when
`crossBoundaryStrategy === KEEP`.
 
As a result, every HLS discontinuity of timestamps, codecs, or encoding
parameters forces a MediaSource reset.
On live streams with server-side DAI, the repeated forced resets corrupt
the SourceBuffer and crash the player with VIDEO_ERROR (error code
3016).

This is a regression introduced in 5.x. Shaka 4.x did not have this
issue.
                  
### Fix

One-line change in `lib/media/streaming_engine.js`:
   
```diff                                                                                                                                                                                                                                                                                                     
  const newCodec = MimeUtils.getNormalizedCodec(
-     MimeUtils.getCodecs(lastInitRef.mimeType));
+     MimeUtils.getCodecs(initRef.mimeType));
```
   
With this fix `KEEP` correctly compares the codec of the outgoing init
segment against the codec of the incoming one. When they match
MediaSource is kept, and when they differ it is reset, which is the
intended behavior.
                  
### How to reproduce
                  
1. Play an HLS live stream with server-side DAI that generates
`EXT-X-DISCONTINUITY` tags at ad boundaries, like FAST channels.
2. Use default Shaka config, do not override `crossBoundaryStrategy`,
default is `KEEP`.
3. Wait for an ad to be triggered.
4. Player crashes with `VIDEO_ERROR` / error code 3016. No network
errors. All segment fetches return 200/206.
2026-04-08 11:13:02 +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
mohammadmseet-hue b6bc40635e fix(TTML): sanitize backgroundImage URL to prevent CSS injection (#9929) 2026-04-07 12:17:57 +02:00
Álvaro Velad Galván 845b6bd197 fix: Properly clone nested cues and CueRegion in Cue.clone() (#9940) 2026-04-07 12:16:44 +02:00
Álvaro Velad Galván b6a2d55f85 fix(Ads): Fix playback of X-ASSET-LIST with X-PLAYOUT-LIMIT on Live (#9915) 2026-04-07 12:16:10 +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 6c286b6ad4 fix: Include isSwitchingContent in UnloadingEvent when load replaces existing content (#9934)
Fixes https://github.com/shaka-project/shaka-player/issues/9922
2026-04-07 11:06:49 +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
Ivan 6f57772c0c perf: replace shift lpop with binary search (#9936)
This PR replaces the repeated shift loop in `fit` method with an already
present binary search, reducing loop complexity - helps TV devices and
reuses existing optimization code
2026-04-06 12:56:21 +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
Wojciech Tyczyński e29052ab5b chore: Simplify TypedArray polyfill (#9924) 2026-04-02 09:01:18 +02:00
Matthias Van Parijs 5dbb2987ff feat: Add basic support for TiVo OS (#9758)
I got in touch with some people at TiVo OS and they're willing to help
out with proper device support.

This is a draft as we'll have to figure out the details (eg; max
resolution probing, HDR capabilities) along the way.

Caveats

- Earlier versions of BMW run on Linux, with user agent "Mozilla/5.0
(X11; Linux aarch64) AppleWebKit/573.36 (KHTML, like Gecko)
Chrome/126.1.0.0.0 Safari/537.36 BMW/156", which is TiVo under the hood.
Current implementation wouldn't match this but there's a few config
variables that need to be adjusted (eg; CrossBoundaryStrategy RESET).
- I have yet to check if newer BMW's (run on Android) contain TiVoOS in
their user agent.
- TiVo is a new player in the TV market, they ship their OS with various
vendors. I shall yet have to receive proper info of what runs where.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-03-31 09:59:01 +02:00
Álvaro Velad Galván e85e74a952 fix(MSF): Add PUBLISH_NAMESPACE_OK response to server PUBLISH_NAMESPACE (#9909) 2026-03-30 12:59:11 +02:00
Álvaro Velad Galván 7e80575446 fix: Fix HDR detection in some devices (#9908) 2026-03-30 10:45:18 +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 db1ab2d2bb chore(HLS): remove unused regex code, update one check (#9905)
This PR removes the regex patterns I forgot to remove in
https://github.com/shaka-project/shaka-player/pull/9857/ - sorry!

also updates one check to remove the regex object entirely
2026-03-29 14:14:55 -07:00
Álvaro Velad Galván 40e46d5ce3 perf(MSF): Reduce startup latency changing the type of subscribe (#9903) 2026-03-27 12:13:32 +01: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
Álvaro Velad Galván c272e0bf60 fix(MSF): Correct handling of PUBLISH_DONE (#9893)
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-03-25 11:22:51 +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
Álvaro Velad Galván 47ed5accfa fix(MSF): Correct parsing of publishDone message (#9890) 2026-03-24 17:42:17 +01:00
Gaurav Mahendroo a62e87b351 fix: Call endOfStream when no data available close to duration (#9866)
When playback reaches near the end of the presentation but no buffer
exists and no segment reference is found, the player continuously
retries without properly detecting end-of-stream, preventing the ended
event from firing.

When close to end (timeUntilEnd < oneMicrosecond) with no buffer and no
segment reference, immediately mark as end-of-stream instead of retrying
indefinitely. Also propagate the endOfStream state to embedded CEA text
streams when the video stream reaches end.
2026-03-24 11:09:09 +01:00
Álvaro Velad Galván 6805b55769 feat(ABR): Inform the ABR whether the stream is low latency or not (#9882)
Our ABR doesn't use it, but it's useful for custom implementations.

Related to https://github.com/shaka-project/shaka-player/issues/9872
2026-03-24 09:22:55 +01:00
splint-disk-8i 5b325018e8 chore: remove duplicate words in code comments (#9879)
Small cleanup - found two instances of 'the the' in code comments:

- lib/hls/manifest_text_parser.js (line 137)
- lib/player.js (line 2569)
2026-03-23 15:01:27 +01:00
Ivan be72faa99a chore(streaming): iterate on Map directly (#9878)
This PR removes the array creation as there is no need to swap the data
structure - could be iterated on directly in both cases
2026-03-23 14:44:08 +01:00
Ivan c2531a8b51 perf(net): avoid array allocations in XHR header parsing to reduce GC pressure (#9874)
This PR reduces GC pressure in the XHR networking plugin by dropping
array creation in the header loop - again adding some help to lower-end
hardware
2026-03-23 11:32:07 +01:00
Erik Herz 313d1ce952 fix(MSF): handle SUBSCRIBE_NAMESPACE (0x11) control message (#9871) 2026-03-23 10:35:30 +01:00
gmamzn 45a86cacd5 fix(HLS): Prevent infinite manifest update delay (#9867)
During a variant switch in HLS live content, shaka may take ~1 second to
create a new segment index (due to network calls). During this window,
the number of active streams temporarily drops to zero. When update()
runs in this state, lastTargetDuration_ gets set to Infinity because
there are no active streams to reduce it. This causes
getUpdatePlaylistDelay_() to return Infinity, so
updatePlaylistTimer_.tickAfter(Infinity) is called, effectively stopping
manifest updates forever.

Fix this with two guards:
1. In update(): return early when there are no active streams, before
setting lastTargetDuration_ to Infinity.
2. In onUpdate_(): if finalDelay is Infinity or NaN, use a 1-second
fallback delay instead of scheduling with a non-finite value.
2026-03-23 10:20:59 +01:00
Ivan 3a5d588dbd perf(DASH): drop array operations on unique IDs when parsing periods (#9870)
Two targeted performance improvements in aimed at reducing overhead on
older devices

1. Avoid intermediate array for representation ID uniqueness check

Previously, all representation IDs were pushed into a temporary ids[]
array, then a Set - this PR eliminates the array allocation entirely.

2. Re-parse only affected AdaptationSets for dependency streams

Previously, when any stream had a dependency stream, every AdaptationSet
was re-parsed from XML. Now, only the specific AdaptationSet nodes that
contain streams with dependencies are re-parsed. This avoids redundant
XML traversal and parsing for the common case where most adaptation sets
have no dependency streams.
2026-03-23 10:09:42 +01:00
Ivan 503234e9c6 perf(VTT): reduce GC pressure in VTT text parser (#9869)
This PR:

 - replaces `splice` with an index variable to avoid array shifts on every cue parse
 - replaces `slice(1).join('\n')` with a manual loop to eliminate two intermediate allocations per cue
 - hoists inline regex literals to static class constants, fixing unreliable literal caching in older Chromium version (helps TV devices and Xbox)
2026-03-20 15:11:10 -07:00
gmamzn 12f7296c6c fix: Increase tolerance for duplicate segment detection (#9865)
In HLS, the segment iterator can add or remove segments rapidly, causing
the same segment to reappear with a slightly different start time. The
existing duplicate detection used a 1ms tolerance, but some streams
exhibit timing inaccuracies between 1ms and 2ms, causing the same
segment to be downloaded twice. This leads to AV sync issues because the
duplicate segment shifts the buffer by one segment duration.

Increase the tolerance from 1ms to 2ms to cover these cases.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-03-20 16:46:41 +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
Álvaro Velad Galván d604cc2956 feat(Ads): Add startedAt param to ad-break-started event (#9858) 2026-03-20 15:55:11 +01:00
Ivan c9f8057f9a perf(DASH): loop over adaptation sets using the partition method (#9862) 2026-03-20 15:45:57 +01:00
Ivan 79d29e08ee perf(HLS): reduce GC pressure when parsing HLS manifest tags (#9857)
Replaces regex and TextParser with indexOf/substring in
`ManifestTextParser.parseTag`

This is also done to reduce GC allocation per one tag by removing
TextParser instance, regex spawns and result arrays. Mostly targeting
older devices like Tizen 3-6, WebOS 4, Xbox One
2026-03-20 15:45:44 +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 feae1d1e81 feat(Ads): Add ad-playing event to signal real ad playback start (#9855)
Close https://github.com/shaka-project/shaka-player/issues/9850
2026-03-20 13:59:01 +01:00
Ivan 8819786564 perf(HLS): parse tag string directly instead of creating an array (#9856)
Another small healthy change, putting code in one place and reducing GC
pressure on TVs
2026-03-20 12:48:32 +01:00
Ivan e687a6c774 perf(Transmuxer): replace identical object literals with named constants (#9852)
In TS Transmuxer, Replaces 9 identical inline Mp4SampleFlags object
literals across 7 stream info methods with 3 named constants
(AUDIO_SAMPLE_FLAGS_, VIDEO_KEYFRAME_FLAGS_, VIDEO_NON_KEYFRAME_FLAGS_)

- Reduces duplication and improves readability — each constant makes the
shared object payload referenced
- As a side benefit, eliminates per-frame object allocations during
transmuxing, reducing GC pressure on low-end devices like Tizen/LG etc.
2026-03-20 12:48:19 +01:00
Ivan 39cc2bd18a perf(player): stop recreating functions on video time update (#9854)
This PR extracts `isQuartile()` and `checkEnded()` from
`onVideoProgress` into class methods to avoid recreating closures on
every `timeupdate` event, improving readability but also somewhat
reducing GC pressure on TV devices.
2026-03-20 11:33:10 +01:00
Álvaro Velad Galván ea95befa54 feat(Ads): Add ad-interstitial-preloaded event (#9853)
Close: https://github.com/shaka-project/shaka-player/issues/9849
2026-03-20 10:52:20 +01:00
Álvaro Velad Galván 72a8e942b5 fix(LCEVC): Fix live support when using DASH dual track (#9841) 2026-03-19 11:54:29 +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
Julian Domingo 941d165c87 fix: Prevent live stream infinite buffering when isAudioMuxedInVideo is present (#9835)
Fixes https://github.com/shaka-project/shaka-player/issues/9836
2026-03-18 21:08:07 -07:00