Skip to content

#372: uncompressed QuickTime (raw RGB / ARGB) output module format - #778

Open
vangel76 wants to merge 1 commit into
storytold:mainfrom
vangel76:gap-uncompressed-mov
Open

vangel76 wants to merge 1 commit into
storytold:mainfrom
vangel76:gap-uncompressed-mov

Conversation

@vangel76

Copy link
Copy Markdown

Fixes #372.

Part of ranked gap #22 "Encoder efficiency" (docs/gaps.md): issue #372, "Add uncompressed single-file output" (maintainer bflatastic agreed to uncompressed RGBA in QuickTime .mov as an Output Module format). FilmCraft's QuickTime muxer (filmcraft-isobmff, already behind crates/export) is reused. Only the raw video sample entry is new.

Problem

The Render Queue had no single-file uncompressed output. To hand a render to your own encoder (for example ffmpeg), you had to go through a lossy codec, ProRes, or an image sequence plus a separate WAV.

Fix

  • New Output Module format QuickTime (Uncompressed) (OutputFormat::Uncompressed, .mov, control-channel name uncompressed).
  • Video is stored as QuickTime raw samples, following the QuickTime File Format spec (video sample description, uncompressed RGB):
    • RGB (and Alpha-only matte): 8-bit RGB, depth 24. Rows are padded to an even byte count, which only matters at odd widths.
    • RGB + Alpha: ARGB, depth 32, straight or premultiplied as set in the module.
  • Muxing goes through FilmCraft's existing Mp4Writer in QuickTime mode. Audio is PCM (16/24-bit or 32-bit float, mono/stereo), the same as ProRes, and the UI's Sample Format menu now offers it for this format.
  • The engine's disk-space estimate (bytes_per_frame) knows the exact frame size. The format parameter docs list uncompressed.
  • Hostile input: frame sizes of 0 px or above 65535 px return an Unsupported error. Short frame buffers return an Encode error. No panics, no indexing on input-derived values.

Tests

  • crates/export/tests/uncompressed_mov.rs uses a 33×20 comp, so 24-bit rows need padding, and a solid on a half pixel, so its edges have partial alpha:
    • RGB and RGB + Alpha: the samples read back with FilmCraft's demuxer match the frames the lossless PNG sequence of the same job writes, byte for byte.
    • ffmpeg, as an external oracle, decodes every frame to exactly those bytes.
    • ffprobe reports rawvideo|raw |33|20|rgb24 / argb.
    • Audio: a tone through 24-bit PCM. ffprobe reports pcm_s24le|48000|2, the sample count matches the 0.6 s span, and the RMS of ffmpeg's decode matches the sine.
  • Unit tests:
    • uncompressed.rs: row padding, ARGB ordering, the 78-byte description with depth 32, hostile sizes.
    • render_queue.rs (project): name parsing via the Debug name the UI sends, .mov still guesses ProRes, switching from ProRes keeps the path and alpha, serde round-trip.
  • rq_tests::without_exporter now expects 13 formats.

Gates

  • cargo fmt --check: ok
  • cargo clippy -j 4 -p effectcraft-project -p effectcraft-export -p effectcraft-engine -p effectcraft-ui-egui --all-targets -- -D warnings: ok
  • cargo test -j 4 -p effectcraft-project -p effectcraft-export: all pass
  • cargo test -j 4 -p effectcraft-engine --no-fail-fast: all pass
  • cargo test -j 4 -p effectcraft-ui-egui --no-fail-fast: every test passes. The ui_gpu binary hits SIGSEGV at process exit after both of its tests pass. This also happens on upstream/main and is unrelated.
  • cargo xtask layers: ok
  • cargo check -p effectcraft-project -p effectcraft-export -p effectcraft-engine --target wasm32-unknown-unknown: ok
  • I did not run the full cargo xtask ci locally because the machine is shared.

What remains

  • 16-bpc uncompressed output (b64a) for 16/32-bpc projects. The export pipeline currently hands movie encoders 8-bit RGBA.
  • AVI (RIFF) as a second uncompressed container, and lossless-compressed single-file codecs (Animation / PNG-in-MOV).
  • Re-importing raw MOVs into EffectCraft: FilmCraft's media layer has no raw video decoder yet.
  • I couldn't check playback in Apple QuickTime on this Linux machine. The layout follows the spec, and ffmpeg reads it exactly.

🤖 Generated with Claude Code

…format

Problem: the Render Queue had no single-file uncompressed output, so
handing a render to an external encoder meant a lossy codec, ProRes,
or an image sequence plus a separate WAV.

Fix: add the "QuickTime (Uncompressed)" Output Module format. Frames
are stored as QuickTime 'raw ' samples: 8-bit RGB (depth 24, rows
padded to even bytes) or ARGB with RGB + Alpha (depth 32), written
through FilmCraft's existing QuickTime muxer with PCM audio
(16/24-bit or float) like ProRes. Format name `uncompressed` on the
control channel; disk-space estimate and Sample Format menu included.

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

This branch has not been deployed

No deployments
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.

Add uncompressed single-file output

1 participant