Skip to content

Fix garbage preview/encode on clean-aperture sources#24

Merged
StuartCameronCode merged 1 commit into
mainfrom
fix-preview-clean-aperture
Jun 9, 2026
Merged

Fix garbage preview/encode on clean-aperture sources#24
StuartCameronCode merged 1 commit into
mainfrom
fix-preview-clean-aperture

Conversation

@StuartCameronCode

Copy link
Copy Markdown
Owner

Problem

A 10-bit 4:2:2 ProRes file showed as garbage in the processed preview even with all filters disabled.

Root cause: ffprobe reports the coded size (720×576), but ffmpeg's decoder outputs the clean aperture (702×576). The worker sized raw frames from the reported 720×576 (1,658,880 bytes/frame) while the decoded stream had 1,617,408-byte frames, so pipe_source read past each frame boundary and progressively desynced → garbage. This affected the full encode too, not just preview.

Fix

Force the decoder to output the declared width×height (-s) in both decode paths (preview + main encode), so the raw stream always matches what pipe_source expects. No-op for normal sources where decoded size == coded size.

Test (TDD)

  • Adds Tests/TestResources/pal-sd-25.mov (10-bit 4:2:2 ProRes, clean aperture).
  • Adds worker/tests/preview_integration_test.rs: runs the worker in --preview mode (filters off) and asserts the processed frame matches a direct decode of the same source frame.
    • Before fix: mean abs diff 102.9 (garbage) — failed.
    • After fix: 5.9 — passes.

Worker builds clean; all 49 unit tests + the new preview test pass.

Note

The fix resamples 702→720 for such sources (aligning to the coded raster the app reports everywhere) — the universally-safe fix. Using the decoded 702 natively would require the app's detection to read the clean aperture (larger change).

🤖 Generated with Claude Code

Some sources decode to a different frame size than ffprobe reports — e.g.
a 10-bit 4:2:2 ProRes file with a clean aperture: ffprobe says 720x576
(coded) but ffmpeg decodes 702x576. The worker sized raw frames from the
reported dimensions, so pipe_source read 1,658,880-byte frames out of a
1,617,408-byte stream and progressively desynced, producing garbage in the
preview (and the full encode) even with all filters disabled.

Force the decoder to output the declared width x height (-s) in both the
preview and main decode paths, so the raw stream always matches what
pipe_source expects. For normal sources where decoded == coded size this
is a no-op.

Adds Tests/TestResources/pal-sd-25.mov (10-bit 4:2:2 ProRes, clean
aperture) and a preview integration test that runs the worker in preview
mode and asserts the processed frame matches a direct decode of the same
source frame (mean abs diff: 102.9 before the fix, 5.9 after).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@StuartCameronCode StuartCameronCode merged commit 35876af into main Jun 9, 2026
4 checks passed
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