1 /* 2 * Copyright (c) 2017 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <assert.h> 12 #include <stdio.h> 13 #include <string.h> 14 15 #include "third_party/googletest/src/include/gtest/gtest.h" 16 17 #include "./vp9_rtcd.h" 18 #include "./vpx_config.h" 19 #include "./vpx_scale_rtcd.h" 20 #include "test/clear_system_state.h" 21 #include "test/register_state_check.h" 22 #include "test/vpx_scale_test.h" 23 #include "vpx_mem/vpx_mem.h" 24 #include "vpx_ports/vpx_timer.h" 25 #include "vpx_scale/yv12config.h" 26 27 namespace libvpx_test { 28 29 typedef void (*ScaleFrameFunc)(const YV12_BUFFER_CONFIG *src, 30 YV12_BUFFER_CONFIG *dst, 31 INTERP_FILTER filter_type, int phase_scaler); 32 33 class ScaleTest : public VpxScaleBase, 34 public ::testing::TestWithParam<ScaleFrameFunc> { 35 public: 36 virtual ~ScaleTest() {} 37 38 protected: 39 virtual void SetUp() { scale_fn_ = GetParam(); } 40 41 void ReferenceScaleFrame(INTERP_FILTER filter_type, int phase_scaler) { 42 vp9_scale_and_extend_frame_c(&img_, &ref_img_, filter_type, phase_scaler); 43 } 44 45 void ScaleFrame(INTERP_FILTER filter_type, int phase_scaler) { 46 ASM_REGISTER_STATE_CHECK( 47 scale_fn_(&img_, &dst_img_, filter_type, phase_scaler)); 48 } 49 50 void RunTest() { 51 static const int kNumSizesToTest = 20; 52 static const int kNumScaleFactorsToTest = 4; 53 static const int kSizesToTest[] = { 54 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 55 22, 24, 26, 28, 30, 32, 34, 68, 128, 134 56 }; 57 static const int kScaleFactors[] = { 1, 2, 3, 4 }; 58 for (INTERP_FILTER filter_type = 0; filter_type < 4; ++filter_type) { 59 for (int phase_scaler = 0; phase_scaler < 16; ++phase_scaler) { 60 for (int h = 0; h < kNumSizesToTest; ++h) { 61 const int src_height = kSizesToTest[h]; 62 for (int w = 0; w < kNumSizesToTest; ++w) { 63 const int src_width = kSizesToTest[w]; 64 for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest; 65 ++sf_up_idx) { 66 const int sf_up = kScaleFactors[sf_up_idx]; 67 for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest; 68 ++sf_down_idx) { 69 const int sf_down = kScaleFactors[sf_down_idx]; 70 const int dst_width = src_width * sf_up / sf_down; 71 const int dst_height = src_height * sf_up / sf_down; 72 if (sf_up == sf_down && sf_up != 1) { 73 continue; 74 } 75 // I420 frame width and height must be even. 76 if (!dst_width || !dst_height || dst_width & 1 || 77 dst_height & 1) { 78 continue; 79 } 80 // vpx_convolve8_c() has restriction on the step which cannot 81 // exceed 64 (ratio 1 to 4). 82 if (src_width > 4 * dst_width || src_height > 4 * dst_height) { 83 continue; 84 } 85 ASSERT_NO_FATAL_FAILURE(ResetScaleImages( 86 src_width, src_height, dst_width, dst_height)); 87 ReferenceScaleFrame(filter_type, phase_scaler); 88 ScaleFrame(filter_type, phase_scaler); 89 if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc, 90 ref_img_.frame_size)) { 91 printf( 92 "filter_type = %d, phase_scaler = %d, src_width = %4d, " 93 "src_height = %4d, dst_width = %4d, dst_height = %4d, " 94 "scale factor = %d:%d\n", 95 filter_type, phase_scaler, src_width, src_height, 96 dst_width, dst_height, sf_down, sf_up); 97 PrintDiff(); 98 } 99 CompareImages(dst_img_); 100 DeallocScaleImages(); 101 } 102 } 103 } 104 } 105 } 106 } 107 } 108 109 void PrintDiffComponent(const uint8_t *const ref, const uint8_t *const opt, 110 const int stride, const int width, const int height, 111 const int plane_idx) const { 112 for (int y = 0; y < height; y++) { 113 for (int x = 0; x < width; x++) { 114 if (ref[y * stride + x] != opt[y * stride + x]) { 115 printf("Plane %d pixel[%d][%d] diff:%6d (ref),%6d (opt)\n", plane_idx, 116 y, x, ref[y * stride + x], opt[y * stride + x]); 117 break; 118 } 119 } 120 } 121 } 122 123 void PrintDiff() const { 124 assert(ref_img_.y_stride == dst_img_.y_stride); 125 assert(ref_img_.y_width == dst_img_.y_width); 126 assert(ref_img_.y_height == dst_img_.y_height); 127 assert(ref_img_.uv_stride == dst_img_.uv_stride); 128 assert(ref_img_.uv_width == dst_img_.uv_width); 129 assert(ref_img_.uv_height == dst_img_.uv_height); 130 131 if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc, 132 ref_img_.frame_size)) { 133 PrintDiffComponent(ref_img_.y_buffer, dst_img_.y_buffer, 134 ref_img_.y_stride, ref_img_.y_width, ref_img_.y_height, 135 0); 136 PrintDiffComponent(ref_img_.u_buffer, dst_img_.u_buffer, 137 ref_img_.uv_stride, ref_img_.uv_width, 138 ref_img_.uv_height, 1); 139 PrintDiffComponent(ref_img_.v_buffer, dst_img_.v_buffer, 140 ref_img_.uv_stride, ref_img_.uv_width, 141 ref_img_.uv_height, 2); 142 } 143 } 144 145 ScaleFrameFunc scale_fn_; 146 }; 147 148 TEST_P(ScaleTest, ScaleFrame) { ASSERT_NO_FATAL_FAILURE(RunTest()); } 149 150 TEST_P(ScaleTest, DISABLED_Speed) { 151 static const int kCountSpeedTestBlock = 100; 152 static const int kNumScaleFactorsToTest = 4; 153 static const int kScaleFactors[] = { 1, 2, 3, 4 }; 154 const int src_width = 1280; 155 const int src_height = 720; 156 for (INTERP_FILTER filter_type = 2; filter_type < 4; ++filter_type) { 157 for (int phase_scaler = 0; phase_scaler < 2; ++phase_scaler) { 158 for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest; ++sf_up_idx) { 159 const int sf_up = kScaleFactors[sf_up_idx]; 160 for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest; 161 ++sf_down_idx) { 162 const int sf_down = kScaleFactors[sf_down_idx]; 163 const int dst_width = src_width * sf_up / sf_down; 164 const int dst_height = src_height * sf_up / sf_down; 165 if (sf_up == sf_down && sf_up != 1) { 166 continue; 167 } 168 // I420 frame width and height must be even. 169 if (dst_width & 1 || dst_height & 1) { 170 continue; 171 } 172 ASSERT_NO_FATAL_FAILURE( 173 ResetScaleImages(src_width, src_height, dst_width, dst_height)); 174 ASM_REGISTER_STATE_CHECK( 175 ReferenceScaleFrame(filter_type, phase_scaler)); 176 177 vpx_usec_timer timer; 178 vpx_usec_timer_start(&timer); 179 for (int i = 0; i < kCountSpeedTestBlock; ++i) { 180 ScaleFrame(filter_type, phase_scaler); 181 } 182 libvpx_test::ClearSystemState(); 183 vpx_usec_timer_mark(&timer); 184 const int elapsed_time = 185 static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000); 186 CompareImages(dst_img_); 187 DeallocScaleImages(); 188 189 printf( 190 "filter_type = %d, phase_scaler = %d, src_width = %4d, " 191 "src_height = %4d, dst_width = %4d, dst_height = %4d, " 192 "scale factor = %d:%d, scale time: %5d ms\n", 193 filter_type, phase_scaler, src_width, src_height, dst_width, 194 dst_height, sf_down, sf_up, elapsed_time); 195 } 196 } 197 } 198 } 199 } 200 201 INSTANTIATE_TEST_CASE_P(C, ScaleTest, 202 ::testing::Values(vp9_scale_and_extend_frame_c)); 203 204 #if HAVE_SSSE3 205 INSTANTIATE_TEST_CASE_P(SSSE3, ScaleTest, 206 ::testing::Values(vp9_scale_and_extend_frame_ssse3)); 207 #endif // HAVE_SSSE3 208 209 #if HAVE_NEON 210 INSTANTIATE_TEST_CASE_P(NEON, ScaleTest, 211 ::testing::Values(vp9_scale_and_extend_frame_neon)); 212 #endif // HAVE_NEON 213 214 } // namespace libvpx_test 215