| /* |
| * Copyright (c) 2019 The WebM project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include <math.h> |
| #include "third_party/googletest/src/include/gtest/gtest.h" |
| #include "vp9/encoder/vp9_non_greedy_mv.h" |
| #include "./vpx_dsp_rtcd.h" |
| |
| namespace { |
| |
| static void read_in_mf(const char *filename, int *rows_ptr, int *cols_ptr, |
| MV **buffer_ptr) { |
| FILE *input = fopen(filename, "rb"); |
| int row, col; |
| int idx; |
| |
| ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl; |
| |
| fscanf(input, "%d,%d\n", rows_ptr, cols_ptr); |
| |
| *buffer_ptr = (MV *)malloc((*rows_ptr) * (*cols_ptr) * sizeof(MV)); |
| |
| for (idx = 0; idx < (*rows_ptr) * (*cols_ptr); ++idx) { |
| fscanf(input, "%d,%d;", &row, &col); |
| (*buffer_ptr)[idx].row = row; |
| (*buffer_ptr)[idx].col = col; |
| } |
| fclose(input); |
| } |
| |
| static void read_in_local_var(const char *filename, int *rows_ptr, |
| int *cols_ptr, |
| int (**M_ptr)[MF_LOCAL_STRUCTURE_SIZE]) { |
| FILE *input = fopen(filename, "rb"); |
| int M00, M01, M10, M11; |
| int idx; |
| int int_type; |
| |
| ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl; |
| |
| fscanf(input, "%d,%d\n", rows_ptr, cols_ptr); |
| |
| *M_ptr = (int(*)[MF_LOCAL_STRUCTURE_SIZE])malloc( |
| (*rows_ptr) * (*cols_ptr) * MF_LOCAL_STRUCTURE_SIZE * sizeof(int_type)); |
| |
| for (idx = 0; idx < (*rows_ptr) * (*cols_ptr); ++idx) { |
| fscanf(input, "%d,%d,%d,%d;", &M00, &M01, &M10, &M11); |
| (*M_ptr)[idx][0] = M00; |
| (*M_ptr)[idx][1] = M01; |
| (*M_ptr)[idx][2] = M10; |
| (*M_ptr)[idx][3] = M11; |
| } |
| fclose(input); |
| } |
| |
| static void compare_mf(const MV *mf1, const MV *mf2, int rows, int cols, |
| float *mean_ptr, float *std_ptr) { |
| float float_type; |
| float *diffs = (float *)malloc(rows * cols * sizeof(float_type)); |
| int idx; |
| float accu = 0.0f; |
| for (idx = 0; idx < rows * cols; ++idx) { |
| MV mv1 = mf1[idx]; |
| MV mv2 = mf2[idx]; |
| float row_diff2 = (float)((mv1.row - mv2.row) * (mv1.row - mv2.row)); |
| float col_diff2 = (float)((mv1.col - mv2.col) * (mv1.col - mv2.col)); |
| diffs[idx] = sqrt(row_diff2 + col_diff2); |
| accu += diffs[idx]; |
| } |
| *mean_ptr = accu / rows / cols; |
| *std_ptr = 0; |
| for (idx = 0; idx < rows * cols; ++idx) { |
| *std_ptr += (diffs[idx] - (*mean_ptr)) * (diffs[idx] - (*mean_ptr)); |
| } |
| *std_ptr = sqrt(*std_ptr / rows / cols); |
| free(diffs); |
| } |
| |
| static void load_frame_info(const char *filename, |
| YV12_BUFFER_CONFIG *ref_frame_ptr) { |
| FILE *input = fopen(filename, "rb"); |
| int idx; |
| uint8_t data_type; |
| |
| ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl; |
| |
| fscanf(input, "%d,%d\n", &(ref_frame_ptr->y_height), |
| &(ref_frame_ptr->y_width)); |
| |
| ref_frame_ptr->y_buffer = (uint8_t *)malloc( |
| (ref_frame_ptr->y_width) * (ref_frame_ptr->y_height) * sizeof(data_type)); |
| |
| for (idx = 0; idx < (ref_frame_ptr->y_width) * (ref_frame_ptr->y_height); |
| ++idx) { |
| int value; |
| fscanf(input, "%d,", &value); |
| ref_frame_ptr->y_buffer[idx] = (uint8_t)value; |
| } |
| |
| ref_frame_ptr->y_stride = ref_frame_ptr->y_width; |
| fclose(input); |
| } |
| |
| static int compare_local_var(const int (*local_var1)[MF_LOCAL_STRUCTURE_SIZE], |
| const int (*local_var2)[MF_LOCAL_STRUCTURE_SIZE], |
| int rows, int cols) { |
| int diff = 0; |
| int outter_idx, inner_idx; |
| for (outter_idx = 0; outter_idx < rows * cols; ++outter_idx) { |
| for (inner_idx = 0; inner_idx < MF_LOCAL_STRUCTURE_SIZE; ++inner_idx) { |
| diff += abs(local_var1[outter_idx][inner_idx] - |
| local_var2[outter_idx][inner_idx]); |
| } |
| } |
| return diff / rows / cols; |
| } |
| |
| TEST(non_greedy_mv, smooth_mf) { |
| const char *search_mf_file = "non_greedy_mv_test_files/exhaust_16x16.txt"; |
| const char *local_var_file = "non_greedy_mv_test_files/localVar_16x16.txt"; |
| const char *estimation_file = "non_greedy_mv_test_files/estimation_16x16.txt"; |
| const char *ground_truth_file = |
| "non_greedy_mv_test_files/ground_truth_16x16.txt"; |
| BLOCK_SIZE bsize = BLOCK_32X32; |
| MV *search_mf = nullptr; |
| MV *smooth_mf = nullptr; |
| MV *estimation = nullptr; |
| MV *ground_truth = nullptr; |
| int(*local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr; |
| int rows = 0, cols = 0; |
| |
| int alpha = 100, max_iter = 100; |
| |
| read_in_mf(search_mf_file, &rows, &cols, &search_mf); |
| read_in_local_var(local_var_file, &rows, &cols, &local_var); |
| read_in_mf(estimation_file, &rows, &cols, &estimation); |
| read_in_mf(ground_truth_file, &rows, &cols, &ground_truth); |
| |
| float sm_mean, sm_std; |
| float est_mean, est_std; |
| |
| smooth_mf = (MV *)malloc(rows * cols * sizeof(MV)); |
| vp9_get_smooth_motion_field(search_mf, local_var, rows, cols, bsize, alpha, |
| max_iter, smooth_mf); |
| |
| compare_mf(smooth_mf, ground_truth, rows, cols, &sm_mean, &sm_std); |
| compare_mf(smooth_mf, estimation, rows, cols, &est_mean, &est_std); |
| |
| EXPECT_LE(sm_mean, 3); |
| EXPECT_LE(est_mean, 2); |
| |
| free(search_mf); |
| free(local_var); |
| free(estimation); |
| free(ground_truth); |
| free(smooth_mf); |
| } |
| |
| TEST(non_greedy_mv, local_var) { |
| const char *ref_frame_file = "non_greedy_mv_test_files/ref_frame_16x16.txt"; |
| const char *cur_frame_file = "non_greedy_mv_test_files/cur_frame_16x16.txt"; |
| const char *gt_local_var_file = "non_greedy_mv_test_files/localVar_16x16.txt"; |
| const char *search_mf_file = "non_greedy_mv_test_files/exhaust_16x16.txt"; |
| BLOCK_SIZE bsize = BLOCK_16X16; |
| int(*gt_local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr; |
| int(*est_local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr; |
| YV12_BUFFER_CONFIG ref_frame, cur_frame; |
| int rows, cols; |
| MV *search_mf; |
| int int_type; |
| int local_var_diff; |
| vp9_variance_fn_ptr_t fn; |
| |
| load_frame_info(ref_frame_file, &ref_frame); |
| load_frame_info(cur_frame_file, &cur_frame); |
| read_in_mf(search_mf_file, &rows, &cols, &search_mf); |
| |
| fn.sdf = vpx_sad16x16; |
| est_local_var = (int(*)[MF_LOCAL_STRUCTURE_SIZE])malloc( |
| rows * cols * MF_LOCAL_STRUCTURE_SIZE * sizeof(int_type)); |
| vp9_get_local_structure(&cur_frame, &ref_frame, search_mf, &fn, rows, cols, |
| bsize, est_local_var); |
| read_in_local_var(gt_local_var_file, &rows, &cols, >_local_var); |
| |
| local_var_diff = compare_local_var(est_local_var, gt_local_var, rows, cols); |
| |
| EXPECT_LE(local_var_diff, 1); |
| |
| free(gt_local_var); |
| free(est_local_var); |
| free(ref_frame.y_buffer); |
| } |
| } // namespace |