2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
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.
15 #include "third_party/googletest/src/include/gtest/gtest.h"
17 #include "./vpx_config.h"
18 #if CONFIG_VP9_ENCODER
19 #include "./vp9_rtcd.h"
22 #include "test/acm_random.h"
23 #include "test/clear_system_state.h"
24 #include "test/register_state_check.h"
25 #include "test/util.h"
26 #include "vpx_dsp/ssim.h"
27 #include "vpx_mem/vpx_mem.h"
30 double vpx_get_ssim_metrics(uint8_t *img1
, int img1_pitch
,
31 uint8_t *img2
, int img2_pitch
,
32 int width
, int height
,
33 Ssimv
*sv2
, Metrics
*m
,
34 int do_inconsistency
);
36 using libvpx_test::ACMRandom
;
39 class ConsistencyTestBase
: public ::testing::Test
{
41 ConsistencyTestBase(int width
, int height
) : width_(width
), height_(height
) {}
43 static void SetUpTestCase() {
44 source_data_
[0] = reinterpret_cast<uint8_t*>(
45 vpx_memalign(kDataAlignment
, kDataBufferSize
));
46 reference_data_
[0] = reinterpret_cast<uint8_t*>(
47 vpx_memalign(kDataAlignment
, kDataBufferSize
));
48 source_data_
[1] = reinterpret_cast<uint8_t*>(
49 vpx_memalign(kDataAlignment
, kDataBufferSize
));
50 reference_data_
[1] = reinterpret_cast<uint8_t*>(
51 vpx_memalign(kDataAlignment
, kDataBufferSize
));
52 ssim_array_
= new Ssimv
[kDataBufferSize
/ 16];
55 static void ClearSsim() {
56 memset(ssim_array_
, 0, kDataBufferSize
/ 16);
58 static void TearDownTestCase() {
59 vpx_free(source_data_
[0]);
60 source_data_
[0] = NULL
;
61 vpx_free(reference_data_
[0]);
62 reference_data_
[0] = NULL
;
63 vpx_free(source_data_
[1]);
64 source_data_
[1] = NULL
;
65 vpx_free(reference_data_
[1]);
66 reference_data_
[1] = NULL
;
71 virtual void TearDown() {
72 libvpx_test::ClearSystemState();
76 // Handle frames up to 640x480
77 static const int kDataAlignment
= 16;
78 static const int kDataBufferSize
= 640*480;
80 virtual void SetUp() {
81 source_stride_
= (width_
+ 31) & ~31;
82 reference_stride_
= width_
* 2;
83 rnd_
.Reset(ACMRandom::DeterministicSeed());
86 void FillRandom(uint8_t *data
, int stride
, int width
, int height
) {
87 for (int h
= 0; h
< height
; ++h
) {
88 for (int w
= 0; w
< width
; ++w
) {
89 data
[h
* stride
+ w
] = rnd_
.Rand8();
94 void FillRandom(uint8_t *data
, int stride
) {
95 FillRandom(data
, stride
, width_
, height_
);
98 void Copy(uint8_t *reference
, uint8_t *source
) {
99 memcpy(reference
, source
, kDataBufferSize
);
102 void Blur(uint8_t *data
, int stride
, int taps
) {
104 int half_taps
= taps
/ 2;
105 for (int h
= 0; h
< height_
; ++h
) {
106 for (int w
= 0; w
< taps
; ++w
) {
107 sum
+= data
[w
+ h
* stride
];
109 for (int w
= taps
; w
< width_
; ++w
) {
110 sum
+= data
[w
+ h
* stride
] - data
[w
- taps
+ h
* stride
];
111 data
[w
- half_taps
+ h
* stride
] = (sum
+ half_taps
) / taps
;
114 for (int w
= 0; w
< width_
; ++w
) {
115 for (int h
= 0; h
< taps
; ++h
) {
116 sum
+= data
[h
+ w
* stride
];
118 for (int h
= taps
; h
< height_
; ++h
) {
119 sum
+= data
[w
+ h
* stride
] - data
[(h
- taps
) * stride
+ w
];
120 data
[(h
- half_taps
) * stride
+ w
] = (sum
+ half_taps
) / taps
;
125 static uint8_t* source_data_
[2];
127 static uint8_t* reference_data_
[2];
128 int reference_stride_
;
129 static Ssimv
*ssim_array_
;
135 #if CONFIG_VP9_ENCODER
136 typedef std::tr1::tuple
<int, int> ConsistencyParam
;
137 class ConsistencyVP9Test
138 : public ConsistencyTestBase
,
139 public ::testing::WithParamInterface
<ConsistencyParam
> {
141 ConsistencyVP9Test() : ConsistencyTestBase(GET_PARAM(0), GET_PARAM(1)) {}
144 double CheckConsistency(int frame
) {
145 EXPECT_LT(frame
, 2)<< "Frame to check has to be less than 2.";
147 vpx_get_ssim_metrics(source_data_
[frame
], source_stride_
,
148 reference_data_
[frame
], reference_stride_
,
149 width_
, height_
, ssim_array_
, &metrics_
, 1);
152 #endif // CONFIG_VP9_ENCODER
154 uint8_t* ConsistencyTestBase::source_data_
[2] = {NULL
, NULL
};
155 uint8_t* ConsistencyTestBase::reference_data_
[2] = {NULL
, NULL
};
156 Ssimv
* ConsistencyTestBase::ssim_array_
= NULL
;
158 #if CONFIG_VP9_ENCODER
159 TEST_P(ConsistencyVP9Test
, ConsistencyIsZero
) {
160 FillRandom(source_data_
[0], source_stride_
);
161 Copy(source_data_
[1], source_data_
[0]);
162 Copy(reference_data_
[0], source_data_
[0]);
163 Blur(reference_data_
[0], reference_stride_
, 3);
164 Copy(reference_data_
[1], source_data_
[0]);
165 Blur(reference_data_
[1], reference_stride_
, 3);
167 double inconsistency
= CheckConsistency(1);
168 inconsistency
= CheckConsistency(0);
169 EXPECT_EQ(inconsistency
, 0.0)
170 << "Should have 0 inconsistency if they are exactly the same.";
172 // If sources are not consistent reference frames inconsistency should
173 // be less than if the source is consistent.
174 FillRandom(source_data_
[0], source_stride_
);
175 FillRandom(source_data_
[1], source_stride_
);
176 FillRandom(reference_data_
[0], reference_stride_
);
177 FillRandom(reference_data_
[1], reference_stride_
);
179 inconsistency
= CheckConsistency(1);
181 Copy(source_data_
[1], source_data_
[0]);
183 double inconsistency2
= CheckConsistency(1);
184 EXPECT_LT(inconsistency
, inconsistency2
)
185 << "Should have less inconsistency if source itself is inconsistent.";
187 // Less of a blur should be less inconsistent than more blur coming off a
188 // a frame with no blur.
190 FillRandom(source_data_
[0], source_stride_
);
191 Copy(source_data_
[1], source_data_
[0]);
192 Copy(reference_data_
[0], source_data_
[0]);
193 Copy(reference_data_
[1], source_data_
[0]);
194 Blur(reference_data_
[1], reference_stride_
, 4);
196 inconsistency
= CheckConsistency(1);
198 Copy(reference_data_
[1], source_data_
[0]);
199 Blur(reference_data_
[1], reference_stride_
, 8);
201 inconsistency2
= CheckConsistency(1);
203 EXPECT_LT(inconsistency
, inconsistency2
)
204 << "Stronger Blur should produce more inconsistency.";
206 #endif // CONFIG_VP9_ENCODER
209 using std::tr1::make_tuple
;
211 //------------------------------------------------------------------------------
214 #if CONFIG_VP9_ENCODER
215 const ConsistencyParam c_vp9_tests
[] = {
216 make_tuple(320, 240),
217 make_tuple(318, 242),
218 make_tuple(318, 238),
220 INSTANTIATE_TEST_CASE_P(C
, ConsistencyVP9Test
,
221 ::testing::ValuesIn(c_vp9_tests
));