1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2019 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
12*fb1b10abSAndroid Build Coastguard Worker #include "gtest/gtest.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_non_greedy_mv.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker namespace {
17*fb1b10abSAndroid Build Coastguard Worker
read_in_mf(const char * filename,int * rows_ptr,int * cols_ptr,MV ** buffer_ptr)18*fb1b10abSAndroid Build Coastguard Worker static void read_in_mf(const char *filename, int *rows_ptr, int *cols_ptr,
19*fb1b10abSAndroid Build Coastguard Worker MV **buffer_ptr) {
20*fb1b10abSAndroid Build Coastguard Worker FILE *input = fopen(filename, "rb");
21*fb1b10abSAndroid Build Coastguard Worker int row, col;
22*fb1b10abSAndroid Build Coastguard Worker int idx;
23*fb1b10abSAndroid Build Coastguard Worker
24*fb1b10abSAndroid Build Coastguard Worker ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl;
25*fb1b10abSAndroid Build Coastguard Worker
26*fb1b10abSAndroid Build Coastguard Worker fscanf(input, "%d,%d\n", rows_ptr, cols_ptr);
27*fb1b10abSAndroid Build Coastguard Worker
28*fb1b10abSAndroid Build Coastguard Worker *buffer_ptr = (MV *)malloc((*rows_ptr) * (*cols_ptr) * sizeof(MV));
29*fb1b10abSAndroid Build Coastguard Worker
30*fb1b10abSAndroid Build Coastguard Worker for (idx = 0; idx < (*rows_ptr) * (*cols_ptr); ++idx) {
31*fb1b10abSAndroid Build Coastguard Worker fscanf(input, "%d,%d;", &row, &col);
32*fb1b10abSAndroid Build Coastguard Worker (*buffer_ptr)[idx].row = row;
33*fb1b10abSAndroid Build Coastguard Worker (*buffer_ptr)[idx].col = col;
34*fb1b10abSAndroid Build Coastguard Worker }
35*fb1b10abSAndroid Build Coastguard Worker fclose(input);
36*fb1b10abSAndroid Build Coastguard Worker }
37*fb1b10abSAndroid Build Coastguard Worker
read_in_local_var(const char * filename,int * rows_ptr,int * cols_ptr,int (** M_ptr)[MF_LOCAL_STRUCTURE_SIZE])38*fb1b10abSAndroid Build Coastguard Worker static void read_in_local_var(const char *filename, int *rows_ptr,
39*fb1b10abSAndroid Build Coastguard Worker int *cols_ptr,
40*fb1b10abSAndroid Build Coastguard Worker int (**M_ptr)[MF_LOCAL_STRUCTURE_SIZE]) {
41*fb1b10abSAndroid Build Coastguard Worker FILE *input = fopen(filename, "rb");
42*fb1b10abSAndroid Build Coastguard Worker int M00, M01, M10, M11;
43*fb1b10abSAndroid Build Coastguard Worker int idx;
44*fb1b10abSAndroid Build Coastguard Worker int int_type;
45*fb1b10abSAndroid Build Coastguard Worker
46*fb1b10abSAndroid Build Coastguard Worker ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl;
47*fb1b10abSAndroid Build Coastguard Worker
48*fb1b10abSAndroid Build Coastguard Worker fscanf(input, "%d,%d\n", rows_ptr, cols_ptr);
49*fb1b10abSAndroid Build Coastguard Worker
50*fb1b10abSAndroid Build Coastguard Worker *M_ptr = (int(*)[MF_LOCAL_STRUCTURE_SIZE])malloc(
51*fb1b10abSAndroid Build Coastguard Worker (*rows_ptr) * (*cols_ptr) * MF_LOCAL_STRUCTURE_SIZE * sizeof(int_type));
52*fb1b10abSAndroid Build Coastguard Worker
53*fb1b10abSAndroid Build Coastguard Worker for (idx = 0; idx < (*rows_ptr) * (*cols_ptr); ++idx) {
54*fb1b10abSAndroid Build Coastguard Worker fscanf(input, "%d,%d,%d,%d;", &M00, &M01, &M10, &M11);
55*fb1b10abSAndroid Build Coastguard Worker (*M_ptr)[idx][0] = M00;
56*fb1b10abSAndroid Build Coastguard Worker (*M_ptr)[idx][1] = M01;
57*fb1b10abSAndroid Build Coastguard Worker (*M_ptr)[idx][2] = M10;
58*fb1b10abSAndroid Build Coastguard Worker (*M_ptr)[idx][3] = M11;
59*fb1b10abSAndroid Build Coastguard Worker }
60*fb1b10abSAndroid Build Coastguard Worker fclose(input);
61*fb1b10abSAndroid Build Coastguard Worker }
62*fb1b10abSAndroid Build Coastguard Worker
compare_mf(const MV * mf1,const MV * mf2,int rows,int cols,float * mean_ptr,float * std_ptr)63*fb1b10abSAndroid Build Coastguard Worker static void compare_mf(const MV *mf1, const MV *mf2, int rows, int cols,
64*fb1b10abSAndroid Build Coastguard Worker float *mean_ptr, float *std_ptr) {
65*fb1b10abSAndroid Build Coastguard Worker float float_type;
66*fb1b10abSAndroid Build Coastguard Worker float *diffs = (float *)malloc(rows * cols * sizeof(float_type));
67*fb1b10abSAndroid Build Coastguard Worker int idx;
68*fb1b10abSAndroid Build Coastguard Worker float accu = 0.0f;
69*fb1b10abSAndroid Build Coastguard Worker for (idx = 0; idx < rows * cols; ++idx) {
70*fb1b10abSAndroid Build Coastguard Worker MV mv1 = mf1[idx];
71*fb1b10abSAndroid Build Coastguard Worker MV mv2 = mf2[idx];
72*fb1b10abSAndroid Build Coastguard Worker float row_diff2 = (float)((mv1.row - mv2.row) * (mv1.row - mv2.row));
73*fb1b10abSAndroid Build Coastguard Worker float col_diff2 = (float)((mv1.col - mv2.col) * (mv1.col - mv2.col));
74*fb1b10abSAndroid Build Coastguard Worker diffs[idx] = sqrt(row_diff2 + col_diff2);
75*fb1b10abSAndroid Build Coastguard Worker accu += diffs[idx];
76*fb1b10abSAndroid Build Coastguard Worker }
77*fb1b10abSAndroid Build Coastguard Worker *mean_ptr = accu / rows / cols;
78*fb1b10abSAndroid Build Coastguard Worker *std_ptr = 0;
79*fb1b10abSAndroid Build Coastguard Worker for (idx = 0; idx < rows * cols; ++idx) {
80*fb1b10abSAndroid Build Coastguard Worker *std_ptr += (diffs[idx] - (*mean_ptr)) * (diffs[idx] - (*mean_ptr));
81*fb1b10abSAndroid Build Coastguard Worker }
82*fb1b10abSAndroid Build Coastguard Worker *std_ptr = sqrt(*std_ptr / rows / cols);
83*fb1b10abSAndroid Build Coastguard Worker free(diffs);
84*fb1b10abSAndroid Build Coastguard Worker }
85*fb1b10abSAndroid Build Coastguard Worker
load_frame_info(const char * filename,YV12_BUFFER_CONFIG * ref_frame_ptr)86*fb1b10abSAndroid Build Coastguard Worker static void load_frame_info(const char *filename,
87*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *ref_frame_ptr) {
88*fb1b10abSAndroid Build Coastguard Worker FILE *input = fopen(filename, "rb");
89*fb1b10abSAndroid Build Coastguard Worker int idx;
90*fb1b10abSAndroid Build Coastguard Worker uint8_t data_type;
91*fb1b10abSAndroid Build Coastguard Worker
92*fb1b10abSAndroid Build Coastguard Worker ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl;
93*fb1b10abSAndroid Build Coastguard Worker
94*fb1b10abSAndroid Build Coastguard Worker fscanf(input, "%d,%d\n", &(ref_frame_ptr->y_height),
95*fb1b10abSAndroid Build Coastguard Worker &(ref_frame_ptr->y_width));
96*fb1b10abSAndroid Build Coastguard Worker
97*fb1b10abSAndroid Build Coastguard Worker ref_frame_ptr->y_buffer = (uint8_t *)malloc(
98*fb1b10abSAndroid Build Coastguard Worker (ref_frame_ptr->y_width) * (ref_frame_ptr->y_height) * sizeof(data_type));
99*fb1b10abSAndroid Build Coastguard Worker
100*fb1b10abSAndroid Build Coastguard Worker for (idx = 0; idx < (ref_frame_ptr->y_width) * (ref_frame_ptr->y_height);
101*fb1b10abSAndroid Build Coastguard Worker ++idx) {
102*fb1b10abSAndroid Build Coastguard Worker int value;
103*fb1b10abSAndroid Build Coastguard Worker fscanf(input, "%d,", &value);
104*fb1b10abSAndroid Build Coastguard Worker ref_frame_ptr->y_buffer[idx] = (uint8_t)value;
105*fb1b10abSAndroid Build Coastguard Worker }
106*fb1b10abSAndroid Build Coastguard Worker
107*fb1b10abSAndroid Build Coastguard Worker ref_frame_ptr->y_stride = ref_frame_ptr->y_width;
108*fb1b10abSAndroid Build Coastguard Worker fclose(input);
109*fb1b10abSAndroid Build Coastguard Worker }
110*fb1b10abSAndroid Build Coastguard Worker
compare_local_var(const int (* local_var1)[MF_LOCAL_STRUCTURE_SIZE],const int (* local_var2)[MF_LOCAL_STRUCTURE_SIZE],int rows,int cols)111*fb1b10abSAndroid Build Coastguard Worker static int compare_local_var(const int (*local_var1)[MF_LOCAL_STRUCTURE_SIZE],
112*fb1b10abSAndroid Build Coastguard Worker const int (*local_var2)[MF_LOCAL_STRUCTURE_SIZE],
113*fb1b10abSAndroid Build Coastguard Worker int rows, int cols) {
114*fb1b10abSAndroid Build Coastguard Worker int diff = 0;
115*fb1b10abSAndroid Build Coastguard Worker int outter_idx, inner_idx;
116*fb1b10abSAndroid Build Coastguard Worker for (outter_idx = 0; outter_idx < rows * cols; ++outter_idx) {
117*fb1b10abSAndroid Build Coastguard Worker for (inner_idx = 0; inner_idx < MF_LOCAL_STRUCTURE_SIZE; ++inner_idx) {
118*fb1b10abSAndroid Build Coastguard Worker diff += abs(local_var1[outter_idx][inner_idx] -
119*fb1b10abSAndroid Build Coastguard Worker local_var2[outter_idx][inner_idx]);
120*fb1b10abSAndroid Build Coastguard Worker }
121*fb1b10abSAndroid Build Coastguard Worker }
122*fb1b10abSAndroid Build Coastguard Worker return diff / rows / cols;
123*fb1b10abSAndroid Build Coastguard Worker }
124*fb1b10abSAndroid Build Coastguard Worker
TEST(non_greedy_mv,smooth_mf)125*fb1b10abSAndroid Build Coastguard Worker TEST(non_greedy_mv, smooth_mf) {
126*fb1b10abSAndroid Build Coastguard Worker const char *search_mf_file = "non_greedy_mv_test_files/exhaust_16x16.txt";
127*fb1b10abSAndroid Build Coastguard Worker const char *local_var_file = "non_greedy_mv_test_files/localVar_16x16.txt";
128*fb1b10abSAndroid Build Coastguard Worker const char *estimation_file = "non_greedy_mv_test_files/estimation_16x16.txt";
129*fb1b10abSAndroid Build Coastguard Worker const char *ground_truth_file =
130*fb1b10abSAndroid Build Coastguard Worker "non_greedy_mv_test_files/ground_truth_16x16.txt";
131*fb1b10abSAndroid Build Coastguard Worker BLOCK_SIZE bsize = BLOCK_32X32;
132*fb1b10abSAndroid Build Coastguard Worker MV *search_mf = nullptr;
133*fb1b10abSAndroid Build Coastguard Worker MV *smooth_mf = nullptr;
134*fb1b10abSAndroid Build Coastguard Worker MV *estimation = nullptr;
135*fb1b10abSAndroid Build Coastguard Worker MV *ground_truth = nullptr;
136*fb1b10abSAndroid Build Coastguard Worker int(*local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr;
137*fb1b10abSAndroid Build Coastguard Worker int rows = 0, cols = 0;
138*fb1b10abSAndroid Build Coastguard Worker
139*fb1b10abSAndroid Build Coastguard Worker int alpha = 100, max_iter = 100;
140*fb1b10abSAndroid Build Coastguard Worker
141*fb1b10abSAndroid Build Coastguard Worker read_in_mf(search_mf_file, &rows, &cols, &search_mf);
142*fb1b10abSAndroid Build Coastguard Worker read_in_local_var(local_var_file, &rows, &cols, &local_var);
143*fb1b10abSAndroid Build Coastguard Worker read_in_mf(estimation_file, &rows, &cols, &estimation);
144*fb1b10abSAndroid Build Coastguard Worker read_in_mf(ground_truth_file, &rows, &cols, &ground_truth);
145*fb1b10abSAndroid Build Coastguard Worker
146*fb1b10abSAndroid Build Coastguard Worker float sm_mean, sm_std;
147*fb1b10abSAndroid Build Coastguard Worker float est_mean, est_std;
148*fb1b10abSAndroid Build Coastguard Worker
149*fb1b10abSAndroid Build Coastguard Worker smooth_mf = (MV *)malloc(rows * cols * sizeof(MV));
150*fb1b10abSAndroid Build Coastguard Worker vp9_get_smooth_motion_field(search_mf, local_var, rows, cols, bsize, alpha,
151*fb1b10abSAndroid Build Coastguard Worker max_iter, smooth_mf);
152*fb1b10abSAndroid Build Coastguard Worker
153*fb1b10abSAndroid Build Coastguard Worker compare_mf(smooth_mf, ground_truth, rows, cols, &sm_mean, &sm_std);
154*fb1b10abSAndroid Build Coastguard Worker compare_mf(smooth_mf, estimation, rows, cols, &est_mean, &est_std);
155*fb1b10abSAndroid Build Coastguard Worker
156*fb1b10abSAndroid Build Coastguard Worker EXPECT_LE(sm_mean, 3);
157*fb1b10abSAndroid Build Coastguard Worker EXPECT_LE(est_mean, 2);
158*fb1b10abSAndroid Build Coastguard Worker
159*fb1b10abSAndroid Build Coastguard Worker free(search_mf);
160*fb1b10abSAndroid Build Coastguard Worker free(local_var);
161*fb1b10abSAndroid Build Coastguard Worker free(estimation);
162*fb1b10abSAndroid Build Coastguard Worker free(ground_truth);
163*fb1b10abSAndroid Build Coastguard Worker free(smooth_mf);
164*fb1b10abSAndroid Build Coastguard Worker }
165*fb1b10abSAndroid Build Coastguard Worker
TEST(non_greedy_mv,local_var)166*fb1b10abSAndroid Build Coastguard Worker TEST(non_greedy_mv, local_var) {
167*fb1b10abSAndroid Build Coastguard Worker const char *ref_frame_file = "non_greedy_mv_test_files/ref_frame_16x16.txt";
168*fb1b10abSAndroid Build Coastguard Worker const char *cur_frame_file = "non_greedy_mv_test_files/cur_frame_16x16.txt";
169*fb1b10abSAndroid Build Coastguard Worker const char *gt_local_var_file = "non_greedy_mv_test_files/localVar_16x16.txt";
170*fb1b10abSAndroid Build Coastguard Worker const char *search_mf_file = "non_greedy_mv_test_files/exhaust_16x16.txt";
171*fb1b10abSAndroid Build Coastguard Worker BLOCK_SIZE bsize = BLOCK_16X16;
172*fb1b10abSAndroid Build Coastguard Worker int(*gt_local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr;
173*fb1b10abSAndroid Build Coastguard Worker int(*est_local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr;
174*fb1b10abSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG ref_frame, cur_frame;
175*fb1b10abSAndroid Build Coastguard Worker int rows, cols;
176*fb1b10abSAndroid Build Coastguard Worker MV *search_mf;
177*fb1b10abSAndroid Build Coastguard Worker int int_type;
178*fb1b10abSAndroid Build Coastguard Worker int local_var_diff;
179*fb1b10abSAndroid Build Coastguard Worker vp9_variance_fn_ptr_t fn;
180*fb1b10abSAndroid Build Coastguard Worker
181*fb1b10abSAndroid Build Coastguard Worker load_frame_info(ref_frame_file, &ref_frame);
182*fb1b10abSAndroid Build Coastguard Worker load_frame_info(cur_frame_file, &cur_frame);
183*fb1b10abSAndroid Build Coastguard Worker read_in_mf(search_mf_file, &rows, &cols, &search_mf);
184*fb1b10abSAndroid Build Coastguard Worker
185*fb1b10abSAndroid Build Coastguard Worker fn.sdf = vpx_sad16x16;
186*fb1b10abSAndroid Build Coastguard Worker est_local_var = (int(*)[MF_LOCAL_STRUCTURE_SIZE])malloc(
187*fb1b10abSAndroid Build Coastguard Worker rows * cols * MF_LOCAL_STRUCTURE_SIZE * sizeof(int_type));
188*fb1b10abSAndroid Build Coastguard Worker vp9_get_local_structure(&cur_frame, &ref_frame, search_mf, &fn, rows, cols,
189*fb1b10abSAndroid Build Coastguard Worker bsize, est_local_var);
190*fb1b10abSAndroid Build Coastguard Worker read_in_local_var(gt_local_var_file, &rows, &cols, >_local_var);
191*fb1b10abSAndroid Build Coastguard Worker
192*fb1b10abSAndroid Build Coastguard Worker local_var_diff = compare_local_var(est_local_var, gt_local_var, rows, cols);
193*fb1b10abSAndroid Build Coastguard Worker
194*fb1b10abSAndroid Build Coastguard Worker EXPECT_LE(local_var_diff, 1);
195*fb1b10abSAndroid Build Coastguard Worker
196*fb1b10abSAndroid Build Coastguard Worker free(gt_local_var);
197*fb1b10abSAndroid Build Coastguard Worker free(est_local_var);
198*fb1b10abSAndroid Build Coastguard Worker free(ref_frame.y_buffer);
199*fb1b10abSAndroid Build Coastguard Worker }
200*fb1b10abSAndroid Build Coastguard Worker } // namespace
201