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
### 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>
## 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.
- Lead with Common Failures section covering the most likely CI gotchas
- Two mandatory registrations for new source files (uncompiled.js +
build/types/)
- Export annotation rules with link to docs/design/current/export.md
- `@suppress warning`, zero runtime deps, lib/device/ sensitivity
- Shallow directory map with self-maintenance instruction
- High-stakes warnings section
- Drop deep lib/ subdirectory listing that goes stale
This is ~30 lines shorter, a couple hundred words shorter, and is
hopefully more focused and less brittle.
Co-authored-by: Claude Code (Claude Sonnet 4.6) <noreply@anthropic.com>
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
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>
## 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`
## Summary
- Adds a `customTrackLabel` callback to the UI configuration that allows
overriding track labels for both audio and text tracks
- The callback receives the default label (or `null` if the language was
unrecognized), the track object, and a type string (`'audio'` or
`'text'`)
- Returning a string overrides the label; returning falsy keeps the
default behavior
Fixes#9821
## Example usage
```javascript
ui.configure({
customTrackLabel: (defaultLabel, track, type) => {
if (track.language === 'fx') return 'Sound Effects';
return null; // use default
}
});
```
## Test plan
- Added integration tests verifying label override, null for
unrecognized languages, type argument, and fallback behavior
- Tests pass in both compiled and uncompiled modes
## AI Disclosure
As highlighted in the new `AGENT-ATTRIBUTION.md`, I've added Claude as a
co-author of the commit as I made use of it during this PR.
Signed-off-by: F1 MultiViewer <f1multiviewer@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
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
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
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
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.