filmcraft/crates/ogg
Brandon Thomas efa8167962 M9.14: MXF (OP1a/OP-Atom) and Ogg demuxers, image sequences, BWF timecode
- crates/mxf (L0): KLV walk, partitions, primer, header metadata, index tables, material ->
  file package resolution, AVC/VC-3/ProRes/MPEG-2 identification, PCM/AES3 (ST 331) sound,
  timecode; OP1a and OP-Atom (clip wrapping).
- crates/ogg (L0): RFC 3533 pages/CRC/packets, RFC 7845 Opus timing (granules, pre-skip, end trim).
- codecs: MxfSource (GOP cache, POC ordering for AVC without temporal offsets, MPEG-2 reported
  unsupported), OggSource (Opus with pre-roll seeking, Vorbis), Annex B H.264 decoder.
- media: image sequences (numbered stills, missing frames held, frame cache); BWF bext/iXML
  TimeReference -> start timecode.
- engine/UI: file.import {imageSequence}, auto-detect setting, file.importImageSequence,
  Media Browser "Import as Image Sequence"; CLI probe details for MXF/Ogg/BWF/sequences.
- Oracle tests vs ffmpeg for MXF, Ogg, image sequences, BWF; truncation/mutation tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 17:33:29 -04:00
..
src M9.14: MXF (OP1a/OP-Atom) and Ogg demuxers, image sequences, BWF timecode 2026-10-02 17:33:29 -04:00
Cargo.toml M9.14: MXF (OP1a/OP-Atom) and Ogg demuxers, image sequences, BWF timecode 2026-10-02 17:33:29 -04:00
README.md M9.14: MXF (OP1a/OP-Atom) and Ogg demuxers, image sequences, BWF timecode 2026-10-02 17:33:29 -04:00

README.md

filmcraft-ogg

A clean-room Ogg demuxer. Layer L0: no dependencies beyond std, no unsafe, builds for wasm32-unknown-unknown. No libogg / libopusfile / FFmpeg code was consulted; FFmpeg is used only as an external fixture generator and test oracle.

Specifications

Document Used for
RFC 3533 (2003) pages, lacing, packet continuation, CRC-32, logical bitstreams
RFC 7845 (2016) Ogg Opus: OpusHead / OpusTags, granule positions, pre-skip, end trimming (§4)
RFC 6716 (2012) §3.1 Opus TOC byte: packet durations
Vorbis I specification (2020-07-04), §4.2.2 and Appendix A Vorbis identification header, Ogg mapping

Use

let bytes = std::fs::read("voice.opus")?;
let ogg = filmcraft_ogg::open(&bytes)?;
let s = ogg.stream_of(filmcraft_ogg::Codec::Opus).unwrap();
let head = &ogg.streams[s].headers[0];                      // OpusHead
let pre_skip = u16::from_le_bytes([head[10], head[11]]) as u32;
let timing = filmcraft_ogg::OpusTiming::of(&ogg.streams[s], pre_skip);
let k = timing.starts.partition_point(|&x| x <= 48_000) - 1; // packet holding sample 48 000
let packet = ogg.read_packet(&bytes, s, k)?;
  • Every page is read and its CRC checked; damaged pages are dropped and the reader resynchronises on the next OggS. Packets spanning pages are lists of byte ranges; a continued page whose start was lost drops the fragment.
  • OpusTiming: packet durations from the TOC; positions anchored on the first page's granule (backwards from it), then accumulated forwards, re-anchoring on any granule discontinuity; the final (end-of-stream) page's smaller granule trims the end. Positions are relative to the first sample after the pre-skip (pre-skip samples are negative).

Tests

src/tests.rs writes synthetic pages: timing with pre-skip and end trimming, packets across pages, a corrupted page (CRC), every truncation and 300 mutations. crates/codecs/tests/ogg_oracle.rs compares with FFmpeg's libopus / Vorbis decodes (exact length; SNR ≥ 50 dB CELT, ≥ 10 dB SILK, Vorbis 139 dB) and checks random seeks against the continuous decode.