blob: 994b30117b6f9020c65ed56d06a161f300d74d29 [file] [log] [blame]
John Koleszar2fb29ff2012-05-23 12:55:27 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
John Koleszar2fb29ff2012-05-23 12:55:27 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*/
James Zern0616fa62016-04-26 19:56:44 -070011
John Koleszar2fb29ff2012-05-23 12:55:27 -070012#include <climits>
13#include <vector>
Tom Finegan7a07ece2017-02-07 17:14:05 -080014#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
John Koleszar706cafe2013-01-18 11:51:12 -080015#include "test/codec_factory.h"
John Koleszar2fb29ff2012-05-23 12:55:27 -070016#include "test/encode_test_driver.h"
John Koleszar88f99f42013-02-06 12:44:20 -080017#include "test/i420_video_source.h"
John Koleszar2fb29ff2012-05-23 12:55:27 -070018#include "test/video_source.h"
John Koleszar706cafe2013-01-18 11:51:12 -080019#include "test/util.h"
John Koleszar2fb29ff2012-05-23 12:55:27 -070020
Adrian Grange88c8ff22013-09-12 09:35:04 -070021// Enable(1) or Disable(0) writing of the compressed bitstream.
22#define WRITE_COMPRESSED_STREAM 0
23
John Koleszar2fb29ff2012-05-23 12:55:27 -070024namespace {
25
Adrian Grange88c8ff22013-09-12 09:35:04 -070026#if WRITE_COMPRESSED_STREAM
Yaowu Xu032573d2017-04-24 15:04:17 -070027static void mem_put_le16(char *const mem, unsigned int val) {
Adrian Grange88c8ff22013-09-12 09:35:04 -070028 mem[0] = val;
29 mem[1] = val >> 8;
30}
31
Yaowu Xu032573d2017-04-24 15:04:17 -070032static void mem_put_le32(char *const mem, unsigned int val) {
Adrian Grange88c8ff22013-09-12 09:35:04 -070033 mem[0] = val;
34 mem[1] = val >> 8;
35 mem[2] = val >> 16;
36 mem[3] = val >> 24;
37}
38
Yaowu Xuf883b422016-08-30 14:01:10 -070039static void write_ivf_file_header(const aom_codec_enc_cfg_t *const cfg,
Adrian Grange88c8ff22013-09-12 09:35:04 -070040 int frame_cnt, FILE *const outfile) {
41 char header[32];
42
43 header[0] = 'D';
44 header[1] = 'K';
45 header[2] = 'I';
46 header[3] = 'F';
clang-format3a826f12016-08-11 17:46:05 -070047 mem_put_le16(header + 4, 0); /* version */
48 mem_put_le16(header + 6, 32); /* headersize */
Yaowu Xuf883b422016-08-30 14:01:10 -070049 mem_put_le32(header + 8, 0x30395056); /* fourcc (av1) */
Adrian Grange88c8ff22013-09-12 09:35:04 -070050 mem_put_le16(header + 12, cfg->g_w); /* width */
51 mem_put_le16(header + 14, cfg->g_h); /* height */
52 mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
53 mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
54 mem_put_le32(header + 24, frame_cnt); /* length */
55 mem_put_le32(header + 28, 0); /* unused */
56
57 (void)fwrite(header, 1, 32, outfile);
58}
59
60static void write_ivf_frame_size(FILE *const outfile, const size_t size) {
61 char header[4];
62 mem_put_le32(header, static_cast<unsigned int>(size));
63 (void)fwrite(header, 1, 4, outfile);
64}
65
Yaowu Xuf883b422016-08-30 14:01:10 -070066static void write_ivf_frame_header(const aom_codec_cx_pkt_t *const pkt,
Adrian Grange88c8ff22013-09-12 09:35:04 -070067 FILE *const outfile) {
68 char header[12];
Yaowu Xuf883b422016-08-30 14:01:10 -070069 aom_codec_pts_t pts;
Adrian Grange88c8ff22013-09-12 09:35:04 -070070
Yaowu Xuf883b422016-08-30 14:01:10 -070071 if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) return;
Adrian Grange88c8ff22013-09-12 09:35:04 -070072
73 pts = pkt->data.frame.pts;
74 mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz));
75 mem_put_le32(header + 4, pts & 0xFFFFFFFF);
76 mem_put_le32(header + 8, pts >> 32);
77
78 (void)fwrite(header, 1, 12, outfile);
79}
80#endif // WRITE_COMPRESSED_STREAM
81
John Koleszar2fb29ff2012-05-23 12:55:27 -070082const unsigned int kInitialWidth = 320;
83const unsigned int kInitialHeight = 240;
84
jackychen9ac42bc2015-09-15 14:17:04 -070085struct FrameInfo {
Yaowu Xuf883b422016-08-30 14:01:10 -070086 FrameInfo(aom_codec_pts_t _pts, unsigned int _w, unsigned int _h)
jackychen9ac42bc2015-09-15 14:17:04 -070087 : pts(_pts), w(_w), h(_h) {}
88
Yaowu Xuf883b422016-08-30 14:01:10 -070089 aom_codec_pts_t pts;
jackychen9ac42bc2015-09-15 14:17:04 -070090 unsigned int w;
91 unsigned int h;
92};
93
clang-format3a826f12016-08-11 17:46:05 -070094void ScaleForFrameNumber(unsigned int frame, unsigned int initial_w,
95 unsigned int initial_h, unsigned int *w,
96 unsigned int *h, int flag_codec) {
Marco3cbc26f2016-02-10 11:39:04 -080097 if (frame < 10) {
98 *w = initial_w;
99 *h = initial_h;
100 return;
101 }
102 if (frame < 20) {
103 *w = initial_w * 3 / 4;
104 *h = initial_h * 3 / 4;
105 return;
106 }
107 if (frame < 30) {
108 *w = initial_w / 2;
109 *h = initial_h / 2;
110 return;
111 }
112 if (frame < 40) {
113 *w = initial_w;
114 *h = initial_h;
115 return;
116 }
117 if (frame < 50) {
118 *w = initial_w * 3 / 4;
119 *h = initial_h * 3 / 4;
120 return;
121 }
122 if (frame < 60) {
123 *w = initial_w / 2;
124 *h = initial_h / 2;
125 return;
126 }
127 if (frame < 70) {
128 *w = initial_w;
129 *h = initial_h;
130 return;
131 }
132 if (frame < 80) {
133 *w = initial_w * 3 / 4;
134 *h = initial_h * 3 / 4;
135 return;
136 }
137 if (frame < 90) {
138 *w = initial_w / 2;
139 *h = initial_h / 2;
140 return;
141 }
142 if (frame < 100) {
143 *w = initial_w * 3 / 4;
144 *h = initial_h * 3 / 4;
145 return;
146 }
147 if (frame < 110) {
148 *w = initial_w;
149 *h = initial_h;
150 return;
151 }
152 if (frame < 120) {
153 *w = initial_w * 3 / 4;
154 *h = initial_h * 3 / 4;
155 return;
156 }
157 if (frame < 130) {
158 *w = initial_w / 2;
159 *h = initial_h / 2;
160 return;
161 }
162 if (frame < 140) {
163 *w = initial_w * 3 / 4;
164 *h = initial_h * 3 / 4;
165 return;
166 }
167 if (frame < 150) {
168 *w = initial_w;
169 *h = initial_h;
170 return;
171 }
172 if (frame < 160) {
173 *w = initial_w * 3 / 4;
174 *h = initial_h * 3 / 4;
175 return;
176 }
177 if (frame < 170) {
178 *w = initial_w / 2;
179 *h = initial_h / 2;
180 return;
181 }
182 if (frame < 180) {
183 *w = initial_w * 3 / 4;
184 *h = initial_h * 3 / 4;
185 return;
186 }
187 if (frame < 190) {
188 *w = initial_w;
189 *h = initial_h;
190 return;
191 }
192 if (frame < 200) {
193 *w = initial_w * 3 / 4;
194 *h = initial_h * 3 / 4;
195 return;
196 }
197 if (frame < 210) {
198 *w = initial_w / 2;
199 *h = initial_h / 2;
200 return;
201 }
202 if (frame < 220) {
203 *w = initial_w * 3 / 4;
204 *h = initial_h * 3 / 4;
205 return;
206 }
207 if (frame < 230) {
208 *w = initial_w;
209 *h = initial_h;
210 return;
211 }
212 if (frame < 240) {
213 *w = initial_w * 3 / 4;
214 *h = initial_h * 3 / 4;
215 return;
216 }
217 if (frame < 250) {
clang-format3a826f12016-08-11 17:46:05 -0700218 *w = initial_w / 2;
Marco3cbc26f2016-02-10 11:39:04 -0800219 *h = initial_h / 2;
220 return;
221 }
222 if (frame < 260) {
223 *w = initial_w;
224 *h = initial_h;
225 return;
226 }
227 // Go down very low.
228 if (frame < 270) {
229 *w = initial_w / 4;
230 *h = initial_h / 4;
231 return;
232 }
233 if (flag_codec == 1) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700234 // Cases that only works for AV1.
235 // For AV1: Swap width and height of original.
Marco3cbc26f2016-02-10 11:39:04 -0800236 if (frame < 320) {
237 *w = initial_h;
238 *h = initial_w;
239 return;
240 }
241 }
242 *w = initial_w;
243 *h = initial_h;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700244}
245
Yaowu Xuc27fc142016-08-22 16:08:15 -0700246class ResizingVideoSource : public ::libaom_test::DummyVideoSource {
John Koleszar2fb29ff2012-05-23 12:55:27 -0700247 public:
248 ResizingVideoSource() {
249 SetSize(kInitialWidth, kInitialHeight);
Marco3cbc26f2016-02-10 11:39:04 -0800250 limit_ = 350;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700251 }
Marco3cbc26f2016-02-10 11:39:04 -0800252 int flag_codec_;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700253 virtual ~ResizingVideoSource() {}
254
John Koleszar2fb29ff2012-05-23 12:55:27 -0700255 protected:
256 virtual void Next() {
257 ++frame_;
Marco3cbc26f2016-02-10 11:39:04 -0800258 unsigned int width;
259 unsigned int height;
260 ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height,
261 flag_codec_);
262 SetSize(width, height);
John Koleszar2fb29ff2012-05-23 12:55:27 -0700263 FillFrame();
264 }
265};
266
clang-format3a826f12016-08-11 17:46:05 -0700267class ResizeTest
Yaowu Xuc27fc142016-08-22 16:08:15 -0700268 : public ::libaom_test::EncoderTest,
269 public ::libaom_test::CodecTestWithParam<libaom_test::TestMode> {
John Koleszar2fb29ff2012-05-23 12:55:27 -0700270 protected:
John Koleszar706cafe2013-01-18 11:51:12 -0800271 ResizeTest() : EncoderTest(GET_PARAM(0)) {}
272
Adrian Grange88c8ff22013-09-12 09:35:04 -0700273 virtual ~ResizeTest() {}
274
John Koleszar2fb29ff2012-05-23 12:55:27 -0700275 virtual void SetUp() {
276 InitializeConfig();
John Koleszar706cafe2013-01-18 11:51:12 -0800277 SetMode(GET_PARAM(1));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700278 }
279
Yaowu Xuf883b422016-08-30 14:01:10 -0700280 virtual void DecompressedFrameHook(const aom_image_t &img,
281 aom_codec_pts_t pts) {
John Koleszar88f99f42013-02-06 12:44:20 -0800282 frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700283 }
284
clang-format3a826f12016-08-11 17:46:05 -0700285 std::vector<FrameInfo> frame_info_list_;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700286};
287
288TEST_P(ResizeTest, TestExternalResizeWorks) {
289 ResizingVideoSource video;
Marco3cbc26f2016-02-10 11:39:04 -0800290 video.flag_codec_ = 0;
Alex Converse910ca852015-01-12 16:26:05 -0800291 cfg_.g_lag_in_frames = 0;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700292 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
293
James Zernbb061382014-01-31 20:11:55 -0800294 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
John Koleszar2fb29ff2012-05-23 12:55:27 -0700295 info != frame_info_list_.end(); ++info) {
James Zern17b89932014-01-31 20:10:28 -0800296 const unsigned int frame = static_cast<unsigned>(info->pts);
Marco3cbc26f2016-02-10 11:39:04 -0800297 unsigned int expected_w;
298 unsigned int expected_h;
clang-format3a826f12016-08-11 17:46:05 -0700299 ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
300 &expected_h, 0);
301 EXPECT_EQ(expected_w, info->w) << "Frame " << frame
302 << " had unexpected width";
303 EXPECT_EQ(expected_h, info->h) << "Frame " << frame
304 << " had unexpected height";
John Koleszar2fb29ff2012-05-23 12:55:27 -0700305 }
306}
307
Adrian Grange88c8ff22013-09-12 09:35:04 -0700308const unsigned int kStepDownFrame = 3;
309const unsigned int kStepUpFrame = 6;
310
John Koleszar88f99f42013-02-06 12:44:20 -0800311class ResizeInternalTest : public ResizeTest {
312 protected:
Adrian Grange88c8ff22013-09-12 09:35:04 -0700313#if WRITE_COMPRESSED_STREAM
314 ResizeInternalTest()
clang-format3a826f12016-08-11 17:46:05 -0700315 : ResizeTest(), frame0_psnr_(0.0), outfile_(NULL), out_frames_(0) {}
Adrian Grange88c8ff22013-09-12 09:35:04 -0700316#else
John Koleszarb683eec2013-02-21 10:38:27 -0800317 ResizeInternalTest() : ResizeTest(), frame0_psnr_(0.0) {}
Adrian Grange88c8ff22013-09-12 09:35:04 -0700318#endif
319
320 virtual ~ResizeInternalTest() {}
321
322 virtual void BeginPassHook(unsigned int /*pass*/) {
323#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700324 outfile_ = fopen("av10-2-05-resize.ivf", "wb");
Adrian Grange88c8ff22013-09-12 09:35:04 -0700325#endif
326 }
327
328 virtual void EndPassHook() {
329#if WRITE_COMPRESSED_STREAM
330 if (outfile_) {
331 if (!fseek(outfile_, 0, SEEK_SET))
332 write_ivf_file_header(&cfg_, out_frames_, outfile_);
333 fclose(outfile_);
334 outfile_ = NULL;
335 }
336#endif
337 }
John Koleszar88f99f42013-02-06 12:44:20 -0800338
Yaowu Xuc27fc142016-08-22 16:08:15 -0700339 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
340 libaom_test::Encoder *encoder) {
jackychen55f092d2015-09-21 09:37:46 -0700341 if (change_config_) {
342 int new_q = 60;
343 if (video->frame() == 0) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700344 struct aom_scaling_mode mode = { AOME_ONETWO, AOME_ONETWO };
345 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700346 }
347 if (video->frame() == 1) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700348 struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
349 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700350 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
351 encoder->Config(&cfg_);
352 }
353 } else {
354 if (video->frame() == kStepDownFrame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700355 struct aom_scaling_mode mode = { AOME_FOURFIVE, AOME_THREEFIVE };
356 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700357 }
358 if (video->frame() == kStepUpFrame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700359 struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
360 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700361 }
John Koleszarb683eec2013-02-21 10:38:27 -0800362 }
John Koleszar88f99f42013-02-06 12:44:20 -0800363 }
John Koleszarb683eec2013-02-21 10:38:27 -0800364
Yaowu Xuf883b422016-08-30 14:01:10 -0700365 virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
clang-format3a826f12016-08-11 17:46:05 -0700366 if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
Deb Mukherjee3cd37df2014-01-17 12:56:36 -0800367 EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
John Koleszarb683eec2013-02-21 10:38:27 -0800368 }
369
Adrian Grange88c8ff22013-09-12 09:35:04 -0700370#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700371 virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) {
Adrian Grange88c8ff22013-09-12 09:35:04 -0700372 ++out_frames_;
373
374 // Write initial file header if first frame.
clang-format3a826f12016-08-11 17:46:05 -0700375 if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
Adrian Grange88c8ff22013-09-12 09:35:04 -0700376
377 // Write frame header and data.
378 write_ivf_frame_header(pkt, outfile_);
379 (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
Adrian Grange88c8ff22013-09-12 09:35:04 -0700380 }
James Zerndbe69172014-08-22 12:11:42 -0700381#endif
Adrian Grange88c8ff22013-09-12 09:35:04 -0700382
John Koleszarb683eec2013-02-21 10:38:27 -0800383 double frame0_psnr_;
jackychen55f092d2015-09-21 09:37:46 -0700384 bool change_config_;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700385#if WRITE_COMPRESSED_STREAM
386 FILE *outfile_;
387 unsigned int out_frames_;
388#endif
John Koleszar88f99f42013-02-06 12:44:20 -0800389};
390
391TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700392 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
John Koleszarb683eec2013-02-21 10:38:27 -0800393 30, 1, 0, 10);
Yaowu Xuf883b422016-08-30 14:01:10 -0700394 init_flags_ = AOM_CODEC_USE_PSNR;
jackychen55f092d2015-09-21 09:37:46 -0700395 change_config_ = false;
Adrian Grange93ffd372013-09-10 12:02:37 -0700396
Adrian Grange88c8ff22013-09-12 09:35:04 -0700397 // q picked such that initial keyframe on this clip is ~30dB PSNR
398 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
399
Adrian Grange93ffd372013-09-10 12:02:37 -0700400 // If the number of frames being encoded is smaller than g_lag_in_frames
401 // the encoded frame is unavailable using the current API. Comparing
402 // frames to detect mismatch would then not be possible. Set
403 // g_lag_in_frames = 0 to get around this.
404 cfg_.g_lag_in_frames = 0;
John Koleszar88f99f42013-02-06 12:44:20 -0800405 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
406
James Zernbb061382014-01-31 20:11:55 -0800407 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
John Koleszar88f99f42013-02-06 12:44:20 -0800408 info != frame_info_list_.end(); ++info) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700409 const aom_codec_pts_t pts = info->pts;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700410 if (pts >= kStepDownFrame && pts < kStepUpFrame) {
John Koleszar88f99f42013-02-06 12:44:20 -0800411 ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
412 ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
413 } else {
414 EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
415 EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
416 }
417 }
418}
419
jackychen55f092d2015-09-21 09:37:46 -0700420TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700421 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen55f092d2015-09-21 09:37:46 -0700422 30, 1, 0, 10);
423 cfg_.g_w = 352;
424 cfg_.g_h = 288;
425 change_config_ = true;
426 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
427}
428
clang-format3a826f12016-08-11 17:46:05 -0700429class ResizeRealtimeTest
Yaowu Xuc27fc142016-08-22 16:08:15 -0700430 : public ::libaom_test::EncoderTest,
431 public ::libaom_test::CodecTestWith2Params<libaom_test::TestMode, int> {
jackychen9ac42bc2015-09-15 14:17:04 -0700432 protected:
jackychen55c88432015-11-09 14:58:14 -0800433 ResizeRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
434 virtual ~ResizeRealtimeTest() {}
jackychen9ac42bc2015-09-15 14:17:04 -0700435
Yaowu Xuc27fc142016-08-22 16:08:15 -0700436 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
437 libaom_test::Encoder *encoder) {
jackychen9ac42bc2015-09-15 14:17:04 -0700438 if (video->frame() == 0) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700439 encoder->Control(AV1E_SET_AQ_MODE, 3);
440 encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
jackychen9ac42bc2015-09-15 14:17:04 -0700441 }
jackychenca8f8fd2015-09-15 15:47:11 -0700442
443 if (change_bitrate_ && video->frame() == 120) {
444 change_bitrate_ = false;
445 cfg_.rc_target_bitrate = 500;
446 encoder->Config(&cfg_);
447 }
jackychen9ac42bc2015-09-15 14:17:04 -0700448 }
449
450 virtual void SetUp() {
451 InitializeConfig();
452 SetMode(GET_PARAM(1));
453 set_cpu_used_ = GET_PARAM(2);
454 }
455
Yaowu Xuf883b422016-08-30 14:01:10 -0700456 virtual void DecompressedFrameHook(const aom_image_t &img,
457 aom_codec_pts_t pts) {
jackychen9ac42bc2015-09-15 14:17:04 -0700458 frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
459 }
460
Yaowu Xuf883b422016-08-30 14:01:10 -0700461 virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2) {
Marcob9cb9552016-03-07 16:58:06 -0800462 double mismatch_psnr = compute_psnr(img1, img2);
463 mismatch_psnr_ += mismatch_psnr;
464 ++mismatch_nframes_;
465 }
466
clang-format3a826f12016-08-11 17:46:05 -0700467 unsigned int GetMismatchFrames() { return mismatch_nframes_; }
Marcob9cb9552016-03-07 16:58:06 -0800468
jackychen9ac42bc2015-09-15 14:17:04 -0700469 void DefaultConfig() {
jackychen9ac42bc2015-09-15 14:17:04 -0700470 cfg_.rc_buf_initial_sz = 500;
471 cfg_.rc_buf_optimal_sz = 600;
472 cfg_.rc_buf_sz = 1000;
473 cfg_.rc_min_quantizer = 2;
474 cfg_.rc_max_quantizer = 56;
475 cfg_.rc_undershoot_pct = 50;
476 cfg_.rc_overshoot_pct = 50;
Yaowu Xuf883b422016-08-30 14:01:10 -0700477 cfg_.rc_end_usage = AOM_CBR;
478 cfg_.kf_mode = AOM_KF_AUTO;
jackychen9ac42bc2015-09-15 14:17:04 -0700479 cfg_.g_lag_in_frames = 0;
480 cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
481 // Enable dropped frames.
482 cfg_.rc_dropframe_thresh = 1;
483 // Enable error_resilience mode.
clang-format3a826f12016-08-11 17:46:05 -0700484 cfg_.g_error_resilient = 1;
jackychen9ac42bc2015-09-15 14:17:04 -0700485 // Enable dynamic resizing.
486 cfg_.rc_resize_allowed = 1;
487 // Run at low bitrate.
488 cfg_.rc_target_bitrate = 200;
489 }
490
clang-format3a826f12016-08-11 17:46:05 -0700491 std::vector<FrameInfo> frame_info_list_;
jackychen9ac42bc2015-09-15 14:17:04 -0700492 int set_cpu_used_;
jackychenca8f8fd2015-09-15 15:47:11 -0700493 bool change_bitrate_;
Marcob9cb9552016-03-07 16:58:06 -0800494 double mismatch_psnr_;
495 int mismatch_nframes_;
jackychen9ac42bc2015-09-15 14:17:04 -0700496};
497
jackychen55c88432015-11-09 14:58:14 -0800498TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
499 ResizingVideoSource video;
Marco3cbc26f2016-02-10 11:39:04 -0800500 video.flag_codec_ = 1;
jackychen55c88432015-11-09 14:58:14 -0800501 DefaultConfig();
Marco34d12d12016-02-10 16:59:09 -0800502 // Disable internal resize for this test.
503 cfg_.rc_resize_allowed = 0;
jackychen55c88432015-11-09 14:58:14 -0800504 change_bitrate_ = false;
Marcob9cb9552016-03-07 16:58:06 -0800505 mismatch_psnr_ = 0.0;
506 mismatch_nframes_ = 0;
jackychen55c88432015-11-09 14:58:14 -0800507 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
508
509 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
510 info != frame_info_list_.end(); ++info) {
511 const unsigned int frame = static_cast<unsigned>(info->pts);
Marco3cbc26f2016-02-10 11:39:04 -0800512 unsigned int expected_w;
513 unsigned int expected_h;
clang-format3a826f12016-08-11 17:46:05 -0700514 ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
515 &expected_h, 1);
516 EXPECT_EQ(expected_w, info->w) << "Frame " << frame
517 << " had unexpected width";
518 EXPECT_EQ(expected_h, info->h) << "Frame " << frame
519 << " had unexpected height";
Marcob9cb9552016-03-07 16:58:06 -0800520 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
jackychen55c88432015-11-09 14:58:14 -0800521 }
522}
523
jackychen9ac42bc2015-09-15 14:17:04 -0700524// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
525// Run at low bitrate, with resize_allowed = 1, and verify that we get
526// one resize down event.
jackychen55c88432015-11-09 14:58:14 -0800527TEST_P(ResizeRealtimeTest, TestInternalResizeDown) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700528 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen9ac42bc2015-09-15 14:17:04 -0700529 30, 1, 0, 299);
530 DefaultConfig();
jackychen55c88432015-11-09 14:58:14 -0800531 cfg_.g_w = 352;
532 cfg_.g_h = 288;
jackychenca8f8fd2015-09-15 15:47:11 -0700533 change_bitrate_ = false;
Marcob9cb9552016-03-07 16:58:06 -0800534 mismatch_psnr_ = 0.0;
535 mismatch_nframes_ = 0;
jackychen9ac42bc2015-09-15 14:17:04 -0700536 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
537
538 unsigned int last_w = cfg_.g_w;
539 unsigned int last_h = cfg_.g_h;
540 int resize_count = 0;
541 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
542 info != frame_info_list_.end(); ++info) {
543 if (info->w != last_w || info->h != last_h) {
544 // Verify that resize down occurs.
545 ASSERT_LT(info->w, last_w);
546 ASSERT_LT(info->h, last_h);
547 last_w = info->w;
548 last_h = info->h;
549 resize_count++;
550 }
551 }
552
Yaowu Xuf883b422016-08-30 14:01:10 -0700553#if CONFIG_AV1_DECODER
jackychen9ac42bc2015-09-15 14:17:04 -0700554 // Verify that we get 1 resize down event in this test.
555 ASSERT_EQ(1, resize_count) << "Resizing should occur.";
Marcob9cb9552016-03-07 16:58:06 -0800556 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
James Zern0616fa62016-04-26 19:56:44 -0700557#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700558 printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
James Zern0616fa62016-04-26 19:56:44 -0700559#endif
jackychen9ac42bc2015-09-15 14:17:04 -0700560}
561
jackychenca8f8fd2015-09-15 15:47:11 -0700562// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
563// Start at low target bitrate, raise the bitrate in the middle of the clip,
564// scaling-up should occur after bitrate changed.
jackychen55c88432015-11-09 14:58:14 -0800565TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700566 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen0465aa42015-11-09 14:04:58 -0800567 30, 1, 0, 359);
jackychenca8f8fd2015-09-15 15:47:11 -0700568 DefaultConfig();
jackychen55c88432015-11-09 14:58:14 -0800569 cfg_.g_w = 352;
570 cfg_.g_h = 288;
jackychenca8f8fd2015-09-15 15:47:11 -0700571 change_bitrate_ = true;
Marcob9cb9552016-03-07 16:58:06 -0800572 mismatch_psnr_ = 0.0;
573 mismatch_nframes_ = 0;
jackychenca8f8fd2015-09-15 15:47:11 -0700574 // Disable dropped frames.
575 cfg_.rc_dropframe_thresh = 0;
576 // Starting bitrate low.
jackychen204cde52015-11-13 16:02:43 -0800577 cfg_.rc_target_bitrate = 80;
jackychenca8f8fd2015-09-15 15:47:11 -0700578 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
579
580 unsigned int last_w = cfg_.g_w;
581 unsigned int last_h = cfg_.g_h;
582 int resize_count = 0;
583 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
584 info != frame_info_list_.end(); ++info) {
585 if (info->w != last_w || info->h != last_h) {
586 resize_count++;
587 if (resize_count == 1) {
588 // Verify that resize down occurs.
589 ASSERT_LT(info->w, last_w);
590 ASSERT_LT(info->h, last_h);
591 } else if (resize_count == 2) {
592 // Verify that resize up occurs.
593 ASSERT_GT(info->w, last_w);
594 ASSERT_GT(info->h, last_h);
595 }
596 last_w = info->w;
597 last_h = info->h;
598 }
599 }
600
Yaowu Xuf883b422016-08-30 14:01:10 -0700601#if CONFIG_AV1_DECODER
jackychen204cde52015-11-13 16:02:43 -0800602 // Verify that we get 2 resize events in this test.
603 ASSERT_EQ(resize_count, 2) << "Resizing should occur twice.";
Marcob9cb9552016-03-07 16:58:06 -0800604 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
James Zern0616fa62016-04-26 19:56:44 -0700605#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700606 printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
James Zern0616fa62016-04-26 19:56:44 -0700607#endif
jackychenca8f8fd2015-09-15 15:47:11 -0700608}
609
Yaowu Xuf883b422016-08-30 14:01:10 -0700610aom_img_fmt_t CspForFrameNumber(int frame) {
611 if (frame < 10) return AOM_IMG_FMT_I420;
612 if (frame < 20) return AOM_IMG_FMT_I444;
613 return AOM_IMG_FMT_I420;
Alex Converse797a2552015-01-15 13:56:55 -0800614}
615
616class ResizeCspTest : public ResizeTest {
617 protected:
618#if WRITE_COMPRESSED_STREAM
619 ResizeCspTest()
clang-format3a826f12016-08-11 17:46:05 -0700620 : ResizeTest(), frame0_psnr_(0.0), outfile_(NULL), out_frames_(0) {}
Alex Converse797a2552015-01-15 13:56:55 -0800621#else
622 ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
623#endif
624
625 virtual ~ResizeCspTest() {}
626
627 virtual void BeginPassHook(unsigned int /*pass*/) {
628#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700629 outfile_ = fopen("av11-2-05-cspchape.ivf", "wb");
Alex Converse797a2552015-01-15 13:56:55 -0800630#endif
631 }
632
633 virtual void EndPassHook() {
634#if WRITE_COMPRESSED_STREAM
635 if (outfile_) {
636 if (!fseek(outfile_, 0, SEEK_SET))
637 write_ivf_file_header(&cfg_, out_frames_, outfile_);
638 fclose(outfile_);
639 outfile_ = NULL;
640 }
641#endif
642 }
643
Yaowu Xuc27fc142016-08-22 16:08:15 -0700644 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
645 libaom_test::Encoder *encoder) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700646 if (CspForFrameNumber(video->frame()) != AOM_IMG_FMT_I420 &&
Alex Converse797a2552015-01-15 13:56:55 -0800647 cfg_.g_profile != 1) {
648 cfg_.g_profile = 1;
649 encoder->Config(&cfg_);
650 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700651 if (CspForFrameNumber(video->frame()) == AOM_IMG_FMT_I420 &&
Alex Converse797a2552015-01-15 13:56:55 -0800652 cfg_.g_profile != 0) {
653 cfg_.g_profile = 0;
654 encoder->Config(&cfg_);
655 }
656 }
657
Yaowu Xuf883b422016-08-30 14:01:10 -0700658 virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
clang-format3a826f12016-08-11 17:46:05 -0700659 if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
Alex Converse797a2552015-01-15 13:56:55 -0800660 EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
661 }
662
663#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700664 virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) {
Alex Converse797a2552015-01-15 13:56:55 -0800665 ++out_frames_;
666
667 // Write initial file header if first frame.
clang-format3a826f12016-08-11 17:46:05 -0700668 if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
Alex Converse797a2552015-01-15 13:56:55 -0800669
670 // Write frame header and data.
671 write_ivf_frame_header(pkt, outfile_);
672 (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
673 }
674#endif
675
676 double frame0_psnr_;
677#if WRITE_COMPRESSED_STREAM
678 FILE *outfile_;
679 unsigned int out_frames_;
680#endif
681};
682
Yaowu Xuc27fc142016-08-22 16:08:15 -0700683class ResizingCspVideoSource : public ::libaom_test::DummyVideoSource {
Alex Converse797a2552015-01-15 13:56:55 -0800684 public:
685 ResizingCspVideoSource() {
686 SetSize(kInitialWidth, kInitialHeight);
687 limit_ = 30;
688 }
689
690 virtual ~ResizingCspVideoSource() {}
691
692 protected:
693 virtual void Next() {
694 ++frame_;
695 SetImageFormat(CspForFrameNumber(frame_));
696 FillFrame();
697 }
698};
699
700TEST_P(ResizeCspTest, TestResizeCspWorks) {
701 ResizingCspVideoSource video;
Yaowu Xuf883b422016-08-30 14:01:10 -0700702 init_flags_ = AOM_CODEC_USE_PSNR;
Alex Converse797a2552015-01-15 13:56:55 -0800703 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
704 cfg_.g_lag_in_frames = 0;
705 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
706}
707
Yaowu Xuf883b422016-08-30 14:01:10 -0700708AV1_INSTANTIATE_TEST_CASE(ResizeTest,
709 ::testing::Values(::libaom_test::kRealTime));
710AV1_INSTANTIATE_TEST_CASE(ResizeInternalTest,
711 ::testing::Values(::libaom_test::kOnePassBest));
712AV1_INSTANTIATE_TEST_CASE(ResizeRealtimeTest,
713 ::testing::Values(::libaom_test::kRealTime),
714 ::testing::Range(5, 9));
715AV1_INSTANTIATE_TEST_CASE(ResizeCspTest,
716 ::testing::Values(::libaom_test::kRealTime));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700717} // namespace