Security - Remove the unsafe Vec::set_len over recycled sector buffers — UB reachable from safe code (GHSA-j8ww-f5fg-9pmh, low). Uses Vec::resize; pooling unchanged. CI / tooling - clippy on stable with the MSRV single-sourced from Cargo.toml; cargo-deny dependency-audit gate with first-party git sources allowed (#15); audience-based comment-guard (#17). Docs - README (keydb ownership, BD-J parser count), drive-access transport/reset notes, mux timeline module-doc links.
5.6 KiB
MP4 audio sample entries (src/mux/mp4/audio.rs)
Module scope
The entry always describes the syntax actually found in the first audio
frame, not the codec the playlist claimed: a track the playlist calls DD+
whose first syncframe is a legacy AC-3 one is declared ac-3/dac3. The fit
oracle (audio_fits) in this module, mirrored by the sink, is what decides
which codecs are muxable at all.
EAC3_MIN_BSID
Lowest bsid that identifies an Annex-E (E-AC-3) bitstream: ETSI TS 102 366
Annex E uses bsid 16, while 8 is AC-3 and 9/10 are the AC-3 alternate bit
stream syntax of Annex D. Both the parser and the sample-entry chooser read
this one constant so they cannot disagree about which syntax was found.
BitReader::read
The accumulate step ((v << 1) | bit) is one instance of a pattern repeated
throughout this file — shift an accumulator left by exactly the width of the
next field, then OR in that field, mask-limited to the same width (the push
closures in dac3_box, dec3_box and ddts_box; the multi-byte bit-field
extractions in parse_eac3 and parse_dts). Because the shift always
vacates precisely the bits the OR then fills, and never more, the two
operands never share a set bit — so | and ^ agree on every input, always.
Mutation testing flags each of these | sites as a surviving |→^ mutant;
that is expected and is not a coverage gap. Don't write tests chasing it and
don't "fix" it by switching to ^ — either spelling is correct and equally
unenforceable by a test, so | stays because it is the conventional way to
write "set these bits" in a bitstream packer.
dec3_box
data_rate states the bitstream's rate in kbit/s and must be non-zero; only
parse_eac3 computes one, so this box is written only for a config that came
from an Annex-E syncframe (see dolby_sample_entry).
DTS_AMODE_CH
DTS core base channel count per AMODE (all 16 defined values). Matches the
per-AMODE channel counts in ETSI TS 102 114 §5.3.1, the same table the
decodability gate in dts.rs (DTS_AMODE_COUNT) also uses, so a spec-legal
DTS-ES / 6.1 / 7.1 core (AMODE 13→7, 14/15→8) is declared with its true
channel count in the mp4 AudioSampleEntry / ddts box rather than a
truncated 6.
DTS_AMODE_LAYOUT
ddts ChannelLayout speaker mask (ETSI TS 102 114 / DTS-in-ISOBMFF) per core
AMODE. Bit assignment: 0=C, 1=L/R, 2=Ls/Rs, 3=LFE, 4=Cs, 5=Lh/Rh, 6=Lsr/Rsr,
7=Ch, 8=Oh, 9=Lc/Rc, 10=Lw/Rw, 11=Lss/Rss, 12=LFE2, 13=Lhs/Rhs, 14=Chr,
15=Lhr/Rhr. Paired bits denote two speakers, single bits one.
This must stay consistent with DTS_AMODE_CH: the ddts box declares both a
channel count and this mask, and a decoder may trust either — so a mask that
describes fewer speakers than the declared count makes the box
self-contradictory and provokes a downmix or an outright error. The previous
_ => 0x0007 catch-all did exactly that for AMODE 6, 7, and 10 through 15.
AMODE 6 (L + R + S) is the reachable one: its S is a single
centre-surround, not the Ls/Rs pair, so it is 3 channels and 0x0012, not 4
and 0x0006. ddts_channel_layout_speaker_count_matches_declared_channels
pins the invariant for all 16 values.
The AMODE annotations on the table name the layout ETSI TS 102 114 §5.3.1
gives for that AMODE and the mask that encodes it. Three of them used to be
rotated by one (AMODE 2 labelled "sum/difference", 3 "left/right total", 4
plain "L/R") and AMODE 9 was labelled "5.1 core with LFE" although 0x0007 is
the 5.0 mask — LFE is bit 3, OR'd in separately by dts_channel_layout. Both
mislabels invited a "correction" to the values, which are right and are
pinned by ddts_channel_layout_speaker_count_matches_declared_channels.
dts_channel_layout
amode must be 0..=15; parse_dts rejects the reserved 16..=63 before this
is reached, so there is no layout to invent for them.
audio_fits
Fit oracle for an audio codec: does mp4:// currently carry it? Covers the
Dolby family (AC-3 / E-AC-3) and DTS (core / DTS-HD HRA / DTS-HD MA — the
core is described, whole access units pass through). TrueHD, LPCM, AAC are
not yet mapped and are skipped with a loud report (never silently dropped).
Test fixtures
ac3_frame_distinct (line ~905 in the test module): AC-3 syncframe with
every BSI field distinct: fscod=1 (44.1 kHz), frmsizecod=37 (bit_rate_code
18), bsid=8, bsmod=5, acmod=6 (2/2), lfeon=1 → 4.1 = 5 channels.
byte4 = fscod(2)=01 | frmsizecod(6)=100101 → 0x65; byte5 = bsid(5)=01000 |
bsmod(3)=101 → 0x45; byte6 = acmod(3)=110 | surmixlev(2)=00 | lfeon=1 |
pad 00 → 0xC4. acmod 6 has surround but no centre, so per §5.4.2 cmixlev is
absent and surmixlev is present: lfeon lands at bit 5 of byte 6.
eac3_frame_distinct: Annex-E syncframe with every field distinct:
frmsiz=0x123 (292 words → 584 bytes), fscod=1 (44.1 kHz), numblkscod=0
(1 block → 256 samples), acmod=5 (3/1), lfeon=1 → 5 channels, bsid=16.
byte2 = strmtyp 00 | substreamid 000 | frmsiz hi 001 → 0x01; byte3 = frmsiz
lo 0x23; byte4 = fscod 01 | numblkscod 00 | acmod 101 | lfeon 1 → 0x4B;
byte5 = bsid 10000 | dialnorm hi 000 → 0x80.
eac3_frame_fscod3: Annex-E syncframe with fscod=3 — the reduced-sample-rate
path, which no other fixture reaches. fscod2=2 → 16 kHz, 6 blocks; acmod=2,
lfeon=0. byte4 = fscod 11 | fscod2 10 | acmod 010 | lfeon 0 = 0xE4. Exactly
6 bytes: also the minimum-length Annex-E header.
dts_frame_high_bits_set: a DTS core whose split fields all have their high
parts set, so a lost high bit is visible: NBLKS bit 6 (byte 4 bit 0) and
FSIZE bits 13-12 (byte 5 bits 1-0). NBLKS=79 → 2560 samples; FSIZE=0x3000 →
core 12289. AMODE=9, SFREQ=13 (48 kHz), LFF=1 out of byte 10 = 0x0A.