Skip to content

Commit 02fdfae

Browse files
committed
libvmaf/motion_v2: port remaining options
1 parent 11cc9b6 commit 02fdfae

1 file changed

Lines changed: 99 additions & 2 deletions

File tree

libvmaf/src/feature/integer_motion_v2.c

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "feature_extractor.h"
4040
#include "feature_name.h"
4141
#include "integer_motion.h"
42+
#include "motion_blend_tools.h"
4243

4344
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
4445

@@ -62,21 +63,68 @@ typedef struct MotionV2State {
6263
unsigned w, h, bpc;
6364
motion_pipeline_fn pipeline;
6465
double motion_max_val;
66+
double motion_blend_factor;
67+
double motion_blend_offset;
68+
double motion_fps_weight;
6569
bool motion_five_frame_window;
70+
bool motion_moving_average;
71+
bool motion_force_zero;
6672
VmafDictionary *feature_name_dict;
6773
} MotionV2State;
6874

6975
static const VmafOption options[] = {
76+
{
77+
.name = "motion_force_zero",
78+
.alias = "force_0",
79+
.help = "forces motion score to be 0",
80+
.offset = offsetof(MotionV2State, motion_force_zero),
81+
.type = VMAF_OPT_TYPE_BOOL,
82+
.default_val.b = false,
83+
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
84+
},
85+
{
86+
.name = "motion_blend_factor",
87+
.alias = "mbf",
88+
.help = "blend motion score given an offset",
89+
.offset = offsetof(MotionV2State, motion_blend_factor),
90+
.type = VMAF_OPT_TYPE_DOUBLE,
91+
.default_val.d = 1.0,
92+
.min = 0.0,
93+
.max = 1.0,
94+
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
95+
},
96+
{
97+
.name = "motion_blend_offset",
98+
.alias = "mbo",
99+
.help = "blend motion score starting from this offset",
100+
.offset = offsetof(MotionV2State, motion_blend_offset),
101+
.type = VMAF_OPT_TYPE_DOUBLE,
102+
.default_val.d = 40.0,
103+
.min = 0.0,
104+
.max = 1000.0,
105+
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
106+
},
107+
{
108+
.name = "motion_fps_weight",
109+
.alias = "mfw",
110+
.help = "fps-aware multiplicative weight/correction",
111+
.offset = offsetof(MotionV2State, motion_fps_weight),
112+
.type = VMAF_OPT_TYPE_DOUBLE,
113+
.default_val.d = 1.0,
114+
.min = 0.0,
115+
.max = 5.0,
116+
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
117+
},
70118
{
71119
.name = "motion_max_val",
120+
.alias = "mmxv",
72121
.help = "maximum value allowed; larger values will be clipped to this value",
73122
.offset = offsetof(MotionV2State, motion_max_val),
74123
.type = VMAF_OPT_TYPE_DOUBLE,
75124
.default_val.d = DEFAULT_MOTION_MAX_VAL,
76125
.min = 0.0,
77126
.max = 10000.0,
78127
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
79-
.alias = "mmxv",
80128
},
81129
{
82130
.name = "motion_five_frame_window",
@@ -87,6 +135,15 @@ static const VmafOption options[] = {
87135
.default_val.b = false,
88136
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
89137
},
138+
{
139+
.name = "motion_moving_average",
140+
.alias = "mma",
141+
.help = "smooth motion3 with a 2-frame moving average",
142+
.offset = offsetof(MotionV2State, motion_moving_average),
143+
.type = VMAF_OPT_TYPE_BOOL,
144+
.default_val.b = false,
145+
.flags = VMAF_OPT_FLAG_FEATURE_PARAM,
146+
},
90147
{ 0 }
91148
};
92149

@@ -249,6 +306,12 @@ static int extract(VmafFeatureExtractor *fex,
249306
(void) ref_pic_90;
250307
(void) dist_pic_90;
251308

309+
if (s->motion_force_zero) {
310+
return vmaf_feature_collector_append_with_dict(feature_collector,
311+
s->feature_name_dict,
312+
"VMAF_integer_feature_motion_v2_sad_score", 0., index);
313+
}
314+
252315
const unsigned min_idx = s->motion_five_frame_window ? 2 : 1;
253316
if (index < min_idx) {
254317
return vmaf_feature_collector_append_with_dict(feature_collector,
@@ -275,7 +338,8 @@ static int extract(VmafFeatureExtractor *fex,
275338

276339
return vmaf_feature_collector_append_with_dict(feature_collector,
277340
s->feature_name_dict,
278-
"VMAF_integer_feature_motion_v2_sad_score", MIN(score, s->motion_max_val), index);
341+
"VMAF_integer_feature_motion_v2_sad_score",
342+
MIN(score * s->motion_fps_weight, s->motion_max_val), index);
279343
}
280344

281345
static int close_fex(VmafFeatureExtractor *fex)
@@ -311,6 +375,19 @@ static int flush(VmafFeatureExtractor *fex,
311375
const unsigned min_idx = s->motion_five_frame_window ? 2 : 1;
312376
if (n_frames == 0) return 1;
313377

378+
double stamp_value = 0.;
379+
if (n_frames > min_idx) {
380+
double sad_at_min_idx;
381+
if (!vmaf_feature_collector_get_score(feature_collector, sad_name,
382+
&sad_at_min_idx, min_idx)) {
383+
stamp_value = MIN(motion_blend(sad_at_min_idx,
384+
s->motion_blend_factor,
385+
s->motion_blend_offset),
386+
s->motion_max_val);
387+
}
388+
}
389+
390+
double prev_processed = 0.;
314391
for (unsigned i = 0; i < n_frames; i++) {
315392
double motion2;
316393

@@ -335,6 +412,25 @@ static int flush(VmafFeatureExtractor *fex,
335412
vmaf_feature_collector_append_with_dict(feature_collector,
336413
s->feature_name_dict,
337414
"VMAF_integer_feature_motion2_v2_score", motion2, i);
415+
416+
double motion3;
417+
if (i < min_idx) {
418+
motion3 = stamp_value;
419+
prev_processed = stamp_value;
420+
} else {
421+
double processed = MIN(motion_blend(motion2,
422+
s->motion_blend_factor,
423+
s->motion_blend_offset),
424+
s->motion_max_val);
425+
motion3 = s->motion_moving_average
426+
? (processed + prev_processed) / 2.0
427+
: processed;
428+
prev_processed = processed;
429+
}
430+
431+
vmaf_feature_collector_append_with_dict(feature_collector,
432+
s->feature_name_dict,
433+
"VMAF_integer_feature_motion3_v2_score", motion3, i);
338434
}
339435

340436
return 1;
@@ -343,6 +439,7 @@ static int flush(VmafFeatureExtractor *fex,
343439
static const char *provided_features[] = {
344440
"VMAF_integer_feature_motion_v2_sad_score",
345441
"VMAF_integer_feature_motion2_v2_score",
442+
"VMAF_integer_feature_motion3_v2_score",
346443
NULL
347444
};
348445

0 commit comments

Comments
 (0)