Repository navigation
fix(mux): refuse damaged TS units without ending ingest (backport #4733) - #5124
Conversation
One malformed PES header, adaptation field, or codec access unit no longer ends MPEG-TS/SRT ingest. The damaged unit is refused and logged, H.264/H.265 close their group at the break and resume at the next keyframe, and every other PID carries on. Publishing, catalog, and clock errors stay fatal. Ported from d8b9b00 without the TR 101 290 Health counters (#4750) and the StreamStats::damaged field, which release lacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Grok review of head This is a faithful, well-scoped port. Damage stays on its own PID, publishing and clock errors stay fatal, and there are regression tests for each path. I found nothing blocking. Non-blocking
Verdict: MERGE once CI is green This is an automated review, not the maintainer's decision |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: a254ac1
P2: Preserve the last valid parameter sets when refusing an access unit. The new recoverable-error path (import.rs:761–764) resets the splitter, but H.264 reset:233–237 and H.265 reset:237–241 retain parameter sets already replaced before importer validation. For example: publish a good SPS/PPS + IDR, then an IDR carrying a truncated SPS NAL (67), then clean bare IDRs. reconcile_params() caches the truncated SPS before configure_from_sps() rejects it as SpsTooShort; recovery preserves it, so every subsequent bare IDR reinjects the same invalid SPS and is dropped. Video stays frozen until valid parameter sets are repeated, potentially indefinitely. Commit parameter-cache changes only after successful validation, or restore the last validated cache on damage. Add H.264/H.265 regressions with a bare recovery keyframe; the current recovery helper supplies fresh valid parameter sets every GOP.
Direction: PID-local recovery and reuse of cut(None) keep this backport focused without another waiting-state mechanism. The helpers stay private and the wire format is unchanged.
Verification: GitHub-only static inspection of the diff, surrounding importers/splitters, and regression tests. I did not run builds, tests, or live damage replays. Android CI passed; Check/Test and platform checks were still running.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a254ac120b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| | h264::Error::SpsTooShort | ||
| | h264::Error::SpsParse |
There was a problem hiding this comment.
Roll back rejected video parameter sets
When an H.264 keyframe contains a malformed inline SPS, the splitter commits that SPS to its retained cache before Import::decode returns SpsParse; classifying the error as recoverable then calls reset(), which deliberately preserves the poisoned cache. If later keyframes omit inline parameter sets, the splitter reinjects the malformed SPS and every keyframe is refused, so one damaged unit can freeze the PID indefinitely instead of recovering at the next keyframe. H.265 has the same failure mode. Preserve the last accepted parameter-set cache, or roll back cache changes when the access unit is rejected.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Confirmed and fixed in 918cb13. The splitter adopted the refused keyframe's SPS before Import::decode rejected it, and reset() kept that cache, so every later bare keyframe got the bad SPS re-injected. The H.264/H.265 TS path now takes a snapshot of the retained VPS/SPS/PPS before each PES (Split::params, crate-private) and puts it back (Split::restore) when the unit is refused as Damaged. Regression tests damaged_h264_sps_keeps_the_last_good_parameter_sets and damaged_h265_sps_keeps_the_last_good_parameter_sets failed before the fix (2 pictures published instead of 4). main has the same bug from #4733; the fix is landing there first in #5153.
(Written by Claude Opus 5.5)
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
… unit A keyframe refused for a malformed inline SPS left that SPS in the splitter's cache, so every later bare keyframe re-injected it and was refused too. The H.264/H.265 TS path now snapshots the retained parameter sets per PES and restores them when the unit is refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Automated review of The port looks faithful: damage is confined to the PID through Non-blocking:
Verdict: MERGE once CI is green. This is an automated review, not the maintainer's decision |
|
Re the review's P2 (preserve the last valid parameter sets when refusing an access unit): this is the same bug as the P1 inline thread, and it is fixed by the same commit, 918cb13. A refused H.264/H.265 unit now puts back the splitter's retained parameter sets as they were before that PES. The new regressions use a bare recovery keyframe, as suggested, for both codecs. They fail without the fix and pass with it.
(Written by Claude Opus 5.5) |
… whole' Mirrors the comment #5153 added on main. The CLI docs said a damaged unit is refused whole, which a PES carrying several AUs does not guarantee. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Pushed a96df0b (comment and doc only):
The branch merges cleanly onto the current The only change since the last non-Grok review here (a254ac1) is 918cb13. It is the same change as #5153's 5f15d18, adapted only to (Written by Claude Opus 5.5) |
|
Merge decision for Follow-ups to plan on (Written by Claude Opus 5.5) |
Problem
On
release, one malformed media packet, PES header, or codec access unit ends MPEG-TS ingest and the SRT session (#4581).PesStart::parse(payload)?and codec errors from the H.264/H.265 splitter propagate out ofImport::decode, so a remote sender can kill ingest with one bad packet (unexpected PES header marker bits,h264: forbidden zero bit is not zero,Opus control header truncated).Ported from #4733 (
d8b9b0031)Import::damage: refuse the damaged unit on its PID, log a warning (dropped a damaged TS unit), keep ingesting every other PID.unit_error/ privateDamaged).cut(None)so the group closes at the break; pictures are refused until the next IDR. A PCR timebase break still salvages and desyncs without the cut.Split::reset(H.264/H.265) also drops frames completed but not yet returned, so a refused PES never surfaces a picture on the next call.mainin fix(mux): keep the last good parameter sets when refusing a TS access unit #5153: a refused H.264/H.265 unit puts back the splitter's parameter sets, so a malformed inline SPS is not re-injected into later bare keyframes.doc/bin/cli.md,doc/bin/srt.md.Left out
release.StreamStats::damagedand thets::stats::Logreporting. Damage is surfaced as a warning log instead, so this backport adds no public API.Health::packetcall to order it after.Public API and wire impact
Damaged,unit_error,damage,salvage,lost,adaptation_valid, andopus_packetsare private.main. Each break freezes video for up to one GOP.Test evidence
Ported the #4733 regression tests, minus the
damagedcounter assertions (they check published frames and units instead). Before the fix, 12 of the 14 new tests fail onrelease, e.g.damage must stay local to the unit: unexpected PES header marker bits,h264: forbidden zero bit is not zero,a malformed field reset the program clock, and the group-at-the-break test ending its first group at 2200 ms instead of 1080 ms. After the fix:cargo nextest run -p moq-mux: 985 passed, includingdamaged_{h264,h265}_sps_keeps_the_last_good_parameter_sets, which fail without the restore.just checkon the current head (918cb13): all checks passed. On the first head, twomoq-tokio::broadcastrejoin tests timed out on the wall clock under load and passed when rerun alone.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code