Netflix / Netflix/vmaf

ADM code looks really more complicated than it should

Open
#952 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
5.5k
Forks
833
Avg merge
13h 8m
Merged PRs (30d)
2

Description

This is from adm_decouple_s, the float version:

kh = DIVS(th, oh + eps);
kv = DIVS(tv, ov + eps);
kd = DIVS(td, od + eps);

kh = kh < 0.0f ? 0.0f : (kh > 1.0f ? 1.0f : kh);
kv = kv < 0.0f ? 0.0f : (kv > 1.0f ? 1.0f : kv);
kd = kd < 0.0f ? 0.0f : (kd > 1.0f ? 1.0f : kd);

rst_h = kh * oh;
rst_v = kv * ov;
rst_d = kd * od;

It boils down to get zero if signs do not match, or the minimum magnitude otherwise (i.e. -2,-3 --> -2).
Another way of seeing it is clipping o{x} to t{x}
Another way is clipping t{x} to o{x}

Equivalent code is:

if(oh > 0)
   rst_h = max(min(th, oh),0) 
else 
   rst_h = min(max(th, oh),0) 

or

if(th > 0)
   rst_h = max(min(th, oh),0) 
else 
   rst_h = min(max(th, oh),0) 

both are fairly easy to port to integer (and AVX-2, for that matters)

Playing a bit with max's and min's, and assuming that adm_enh_gain_limit is an integer, a super easily simd-able integer version is

            int32_t gain_limit = angle_flag ? adm_enhn_gain_limit : 1;
            int16_t thneg = th & (th >> (sizeof(th) * 8 - 1)); // this is min(th, 0)
            int16_t tvneg = tv & (tv >> (sizeof(tv) * 8 - 1));
            int16_t tdneg = td & (td >> (sizeof(td) * 8 - 1));
            int16_t rst_h = MAX(thneg, MIN(th - thneg, oh * gain_limit));
            int16_t rst_v = MAX(tvneg, MIN(tv - tvneg, ov * gain_limit));
            int16_t rst_d = MAX(tdneg, MIN(td - tdneg, od * gain_limit));

Almost unbelievably, the match is 100% on test sequences src01_hrc00_576x324.yuv src01_hrc01_576x324.yuv, and another couple of sequences I tried,

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the adm_decouple_s float implementation and compare its gain calculations with the proposed clipping forms and integer/SIMD approach. Run the listed src01_hrc00_576x324.yuv and src01_hrc01_576x324.yuv sequences, plus the other referenced test sequences, and verify the refactored implementation preserves the current results.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
performance
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.