Skip to content

Guard --ire0_adjust hsync against a degenerate field (ZeroDivisionError aborts the decode) - #340

Merged
harrypm merged 1 commit into
oyvindln:vhs_decodefrom
skyeckstrom:fix/ire0-hsync-divide-by-zero
Jul 20, 2026
Merged

Guard --ire0_adjust hsync against a degenerate field (ZeroDivisionError aborts the decode)#340
harrypm merged 1 commit into
oyvindln:vhs_decodefrom
skyeckstrom:fix/ire0-hsync-divide-by-zero

Conversation

@skyeckstrom

Copy link
Copy Markdown

Checklist

  • I have searched the open pull requests to confirm this change has not already been submitted.
  • My branch is up to date with the target branch.
  • I have tested my changes and all existing tests pass.
  • I have updated documentation where necessary.
  • My code follows the project's coding standards (see CONTRIBUTING.md).

Description

In FieldShared.hz_to_output's hsync submode, a degenerate field makes the backporch and hsync
windows read the same level, so hz_ire = (ire0 - hsync_level) / -vsync_ire becomes 0
(field.py:1074).
hz_to_output_array then divides out_scale by it
(utils.py:1111)
and raises ZeroDivisionError, aborting the decode. This guards the per-field hz_ire: if 0 or
non-finite, warn and fall back to the calibrated DecoderParams["hz_ire"].

Motivation

A single degenerate field currently discards an arbitrarily long decode with no partial output — mine
died at frame 94056 after ~14.6h. It's the exact tape condition the hsync submode exists to help
with (out-of-spec / AGC tapes with dropouts; cf. #314, #318).

Related Issues

Fixes #339

Changes Made

  • vhsdecode/field.py: in hz_to_output's hsync submode, if the computed hz_ire is non-finite
    or 0, log a warning and fall back to self.rf.DecoderParams["hz_ire"] for that field.

Testing

  • All existing tests pass
  • New tests: tests/unit/test_ire0_adjust.py — 3 tests; 2 fail unpatched (ZeroDivisionError at
    hz_to_output), all pass with the guard. Also a full from-frame-0 decode past the failure point.

The fallback reuses the global hz_ire (the value used when the submode is off), so a degenerate
field degrades to "as if hsync adjustment weren't available here" rather than crashing. Happy to take
a different remedy. A no-capture repro script is inlined in #339. Written with AI assistance.

@harrypm harrypm added bug Something isn't working enhancement New feature or request Signal Processing Related to decodes signal processing and filtering code. labels Jul 19, 2026
…generate fields

When --ire0_adjust includes hsync, hz_to_output measures the per-field black level
(backporch window) and sync level (hsync window). On a degenerate field (dropout /
sync collapse) both windows read the same level, so ire0 == hsync_level, hz_ire =
(ire0 - hsync_level)/-vsync_ire = 0, and hz_to_output_array divides out_scale by it
-> uncaught ZeroDivisionError that aborts the entire decode.

Guard the per-field hz_ire: if non-finite or zero, warn and fall back to the globally
calibrated hz_ire for that field, so a bad field yields an imperfect frame instead of
killing the decode.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
github-actions Bot force-pushed the fix/ire0-hsync-divide-by-zero branch from f1c0edf to 9caadd4 Compare July 20, 2026 10:47
@harrypm
harrypm merged commit 0f902ba into oyvindln:vhs_decode Jul 20, 2026
9 checks passed
@skyeckstrom
skyeckstrom deleted the fix/ire0-hsync-divide-by-zero branch July 20, 2026 20:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request Signal Processing Related to decodes signal processing and filtering code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--ire0_adjust hsync: ZeroDivisionError on a degenerate field aborts the whole decode

2 participants