Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 99 additions & 71 deletions libvmaf/src/feature/integer_motion.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ typedef struct MotionState {
double motion_blend_factor;
double motion_blend_offset;
double motion_fps_weight;
double prev_processed;
double stamp_value;
bool motion_five_frame_window;
bool motion_moving_average;
bool motion_force_zero;
Expand Down Expand Up @@ -259,6 +261,9 @@ static int init(VmafFeatureExtractor *fex, enum VmafPixelFormat pix_fmt,
s->h = h;
s->bpc = bpc;

s->prev_processed = 0.0;
s->stamp_value = 0.0;

s->feature_name_dict =
vmaf_feature_name_dict_from_provided_features(fex->provided_features,
fex->options, s);
Expand Down Expand Up @@ -292,6 +297,80 @@ static int init(VmafFeatureExtractor *fex, enum VmafPixelFormat pix_fmt,
return 0;
}


static int calculate_integer_motionx_features(VmafFeatureExtractor *fex,
VmafFeatureCollector *feature_collector,
unsigned index) {
if (index == 0)
return 0;

MotionState* s = fex->priv;
const unsigned min_idx = s->motion_five_frame_window ? 2 : 1;
const unsigned stride = s->motion_five_frame_window ? 2 : 1;
const unsigned i = index - 1;

const VmafDictionaryEntry *sad_entry = vmaf_dictionary_get(
&s->feature_name_dict, "VMAF_integer_feature_motion_sad_score", 0);
if (!sad_entry) return -EINVAL;
const char *sad_name = sad_entry->val;

double sad_i;
int err = 0;
do {
err = vmaf_feature_collector_get_score(feature_collector, sad_name, &sad_i,
i);
}
while(err);

double motion2;
if (i < min_idx) {
motion2 = 0.;
} else {
const int lo_idx = (int)i - (int)(stride - 1);
const int hi_idx = (int)i + 1;
double hi;
const bool has_hi = !vmaf_feature_collector_get_score(
feature_collector, sad_name, &hi, hi_idx);

if (!has_hi) {
motion2 = sad_i;
} else if (lo_idx >= (int)min_idx) {
double lo;
vmaf_feature_collector_get_score(
feature_collector, sad_name, &lo, lo_idx);
motion2 = lo < hi ? lo : hi;
} else {
motion2 = hi;
}
}

vmaf_feature_collector_append_with_dict(feature_collector,
s->feature_name_dict,
"VMAF_integer_feature_motion2_score", motion2, i);

double motion3;
if (i < min_idx) {
motion3 = s->stamp_value;
s->prev_processed = s->stamp_value;
} else {
double processed = MIN(motion_blend(motion2,
s->motion_blend_factor,
s->motion_blend_offset),
s->motion_max_val);
motion3 = s->motion_moving_average
? (processed + s->prev_processed) / 2.0
: processed;
s->prev_processed = processed;
}

vmaf_feature_collector_append_with_dict(feature_collector,
s->feature_name_dict,
"VMAF_integer_feature_motion3_score", motion3, i);

return 0;
}


static int extract(VmafFeatureExtractor *fex,
VmafPicture *ref_pic, VmafPicture *ref_pic_90,
VmafPicture *dist_pic, VmafPicture *dist_pic_90,
Expand All @@ -311,23 +390,31 @@ static int extract(VmafFeatureExtractor *fex,
const unsigned min_idx = s->motion_five_frame_window ? 2 : 1;
if (index >= min_idx) {
const VmafPicture *prev = s->motion_five_frame_window
? &fex->prev_prev_ref
: &fex->prev_ref;
? &fex->prev_prev_ref
: &fex->prev_ref;
if (!prev->ref)
return -EINVAL;
return -EINVAL;

const unsigned w = s->w;
const unsigned h = s->h;
const uint8_t *prev_data = (const uint8_t *)prev->data[0];
const uint8_t *cur_data = (const uint8_t *)ref_pic->data[0];

uint64_t sad = s->pipeline(prev_data, prev->stride[0],
cur_data, ref_pic->stride[0],
s->y_row, w, h, s->bpc);
cur_data, ref_pic->stride[0],
s->y_row, w, h, s->bpc);

score = MIN((double)sad / 256. / (w * h) * s->motion_fps_weight,
s->motion_max_val);
}
s->motion_max_val);


if (index >= min_idx) {
s->stamp_value = MIN(motion_blend(score,
s->motion_blend_factor,
s->motion_blend_offset),
s->motion_max_val);
}
}

write_score:
err = vmaf_feature_collector_append_with_dict(feature_collector,
Expand All @@ -341,9 +428,13 @@ static int extract(VmafFeatureExtractor *fex,
"VMAF_integer_feature_motion_score", score, index);
}

err = calculate_integer_motionx_features(fex, feature_collector, index);
if (err) return err;

return 0;
}


static int close_fex(VmafFeatureExtractor *fex)
{
MotionState *s = fex->priv;
Expand Down Expand Up @@ -371,75 +462,12 @@ static int flush(VmafFeatureExtractor *fex,
double score;
while (!vmaf_feature_collector_get_score(feature_collector, sad_name, &score, n))
n++;
const unsigned stride = s->motion_five_frame_window ? 2 : 1;
const unsigned min_idx = s->motion_five_frame_window ? 2 : 1;
if (!n) {
vmaf_dictionary_free(&s->feature_name_dict);
return 1;
}

double stamp_value = 0.;
if (n > min_idx) {
double sad_at_min_idx;
if (!vmaf_feature_collector_get_score(feature_collector, sad_name,
&sad_at_min_idx, min_idx)) {
stamp_value = MIN(motion_blend(sad_at_min_idx,
s->motion_blend_factor,
s->motion_blend_offset),
s->motion_max_val);
}
}

double prev_processed = 0.;
for (unsigned i = 0; i < n; i++) {
double sad_i;
vmaf_feature_collector_get_score(feature_collector, sad_name, &sad_i, i);

double motion2;

if (i < min_idx) {
motion2 = 0.;
} else {
const int lo_idx = (int)i - (int)(stride - 1);
const int hi_idx = (int)i + 1;
double hi;
const bool has_hi = !vmaf_feature_collector_get_score(
feature_collector, sad_name, &hi, hi_idx);
if (!has_hi) {
motion2 = sad_i;
} else if (lo_idx >= (int)min_idx) {
double lo;
vmaf_feature_collector_get_score(
feature_collector, sad_name, &lo, lo_idx);
motion2 = lo < hi ? lo : hi;
} else {
motion2 = hi;
}
}

vmaf_feature_collector_append_with_dict(feature_collector,
s->feature_name_dict,
"VMAF_integer_feature_motion2_score", motion2, i);

double motion3;
if (i < min_idx) {
motion3 = stamp_value;
prev_processed = stamp_value;
} else {
double processed = MIN(motion_blend(motion2,
s->motion_blend_factor,
s->motion_blend_offset),
s->motion_max_val);
motion3 = s->motion_moving_average
? (processed + prev_processed) / 2.0
: processed;
prev_processed = processed;
}

vmaf_feature_collector_append_with_dict(feature_collector,
s->feature_name_dict,
"VMAF_integer_feature_motion3_score", motion3, i);
}
calculate_integer_motionx_features(fex, feature_collector, n);

vmaf_dictionary_free(&s->feature_name_dict);
return 1;
Expand Down
Loading