vp9_scale_test.cc 8.14 KB
Newer Older
Linfeng Zhang's avatar
Linfeng Zhang committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/*
 *  Copyright (c) 2017 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 <assert.h>
#include <stdio.h>
#include <string.h>

#include "third_party/googletest/src/include/gtest/gtest.h"

#include "./vp9_rtcd.h"
#include "./vpx_config.h"
#include "./vpx_scale_rtcd.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/vpx_scale_test.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/vpx_timer.h"
#include "vpx_scale/yv12config.h"

namespace libvpx_test {

typedef void (*ScaleFrameFunc)(const YV12_BUFFER_CONFIG *src,
                               YV12_BUFFER_CONFIG *dst,
                               INTERP_FILTER filter_type, int phase_scaler);

class ScaleTest : public VpxScaleBase,
                  public ::testing::TestWithParam<ScaleFrameFunc> {
 public:
  virtual ~ScaleTest() {}

 protected:
  virtual void SetUp() { scale_fn_ = GetParam(); }

  void ReferenceScaleFrame(INTERP_FILTER filter_type, int phase_scaler) {
    vp9_scale_and_extend_frame_c(&img_, &ref_img_, filter_type, phase_scaler);
  }

  void ScaleFrame(INTERP_FILTER filter_type, int phase_scaler) {
    ASM_REGISTER_STATE_CHECK(
        scale_fn_(&img_, &dst_img_, filter_type, phase_scaler));
  }

  void RunTest() {
51
    static const int kNumSizesToTest = 20;
52
    static const int kNumScaleFactorsToTest = 4;
53 54 55 56
    static const int kSizesToTest[] = {
      2,  4,  6,  8,  10, 12, 14, 16, 18,  20,
      22, 24, 26, 28, 30, 32, 34, 68, 128, 134
    };
57
    static const int kScaleFactors[] = { 1, 2, 3, 4 };
Linfeng Zhang's avatar
Linfeng Zhang committed
58 59 60
    for (INTERP_FILTER filter_type = 0; filter_type < 4; ++filter_type) {
      for (int phase_scaler = 0; phase_scaler < 16; ++phase_scaler) {
        for (int h = 0; h < kNumSizesToTest; ++h) {
61
          const int src_height = kSizesToTest[h];
Linfeng Zhang's avatar
Linfeng Zhang committed
62
          for (int w = 0; w < kNumSizesToTest; ++w) {
63
            const int src_width = kSizesToTest[w];
Linfeng Zhang's avatar
Linfeng Zhang committed
64 65 66 67 68 69 70 71 72 73 74 75
            for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest;
                 ++sf_up_idx) {
              const int sf_up = kScaleFactors[sf_up_idx];
              for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest;
                   ++sf_down_idx) {
                const int sf_down = kScaleFactors[sf_down_idx];
                const int dst_width = src_width * sf_up / sf_down;
                const int dst_height = src_height * sf_up / sf_down;
                if (sf_up == sf_down && sf_up != 1) {
                  continue;
                }
                // I420 frame width and height must be even.
76 77 78 79 80 81 82
                if (!dst_width || !dst_height || dst_width & 1 ||
                    dst_height & 1) {
                  continue;
                }
                // vpx_convolve8_c() has restriction on the step which cannot
                // exceed 64 (ratio 1 to 4).
                if (src_width > 4 * dst_width || src_height > 4 * dst_height) {
Linfeng Zhang's avatar
Linfeng Zhang committed
83 84 85 86 87 88
                  continue;
                }
                ASSERT_NO_FATAL_FAILURE(ResetScaleImages(
                    src_width, src_height, dst_width, dst_height));
                ReferenceScaleFrame(filter_type, phase_scaler);
                ScaleFrame(filter_type, phase_scaler);
89 90 91 92 93 94 95 96 97 98
                if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc,
                           ref_img_.frame_size)) {
                  printf(
                      "filter_type = %d, phase_scaler = %d, src_width = %4d, "
                      "src_height = %4d, dst_width = %4d, dst_height = %4d, "
                      "scale factor = %d:%d\n",
                      filter_type, phase_scaler, src_width, src_height,
                      dst_width, dst_height, sf_down, sf_up);
                  PrintDiff();
                }
Linfeng Zhang's avatar
Linfeng Zhang committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
                CompareImages(dst_img_);
                DeallocScaleImages();
              }
            }
          }
        }
      }
    }
  }

  void PrintDiffComponent(const uint8_t *const ref, const uint8_t *const opt,
                          const int stride, const int width, const int height,
                          const int plane_idx) const {
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        if (ref[y * stride + x] != opt[y * stride + x]) {
          printf("Plane %d pixel[%d][%d] diff:%6d (ref),%6d (opt)\n", plane_idx,
                 y, x, ref[y * stride + x], opt[y * stride + x]);
          break;
        }
      }
    }
  }

  void PrintDiff() const {
    assert(ref_img_.y_stride == dst_img_.y_stride);
    assert(ref_img_.y_width == dst_img_.y_width);
    assert(ref_img_.y_height == dst_img_.y_height);
    assert(ref_img_.uv_stride == dst_img_.uv_stride);
    assert(ref_img_.uv_width == dst_img_.uv_width);
    assert(ref_img_.uv_height == dst_img_.uv_height);

    if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc,
               ref_img_.frame_size)) {
      PrintDiffComponent(ref_img_.y_buffer, dst_img_.y_buffer,
                         ref_img_.y_stride, ref_img_.y_width, ref_img_.y_height,
                         0);
      PrintDiffComponent(ref_img_.u_buffer, dst_img_.u_buffer,
                         ref_img_.uv_stride, ref_img_.uv_width,
                         ref_img_.uv_height, 1);
      PrintDiffComponent(ref_img_.v_buffer, dst_img_.v_buffer,
                         ref_img_.uv_stride, ref_img_.uv_width,
                         ref_img_.uv_height, 2);
    }
  }

  ScaleFrameFunc scale_fn_;
};

TEST_P(ScaleTest, ScaleFrame) { ASSERT_NO_FATAL_FAILURE(RunTest()); }

TEST_P(ScaleTest, DISABLED_Speed) {
  static const int kCountSpeedTestBlock = 100;
152 153
  static const int kNumScaleFactorsToTest = 4;
  static const int kScaleFactors[] = { 1, 2, 3, 4 };
154 155
  const int src_width = 1280;
  const int src_height = 720;
Linfeng Zhang's avatar
Linfeng Zhang committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
  for (INTERP_FILTER filter_type = 2; filter_type < 4; ++filter_type) {
    for (int phase_scaler = 0; phase_scaler < 2; ++phase_scaler) {
      for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest; ++sf_up_idx) {
        const int sf_up = kScaleFactors[sf_up_idx];
        for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest;
             ++sf_down_idx) {
          const int sf_down = kScaleFactors[sf_down_idx];
          const int dst_width = src_width * sf_up / sf_down;
          const int dst_height = src_height * sf_up / sf_down;
          if (sf_up == sf_down && sf_up != 1) {
            continue;
          }
          // I420 frame width and height must be even.
          if (dst_width & 1 || dst_height & 1) {
            continue;
          }
          ASSERT_NO_FATAL_FAILURE(
              ResetScaleImages(src_width, src_height, dst_width, dst_height));
          ASM_REGISTER_STATE_CHECK(
              ReferenceScaleFrame(filter_type, phase_scaler));

          vpx_usec_timer timer;
          vpx_usec_timer_start(&timer);
          for (int i = 0; i < kCountSpeedTestBlock; ++i) {
            ScaleFrame(filter_type, phase_scaler);
          }
          libvpx_test::ClearSystemState();
          vpx_usec_timer_mark(&timer);
          const int elapsed_time =
              static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
          CompareImages(dst_img_);
          DeallocScaleImages();

          printf(
              "filter_type = %d, phase_scaler = %d, src_width = %4d, "
              "src_height = %4d, dst_width = %4d, dst_height = %4d, "
              "scale factor = %d:%d, scale time: %5d ms\n",
              filter_type, phase_scaler, src_width, src_height, dst_width,
              dst_height, sf_down, sf_up, elapsed_time);
        }
      }
    }
  }
}

201 202 203
INSTANTIATE_TEST_CASE_P(C, ScaleTest,
                        ::testing::Values(vp9_scale_and_extend_frame_c));

Linfeng Zhang's avatar
Linfeng Zhang committed
204 205 206 207 208
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, ScaleTest,
                        ::testing::Values(vp9_scale_and_extend_frame_ssse3));
#endif  // HAVE_SSSE3

209 210 211 212 213
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, ScaleTest,
                        ::testing::Values(vp9_scale_and_extend_frame_neon));
#endif  // HAVE_NEON

Linfeng Zhang's avatar
Linfeng Zhang committed
214
}  // namespace libvpx_test