Skip to content

esds: fix descriptor size varint and AudioSpecificConfig bit parsing#201

Draft
kixelated wants to merge 1 commit into
mainfrom
fix/esds-192
Draft

esds: fix descriptor size varint and AudioSpecificConfig bit parsing#201
kixelated wants to merge 1 commit into
mainfrom
fix/esds-192

Conversation

@kixelated

Copy link
Copy Markdown
Owner

Fixes the concrete defects catalogued in #192 (all in src/moov/trak/mdia/minf/stbl/stsd/mp4a/esds.rs).

Changes

1. Descriptor size varint (encode). The base-128 length was emitted least-significant group first, so a 200-byte body wrote C8 01 (decoded as 9217) and a zero-length body wrote no length byte at all. It now emits most-significant group first with the continuation bit on all but the last byte — matching the decoder — and always writes at least one byte.

2. Size varint (decode). A size field whose 4th byte still has the continuation bit set now returns Error::InvalidSize instead of silently truncating and desyncing the parse.

3. AudioSpecificConfig. Replaced the ad-hoc byte masking with an MSB-first bit reader/writer, fixing:

  • extended audioObjectType (≥ 32, e.g. xHE-AAC = 42) — the 6-bit extension was OR'd on top of itself (missing << 3);
  • extended-profile channelConfiguration extraction;
  • the samplingFrequencyIndex == 15 escape — the explicit 24-bit sample rate was misread, discarded, and unencodable. It's now stored in a new sample_rate field and round-trips.
  • encoding an unrepresentable object type now errors instead of truncating.

4. ES_Descriptor flags byte. streamDependenceFlag / URL_Flag / OCRstreamFlag were read and discarded, so when set the following dependsOn_ES_ID / URL / OCR_ES_ID bytes were misparsed as child descriptors. They're now parsed and preserved via new depends_on_es_id / url / ocr_es_id / stream_priority fields.

Tests

Added a tests module covering: varint round-trips (incl. empty payload), the 81 48 (200-byte) and 4-byte-desync regressions, basic/extended/explicit-rate AudioSpecificConfig round-trips, and the ES flags round-trip. Full suite (244 tests + doc-tests), clippy -D warnings, and fmt --check all pass.

⚠️ Breaking change

DecoderSpecific and EsDescriptor gain public fields, and EsDescriptor is no longer Copy. Existing struct literals need ..Default::default() (all in-tree call sites are updated).

🤖 Generated with Claude Code

Fixes the concrete defects listed in #192:

- Descriptor size is now encoded as an ISO 14496-1 base-128 varint with the
  most-significant 7-bit group first (matching the decoder). Previously the
  groups were emitted in reverse order, so e.g. a 200-byte body wrote `C8 01`
  (decoded as 9217) and a zero-length body wrote no length byte at all.
- Size varint decode now errors (InvalidSize) when the continuation bit is
  still set after 4 bytes instead of silently truncating and desyncing.
- AudioSpecificConfig is now parsed/written with a proper MSB-first bit
  reader/writer, fixing the extended audioObjectType (>= 32) assembly, the
  extended-profile channelConfiguration extraction, and the freq_index == 15
  explicit-sample-rate escape (now stored in a new `sample_rate` field so it
  round-trips). Encoding an unrepresentable object type now errors.
- The ES_Descriptor flags byte is parsed: streamDependenceFlag / URL_Flag /
  OCRstreamFlag now consume and preserve their trailing fields (new
  `depends_on_es_id` / `url` / `ocr_es_id` / `stream_priority` fields) instead
  of being discarded and desyncing the child-descriptor parse.

Adds unit tests covering the varint round-trips, the 200-byte and desync
regressions, extended/explicit-rate AudioSpecificConfig, and the ES flags.

Note: this is a breaking change — `DecoderSpecific` and `EsDescriptor` gain
public fields and `EsDescriptor` is no longer `Copy`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@kixelated, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8024a6e5-bbd0-49cb-9faa-9bc30679bd6a

📥 Commits

Reviewing files that changed from the base of the PR and between ac798db and 3db4afe.

📒 Files selected for processing (5)
  • src/moov/trak/mdia/minf/stbl/stsd/mp4a/esds.rs
  • src/moov/trak/mdia/minf/stbl/stsd/mp4a/mod.rs
  • src/test/bbb.rs
  • src/test/esds.rs
  • src/test/h264.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/esds-192

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kixelated
kixelated marked this pull request as draft July 17, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant