12 Commits
Author SHA1 Message Date
vangel76andClaude Sonnet 5.5 3516207de7 #1402: import MP1 (A_MPEG/L1) audio from Matroska
Problem: the Matroska demuxer mapped A_MPEG/L2 and A_MPEG/L3 only, so a
Layer I track was reported as an unsupported codec even though the MP1/MP2
decoder (#809) reads Layer I.

Fix: add Codec::Mp1 for A_MPEG/L1 and route it through the same packet
duration and decoder path as Mp2. Test remuxes synthetic Layer I frames
into Matroska with ffmpeg and compares our decode (max error 3e-5).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-12 20:55:35 +02:00
liangforstudyandClaude Opus 5.5 4f8dcdf587 #402: WebM transparency (VP9 alpha in BlockAdditions)
A WebM VP9 track with AlphaMode 1 stores its alpha as a second, independently coded VP9
stream in each block's BlockAdditional (BlockAddID 1). The Matroska reader detected
AlphaMode (has_alpha was true) but never read the additions, so transparent areas
rendered black.

- matroska: BlockGroups' BlockAdditions are parsed; the BlockAdditional with ID 1 of an
  unlaced block is kept as Sample::addition, read with MkvFile::read_sample_addition.
- codecs: a WebM VP9 track with AlphaMode and additions gets an AlphaDecoder
  (webm_alpha.rs): it decodes each sample's alpha frame with a second software VP9
  decoder and attaches its luma plane (full range, converted to the picture's depth)
  as the frame's alpha. After a seek the alpha decoder resynchronises from the nearest
  alpha key frame. Colour pictures are held until their alpha picture is out, since the
  two decoders may return pictures after different calls. A missing or undecodable alpha
  frame leaves that picture opaque; it never fails the colour decode.

Tests: vp9_webm_alpha_layer_matches_libvpx (frames out of order and forward, colour and
alpha exact against ffmpeg's libvpx decode; fails before: no alpha plane; passed 200 of
200 runs with four in parallel), set_alpha unit tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Qq8BK1LmohzE1ga4NgAdWM
2026-10-10 17:40:58 +08:00
WavJaby 92c6aa2b63 chore(lints): preserve behavior in workspace clippy cleanup
- Move conditional no-op match arms into guards

- Preserve renderer predicate order with De Morgan's law

- Strict clippy, fmt, layers, assets and WASM pass on Rust 1.95

- Clean engine runs match main: 379 pass, 10 fail, 3 ignored

- Full CI is not green; upstream baseline failures remain
2026-10-08 18:22:27 +08:00
mweinbach 15787f7fe8 Codecs: add clean-room APV (RFC 9924) decoder, encoder, container support, and export presets 2026-10-06 17:24:34 -04:00
Brandon ThomasandClaude Opus 5.5 fa40a3c030 Containers: never crash — mpegts, ogg, mxf, matroska without expect/unreachable
- mpegts: a PES unit is built before it is stored (no `as_mut().expect`); stream maps are
  drained with `let … else` instead of `remove().expect`.
- ogg: completing a packet and reading the page granule no longer expect.
- mxf writer: the picture descriptor uses `let … else` on the picture configuration.
- matroska: the `Lacing::None` arm returns the single frame instead of `unreachable!`.
- Each crate denies unwrap/expect/panic/unimplemented/todo/unreachable outside tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-04 11:37:58 -04:00
Brandon ThomasandClaude Opus 5.5 e2afbed6c2 Tests for display rotation: Matroska roll → quarter turns (incl. flips, odd and malformed angles), MP4 mirrored/scaled matrices
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-04 02:50:16 -04:00
storybored379andClaude Opus 5.5 27a1f78df7 Media: apply the container's display rotation (portrait phone video)
Phones record portrait video as landscape pictures plus a rotation in the
container: the MP4/MOV tkhd matrix (ISO/IEC 14496-12 §8.3.2) or the
Matroska Projection pose roll (RFC 9559 §5.1.4.1.28.46). The matrix was
parsed but never used, so every portrait iPhone clip imported sideways
at its landscape size.

- isobmff: Track::display_rotation() reads 0/90/180/270° from the matrix
  signs (mirrored / sheared matrices are left alone).
- matroska: parse Projection (type, yaw, pitch, roll);
  VideoInfo::display_rotation() for rectangular projections.
- frame: VideoFrame::rotated() turns every plane at its own resolution
  (4:2:2 chroma is widened to 4:4:4 for quarter turns) and swaps the PAR.
- codecs: Mp4Source / MkvSource report the displayed size and PAR, and
  GopCache rotates decoded frames before caching them.
- web: the WebCodecs source configures the decoder with the coded size
  and rotates its output the same way.

Tests: a one-frame ProRes MOV built in the test with 0/90/180/270°
matrices (reported size + which half ends up on top), plane rotation for
RGBA / 4:2:0 / 4:2:2, and a synthetic Matroska file with a -90° roll.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-04 02:50:16 -04:00
Brandon ThomasandClaude Opus 5.5 3704002f89 T2: cargo xtask fixtures pre-generates the oracle fixture matrix
Runs each crate's ignored generate_fixtures test (h264, hevc, isobmff,
matroska, prores) - the same generators the oracle tests use - and
prints made/cached/skipped per fixture plus a summary. Optional crate
filter: cargo xtask fixtures hevc prores.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 00:20:59 -04:00
Brandon ThomasandClaude Opus 5.5 8780d5ffa2 T1: shared ffmpeg/ffprobe discovery in filmcraft-testkit
New dev-dependency-only crate crates/testkit (L0, no FilmCraft deps):
FILMCRAFT_FFMPEG/FILMCRAFT_FFPROBE, then PATH (incl. .exe), then known
dirs; SKIPPED lines and FILMCRAFT_REQUIRE_ORACLES=1 to make skips fail;
require_ffmpeg!/require_ffprobe!/require_oracles!; fixtures_dir() under
<workspace>/target/fixtures with per-thread temp names and atomic
generation. Oracle helpers in aac, opus, h264, hevc, h264enc, isobmff,
matroska, prores and export migrated (codecs left on its local lookup).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 00:10:59 -04:00
Brandon ThomasandClaude Opus 5.5 4c6e1db167 Add LICENSE-MIT and LICENSE-APACHE (the declared MIT OR Apache-2.0 licence had no licence files); README licence section; xtask layer error points at docs/architecture.md; matroska description includes muxer
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 23:25:35 -04:00
Brandon ThomasandClaude Opus 5.5 3ccd91820e M9.9: Matroska/WebM demuxer
Clean-room filmcraft-matroska (L0, std only, wasm-clean) from RFC 8794/9559:
EBML reader (VINT ids/sizes, unknown sizes, CRC-32, Void, resync on damage),
Segment metadata (Info, Tracks incl. Colour/HDR mastering, ContentEncoding
header stripping, SeekHead, Cues, Chapters, Tags, Attachments), cluster scan
into isobmff-style sample tables, streaming Demuxer (Read+Seek / slice),
Xiph/EBML/fixed lacing, keyframe seek via index/Cues/on-demand scan, CodecID
mapping. Minimal MkvWriter (SimpleBlocks, lacing, Cues, SeekHead).
ffprobe-oracle tests over 12 ffmpeg fixtures plus laced remuxes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 11:07:40 -04:00
Brandon ThomasandClaude Opus 5.5 77a096884b M9.9: Matroska/WebM demuxer (WIP: EBML reader, metadata, cluster scan, packets, seek)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 10:57:02 -04:00