vpx_scale_test.h 7.03 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
/*
 *  Copyright (c) 2014 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.
 */

#ifndef TEST_VPX_SCALE_TEST_H_
#define TEST_VPX_SCALE_TEST_H_

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

#include "./vpx_config.h"
#include "./vpx_scale_rtcd.h"
18
#include "test/acm_random.h"
Linfeng Zhang's avatar
Linfeng Zhang committed
19 20 21 22 23
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_scale/yv12config.h"

24 25
using libvpx_test::ACMRandom;

Linfeng Zhang's avatar
Linfeng Zhang committed
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 51 52 53 54 55 56
namespace libvpx_test {

class VpxScaleBase {
 public:
  virtual ~VpxScaleBase() { libvpx_test::ClearSystemState(); }

  void ResetImage(YV12_BUFFER_CONFIG *const img, const int width,
                  const int height) {
    memset(img, 0, sizeof(*img));
    ASSERT_EQ(
        0, vp8_yv12_alloc_frame_buffer(img, width, height, VP8BORDERINPIXELS));
    memset(img->buffer_alloc, kBufFiller, img->frame_size);
  }

  void ResetImages(const int width, const int height) {
    ResetImage(&img_, width, height);
    ResetImage(&ref_img_, width, height);
    ResetImage(&dst_img_, width, height);

    FillPlane(img_.y_buffer, img_.y_crop_width, img_.y_crop_height,
              img_.y_stride);
    FillPlane(img_.u_buffer, img_.uv_crop_width, img_.uv_crop_height,
              img_.uv_stride);
    FillPlane(img_.v_buffer, img_.uv_crop_width, img_.uv_crop_height,
              img_.uv_stride);
  }

  void ResetScaleImage(YV12_BUFFER_CONFIG *const img, const int width,
                       const int height) {
    memset(img, 0, sizeof(*img));
#if CONFIG_VP9_HIGHBITDEPTH
57
    ASSERT_EQ(0, vpx_alloc_frame_buffer(img, width, height, 1, 1, 0,
Linfeng Zhang's avatar
Linfeng Zhang committed
58
                                        VP9_ENC_BORDER_IN_PIXELS, 0));
59 60 61 62
#else
    ASSERT_EQ(0, vpx_alloc_frame_buffer(img, width, height, 1, 1,
                                        VP9_ENC_BORDER_IN_PIXELS, 0));
#endif
Linfeng Zhang's avatar
Linfeng Zhang committed
63 64 65 66 67 68 69 70
    memset(img->buffer_alloc, kBufFiller, img->frame_size);
  }

  void ResetScaleImages(const int src_width, const int src_height,
                        const int dst_width, const int dst_height) {
    ResetScaleImage(&img_, src_width, src_height);
    ResetScaleImage(&ref_img_, dst_width, dst_height);
    ResetScaleImage(&dst_img_, dst_width, dst_height);
71 72 73 74 75 76
    FillPlaneExtreme(img_.y_buffer, img_.y_crop_width, img_.y_crop_height,
                     img_.y_stride);
    FillPlaneExtreme(img_.u_buffer, img_.uv_crop_width, img_.uv_crop_height,
                     img_.uv_stride);
    FillPlaneExtreme(img_.v_buffer, img_.uv_crop_width, img_.uv_crop_height,
                     img_.uv_stride);
Linfeng Zhang's avatar
Linfeng Zhang committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
  }

  void DeallocImages() {
    vp8_yv12_de_alloc_frame_buffer(&img_);
    vp8_yv12_de_alloc_frame_buffer(&ref_img_);
    vp8_yv12_de_alloc_frame_buffer(&dst_img_);
  }

  void DeallocScaleImages() {
    vpx_free_frame_buffer(&img_);
    vpx_free_frame_buffer(&ref_img_);
    vpx_free_frame_buffer(&dst_img_);
  }

 protected:
  static const int kBufFiller = 123;
  static const int kBufMax = kBufFiller - 1;

95 96
  static void FillPlane(uint8_t *const buf, const int width, const int height,
                        const int stride) {
Linfeng Zhang's avatar
Linfeng Zhang committed
97 98 99 100 101 102 103
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        buf[x + (y * stride)] = (x + (width * y)) % kBufMax;
      }
    }
  }

104 105 106 107 108 109 110 111 112 113
  static void FillPlaneExtreme(uint8_t *const buf, const int width,
                               const int height, const int stride) {
    ACMRandom rnd;
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        buf[x + (y * stride)] = rnd.Rand8() % 2 ? 255 : 0;
      }
    }
  }

Linfeng Zhang's avatar
Linfeng Zhang committed
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 152 153 154 155 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
  static void ExtendPlane(uint8_t *buf, int crop_width, int crop_height,
                          int width, int height, int stride, int padding) {
    // Copy the outermost visible pixel to a distance of at least 'padding.'
    // The buffers are allocated such that there may be excess space outside the
    // padding. As long as the minimum amount of padding is achieved it is not
    // necessary to fill this space as well.
    uint8_t *left = buf - padding;
    uint8_t *right = buf + crop_width;
    const int right_extend = padding + (width - crop_width);
    const int bottom_extend = padding + (height - crop_height);

    // Fill the border pixels from the nearest image pixel.
    for (int y = 0; y < crop_height; ++y) {
      memset(left, left[padding], padding);
      memset(right, right[-1], right_extend);
      left += stride;
      right += stride;
    }

    left = buf - padding;
    uint8_t *top = left - (stride * padding);
    // The buffer does not always extend as far as the stride.
    // Equivalent to padding + width + padding.
    const int extend_width = padding + crop_width + right_extend;

    // The first row was already extended to the left and right. Copy it up.
    for (int y = 0; y < padding; ++y) {
      memcpy(top, left, extend_width);
      top += stride;
    }

    uint8_t *bottom = left + (crop_height * stride);
    for (int y = 0; y < bottom_extend; ++y) {
      memcpy(bottom, left + (crop_height - 1) * stride, extend_width);
      bottom += stride;
    }
  }

  void ReferenceExtendBorder() {
    ExtendPlane(ref_img_.y_buffer, ref_img_.y_crop_width,
                ref_img_.y_crop_height, ref_img_.y_width, ref_img_.y_height,
                ref_img_.y_stride, ref_img_.border);
    ExtendPlane(ref_img_.u_buffer, ref_img_.uv_crop_width,
                ref_img_.uv_crop_height, ref_img_.uv_width, ref_img_.uv_height,
                ref_img_.uv_stride, ref_img_.border / 2);
    ExtendPlane(ref_img_.v_buffer, ref_img_.uv_crop_width,
                ref_img_.uv_crop_height, ref_img_.uv_width, ref_img_.uv_height,
                ref_img_.uv_stride, ref_img_.border / 2);
  }

  void ReferenceCopyFrame() {
    // Copy img_ to ref_img_ and extend frame borders. This will be used for
    // verifying extend_fn_ as well as copy_frame_fn_.
    EXPECT_EQ(ref_img_.frame_size, img_.frame_size);
    for (int y = 0; y < img_.y_crop_height; ++y) {
      for (int x = 0; x < img_.y_crop_width; ++x) {
        ref_img_.y_buffer[x + y * ref_img_.y_stride] =
            img_.y_buffer[x + y * img_.y_stride];
      }
    }

    for (int y = 0; y < img_.uv_crop_height; ++y) {
      for (int x = 0; x < img_.uv_crop_width; ++x) {
        ref_img_.u_buffer[x + y * ref_img_.uv_stride] =
            img_.u_buffer[x + y * img_.uv_stride];
        ref_img_.v_buffer[x + y * ref_img_.uv_stride] =
            img_.v_buffer[x + y * img_.uv_stride];
      }
    }

    ReferenceExtendBorder();
  }

  void CompareImages(const YV12_BUFFER_CONFIG actual) {
    EXPECT_EQ(ref_img_.frame_size, actual.frame_size);
    EXPECT_EQ(0, memcmp(ref_img_.buffer_alloc, actual.buffer_alloc,
                        ref_img_.frame_size));
  }

  YV12_BUFFER_CONFIG img_;
  YV12_BUFFER_CONFIG ref_img_;
  YV12_BUFFER_CONFIG dst_img_;
};

}  // namespace libvpx_test

#endif  // TEST_VPX_SCALE_TEST_H_