Skip to content

speed: apply speed_max_val to speed_temporal - #1668

Open
lusoris wants to merge 1 commit into
Netflix:masterfrom
VMAFx:fix/speed-temporal-max-val
Open

lusoris wants to merge 1 commit into
Netflix:masterfrom
VMAFx:fix/speed-temporal-max-val

Conversation

@lusoris

@lusoris lusoris commented Oct 2, 2026 •

Copy link
Copy Markdown

speed_temporal declares speed_max_val ("maximum value allowed; larger values will be clipped to this value", default 1000, range 0 to 1000) and stores it in speed_temporal_max_val, but extract() appends the raw score and never reads it. speed_chroma applies the same option with MIN(score, speed_chroma_max_val), so the option works on one extractor and is silently ignored on the other.

What breaks today

speed.c:1643-1645 on master 9e48141b:

err = vmaf_feature_collector_append_with_dict(
    feature_collector, s->feature_name_dict,
    "Speed_temporal_feature_speed_temporal_score", score, index);

speed_temporal_max_val has no other use in the file (grep speed_temporal_max_val speed.c: the struct member and the option offset).

Reproducer, GCC 16.2.1 release build, src01 576x324, frames 1 to 3 (identical under --cpumask -1):

vmaf -r src01_hrc00_576x324.yuv -d src01_hrc01_576x324.yuv -w 576 -h 324 -p 420 -b 8 --no_prediction --feature speed_temporal=speed_max_val=3 -q --json -o /dev/stdout
master this branch
no option 24.802658, 23.856455, 23.384417 same
speed_max_val=3 24.802658, 23.856455, 23.384417 (max over the clip 40.933533) 3.0, 3.0, 3.0 (max 3.0)

Fix

MIN(score, s->speed_temporal_max_val) on the appended value, the expression speed_chroma uses. Scores below the bound are unchanged, which is every score at the default of 1000.

Test

test_speed_temporal (new): 256x256 noise against weaker noise through the extractor (vmaf_feature_extractor_context_*), scored with the default bound (the fixture must exceed 0.5) and with speed_max_val=0.5 (the score must be exactly 0.5). The second assertion fails on master ("speed_max_val must clip the score") and passes with this change.

Validation

x86-64 Linux, GCC 16.2.1, master 9e48141b, branch head 21f913f1; -Denable_float=true -Denable_checkasm=true.

  • Release meson test: 26/26 here, 25/25 on master (the extra test is the new one).
  • -Db_sanitize=address,undefined -Db_lto=false: 23 pass and 3 fail of 26 here, 22 pass and 3 fail of 25 on master; test_predict and test_pic_preallocation (SIGABRT from LeakSanitizer) and checkasm (heap-buffer-overflow in adm_dwt2_16) fail on both and are untouched by this change; test_speed_temporal passes.
  • The three Netflix pairs, .engagement/golden_compare.py master binary against this branch: ALL IDENTICAL (default dispatch and cpumask=-1).
  • No shipped model uses speed_temporal (the vmaf_v1.0.16* models set speed_max_val=45 for speed_chroma only). speed_temporal_feature_extractor_test.py asserts 18.9411808 and 16.721622 with the default bound; they are below it and unchanged. The Python suite itself was not run.

Not covered

speed_temporal declares speed_max_val ("maximum value allowed; larger
values will be clipped to this value", default 1000, range 0 to 1000) and
stores it in speed_temporal_max_val, but extract() appends the raw score
and never reads it. speed_chroma applies the same option with
MIN(score, speed_chroma_max_val), so the option works on one extractor and
is ignored on the other.

On src01_hrc00_576x324 against src01_hrc01_576x324,
--feature speed_temporal=speed_max_val=3 scores 24.802658, 23.856455 and
23.384417 for frames 1 to 3 (the same as without the option) on master;
with this change every frame is 3.0. Scores below the bound, which is every
score at the default of 1000 that the shipped models produce, are not
changed.

Add test_speed_temporal: 256x256 noise against weaker noise, scored with
the default bound (above 0.5) and with speed_max_val=0.5 (exactly 0.5). The
second case fails on master and passes with this change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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