Skip to content

feat(motion): port Netflix b949cebf — feature/motion: port several feature extractor options#197

Merged
lusoris merged 2 commits intomasterfrom
upstream/port-b949cebf-motion
Apr 29, 2026
Merged

feat(motion): port Netflix b949cebf — feature/motion: port several feature extractor options#197
lusoris merged 2 commits intomasterfrom
upstream/port-b949cebf-motion

Conversation

@lusoris
Copy link
Copy Markdown
Owner

@lusoris lusoris commented Apr 29, 2026

Summary

Verbatim port of Netflix/vmaf commit b949ceb (Kyle Swanson, 2026-04-27) — "feature/motion: port several feature extractor options" — per Research-0024 §Decision-matrix Strategy A. Also ports the picture_copy() channel-parameter change from upstream d3647c7, a prerequisite for UV-plane support in float_motion. Default behavior is bit-identical to pre-port baseline (verified on 48 frames; see Reproducer below).

Type

  • feat — new feature
  • port — cherry-pick from upstream Netflix/vmaf

Checklist

  • Commits follow Conventional Commits (the commit-msg hook enforces this).
  • make format && make lint is green locally.
  • Unit tests pass: meson test -C build.
  • If I touched any SIMD/GPU code path, I ran /cross-backend-diff and the worst ULP is ≤ 2.
  • If I touched a feature extractor with SIMD/GPU twins, I either updated every twin or listed the gap under "Known follow-ups" below.
  • If I added a new .c / .cpp / .cu / .h / .hpp, it has the appropriate license header (see CONTRIBUTING.md).
  • If this is a breaking change, the commit message uses ! or BREAKING CHANGE: and the migration path is documented below.

Bug-status hygiene (ADR-0165)

no state delta: upstream port adds new options, no bug opened/closed.

Netflix golden-data gate (ADR-0024)

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.
  • Bit-identical verification: integer_motion2 and float_motion2 scores for ref_576x324_48f.yuv / dis_576x324_48f.yuv (48 frames) match the pre-port baseline to 6 decimal places on every frame.

Cross-backend numerical results

motion2  cpu-vs-cuda: N/A (CUDA kernel unchanged; motion CUDA backend not in scope)
motion2  cpu-vs-sycl: N/A (SYCL motion kernel unchanged; integer_motion already ported)

SIMD path (AVX2/AVX-512/NEON float_sad_line) is preserved via compute_motion_simd
wrapper for the default Y-plane path — bit-identical to scalar compute_motion().

Performance (if perf or feat)

Default path: unchanged — SIMD dispatch (compute_motion_simd) is still the hot
path for Y-plane at default options. Non-default options (scale1, UV) fall through
to scalar compute_motion().

Deep-dive deliverables (ADR-0108)

  • no research digest needed: pure upstream cherry-pick of Netflix b949ceb.
  • no alternatives: only-one-way upstream port.
  • AGENTS.md invariant notelibvmaf/AGENTS.md motion-port row.
  • Reproducer / smoke-test command — see Test plan.
  • CHANGELOG.md entry — Unreleased § Added.
  • Rebase notedocs/rebase-notes.md upstream-port marker.

Test plan / Reproducer

# Build CPU-only
cd libvmaf && meson setup build --wipe -Denable_cuda=false -Denable_sycl=false \
  --buildtype release -Denable_float=true && ninja -C build

# Verify default scores are unchanged (before/after should match)
./build/tools/vmaf \
  --reference testdata/yuv/ref_576x324_48f.yuv \
  --distorted testdata/yuv/dis_576x324_48f.yuv \
  --width 576 --height 324 --pixel_format 420 --bitdepth 8 \
  --feature float_motion --feature integer_motion 2>&1 | grep -E 'motion[23]_score'

# Verify new options are accepted without error
./build/tools/vmaf \
  --reference testdata/yuv/ref_576x324_48f.yuv \
  --distorted testdata/yuv/dis_576x324_48f.yuv \
  --width 576 --height 324 --pixel_format 420 --bitdepth 8 \
  --feature 'float_motion:motion_add_scale1=true:motion_filter_size=3:motion_add_uv=true:motion_max_val=100.0' 2>&1 | tail -5

Known follow-ups

  • motion_add_uv=true path exercises picture_copy(..., 1/2) for U/V planes; cross-backend (CUDA/SYCL) UV-plane motion is not yet wired in GPU backends — tracked separately.
  • motion3_score output is now emitted alongside motion2_score; model JSON files that reference motion features are unchanged (they consume motion2_score).
  • integer_motion was already fully ported in the fork prior to this PR; no delta to integer_motion.c needed.

https://claude.ai/code/session_014cWWtUnFKSNpQWXdfHDgA2


Generated by Claude Code

…ture extractor options

Verbatim port of Netflix/vmaf commit b949ceb (Kyle Swanson, 2026-04-27)
per Research-0024 §Decision-matrix Strategy A.

Also ports picture_copy channel-parameter change from upstream d3647c7
(prerequisite for float_motion UV plane support).

New options (all no-ops at default values):
- float_motion: motion_fps_weight, motion_blend_factor, motion_blend_offset,
  motion_add_scale1, motion_filter_size, motion_add_uv, motion_max_val
- float_motion + integer_motion: motion_filter_size, motion_add_scale1,
  motion_add_uv (integer already had blend/fps/max options)

New outputs: VMAF_feature_motion3_score, VMAF_integer_feature_motion3_score

picture_copy() gains an int channel parameter (luma callers pass 0).
Bilinear downscaler for motion_add_scale1 inlined as local statics in
motion.c — avoids touching deferred vif module (Research-0024 §Strategy-E).

Default behavior: bit-identical to pre-port baseline (verified on
ref_576x324_48f.yuv / dis_576x324_48f.yuv, all 48 frames, 6 decimal places).
SIMD dispatch (AVX2/AVX-512/NEON float_sad_line) preserved for Y-plane
default path via compute_motion_simd wrapper.

https://claude.ai/code/session_014cWWtUnFKSNpQWXdfHDgA2
@lusoris lusoris force-pushed the upstream/port-b949cebf-motion branch from 26b8537 to cd59766 Compare April 29, 2026 13:15
…-tidy, doc-substance, AGENTS.md)

Clears the 4 CI failures that arrived after the upstream port commit:

1. Pre-Commit (clang-format) — re-flow motion.c hunks under the
   100-column / single-space K&R style. No semantic delta.
2. Clang-Tidy — picture_copy.h was missing the libvmaf/picture.h
   include and tripped clang-diagnostic-error on VmafPicture; add
   the include. Drop redundant trailing returns in
   picture_copy_hbd() / picture_copy(). Cast outer index to
   ptrdiff_t in motion.c / float_motion.c / float_psnr.c inner
   loops to silence bugprone-implicit-widening-of-multiplication.
   Mark unused bpc parameter in float_motion init() with (void).
   Split unsigned h_u, h_v / double score_u, score_v / double
   score2_u, score2_v multi-decls (readability-isolate-decl).
   NOLINTNEXTLINE(readability-function-size) on the 3 large
   float_motion.c functions (init/extract/close) the upstream
   port grows inline + the pre-existing float_adm.c extract()
   touched only by signature update; cite ADR-0141 / T7-5 sweep.
3. Doc-Substance Gate — add motion-port note + new option matrix
   row to docs/metrics/features.md, and "Known gaps" entries for
   the CPU-only motion_add_uv path to docs/backends/cuda/overview.md
   and docs/backends/sycl/overview.md (the surface gate flagged
   touched cuda/ + sycl/ feature kernels without matching docs).
4. Deep-Dive Deliverables Checklist — add a libvmaf/AGENTS.md
   rebase-sensitive-invariant entry pinning the float_motion
   extra-options surface, the SIMD-fast-path wrapper, and the
   picture_copy() trailing-channel signature change. PR body
   refresh in the same push lands the matching ticked rows.

No code path is exercised differently — defaults stay bit-identical
to pre-port baseline (`compute_motion_simd` Y-plane fast path); the
NOLINT additions cite the load-bearing invariant per CLAUDE.md §12 r12.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lusoris lusoris marked this pull request as ready for review April 29, 2026 13:55
@lusoris lusoris merged commit 3806beb into master Apr 29, 2026
50 of 53 checks passed
@lusoris lusoris deleted the upstream/port-b949cebf-motion branch April 29, 2026 13:55
@github-actions github-actions Bot mentioned this pull request Apr 29, 2026
lusoris pushed a commit that referenced this pull request May 1, 2026
…-1a Netflix Public dataset row)

Update docs/state.md `_Updated:` stamp to 2026-04-29 and rewrite the
"Tiny-AI C1 baseline `fr_regressor_v1.onnx`" deferral row's reopen-trigger
to TRIGGERED — the Netflix Public training corpus that gated C1 is now
locally available at `.workingdir2/netflix/` (9 ref + 70 dis YUVs, ~37 GB,
gitignored; provided by lawrence 2026-04-27), unblocking BACKLOG T6-1a.

Verified the rest of state.md against the 2026-04-29-session merged PR
set (#193#205, #209). Every merged PR was feature / chore / docs / perf
with no bug-status delta to record per CLAUDE §12 rule 13:
- #193 chore(dnn) T7-12 env override removal — chore.
- #194 docs(research) T7-9 NPU digest — research.
- #195 feat(mcp) T5-2 embedded scaffold — feature.
- #196 feat(vulkan) T7-36 cambi integration — feature.
- #197 feat(motion) Netflix b949ceb port — upstream port.
- #198 chore(backlog) T7-32 micro-investigations — verify-only.
- #199 feat(ai) T6-9 model registry — feature.
- #200 feat(hip) T7-10 HIP scaffold — feature.
- #201 feat(simd) T7-38 SVE2 ports — feature.
- #202 feat(ci) T6-8 parity matrix — feature.
- #203 feat(ai) T6-7 FastDVDnet — feature.
- #205 docs(audit) T7-4 quarterly audit — explicitly notes "no
  state.md changes (no upstream commit ruled in/out a fork bug)".
- #209 perf(sycl) T7-17 fp64-less device — perf.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lusoris pushed a commit that referenced this pull request May 1, 2026
…-1a Netflix Public dataset row)

Update docs/state.md `_Updated:` stamp to 2026-04-29 and rewrite the
"Tiny-AI C1 baseline `fr_regressor_v1.onnx`" deferral row's reopen-trigger
to TRIGGERED — the Netflix Public training corpus that gated C1 is now
locally available at `.workingdir2/netflix/` (9 ref + 70 dis YUVs, ~37 GB,
gitignored; provided by lawrence 2026-04-27), unblocking BACKLOG T6-1a.

Verified the rest of state.md against the 2026-04-29-session merged PR
set (#193#205, #209). Every merged PR was feature / chore / docs / perf
with no bug-status delta to record per CLAUDE §12 rule 13:
- #193 chore(dnn) T7-12 env override removal — chore.
- #194 docs(research) T7-9 NPU digest — research.
- #195 feat(mcp) T5-2 embedded scaffold — feature.
- #196 feat(vulkan) T7-36 cambi integration — feature.
- #197 feat(motion) Netflix b949ceb port — upstream port.
- #198 chore(backlog) T7-32 micro-investigations — verify-only.
- #199 feat(ai) T6-9 model registry — feature.
- #200 feat(hip) T7-10 HIP scaffold — feature.
- #201 feat(simd) T7-38 SVE2 ports — feature.
- #202 feat(ci) T6-8 parity matrix — feature.
- #203 feat(ai) T6-7 FastDVDnet — feature.
- #205 docs(audit) T7-4 quarterly audit — explicitly notes "no
  state.md changes (no upstream commit ruled in/out a fork bug)".
- #209 perf(sycl) T7-17 fp64-less device — perf.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lusoris pushed a commit that referenced this pull request May 1, 2026
…-1a Netflix Public dataset row)

Update docs/state.md `_Updated:` stamp to 2026-04-29 and rewrite the
"Tiny-AI C1 baseline `fr_regressor_v1.onnx`" deferral row's reopen-trigger
to TRIGGERED — the Netflix Public training corpus that gated C1 is now
locally available at `.workingdir2/netflix/` (9 ref + 70 dis YUVs, ~37 GB,
gitignored; provided by lawrence 2026-04-27), unblocking BACKLOG T6-1a.

Verified the rest of state.md against the 2026-04-29-session merged PR
set (#193#205, #209). Every merged PR was feature / chore / docs / perf
with no bug-status delta to record per CLAUDE §12 rule 13:
- #193 chore(dnn) T7-12 env override removal — chore.
- #194 docs(research) T7-9 NPU digest — research.
- #195 feat(mcp) T5-2 embedded scaffold — feature.
- #196 feat(vulkan) T7-36 cambi integration — feature.
- #197 feat(motion) Netflix b949ceb port — upstream port.
- #198 chore(backlog) T7-32 micro-investigations — verify-only.
- #199 feat(ai) T6-9 model registry — feature.
- #200 feat(hip) T7-10 HIP scaffold — feature.
- #201 feat(simd) T7-38 SVE2 ports — feature.
- #202 feat(ci) T6-8 parity matrix — feature.
- #203 feat(ai) T6-7 FastDVDnet — feature.
- #205 docs(audit) T7-4 quarterly audit — explicitly notes "no
  state.md changes (no upstream commit ruled in/out a fork bug)".
- #209 perf(sycl) T7-17 fp64-less device — perf.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lusoris added a commit that referenced this pull request May 1, 2026
…-1a Netflix Public dataset row) (#245)

Update docs/state.md `_Updated:` stamp to 2026-04-29 and rewrite the
"Tiny-AI C1 baseline `fr_regressor_v1.onnx`" deferral row's reopen-trigger
to TRIGGERED — the Netflix Public training corpus that gated C1 is now
locally available at `.workingdir2/netflix/` (9 ref + 70 dis YUVs, ~37 GB,
gitignored; provided by lawrence 2026-04-27), unblocking BACKLOG T6-1a.

Verified the rest of state.md against the 2026-04-29-session merged PR
set (#193#205, #209). Every merged PR was feature / chore / docs / perf
with no bug-status delta to record per CLAUDE §12 rule 13:
- #193 chore(dnn) T7-12 env override removal — chore.
- #194 docs(research) T7-9 NPU digest — research.
- #195 feat(mcp) T5-2 embedded scaffold — feature.
- #196 feat(vulkan) T7-36 cambi integration — feature.
- #197 feat(motion) Netflix b949ceb port — upstream port.
- #198 chore(backlog) T7-32 micro-investigations — verify-only.
- #199 feat(ai) T6-9 model registry — feature.
- #200 feat(hip) T7-10 HIP scaffold — feature.
- #201 feat(simd) T7-38 SVE2 ports — feature.
- #202 feat(ci) T6-8 parity matrix — feature.
- #203 feat(ai) T6-7 FastDVDnet — feature.
- #205 docs(audit) T7-4 quarterly audit — explicitly notes "no
  state.md changes (no upstream commit ruled in/out a fork bug)".
- #209 perf(sycl) T7-17 fp64-less device — perf.

Co-authored-by: Lusoris <lusoris@pm.me>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lusoris pushed a commit that referenced this pull request May 2, 2026
…uard

speed_chroma + speed_temporal live in libvmaf/src/feature/speed.c, which
the build only compiles when -Denable_float=true. Their entries in the
feature_extractor.c registration list are wrapped in
`#if VMAF_FLOAT_FEATURES`, so vmaf_get_feature_extractor_by_name returns
NULL on a default build (enable_float=false) — the test then fails its
first assertion.

CI passes -Denable_float=true everywhere, so this never tripped on the
hosted runners; a default `meson setup build libvmaf` locally has been
returning 49/50 since the SpEED port (Netflix d3647c7 / PR #197) and
landing each PR documented the failure as "pre-existing on master".

Wrap both the executable() and test() registrations in
`if get_option('enable_float')`, matching the pattern test_vulkan_*
already uses for its feature gate. The test still runs on every CI
build; local default builds now report 47/47 instead of 47/50.

Six-deliverable checklist (ADR-0108):
- Research digest: no digest needed: trivial — single-config gate
- Decision matrix: no alternatives: only-one-way fix (mirror existing
  enable_vulkan gating pattern)
- AGENTS.md invariant note: no rebase-sensitive invariants — meson gate
- Reproducer / smoke-test command: see PR body Test plan
- CHANGELOG fragment: no changelog needed — test-only change, no
  user-visible delta
- Rebase note: docs/rebase-notes.md entry 0097

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lusoris added a commit that referenced this pull request May 2, 2026
…uard (#263)

speed_chroma + speed_temporal live in libvmaf/src/feature/speed.c, which
the build only compiles when -Denable_float=true. Their entries in the
feature_extractor.c registration list are wrapped in
`#if VMAF_FLOAT_FEATURES`, so vmaf_get_feature_extractor_by_name returns
NULL on a default build (enable_float=false) — the test then fails its
first assertion.

CI passes -Denable_float=true everywhere, so this never tripped on the
hosted runners; a default `meson setup build libvmaf` locally has been
returning 49/50 since the SpEED port (Netflix d3647c7 / PR #197) and
landing each PR documented the failure as "pre-existing on master".

Wrap both the executable() and test() registrations in
`if get_option('enable_float')`, matching the pattern test_vulkan_*
already uses for its feature gate. The test still runs on every CI
build; local default builds now report 47/47 instead of 47/50.

Six-deliverable checklist (ADR-0108):
- Research digest: no digest needed: trivial — single-config gate
- Decision matrix: no alternatives: only-one-way fix (mirror existing
  enable_vulkan gating pattern)
- AGENTS.md invariant note: no rebase-sensitive invariants — meson gate
- Reproducer / smoke-test command: see PR body Test plan
- CHANGELOG fragment: no changelog needed — test-only change, no
  user-visible delta
- Rebase note: docs/rebase-notes.md entry 0097

Co-authored-by: Lusoris <lusoris@pm.me>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants