Skip to content

Fix IVTC failure on >8-bit sources (e.g. 10-bit ProRes 422)#46

Merged
StuartCameronCode merged 2 commits into
mainfrom
fix-ivtc-high-bit-depth
Jul 1, 2026
Merged

Fix IVTC failure on >8-bit sources (e.g. 10-bit ProRes 422)#46
StuartCameronCode merged 2 commits into
mainfrom
fix-ivtc-high-bit-depth

Conversation

@StuartCameronCode

@StuartCameronCode StuartCameronCode commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Problem

A user reported that the preview (and, in fact, the full encode too) fails on a 10-bit ProRes 422 source:

Python exception: VFM: input clip must be constant format YUV420P8, YUV422P8, YUV440P8, YUV444P8, or GRAY8
  ...
clip = core.vivtc.VFM(clip, order=0, ...)

The source decodes to yuv422p10le (10-bit). This isn't a global 8-bit limitation — it's specific to the IVTC (Inverse Telecine) pass: vivtc.VFM only accepts 8-bit YUV/GRAY. descratch already had an 8-bit guard, but the IVTC pass had none — in both preview_template.vpy and pipeline_template.vpy, so the actual export would have failed identically, not just the preview.

Fix

The IVTC block now runs VFM's field-matching on an 8-bit metrics copy (only converted when the source isn't already 8-bit) while emitting the full-depth pixels via VFM's clip2 parameter — so 10-bit precision is preserved rather than truncated to 8-bit.

Confirmed against the bundled libvivtc that VDecimate already accepts 8–16 bit natively (only VFM is 8-bit-limited), so VDecimate runs directly on the full-depth VFM output and the soft-telecine path needed no change.

Test fixture

Adds Tests/TestResources/prores422_10bit_telecine.mov — a small (2.9 MB, 30-frame) Apple ProRes 422 Standard telecine clip (yuv422p10le) matching the reported source, plus generate_prores422_10bit_test.sh to reproduce it. It can be dropped into the app to exercise the high-bit-depth IVTC path via the UI.

Tests

  • Script-gen (push gate):
    • worker/tests/filter_integration_test.rstest_57_ivtc_high_bit_depth_guard
    • app/test/integration_filter_parameters_test.dartivtc: VFM/VDecimate 8-bit guard + clip2 (adds a deinterlace param to the test's buildJob helper)
    • Both assert the guard + clip2 wiring appear in the generated script.
  • End-to-end regression guard (nightly / heavy):
    • app/test/integration_high_bit_depth_test.dart → probes the ProRes fixture, confirms it is >8-bit, then runs the worker end-to-end with IVTC and asserts a valid encode. Verified it fails on the pre-fix template (encode aborts at the VFM 8-bit error) and passes with the fix — the real regression guard the script-only tests cannot provide.

Manual verification

Decoded the 10-bit yuv422p10le source through the real ffmpeg | vspipe | ffmpeg pipe: previously errored, now processes cleanly (90→72 frames) with the output remaining yuv422p10le.

🤖 Generated with Claude Code

StuartCameronCode and others added 2 commits July 1, 2026 17:20
vivtc.VFM only accepts 8-bit YUV/GRAY, so IVTC on a 10-bit source such as
ProRes 422 (yuv422p10le) failed with "VFM: input clip must be constant
format YUV420P8, ...". descratch already guarded for this but the IVTC pass
did not — in both the preview and the full-encode templates, so the export
would fail the same way, not just the preview.

Run VFM's field-matching on an 8-bit metrics copy (only converted when the
source isn't already 8-bit) but emit the full-depth pixels via VFM's clip2
parameter, so 10-bit precision is preserved rather than truncated. VDecimate
accepts 8..16 bit natively (confirmed against the bundled libvivtc), so it
runs directly on the full-depth output and the soft-telecine path is
unchanged.

Verified end-to-end by decoding a 10-bit yuv422p10le ProRes 422 source
through the real ffmpeg | vspipe pipe: previously errored, now processes
cleanly (90->72 frames) with the output remaining yuv422p10le.

Tests (both CI suites):
- worker: test_57_ivtc_high_bit_depth_guard
- app: "ivtc: VFM/VDecimate 8-bit guard + clip2" (adds a deinterlace param
  to buildJob)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a small (2.9 MB, 30-frame) Apple ProRes 422 Standard telecine clip
(yuv422p10le) under Tests/TestResources, matching the source from the bug
report, plus generate_prores422_10bit_test.sh to reproduce it. The clip can
also be dropped into the app to exercise the high-bit-depth IVTC path via the
UI.

Adds integration_high_bit_depth_test.dart (@tags(['heavy'])): probes the
fixture, confirms it is >8-bit, then runs the worker end-to-end with IVTC and
asserts a valid encode. Verified this test fails on the pre-fix template (the
encode aborts at the VFM 8-bit error) and passes with the clip2 guard — a real
regression guard the script-only tests could not provide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@StuartCameronCode StuartCameronCode merged commit 5da0d3a into main Jul 1, 2026
7 of 8 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