blob: 534025ddb1bc1e7645f50856137939e66b130934 [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.
Johann123e8a62017-12-28 14:40:49 -080010 */
James Zern0616fa62016-04-26 19:56:44 -070011
John Koleszar2fb29ff2012-05-23 12:55:27 -070012#include <climits>
13#include <vector>
Imdad Sardharwalla102c8652018-02-23 16:35:13 +000014#include "aom_dsp/aom_dsp_common.h"
Tom Finegan7a07ece2017-02-07 17:14:05 -080015#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
John Koleszar706cafe2013-01-18 11:51:12 -080016#include "test/codec_factory.h"
John Koleszar2fb29ff2012-05-23 12:55:27 -070017#include "test/encode_test_driver.h"
John Koleszar88f99f42013-02-06 12:44:20 -080018#include "test/i420_video_source.h"
John Koleszar2fb29ff2012-05-23 12:55:27 -070019#include "test/video_source.h"
John Koleszar706cafe2013-01-18 11:51:12 -080020#include "test/util.h"
John Koleszar2fb29ff2012-05-23 12:55:27 -070021
Adrian Grange88c8ff22013-09-12 09:35:04 -070022// Enable(1) or Disable(0) writing of the compressed bitstream.
23#define WRITE_COMPRESSED_STREAM 0
24
John Koleszar2fb29ff2012-05-23 12:55:27 -070025namespace {
26
Adrian Grange88c8ff22013-09-12 09:35:04 -070027#if WRITE_COMPRESSED_STREAM
Yaowu Xu032573d2017-04-24 15:04:17 -070028static void mem_put_le16(char *const mem, unsigned int val) {
Adrian Grange88c8ff22013-09-12 09:35:04 -070029 mem[0] = val;
30 mem[1] = val >> 8;
31}
32
Yaowu Xu032573d2017-04-24 15:04:17 -070033static void mem_put_le32(char *const mem, unsigned int val) {
Adrian Grange88c8ff22013-09-12 09:35:04 -070034 mem[0] = val;
35 mem[1] = val >> 8;
36 mem[2] = val >> 16;
37 mem[3] = val >> 24;
38}
39
Yaowu Xuf883b422016-08-30 14:01:10 -070040static void write_ivf_file_header(const aom_codec_enc_cfg_t *const cfg,
Adrian Grange88c8ff22013-09-12 09:35:04 -070041 int frame_cnt, FILE *const outfile) {
42 char header[32];
43
44 header[0] = 'D';
45 header[1] = 'K';
46 header[2] = 'I';
47 header[3] = 'F';
clang-format3a826f12016-08-11 17:46:05 -070048 mem_put_le16(header + 4, 0); /* version */
49 mem_put_le16(header + 6, 32); /* headersize */
Yaowu Xuf883b422016-08-30 14:01:10 -070050 mem_put_le32(header + 8, 0x30395056); /* fourcc (av1) */
Adrian Grange88c8ff22013-09-12 09:35:04 -070051 mem_put_le16(header + 12, cfg->g_w); /* width */
52 mem_put_le16(header + 14, cfg->g_h); /* height */
53 mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
54 mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
55 mem_put_le32(header + 24, frame_cnt); /* length */
56 mem_put_le32(header + 28, 0); /* unused */
57
58 (void)fwrite(header, 1, 32, outfile);
59}
60
61static void write_ivf_frame_size(FILE *const outfile, const size_t size) {
62 char header[4];
63 mem_put_le32(header, static_cast<unsigned int>(size));
64 (void)fwrite(header, 1, 4, outfile);
65}
66
Yaowu Xuf883b422016-08-30 14:01:10 -070067static void write_ivf_frame_header(const aom_codec_cx_pkt_t *const pkt,
Adrian Grange88c8ff22013-09-12 09:35:04 -070068 FILE *const outfile) {
69 char header[12];
Yaowu Xuf883b422016-08-30 14:01:10 -070070 aom_codec_pts_t pts;
Adrian Grange88c8ff22013-09-12 09:35:04 -070071
Yaowu Xuf883b422016-08-30 14:01:10 -070072 if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) return;
Adrian Grange88c8ff22013-09-12 09:35:04 -070073
74 pts = pkt->data.frame.pts;
75 mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz));
76 mem_put_le32(header + 4, pts & 0xFFFFFFFF);
77 mem_put_le32(header + 8, pts >> 32);
78
79 (void)fwrite(header, 1, 12, outfile);
80}
81#endif // WRITE_COMPRESSED_STREAM
82
John Koleszar2fb29ff2012-05-23 12:55:27 -070083const unsigned int kInitialWidth = 320;
84const unsigned int kInitialHeight = 240;
85
jackychen9ac42bc2015-09-15 14:17:04 -070086struct FrameInfo {
Yaowu Xuf883b422016-08-30 14:01:10 -070087 FrameInfo(aom_codec_pts_t _pts, unsigned int _w, unsigned int _h)
jackychen9ac42bc2015-09-15 14:17:04 -070088 : pts(_pts), w(_w), h(_h) {}
89
Yaowu Xuf883b422016-08-30 14:01:10 -070090 aom_codec_pts_t pts;
jackychen9ac42bc2015-09-15 14:17:04 -070091 unsigned int w;
92 unsigned int h;
93};
94
clang-format3a826f12016-08-11 17:46:05 -070095void ScaleForFrameNumber(unsigned int frame, unsigned int initial_w,
96 unsigned int initial_h, unsigned int *w,
97 unsigned int *h, int flag_codec) {
Marco3cbc26f2016-02-10 11:39:04 -080098 if (frame < 10) {
99 *w = initial_w;
100 *h = initial_h;
101 return;
102 }
103 if (frame < 20) {
104 *w = initial_w * 3 / 4;
105 *h = initial_h * 3 / 4;
106 return;
107 }
108 if (frame < 30) {
109 *w = initial_w / 2;
110 *h = initial_h / 2;
111 return;
112 }
113 if (frame < 40) {
114 *w = initial_w;
115 *h = initial_h;
116 return;
117 }
118 if (frame < 50) {
119 *w = initial_w * 3 / 4;
120 *h = initial_h * 3 / 4;
121 return;
122 }
123 if (frame < 60) {
124 *w = initial_w / 2;
125 *h = initial_h / 2;
126 return;
127 }
128 if (frame < 70) {
129 *w = initial_w;
130 *h = initial_h;
131 return;
132 }
133 if (frame < 80) {
134 *w = initial_w * 3 / 4;
135 *h = initial_h * 3 / 4;
136 return;
137 }
138 if (frame < 90) {
139 *w = initial_w / 2;
140 *h = initial_h / 2;
141 return;
142 }
143 if (frame < 100) {
144 *w = initial_w * 3 / 4;
145 *h = initial_h * 3 / 4;
146 return;
147 }
148 if (frame < 110) {
149 *w = initial_w;
150 *h = initial_h;
151 return;
152 }
153 if (frame < 120) {
154 *w = initial_w * 3 / 4;
155 *h = initial_h * 3 / 4;
156 return;
157 }
158 if (frame < 130) {
159 *w = initial_w / 2;
160 *h = initial_h / 2;
161 return;
162 }
163 if (frame < 140) {
164 *w = initial_w * 3 / 4;
165 *h = initial_h * 3 / 4;
166 return;
167 }
168 if (frame < 150) {
169 *w = initial_w;
170 *h = initial_h;
171 return;
172 }
173 if (frame < 160) {
174 *w = initial_w * 3 / 4;
175 *h = initial_h * 3 / 4;
176 return;
177 }
178 if (frame < 170) {
179 *w = initial_w / 2;
180 *h = initial_h / 2;
181 return;
182 }
183 if (frame < 180) {
184 *w = initial_w * 3 / 4;
185 *h = initial_h * 3 / 4;
186 return;
187 }
188 if (frame < 190) {
189 *w = initial_w;
190 *h = initial_h;
191 return;
192 }
193 if (frame < 200) {
194 *w = initial_w * 3 / 4;
195 *h = initial_h * 3 / 4;
196 return;
197 }
198 if (frame < 210) {
199 *w = initial_w / 2;
200 *h = initial_h / 2;
201 return;
202 }
203 if (frame < 220) {
204 *w = initial_w * 3 / 4;
205 *h = initial_h * 3 / 4;
206 return;
207 }
208 if (frame < 230) {
209 *w = initial_w;
210 *h = initial_h;
211 return;
212 }
213 if (frame < 240) {
214 *w = initial_w * 3 / 4;
215 *h = initial_h * 3 / 4;
216 return;
217 }
218 if (frame < 250) {
clang-format3a826f12016-08-11 17:46:05 -0700219 *w = initial_w / 2;
Marco3cbc26f2016-02-10 11:39:04 -0800220 *h = initial_h / 2;
221 return;
222 }
223 if (frame < 260) {
224 *w = initial_w;
225 *h = initial_h;
226 return;
227 }
228 // Go down very low.
229 if (frame < 270) {
230 *w = initial_w / 4;
231 *h = initial_h / 4;
232 return;
233 }
234 if (flag_codec == 1) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700235 // Cases that only works for AV1.
236 // For AV1: Swap width and height of original.
Marco3cbc26f2016-02-10 11:39:04 -0800237 if (frame < 320) {
238 *w = initial_h;
239 *h = initial_w;
240 return;
241 }
242 }
243 *w = initial_w;
244 *h = initial_h;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700245}
246
Yaowu Xuc27fc142016-08-22 16:08:15 -0700247class ResizingVideoSource : public ::libaom_test::DummyVideoSource {
John Koleszar2fb29ff2012-05-23 12:55:27 -0700248 public:
249 ResizingVideoSource() {
250 SetSize(kInitialWidth, kInitialHeight);
Imdad Sardharwalla102c8652018-02-23 16:35:13 +0000251 limit_ = 350;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700252 }
Marco3cbc26f2016-02-10 11:39:04 -0800253 int flag_codec_;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700254 virtual ~ResizingVideoSource() {}
255
John Koleszar2fb29ff2012-05-23 12:55:27 -0700256 protected:
257 virtual void Next() {
258 ++frame_;
Marco3cbc26f2016-02-10 11:39:04 -0800259 unsigned int width;
260 unsigned int height;
261 ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height,
262 flag_codec_);
263 SetSize(width, height);
John Koleszar2fb29ff2012-05-23 12:55:27 -0700264 FillFrame();
265 }
266};
267
clang-format3a826f12016-08-11 17:46:05 -0700268class ResizeTest
Sebastien Alaiwan4322bc12017-06-05 10:18:28 +0200269 : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
270 public ::libaom_test::EncoderTest {
John Koleszar2fb29ff2012-05-23 12:55:27 -0700271 protected:
John Koleszar706cafe2013-01-18 11:51:12 -0800272 ResizeTest() : EncoderTest(GET_PARAM(0)) {}
273
Adrian Grange88c8ff22013-09-12 09:35:04 -0700274 virtual ~ResizeTest() {}
275
John Koleszar2fb29ff2012-05-23 12:55:27 -0700276 virtual void SetUp() {
277 InitializeConfig();
John Koleszar706cafe2013-01-18 11:51:12 -0800278 SetMode(GET_PARAM(1));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700279 }
280
Yaowu Xuf883b422016-08-30 14:01:10 -0700281 virtual void DecompressedFrameHook(const aom_image_t &img,
282 aom_codec_pts_t pts) {
John Koleszar88f99f42013-02-06 12:44:20 -0800283 frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700284 }
285
clang-format3a826f12016-08-11 17:46:05 -0700286 std::vector<FrameInfo> frame_info_list_;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700287};
288
289TEST_P(ResizeTest, TestExternalResizeWorks) {
290 ResizingVideoSource video;
Marco3cbc26f2016-02-10 11:39:04 -0800291 video.flag_codec_ = 0;
Alex Converse910ca852015-01-12 16:26:05 -0800292 cfg_.g_lag_in_frames = 0;
Imdad Sardharwalla102c8652018-02-23 16:35:13 +0000293 // We use max(kInitialWidth, kInitialHeight) because during the test
294 // the width and height of the frame are swapped
295 cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
296 AOMMAX(kInitialWidth, kInitialHeight);
John Koleszar2fb29ff2012-05-23 12:55:27 -0700297 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
298
Imdad Sardharwalladadaba62018-02-23 12:06:56 +0000299 // Check we decoded the same number of frames as we attempted to encode
300 ASSERT_EQ(frame_info_list_.size(), video.limit());
301
James Zernbb061382014-01-31 20:11:55 -0800302 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
John Koleszar2fb29ff2012-05-23 12:55:27 -0700303 info != frame_info_list_.end(); ++info) {
James Zern17b89932014-01-31 20:10:28 -0800304 const unsigned int frame = static_cast<unsigned>(info->pts);
Marco3cbc26f2016-02-10 11:39:04 -0800305 unsigned int expected_w;
306 unsigned int expected_h;
clang-format3a826f12016-08-11 17:46:05 -0700307 ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
308 &expected_h, 0);
clang-format4eafefe2017-09-04 12:51:20 -0700309 EXPECT_EQ(expected_w, info->w)
310 << "Frame " << frame << " had unexpected width";
311 EXPECT_EQ(expected_h, info->h)
312 << "Frame " << frame << " had unexpected height";
John Koleszar2fb29ff2012-05-23 12:55:27 -0700313 }
314}
315
Adrian Grange88c8ff22013-09-12 09:35:04 -0700316const unsigned int kStepDownFrame = 3;
317const unsigned int kStepUpFrame = 6;
318
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700319class ResizeInternalTestLarge : public ResizeTest {
John Koleszar88f99f42013-02-06 12:44:20 -0800320 protected:
Adrian Grange88c8ff22013-09-12 09:35:04 -0700321#if WRITE_COMPRESSED_STREAM
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700322 ResizeInternalTestLarge()
clang-format3a826f12016-08-11 17:46:05 -0700323 : ResizeTest(), frame0_psnr_(0.0), outfile_(NULL), out_frames_(0) {}
Adrian Grange88c8ff22013-09-12 09:35:04 -0700324#else
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700325 ResizeInternalTestLarge() : ResizeTest(), frame0_psnr_(0.0) {}
Adrian Grange88c8ff22013-09-12 09:35:04 -0700326#endif
327
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700328 virtual ~ResizeInternalTestLarge() {}
Adrian Grange88c8ff22013-09-12 09:35:04 -0700329
330 virtual void BeginPassHook(unsigned int /*pass*/) {
331#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700332 outfile_ = fopen("av10-2-05-resize.ivf", "wb");
Adrian Grange88c8ff22013-09-12 09:35:04 -0700333#endif
334 }
335
336 virtual void EndPassHook() {
337#if WRITE_COMPRESSED_STREAM
338 if (outfile_) {
339 if (!fseek(outfile_, 0, SEEK_SET))
340 write_ivf_file_header(&cfg_, out_frames_, outfile_);
341 fclose(outfile_);
342 outfile_ = NULL;
343 }
344#endif
345 }
John Koleszar88f99f42013-02-06 12:44:20 -0800346
Yaowu Xuc27fc142016-08-22 16:08:15 -0700347 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
348 libaom_test::Encoder *encoder) {
jackychen55f092d2015-09-21 09:37:46 -0700349 if (change_config_) {
350 int new_q = 60;
351 if (video->frame() == 0) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700352 struct aom_scaling_mode mode = { AOME_ONETWO, AOME_ONETWO };
353 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700354 }
355 if (video->frame() == 1) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700356 struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
357 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700358 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
359 encoder->Config(&cfg_);
360 }
361 } else {
Debargha Mukherjeeccb27262017-09-25 14:19:46 -0700362 if (video->frame() >= kStepDownFrame && video->frame() < kStepUpFrame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700363 struct aom_scaling_mode mode = { AOME_FOURFIVE, AOME_THREEFIVE };
364 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700365 }
Debargha Mukherjeeccb27262017-09-25 14:19:46 -0700366 if (video->frame() >= kStepUpFrame) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700367 struct aom_scaling_mode mode = { AOME_NORMAL, AOME_NORMAL };
368 encoder->Control(AOME_SET_SCALEMODE, &mode);
jackychen55f092d2015-09-21 09:37:46 -0700369 }
John Koleszarb683eec2013-02-21 10:38:27 -0800370 }
John Koleszar88f99f42013-02-06 12:44:20 -0800371 }
John Koleszarb683eec2013-02-21 10:38:27 -0800372
Yaowu Xuf883b422016-08-30 14:01:10 -0700373 virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
clang-format3a826f12016-08-11 17:46:05 -0700374 if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
Debargha Mukherjee34e3a142017-10-05 12:46:14 -0700375 EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.5);
John Koleszarb683eec2013-02-21 10:38:27 -0800376 }
377
Adrian Grange88c8ff22013-09-12 09:35:04 -0700378#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700379 virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) {
Adrian Grange88c8ff22013-09-12 09:35:04 -0700380 ++out_frames_;
381
382 // Write initial file header if first frame.
clang-format3a826f12016-08-11 17:46:05 -0700383 if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
Adrian Grange88c8ff22013-09-12 09:35:04 -0700384
385 // Write frame header and data.
386 write_ivf_frame_header(pkt, outfile_);
387 (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
Adrian Grange88c8ff22013-09-12 09:35:04 -0700388 }
James Zerndbe69172014-08-22 12:11:42 -0700389#endif
Adrian Grange88c8ff22013-09-12 09:35:04 -0700390
John Koleszarb683eec2013-02-21 10:38:27 -0800391 double frame0_psnr_;
jackychen55f092d2015-09-21 09:37:46 -0700392 bool change_config_;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700393#if WRITE_COMPRESSED_STREAM
394 FILE *outfile_;
395 unsigned int out_frames_;
396#endif
John Koleszar88f99f42013-02-06 12:44:20 -0800397};
398
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700399TEST_P(ResizeInternalTestLarge, TestInternalResizeWorks) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700400 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
John Koleszarb683eec2013-02-21 10:38:27 -0800401 30, 1, 0, 10);
Yaowu Xuf883b422016-08-30 14:01:10 -0700402 init_flags_ = AOM_CODEC_USE_PSNR;
jackychen55f092d2015-09-21 09:37:46 -0700403 change_config_ = false;
Adrian Grange93ffd372013-09-10 12:02:37 -0700404
Adrian Grange88c8ff22013-09-12 09:35:04 -0700405 // q picked such that initial keyframe on this clip is ~30dB PSNR
406 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
407
Adrian Grange93ffd372013-09-10 12:02:37 -0700408 // If the number of frames being encoded is smaller than g_lag_in_frames
409 // the encoded frame is unavailable using the current API. Comparing
410 // frames to detect mismatch would then not be possible. Set
411 // g_lag_in_frames = 0 to get around this.
412 cfg_.g_lag_in_frames = 0;
John Koleszar88f99f42013-02-06 12:44:20 -0800413 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
414
James Zernbb061382014-01-31 20:11:55 -0800415 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
John Koleszar88f99f42013-02-06 12:44:20 -0800416 info != frame_info_list_.end(); ++info) {
Debargha Mukherjeeccb27262017-09-25 14:19:46 -0700417 }
418 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
419 info != frame_info_list_.end(); ++info) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700420 const aom_codec_pts_t pts = info->pts;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700421 if (pts >= kStepDownFrame && pts < kStepUpFrame) {
John Koleszar88f99f42013-02-06 12:44:20 -0800422 ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
423 ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
424 } else {
425 EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
426 EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
427 }
428 }
429}
430
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700431TEST_P(ResizeInternalTestLarge, TestInternalResizeChangeConfig) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700432 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen55f092d2015-09-21 09:37:46 -0700433 30, 1, 0, 10);
434 cfg_.g_w = 352;
435 cfg_.g_h = 288;
436 change_config_ = true;
437 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
438}
439
clang-format3a826f12016-08-11 17:46:05 -0700440class ResizeRealtimeTest
Sebastien Alaiwan4322bc12017-06-05 10:18:28 +0200441 : public ::libaom_test::CodecTestWith2Params<libaom_test::TestMode, int>,
442 public ::libaom_test::EncoderTest {
jackychen9ac42bc2015-09-15 14:17:04 -0700443 protected:
jackychen55c88432015-11-09 14:58:14 -0800444 ResizeRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
445 virtual ~ResizeRealtimeTest() {}
jackychen9ac42bc2015-09-15 14:17:04 -0700446
Yaowu Xuc27fc142016-08-22 16:08:15 -0700447 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
448 libaom_test::Encoder *encoder) {
jackychen9ac42bc2015-09-15 14:17:04 -0700449 if (video->frame() == 0) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700450 encoder->Control(AV1E_SET_AQ_MODE, 3);
451 encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
jackychen9ac42bc2015-09-15 14:17:04 -0700452 }
jackychenca8f8fd2015-09-15 15:47:11 -0700453
454 if (change_bitrate_ && video->frame() == 120) {
455 change_bitrate_ = false;
456 cfg_.rc_target_bitrate = 500;
457 encoder->Config(&cfg_);
458 }
jackychen9ac42bc2015-09-15 14:17:04 -0700459 }
460
461 virtual void SetUp() {
462 InitializeConfig();
463 SetMode(GET_PARAM(1));
464 set_cpu_used_ = GET_PARAM(2);
465 }
466
Yaowu Xuf883b422016-08-30 14:01:10 -0700467 virtual void DecompressedFrameHook(const aom_image_t &img,
468 aom_codec_pts_t pts) {
jackychen9ac42bc2015-09-15 14:17:04 -0700469 frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
470 }
471
Yaowu Xuf883b422016-08-30 14:01:10 -0700472 virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2) {
Marcob9cb9552016-03-07 16:58:06 -0800473 double mismatch_psnr = compute_psnr(img1, img2);
474 mismatch_psnr_ += mismatch_psnr;
475 ++mismatch_nframes_;
476 }
477
clang-format3a826f12016-08-11 17:46:05 -0700478 unsigned int GetMismatchFrames() { return mismatch_nframes_; }
Marcob9cb9552016-03-07 16:58:06 -0800479
jackychen9ac42bc2015-09-15 14:17:04 -0700480 void DefaultConfig() {
jackychen9ac42bc2015-09-15 14:17:04 -0700481 cfg_.rc_buf_initial_sz = 500;
482 cfg_.rc_buf_optimal_sz = 600;
483 cfg_.rc_buf_sz = 1000;
484 cfg_.rc_min_quantizer = 2;
485 cfg_.rc_max_quantizer = 56;
486 cfg_.rc_undershoot_pct = 50;
487 cfg_.rc_overshoot_pct = 50;
Yaowu Xuf883b422016-08-30 14:01:10 -0700488 cfg_.rc_end_usage = AOM_CBR;
489 cfg_.kf_mode = AOM_KF_AUTO;
jackychen9ac42bc2015-09-15 14:17:04 -0700490 cfg_.g_lag_in_frames = 0;
491 cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
492 // Enable dropped frames.
493 cfg_.rc_dropframe_thresh = 1;
Soo-Chul Han2638cb52017-11-22 16:34:47 -0500494 // Disable error_resilience mode.
495 cfg_.g_error_resilient = 0;
jackychen9ac42bc2015-09-15 14:17:04 -0700496 // Run at low bitrate.
497 cfg_.rc_target_bitrate = 200;
Imdad Sardharwalla102c8652018-02-23 16:35:13 +0000498 // We use max(kInitialWidth, kInitialHeight) because during the test
499 // the width and height of the frame are swapped
500 cfg_.g_forced_max_frame_width = cfg_.g_forced_max_frame_height =
501 AOMMAX(kInitialWidth, kInitialHeight);
jackychen9ac42bc2015-09-15 14:17:04 -0700502 }
503
clang-format3a826f12016-08-11 17:46:05 -0700504 std::vector<FrameInfo> frame_info_list_;
jackychen9ac42bc2015-09-15 14:17:04 -0700505 int set_cpu_used_;
jackychenca8f8fd2015-09-15 15:47:11 -0700506 bool change_bitrate_;
Marcob9cb9552016-03-07 16:58:06 -0800507 double mismatch_psnr_;
508 int mismatch_nframes_;
jackychen9ac42bc2015-09-15 14:17:04 -0700509};
510
Debargha Mukherjeeccb27262017-09-25 14:19:46 -0700511TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
jackychen55c88432015-11-09 14:58:14 -0800512 ResizingVideoSource video;
Marco3cbc26f2016-02-10 11:39:04 -0800513 video.flag_codec_ = 1;
jackychen55c88432015-11-09 14:58:14 -0800514 DefaultConfig();
515 change_bitrate_ = false;
Marcob9cb9552016-03-07 16:58:06 -0800516 mismatch_psnr_ = 0.0;
517 mismatch_nframes_ = 0;
jackychen55c88432015-11-09 14:58:14 -0800518 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
519
Imdad Sardharwalladadaba62018-02-23 12:06:56 +0000520 // Check we decoded the same number of frames as we attempted to encode
521 ASSERT_EQ(frame_info_list_.size(), video.limit());
522
jackychen55c88432015-11-09 14:58:14 -0800523 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
524 info != frame_info_list_.end(); ++info) {
525 const unsigned int frame = static_cast<unsigned>(info->pts);
Marco3cbc26f2016-02-10 11:39:04 -0800526 unsigned int expected_w;
527 unsigned int expected_h;
clang-format3a826f12016-08-11 17:46:05 -0700528 ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
529 &expected_h, 1);
clang-format4eafefe2017-09-04 12:51:20 -0700530 EXPECT_EQ(expected_w, info->w)
531 << "Frame " << frame << " had unexpected width";
532 EXPECT_EQ(expected_h, info->h)
533 << "Frame " << frame << " had unexpected height";
Marcob9cb9552016-03-07 16:58:06 -0800534 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
jackychen55c88432015-11-09 14:58:14 -0800535 }
536}
537
jackychen9ac42bc2015-09-15 14:17:04 -0700538// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
539// Run at low bitrate, with resize_allowed = 1, and verify that we get
540// one resize down event.
Urvang Joshic9ac07f2017-08-15 12:21:35 -0700541TEST_P(ResizeRealtimeTest, DISABLED_TestInternalResizeDown) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700542 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen9ac42bc2015-09-15 14:17:04 -0700543 30, 1, 0, 299);
544 DefaultConfig();
jackychen55c88432015-11-09 14:58:14 -0800545 cfg_.g_w = 352;
546 cfg_.g_h = 288;
jackychenca8f8fd2015-09-15 15:47:11 -0700547 change_bitrate_ = false;
Marcob9cb9552016-03-07 16:58:06 -0800548 mismatch_psnr_ = 0.0;
549 mismatch_nframes_ = 0;
jackychen9ac42bc2015-09-15 14:17:04 -0700550 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
551
552 unsigned int last_w = cfg_.g_w;
553 unsigned int last_h = cfg_.g_h;
554 int resize_count = 0;
555 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
556 info != frame_info_list_.end(); ++info) {
557 if (info->w != last_w || info->h != last_h) {
558 // Verify that resize down occurs.
559 ASSERT_LT(info->w, last_w);
560 ASSERT_LT(info->h, last_h);
561 last_w = info->w;
562 last_h = info->h;
563 resize_count++;
564 }
565 }
566
Yaowu Xuf883b422016-08-30 14:01:10 -0700567#if CONFIG_AV1_DECODER
jackychen9ac42bc2015-09-15 14:17:04 -0700568 // Verify that we get 1 resize down event in this test.
569 ASSERT_EQ(1, resize_count) << "Resizing should occur.";
Marcob9cb9552016-03-07 16:58:06 -0800570 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
James Zern0616fa62016-04-26 19:56:44 -0700571#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700572 printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
James Zern0616fa62016-04-26 19:56:44 -0700573#endif
jackychen9ac42bc2015-09-15 14:17:04 -0700574}
575
jackychenca8f8fd2015-09-15 15:47:11 -0700576// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
577// Start at low target bitrate, raise the bitrate in the middle of the clip,
578// scaling-up should occur after bitrate changed.
Urvang Joshic9ac07f2017-08-15 12:21:35 -0700579TEST_P(ResizeRealtimeTest, DISABLED_TestInternalResizeDownUpChangeBitRate) {
Yaowu Xuc27fc142016-08-22 16:08:15 -0700580 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen0465aa42015-11-09 14:04:58 -0800581 30, 1, 0, 359);
jackychenca8f8fd2015-09-15 15:47:11 -0700582 DefaultConfig();
jackychen55c88432015-11-09 14:58:14 -0800583 cfg_.g_w = 352;
584 cfg_.g_h = 288;
jackychenca8f8fd2015-09-15 15:47:11 -0700585 change_bitrate_ = true;
Marcob9cb9552016-03-07 16:58:06 -0800586 mismatch_psnr_ = 0.0;
587 mismatch_nframes_ = 0;
jackychenca8f8fd2015-09-15 15:47:11 -0700588 // Disable dropped frames.
589 cfg_.rc_dropframe_thresh = 0;
590 // Starting bitrate low.
jackychen204cde52015-11-13 16:02:43 -0800591 cfg_.rc_target_bitrate = 80;
jackychenca8f8fd2015-09-15 15:47:11 -0700592 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
593
594 unsigned int last_w = cfg_.g_w;
595 unsigned int last_h = cfg_.g_h;
596 int resize_count = 0;
597 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
598 info != frame_info_list_.end(); ++info) {
599 if (info->w != last_w || info->h != last_h) {
600 resize_count++;
601 if (resize_count == 1) {
602 // Verify that resize down occurs.
603 ASSERT_LT(info->w, last_w);
604 ASSERT_LT(info->h, last_h);
605 } else if (resize_count == 2) {
606 // Verify that resize up occurs.
607 ASSERT_GT(info->w, last_w);
608 ASSERT_GT(info->h, last_h);
609 }
610 last_w = info->w;
611 last_h = info->h;
612 }
613 }
614
Yaowu Xuf883b422016-08-30 14:01:10 -0700615#if CONFIG_AV1_DECODER
jackychen204cde52015-11-13 16:02:43 -0800616 // Verify that we get 2 resize events in this test.
617 ASSERT_EQ(resize_count, 2) << "Resizing should occur twice.";
Marcob9cb9552016-03-07 16:58:06 -0800618 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
James Zern0616fa62016-04-26 19:56:44 -0700619#else
Yaowu Xuf883b422016-08-30 14:01:10 -0700620 printf("Warning: AV1 decoder unavailable, unable to check resize count!\n");
James Zern0616fa62016-04-26 19:56:44 -0700621#endif
jackychenca8f8fd2015-09-15 15:47:11 -0700622}
623
Yaowu Xuf883b422016-08-30 14:01:10 -0700624aom_img_fmt_t CspForFrameNumber(int frame) {
625 if (frame < 10) return AOM_IMG_FMT_I420;
626 if (frame < 20) return AOM_IMG_FMT_I444;
627 return AOM_IMG_FMT_I420;
Alex Converse797a2552015-01-15 13:56:55 -0800628}
629
630class ResizeCspTest : public ResizeTest {
631 protected:
632#if WRITE_COMPRESSED_STREAM
633 ResizeCspTest()
clang-format3a826f12016-08-11 17:46:05 -0700634 : ResizeTest(), frame0_psnr_(0.0), outfile_(NULL), out_frames_(0) {}
Alex Converse797a2552015-01-15 13:56:55 -0800635#else
636 ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
637#endif
638
639 virtual ~ResizeCspTest() {}
640
641 virtual void BeginPassHook(unsigned int /*pass*/) {
642#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700643 outfile_ = fopen("av11-2-05-cspchape.ivf", "wb");
Alex Converse797a2552015-01-15 13:56:55 -0800644#endif
645 }
646
647 virtual void EndPassHook() {
648#if WRITE_COMPRESSED_STREAM
649 if (outfile_) {
650 if (!fseek(outfile_, 0, SEEK_SET))
651 write_ivf_file_header(&cfg_, out_frames_, outfile_);
652 fclose(outfile_);
653 outfile_ = NULL;
654 }
655#endif
656 }
657
Yaowu Xuc27fc142016-08-22 16:08:15 -0700658 virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
659 libaom_test::Encoder *encoder) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700660 if (CspForFrameNumber(video->frame()) != AOM_IMG_FMT_I420 &&
Alex Converse797a2552015-01-15 13:56:55 -0800661 cfg_.g_profile != 1) {
662 cfg_.g_profile = 1;
663 encoder->Config(&cfg_);
664 }
Yaowu Xuf883b422016-08-30 14:01:10 -0700665 if (CspForFrameNumber(video->frame()) == AOM_IMG_FMT_I420 &&
Alex Converse797a2552015-01-15 13:56:55 -0800666 cfg_.g_profile != 0) {
667 cfg_.g_profile = 0;
668 encoder->Config(&cfg_);
669 }
670 }
671
Yaowu Xuf883b422016-08-30 14:01:10 -0700672 virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
clang-format3a826f12016-08-11 17:46:05 -0700673 if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
Alex Converse797a2552015-01-15 13:56:55 -0800674 EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
675 }
676
677#if WRITE_COMPRESSED_STREAM
Yaowu Xuf883b422016-08-30 14:01:10 -0700678 virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) {
Alex Converse797a2552015-01-15 13:56:55 -0800679 ++out_frames_;
680
681 // Write initial file header if first frame.
clang-format3a826f12016-08-11 17:46:05 -0700682 if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
Alex Converse797a2552015-01-15 13:56:55 -0800683
684 // Write frame header and data.
685 write_ivf_frame_header(pkt, outfile_);
686 (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
687 }
688#endif
689
690 double frame0_psnr_;
691#if WRITE_COMPRESSED_STREAM
692 FILE *outfile_;
693 unsigned int out_frames_;
694#endif
695};
696
Yaowu Xuc27fc142016-08-22 16:08:15 -0700697class ResizingCspVideoSource : public ::libaom_test::DummyVideoSource {
Alex Converse797a2552015-01-15 13:56:55 -0800698 public:
699 ResizingCspVideoSource() {
700 SetSize(kInitialWidth, kInitialHeight);
701 limit_ = 30;
702 }
703
704 virtual ~ResizingCspVideoSource() {}
705
706 protected:
707 virtual void Next() {
708 ++frame_;
709 SetImageFormat(CspForFrameNumber(frame_));
710 FillFrame();
711 }
712};
713
Debargha Mukherjee34e3a142017-10-05 12:46:14 -0700714#if (defined(DISABLE_TRELLISQ_SEARCH) && DISABLE_TRELLISQ_SEARCH)
Angie Chianga6034882017-09-28 15:35:14 -0700715TEST_P(ResizeCspTest, DISABLED_TestResizeCspWorks) {
716#else
Alex Converse797a2552015-01-15 13:56:55 -0800717TEST_P(ResizeCspTest, TestResizeCspWorks) {
Angie Chianga6034882017-09-28 15:35:14 -0700718#endif
Alex Converse797a2552015-01-15 13:56:55 -0800719 ResizingCspVideoSource video;
Yaowu Xuf883b422016-08-30 14:01:10 -0700720 init_flags_ = AOM_CODEC_USE_PSNR;
Alex Converse797a2552015-01-15 13:56:55 -0800721 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
722 cfg_.g_lag_in_frames = 0;
723 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
Imdad Sardharwalladadaba62018-02-23 12:06:56 +0000724
725 // Check we decoded the same number of frames as we attempted to encode
726 ASSERT_EQ(frame_info_list_.size(), video.limit());
Alex Converse797a2552015-01-15 13:56:55 -0800727}
728
Yaowu Xuf883b422016-08-30 14:01:10 -0700729AV1_INSTANTIATE_TEST_CASE(ResizeTest,
730 ::testing::Values(::libaom_test::kRealTime));
Debargha Mukherjee15b6ae02017-10-10 19:56:05 -0700731AV1_INSTANTIATE_TEST_CASE(ResizeInternalTestLarge,
Urvang Joshic9ac07f2017-08-15 12:21:35 -0700732 ::testing::Values(::libaom_test::kOnePassGood));
Yaowu Xuf883b422016-08-30 14:01:10 -0700733AV1_INSTANTIATE_TEST_CASE(ResizeRealtimeTest,
734 ::testing::Values(::libaom_test::kRealTime),
735 ::testing::Range(5, 9));
736AV1_INSTANTIATE_TEST_CASE(ResizeCspTest,
737 ::testing::Values(::libaom_test::kRealTime));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700738} // namespace