1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2012 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 <limits.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <tuple>
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker #include "gtest/gtest.h"
17*fb1b10abSAndroid Build Coastguard Worker
18*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
19*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
20*fb1b10abSAndroid Build Coastguard Worker #include "./vp9_rtcd.h"
21*fb1b10abSAndroid Build Coastguard Worker #endif
22*fb1b10abSAndroid Build Coastguard Worker
23*fb1b10abSAndroid Build Coastguard Worker #include "test/acm_random.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "test/clear_system_state.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "test/register_state_check.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "test/util.h"
27*fb1b10abSAndroid Build Coastguard Worker
28*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
29*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_blockiness.h"
30*fb1b10abSAndroid Build Coastguard Worker
31*fb1b10abSAndroid Build Coastguard Worker using libvpx_test::ACMRandom;
32*fb1b10abSAndroid Build Coastguard Worker
33*fb1b10abSAndroid Build Coastguard Worker namespace {
34*fb1b10abSAndroid Build Coastguard Worker class BlockinessTestBase : public ::testing::Test {
35*fb1b10abSAndroid Build Coastguard Worker public:
BlockinessTestBase(int width,int height)36*fb1b10abSAndroid Build Coastguard Worker BlockinessTestBase(int width, int height) : width_(width), height_(height) {}
37*fb1b10abSAndroid Build Coastguard Worker
SetUpTestSuite()38*fb1b10abSAndroid Build Coastguard Worker static void SetUpTestSuite() {
39*fb1b10abSAndroid Build Coastguard Worker source_data_ = reinterpret_cast<uint8_t *>(
40*fb1b10abSAndroid Build Coastguard Worker vpx_memalign(kDataAlignment, kDataBufferSize));
41*fb1b10abSAndroid Build Coastguard Worker reference_data_ = reinterpret_cast<uint8_t *>(
42*fb1b10abSAndroid Build Coastguard Worker vpx_memalign(kDataAlignment, kDataBufferSize));
43*fb1b10abSAndroid Build Coastguard Worker }
44*fb1b10abSAndroid Build Coastguard Worker
TearDownTestSuite()45*fb1b10abSAndroid Build Coastguard Worker static void TearDownTestSuite() {
46*fb1b10abSAndroid Build Coastguard Worker vpx_free(source_data_);
47*fb1b10abSAndroid Build Coastguard Worker source_data_ = nullptr;
48*fb1b10abSAndroid Build Coastguard Worker vpx_free(reference_data_);
49*fb1b10abSAndroid Build Coastguard Worker reference_data_ = nullptr;
50*fb1b10abSAndroid Build Coastguard Worker }
51*fb1b10abSAndroid Build Coastguard Worker
TearDown()52*fb1b10abSAndroid Build Coastguard Worker void TearDown() override { libvpx_test::ClearSystemState(); }
53*fb1b10abSAndroid Build Coastguard Worker
54*fb1b10abSAndroid Build Coastguard Worker protected:
55*fb1b10abSAndroid Build Coastguard Worker // Handle frames up to 640x480
56*fb1b10abSAndroid Build Coastguard Worker static const int kDataAlignment = 16;
57*fb1b10abSAndroid Build Coastguard Worker static const int kDataBufferSize = 640 * 480;
58*fb1b10abSAndroid Build Coastguard Worker
SetUp()59*fb1b10abSAndroid Build Coastguard Worker void SetUp() override {
60*fb1b10abSAndroid Build Coastguard Worker source_stride_ = (width_ + 31) & ~31;
61*fb1b10abSAndroid Build Coastguard Worker reference_stride_ = width_ * 2;
62*fb1b10abSAndroid Build Coastguard Worker rnd_.Reset(ACMRandom::DeterministicSeed());
63*fb1b10abSAndroid Build Coastguard Worker }
64*fb1b10abSAndroid Build Coastguard Worker
FillConstant(uint8_t * data,int stride,uint8_t fill_constant,int width,int height)65*fb1b10abSAndroid Build Coastguard Worker void FillConstant(uint8_t *data, int stride, uint8_t fill_constant, int width,
66*fb1b10abSAndroid Build Coastguard Worker int height) {
67*fb1b10abSAndroid Build Coastguard Worker for (int h = 0; h < height; ++h) {
68*fb1b10abSAndroid Build Coastguard Worker for (int w = 0; w < width; ++w) {
69*fb1b10abSAndroid Build Coastguard Worker data[h * stride + w] = fill_constant;
70*fb1b10abSAndroid Build Coastguard Worker }
71*fb1b10abSAndroid Build Coastguard Worker }
72*fb1b10abSAndroid Build Coastguard Worker }
73*fb1b10abSAndroid Build Coastguard Worker
FillConstant(uint8_t * data,int stride,uint8_t fill_constant)74*fb1b10abSAndroid Build Coastguard Worker void FillConstant(uint8_t *data, int stride, uint8_t fill_constant) {
75*fb1b10abSAndroid Build Coastguard Worker FillConstant(data, stride, fill_constant, width_, height_);
76*fb1b10abSAndroid Build Coastguard Worker }
77*fb1b10abSAndroid Build Coastguard Worker
FillRandom(uint8_t * data,int stride,int width,int height)78*fb1b10abSAndroid Build Coastguard Worker void FillRandom(uint8_t *data, int stride, int width, int height) {
79*fb1b10abSAndroid Build Coastguard Worker for (int h = 0; h < height; ++h) {
80*fb1b10abSAndroid Build Coastguard Worker for (int w = 0; w < width; ++w) {
81*fb1b10abSAndroid Build Coastguard Worker data[h * stride + w] = rnd_.Rand8();
82*fb1b10abSAndroid Build Coastguard Worker }
83*fb1b10abSAndroid Build Coastguard Worker }
84*fb1b10abSAndroid Build Coastguard Worker }
85*fb1b10abSAndroid Build Coastguard Worker
FillRandom(uint8_t * data,int stride)86*fb1b10abSAndroid Build Coastguard Worker void FillRandom(uint8_t *data, int stride) {
87*fb1b10abSAndroid Build Coastguard Worker FillRandom(data, stride, width_, height_);
88*fb1b10abSAndroid Build Coastguard Worker }
89*fb1b10abSAndroid Build Coastguard Worker
FillRandomBlocky(uint8_t * data,int stride)90*fb1b10abSAndroid Build Coastguard Worker void FillRandomBlocky(uint8_t *data, int stride) {
91*fb1b10abSAndroid Build Coastguard Worker for (int h = 0; h < height_; h += 4) {
92*fb1b10abSAndroid Build Coastguard Worker for (int w = 0; w < width_; w += 4) {
93*fb1b10abSAndroid Build Coastguard Worker FillRandom(data + h * stride + w, stride, 4, 4);
94*fb1b10abSAndroid Build Coastguard Worker }
95*fb1b10abSAndroid Build Coastguard Worker }
96*fb1b10abSAndroid Build Coastguard Worker }
97*fb1b10abSAndroid Build Coastguard Worker
FillCheckerboard(uint8_t * data,int stride)98*fb1b10abSAndroid Build Coastguard Worker void FillCheckerboard(uint8_t *data, int stride) {
99*fb1b10abSAndroid Build Coastguard Worker for (int h = 0; h < height_; h += 4) {
100*fb1b10abSAndroid Build Coastguard Worker for (int w = 0; w < width_; w += 4) {
101*fb1b10abSAndroid Build Coastguard Worker if (((h / 4) ^ (w / 4)) & 1) {
102*fb1b10abSAndroid Build Coastguard Worker FillConstant(data + h * stride + w, stride, 255, 4, 4);
103*fb1b10abSAndroid Build Coastguard Worker } else {
104*fb1b10abSAndroid Build Coastguard Worker FillConstant(data + h * stride + w, stride, 0, 4, 4);
105*fb1b10abSAndroid Build Coastguard Worker }
106*fb1b10abSAndroid Build Coastguard Worker }
107*fb1b10abSAndroid Build Coastguard Worker }
108*fb1b10abSAndroid Build Coastguard Worker }
109*fb1b10abSAndroid Build Coastguard Worker
Blur(uint8_t * data,int stride,int taps)110*fb1b10abSAndroid Build Coastguard Worker void Blur(uint8_t *data, int stride, int taps) {
111*fb1b10abSAndroid Build Coastguard Worker int sum = 0;
112*fb1b10abSAndroid Build Coastguard Worker int half_taps = taps / 2;
113*fb1b10abSAndroid Build Coastguard Worker for (int h = 0; h < height_; ++h) {
114*fb1b10abSAndroid Build Coastguard Worker for (int w = 0; w < taps; ++w) {
115*fb1b10abSAndroid Build Coastguard Worker sum += data[w + h * stride];
116*fb1b10abSAndroid Build Coastguard Worker }
117*fb1b10abSAndroid Build Coastguard Worker for (int w = taps; w < width_; ++w) {
118*fb1b10abSAndroid Build Coastguard Worker sum += data[w + h * stride] - data[w - taps + h * stride];
119*fb1b10abSAndroid Build Coastguard Worker data[w - half_taps + h * stride] = (sum + half_taps) / taps;
120*fb1b10abSAndroid Build Coastguard Worker }
121*fb1b10abSAndroid Build Coastguard Worker }
122*fb1b10abSAndroid Build Coastguard Worker for (int w = 0; w < width_; ++w) {
123*fb1b10abSAndroid Build Coastguard Worker for (int h = 0; h < taps; ++h) {
124*fb1b10abSAndroid Build Coastguard Worker sum += data[h + w * stride];
125*fb1b10abSAndroid Build Coastguard Worker }
126*fb1b10abSAndroid Build Coastguard Worker for (int h = taps; h < height_; ++h) {
127*fb1b10abSAndroid Build Coastguard Worker sum += data[w + h * stride] - data[(h - taps) * stride + w];
128*fb1b10abSAndroid Build Coastguard Worker data[(h - half_taps) * stride + w] = (sum + half_taps) / taps;
129*fb1b10abSAndroid Build Coastguard Worker }
130*fb1b10abSAndroid Build Coastguard Worker }
131*fb1b10abSAndroid Build Coastguard Worker }
132*fb1b10abSAndroid Build Coastguard Worker int width_, height_;
133*fb1b10abSAndroid Build Coastguard Worker static uint8_t *source_data_;
134*fb1b10abSAndroid Build Coastguard Worker int source_stride_;
135*fb1b10abSAndroid Build Coastguard Worker static uint8_t *reference_data_;
136*fb1b10abSAndroid Build Coastguard Worker int reference_stride_;
137*fb1b10abSAndroid Build Coastguard Worker
138*fb1b10abSAndroid Build Coastguard Worker ACMRandom rnd_;
139*fb1b10abSAndroid Build Coastguard Worker };
140*fb1b10abSAndroid Build Coastguard Worker
141*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
142*fb1b10abSAndroid Build Coastguard Worker typedef std::tuple<int, int> BlockinessParam;
143*fb1b10abSAndroid Build Coastguard Worker class BlockinessVP9Test
144*fb1b10abSAndroid Build Coastguard Worker : public BlockinessTestBase,
145*fb1b10abSAndroid Build Coastguard Worker public ::testing::WithParamInterface<BlockinessParam> {
146*fb1b10abSAndroid Build Coastguard Worker public:
BlockinessVP9Test()147*fb1b10abSAndroid Build Coastguard Worker BlockinessVP9Test() : BlockinessTestBase(GET_PARAM(0), GET_PARAM(1)) {}
148*fb1b10abSAndroid Build Coastguard Worker
149*fb1b10abSAndroid Build Coastguard Worker protected:
GetBlockiness() const150*fb1b10abSAndroid Build Coastguard Worker double GetBlockiness() const {
151*fb1b10abSAndroid Build Coastguard Worker return vp9_get_blockiness(source_data_, source_stride_, reference_data_,
152*fb1b10abSAndroid Build Coastguard Worker reference_stride_, width_, height_);
153*fb1b10abSAndroid Build Coastguard Worker }
154*fb1b10abSAndroid Build Coastguard Worker };
155*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_ENCODER
156*fb1b10abSAndroid Build Coastguard Worker
157*fb1b10abSAndroid Build Coastguard Worker uint8_t *BlockinessTestBase::source_data_ = nullptr;
158*fb1b10abSAndroid Build Coastguard Worker uint8_t *BlockinessTestBase::reference_data_ = nullptr;
159*fb1b10abSAndroid Build Coastguard Worker
160*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
TEST_P(BlockinessVP9Test,SourceBlockierThanReference)161*fb1b10abSAndroid Build Coastguard Worker TEST_P(BlockinessVP9Test, SourceBlockierThanReference) {
162*fb1b10abSAndroid Build Coastguard Worker // Source is blockier than reference.
163*fb1b10abSAndroid Build Coastguard Worker FillRandomBlocky(source_data_, source_stride_);
164*fb1b10abSAndroid Build Coastguard Worker FillConstant(reference_data_, reference_stride_, 128);
165*fb1b10abSAndroid Build Coastguard Worker const double super_blocky = GetBlockiness();
166*fb1b10abSAndroid Build Coastguard Worker
167*fb1b10abSAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, super_blocky)
168*fb1b10abSAndroid Build Coastguard Worker << "Blocky source should produce 0 blockiness.";
169*fb1b10abSAndroid Build Coastguard Worker }
170*fb1b10abSAndroid Build Coastguard Worker
TEST_P(BlockinessVP9Test,ReferenceBlockierThanSource)171*fb1b10abSAndroid Build Coastguard Worker TEST_P(BlockinessVP9Test, ReferenceBlockierThanSource) {
172*fb1b10abSAndroid Build Coastguard Worker // Source is blockier than reference.
173*fb1b10abSAndroid Build Coastguard Worker FillConstant(source_data_, source_stride_, 128);
174*fb1b10abSAndroid Build Coastguard Worker FillRandomBlocky(reference_data_, reference_stride_);
175*fb1b10abSAndroid Build Coastguard Worker const double super_blocky = GetBlockiness();
176*fb1b10abSAndroid Build Coastguard Worker
177*fb1b10abSAndroid Build Coastguard Worker EXPECT_GT(super_blocky, 0.0)
178*fb1b10abSAndroid Build Coastguard Worker << "Blocky reference should score high for blockiness.";
179*fb1b10abSAndroid Build Coastguard Worker }
180*fb1b10abSAndroid Build Coastguard Worker
TEST_P(BlockinessVP9Test,BlurringDecreasesBlockiness)181*fb1b10abSAndroid Build Coastguard Worker TEST_P(BlockinessVP9Test, BlurringDecreasesBlockiness) {
182*fb1b10abSAndroid Build Coastguard Worker // Source is blockier than reference.
183*fb1b10abSAndroid Build Coastguard Worker FillConstant(source_data_, source_stride_, 128);
184*fb1b10abSAndroid Build Coastguard Worker FillRandomBlocky(reference_data_, reference_stride_);
185*fb1b10abSAndroid Build Coastguard Worker const double super_blocky = GetBlockiness();
186*fb1b10abSAndroid Build Coastguard Worker
187*fb1b10abSAndroid Build Coastguard Worker Blur(reference_data_, reference_stride_, 4);
188*fb1b10abSAndroid Build Coastguard Worker const double less_blocky = GetBlockiness();
189*fb1b10abSAndroid Build Coastguard Worker
190*fb1b10abSAndroid Build Coastguard Worker EXPECT_GT(super_blocky, less_blocky)
191*fb1b10abSAndroid Build Coastguard Worker << "A straight blur should decrease blockiness.";
192*fb1b10abSAndroid Build Coastguard Worker }
193*fb1b10abSAndroid Build Coastguard Worker
TEST_P(BlockinessVP9Test,WorstCaseBlockiness)194*fb1b10abSAndroid Build Coastguard Worker TEST_P(BlockinessVP9Test, WorstCaseBlockiness) {
195*fb1b10abSAndroid Build Coastguard Worker // Source is blockier than reference.
196*fb1b10abSAndroid Build Coastguard Worker FillConstant(source_data_, source_stride_, 128);
197*fb1b10abSAndroid Build Coastguard Worker FillCheckerboard(reference_data_, reference_stride_);
198*fb1b10abSAndroid Build Coastguard Worker
199*fb1b10abSAndroid Build Coastguard Worker const double super_blocky = GetBlockiness();
200*fb1b10abSAndroid Build Coastguard Worker
201*fb1b10abSAndroid Build Coastguard Worker Blur(reference_data_, reference_stride_, 4);
202*fb1b10abSAndroid Build Coastguard Worker const double less_blocky = GetBlockiness();
203*fb1b10abSAndroid Build Coastguard Worker
204*fb1b10abSAndroid Build Coastguard Worker EXPECT_GT(super_blocky, less_blocky)
205*fb1b10abSAndroid Build Coastguard Worker << "A straight blur should decrease blockiness.";
206*fb1b10abSAndroid Build Coastguard Worker }
207*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_ENCODER
208*fb1b10abSAndroid Build Coastguard Worker
209*fb1b10abSAndroid Build Coastguard Worker using std::make_tuple;
210*fb1b10abSAndroid Build Coastguard Worker
211*fb1b10abSAndroid Build Coastguard Worker //------------------------------------------------------------------------------
212*fb1b10abSAndroid Build Coastguard Worker // C functions
213*fb1b10abSAndroid Build Coastguard Worker
214*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_ENCODER
215*fb1b10abSAndroid Build Coastguard Worker const BlockinessParam c_vp9_tests[] = { make_tuple(320, 240),
216*fb1b10abSAndroid Build Coastguard Worker make_tuple(318, 242),
217*fb1b10abSAndroid Build Coastguard Worker make_tuple(318, 238) };
218*fb1b10abSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(C, BlockinessVP9Test,
219*fb1b10abSAndroid Build Coastguard Worker ::testing::ValuesIn(c_vp9_tests));
220*fb1b10abSAndroid Build Coastguard Worker #endif
221*fb1b10abSAndroid Build Coastguard Worker
222*fb1b10abSAndroid Build Coastguard Worker } // namespace
223