This PR removes the CLOSED-CAPTIONS attribute (and a few others) from
the EXT-X-I-FRAME-STREAM-INF tag in the HLS master playlist.
According to the HLS RFC (Section 4.4.6.3), the CLOSED-CAPTIONS
attribute is not defined for EXT-X-I-FRAME-STREAM-INF tags. Including it
causes non-compliance and may result in playback issues on strictly
compliant players.
References
[RFC 8216 Section
4.4.6.3](https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-16#section-4.4.6.3)
Affected version : >= 2.5
---------
Co-authored-by: Xavier Laffargue <xavier.laffargue@radio-canada.ca>
Current deps require an old CMake version, support for which has been
removed from latest CMake in Ubuntu and Arch.
```
CMake Error at packager/third_party/c-ares/source/CMakeLists.txt:3 (CMAKE_MINIMUM_REQUIRED):
Compatibility with CMake < 3.5 has been removed from CMake.
```
This upgrades:
- abseil-cpp, 20240116.0 => 20260107.1
- c-ares, v1.20.1 => v1.34.5
- json, v3.10.1-115-g954b10ad => v3.12.0
- libwebm, 1.0.0.28 => 1.0.0.32
With these changes, the build has been verified with CMake 3.31.11
(latest v3) and CMake 4.2.3 (latest v4).
---------
Co-authored-by: Joey Parrish <joeyparrish@google.com>
I've finally generated test material and tests to make a PR to fix text
segment generation for MPEG-2 TS streams with sparse teletext data,
making a big improvement compared to the original teletext support in
#1344.
## Problem
When packaging MPEG-TS input containing DVB-Teletext subtitles for
DASH/HLS output, two fundamental issues arise:
1. **Sparse input handling** - Teletext streams only contain data when
subtitles are displayed. During gaps (which can span multiple segments),
no PES packets arrive, leaving the text chunker with no timing
information to drive segment generation. This results in missing
segments or segments with incorrect timing.
2. **Misaligned segment boundaries** - Even when segments are generated,
the text segment timestamps and boundaries differ from video/audio
segments. This causes `<SegmentTimeline>` mismatches in the MPD,
playback issues on some players, and sometimes fewer text segments than
video segments.
## Solution
This PR introduces two complementary mechanisms:
### 1. Heartbeat mechanism (sparse input handling)
The `Mp2tMediaParser` now sends periodic "heartbeat" signals to text
streams:
- Video PTS timestamps are forwarded to all text PIDs as
`MediaHeartBeat` samples
- `EsParserTeletext` emits `TextHeartBeat` samples when PES packets
arrive without displayable content
- `TextChunker` uses these heartbeats to drive segment generation even
during gaps in subtitle content
- Ongoing cues that span segment boundaries are properly split and
continued
A new `heartbeat_shift` stream descriptor parameter (default: 2 seconds
at 90kHz) controls the timing offset between video PTS and text segment
generation, compensating for pipeline processing delays.
### 2. SegmentCoordinator (segment boundary alignment)
A new N-to-N media handler (`SegmentCoordinator`) ensures text segments
align precisely with video:
- Passes all streams through unchanged
- Replicates `SegmentInfo` from video/audio `ChunkingHandler` to
registered teletext streams
- `TextChunker` in "coordinator mode" uses received `SegmentInfo` events
to determine segment boundaries instead of calculating from text
timestamps
This guarantees identical segment timelines across all adaptation sets.
## Testing
- **Integration tests** in `packager_test.cc`:
- `TeletextSegmentAlignmentTest.VideoAndTextSegmentsAligned` - Verifies
segment count, start times, and durations match between video and text
-
`TeletextSegmentAlignmentTest.VideoAndTextSegmentsAlignedWithWrapAround`
- Same verification with PTS timestamps near the 33-bit wrap-around
point (~26.5 hours)
- **Test files** (synthetic teletext with known cue timings at 1.0s,
3.5s, 13.0s):
- `test_teletext_live.ts` - Normal PTS range
- `test_teletext_live_wrap.ts` - PTS near wrap-around boundary
- **Unit tests** for `SegmentCoordinator` and updated `TextChunker`
tests
## Documentation
- Extended `docs/source/tutorials/text.rst` with DVB-Teletext section
covering:
- Page numbering (3-digit cc_index format)
- Heartbeat mechanism explanation
- Segment alignment behavior
- `--ts_ttx_heartbeat_shift` parameter tuning
- Troubleshooting guide
- Added teletext processing pipeline diagram to `docs/source/design.rst`
## Future work
The heartbeat and `SegmentCoordinator` mechanisms would likely benefit
**DVB-SUB (bitmap subtitles)** as well (Issue #1477) , which faces
similar challenges with sparse subtitle data in MPEG-TS input and
segment alignment. The infrastructure is now in place to extend this
support.
## Example usage
```bash
packager \
--segment_duration 6 \
--mpd_output manifest.mpd \
'in=input.ts,stream=video,init_segment=video/init.mp4,segment_template=video/$Number$.m4s' \
'in=input.ts,stream=audio,init_segment=audio/init.mp4,segment_template=audio/$Number$.m4s' \
'in=input.ts,stream=text,cc_index=888,lang=en,init_segment=text/init.mp4,segment_template=text/$Number$.m4s,dash_only=1'
```
Fixes#1428Fixes#1401Fixes#1355Fixes#1430
This change introduces support for signaling CEA-608 and CEA-708 closed
captions in DASH. (Equivalent of
https://github.com/shaka-project/shaka-packager/pull/1532)
It reuses the existing --closed_captions command-line flag. Note that
some options (name, autoselect, and default) are not used for DASH.
```
--closed_captions 'channel=CC1,lang=fra;channel=CC2,lang=eng;channel=SERVICE1,lang=eng'
```
For Dash this adds an Accessibility tag in each video AdaptationSet.
Example output :
```
<AdaptationSet id="1" contentType="video" ....>
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-608:2015" value="CC1=fra"/>
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-608:2015" value="CC2=eng"/>
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-708:2015" value="1=lang:eng"/>
```
HLS changes :
* We force the language to 2 characters to be consistent with the
language of the audio files, for example.
* closed_captions is now in packaging_params
**Description**
This PR introduces support for subsample encryption for Dolby AC-4 audio
streams including muxing and packaging in Shaka Pakager.
**Motivation**
Subsample encryption is a mode of Common Encryption (CENC) that allows
selective encryption of media samples, leaving specific portions (such
as headers) in the clear. In most cases, subsample encryption is applied
to video streams (e.g., H.265/HEVC or AV1). It can also be used for
audio streams, even though many pipelines default to full-sample
encryption for audio. For Dolby AC-4, this is particularly useful
because the AC-4 frame header (ac4_toc) contains configuration data that
must remain accessible to parsers and playback systems even when the
rest of the frame is encrypted.
By implementing subsample encryption for AC-4:
- Parsers can validate and process encrypted streams without full
decryption.
- Playback systems can perform certain bitstream operations (e.g.,
stream identification, sync validation) efficiently.
- This aligns with best practices for encrypted media delivery and
improves performance with streaming platforms.
**Implementation Details**
- The implementation ensures that the ac4_toc() portion of each AC-4
frame remains unencrypted.
- The remaining payload is encrypted using the selected CENC protection
scheme (e.g., cbcs or cenc).
**Specification Reference**
This feature is not mentioned in any published specification. However,
it is discussed in detail in the specification, which has not yet been
publicly released but is expected to be published in the near future.
Once available, it will provide formal guidance on subsample encryption
for AC-4, including the handling of the ac4_toc() structure and
encryption boundaries.
**Notes**
- This implementation is compatible with the upcoming public release of
the AC-4 ISOBMFF specification.
- The feature has been tested on encryption/decryption, DASH, HLS, and
DRM. The generated content is conforms to expected encryption behavior.
- Additional documentation will be provided once the specification is
officially published.
---------
Co-authored-by: Xingzhao Yun <xyun@dolby.com>
Implement the MPEG DASH/HLS specifications to switch event/live streams
to VOD when the streams end. Use --event_to_vod_on_end_of_stream.
This change implements the DASH standard by:
1. Change MPD@type to static
2. Set MPD@mediaPresentationDuration to the media duration
3. Removing dynamic specific attributes in element, e.g.
availabilityStartTime, minimumUpdatePeriod, timeShiftBufferDepth etc.
4. Set SegmentTemplate@presentationTimeOffset in Representations
This change implements the HLS standard by:
1. Switch the PLAYLIST-TYPE to VOD at the conclusion of a LIVE stream
2. Append an EXT-X-ENDLIST tag at the end of the stream
Fixes#321
Before, we would add clear ranges to the start of the subsample,
therefore moving the encrypted start further into the video frame; now
we add clear ranges to the end by adding a new subsample (if needed).
This seems more correct. Both are allowed by the spec, but it would be
better to encrypt the beginning of the frame to give attackers less info
about the start of the frame. Having the clear data at the end of the
frame doesn't give attackers much info since most data depends on the
encrypted state.
This change introduces support for signaling CEA-608 and CEA-708 closed
captions in HLS.
New command-line flags, `--closed_captions`, have been added to allow
users to specify the caption tracks. The format for these flags is a
comma-separated list of semicolon-separated key-value pairs, e.g.,
`--closed_captions
"channel=CC1,name=French,lang=fra,default=no,autoselect=yes;channel=SERVICE1,name=English,lang=eng,default=yes,autoselect=yes"`.
For HLS, this change adds `#EXT-X-MEDIA` tags for each caption track
with a common `GROUP-ID` of "cc". The `EXT-X-STREAM-INF` tag for video
streams has been updated to reference this `GROUP-ID`.
Dash will be supported in another PR.
Fixes#986
Fix incorrect error handling in `LocalFile::Open()` when
`create_directories()` encounters an already-existing directory.
### Problem
The current code treats `create_directories()` returning `false` as a
failure:
```cpp
if (!std::filesystem::create_directories(parent_path, ec)) {
return false; // BUG: ec is not checked
}
```
However, according to the C++ standard,
[std::filesystem::create_directories()](https://en.cppreference.com/w/cpp/filesystem/create_directory.html):
- Returns true if a new directory was created
- Returns false with ec.clear() if the directory already exists (not an
error)
- Returns false with ec set if an actual error occurred
This causes failures in several scenarios:
1. Concurrent packaging: Multiple threads creating the same output
directory
2. External directory creation: Another process creates the directory
between is_directory() check and create_directories()
call
3. Retry after partial failure: Directory was created in a previous
failed attempt
### Example Failure (strace)
```bash
newfstatat("/tmp/out/dir") = -1 ENOENT ← Directory doesn't exist
mkdirat("/tmp/out/dir", 0777) = -1 EEXIST ← Created by another
process/thread
exit(0) ← Packager exits without writing output
```
The directory exists and is ready to use, but the code incorrectly
treats this as a failure.
### Solution
Check the error_code after create_directories() returns false. Only
return failure if ec indicates an actual error.
```cpp
if (!std::filesystem::create_directories(parent_path, ec)) {
if (ec) { // Only fail if there's an actual error
return false;
}
// ec is empty means directory already exists - continue normally
}
```
---------
Co-authored-by: Joey Parrish <joeyparrish@google.com>
Change EXT-X-TARGETDURATION to have the value set to the highest
duration for each variant instead of the highest duration for all the
variants.
Fixes#1510
WebM color range metadata was not being converted to MP4 colr box
format, causing incorrect color range value and video may look washed
out. Add colr box generation for VP8/VP9 codecs in WebMVideoClient.
Fixes#1515
This handles trusted publishing for Shaka Packager to NPM without
tokens.
This also updates upload/download actions, and adds a filter on specific
artifacts downloaded to avoid conflicts that have arisen since the last
release.
Also updates the images used in the build matrix.
Issue shaka-project/shaka-player#9132
Inspired by @r0ro
https://github.com/shaka-project/shaka-packager/pull/840
Add a new --add_program_date_time HLS flag to enable or disable this
feature.
Introduces support for the EXT-X-PROGRAM-DATE-TIME tag in HLS media
playlists, aligning with the HLS RFC specifications.
Closes#365
This upgrades libpng from v1.6.37 to v1.6.50
This newer libpng doesn't assume the existence of fp.h on Mac (which
isn't present on newer ones), but the CMake options for libpng changed
and had to be adjusted somewhat.
This adds missing cstdint headers in every header where we reference a
uint*_t.
This also adds a cmake definition that works around a guard in newer
cmakes that is meant to guard against libraries that only work in older
ones. (`-DCMAKE_POLICY_VERSION_MINIMUM=3.5`)
musl.cc is overwhelmed by GitHub traffic, and therefore has blocked all
of Microsoft. This switches to a mirror run on GitHub so that we can
continue to access the toolchains.
The `SimpleHlsNotifier::NotifyEncryptionUpdate` method was modified :
When this method is called with the Common System ID, it now checks if
the stream's encryption method is CENC. If it is CENC, the notifier
skips adding the EXT-X-KEY tag with KEYFORMAT="identity", as CENC
content should be handled by the specific DRM system's key format (e.g.,
Widevine's urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed).
Closes#1439
---------
Co-authored-by: Joey Parrish <joeyparrish@google.com>
Adding MV-HEVC support limited to stereo video, issue #1483.
Stereo video coded in MV-HEVC is becoming more widely available: Apple
Vision Pro supports stereo video playback in MV-HEVC and both the
headset and iPhone supports capturing stereo video using the format.
FFmpeg has also added support for MV-HEVC.
Note that this PR is only focusing on adding MV-HEVC support to .mp4 for
encryption/decryption support. Proper HLS and DASH support will still
need to be added.
This adds support for Docker-based testing on arm64 images and runners.
This also adds a multiarch build process so that future releases cover
both x64 and arm64.
This is tagged as "feat" so that this gets called out in the changelog
for the next release.
We no longer need a separate repo for CMake.
This fixes build failures on OpenSUSE 15.5. The extra repo for CMake is
no longer available. So it's lucky we no longer need it with the latest
OS.
Since the introduction of `vars` to GitHub Actions, I started using that
instead of the "environments" trick I used in Packager. However, it has
become clear now that the `vars` strategy has major drawbacks, such as
requiring the use of `pull_request_target`, which should only be used
for actions that do not execute PR-author-controlled code.
This updates the comments to clarify why this is used. This reusable
settings workflow will also be deployed now in other repos to
standardize on this "environments" mechanism, which is safer than
`vars`.
Because we used require() to read build-matrix.json, the file could be
replaced with build-matrix.json.js, allowing code injection into our CI
pipelines. This fixes this vulnerability by reading the JSON text with
the fs module, then explicitly parsing it, rather than relying on
require().
This also changes the location of the file, to match its location in
other projects.
Note that this workflow is not currently giving any elevated permissions
to users, so it is not currently possible to damage the repo through a
PR. But this might have been possible in the past, due to
organization-wide defaults for token permissions (recently fixed). No
evidence has been found of past exploit.
See also https://github.com/shaka-project/shaka-streamer/issues/216 and
https://github.com/shaka-project/static-ffmpeg-binaries/issues/57
When uploading a live stream, if a single segment upload fails, we shouldn't give up.
This adds an option to ignore HTTP output failures so that a single failed upload does not result in a hung stream. See https://github.com/shaka-project/shaka-streamer/issues/195 for details.
These errors were specifically coming up in Windows builds and in Linux release builds. This initializes those variables.
This also fixes errors in IAMF tests like "offset 2 out of bounds", which some compilers raise when you try to statically initialize a vector, then add to it later.
Upgrading curl fixes errors like "Failed sending data to the peer" flooding the log. This is described upstream in https://github.com/curl/curl/issues/10591 and fixed in curl 8.2.0. Here we upgrade to curl 8.9.1 (latest as of today).
This required updating the way we attach c-ares to libcurl and updating CURLOPT_PUT (deprecated) to CURLOPT_UPLOAD (compatible equivalent AFAICT).