blob: 46a3b6e03cb0e3ce342eb7e777f5e41726ec53d3 [file] [log] [blame]
John Koleszar2fb29ff2012-05-23 12:55:27 -07001/*
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3 *
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.
9 */
James Zern0616fa62016-04-26 19:56:44 -070010#include <stdio.h>
11
John Koleszar2fb29ff2012-05-23 12:55:27 -070012#include <climits>
13#include <vector>
John Koleszar706cafe2013-01-18 11:51:12 -080014#include "third_party/googletest/src/include/gtest/gtest.h"
15#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
27static void mem_put_le16(char *const mem, const unsigned int val) {
28 mem[0] = val;
29 mem[1] = val >> 8;
30}
31
32static void mem_put_le32(char *const mem, const unsigned int val) {
33 mem[0] = val;
34 mem[1] = val >> 8;
35 mem[2] = val >> 16;
36 mem[3] = val >> 24;
37}
38
39static void write_ivf_file_header(const vpx_codec_enc_cfg_t *const cfg,
40 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';
47 mem_put_le16(header + 4, 0); /* version */
48 mem_put_le16(header + 6, 32); /* headersize */
49 mem_put_le32(header + 8, 0x30395056); /* fourcc (vp9) */
50 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
66static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt,
67 FILE *const outfile) {
68 char header[12];
69 vpx_codec_pts_t pts;
70
71 if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
72 return;
73
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 {
87 FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
88 : pts(_pts), w(_w), h(_h) {}
89
90 vpx_codec_pts_t pts;
91 unsigned int w;
92 unsigned int h;
93};
94
Marco3cbc26f2016-02-10 11:39:04 -080095void ScaleForFrameNumber(unsigned int frame,
96 unsigned int initial_w,
97 unsigned int initial_h,
98 unsigned int *w,
99 unsigned int *h,
100 int flag_codec) {
101 if (frame < 10) {
102 *w = initial_w;
103 *h = initial_h;
104 return;
105 }
106 if (frame < 20) {
107 *w = initial_w * 3 / 4;
108 *h = initial_h * 3 / 4;
109 return;
110 }
111 if (frame < 30) {
112 *w = initial_w / 2;
113 *h = initial_h / 2;
114 return;
115 }
116 if (frame < 40) {
117 *w = initial_w;
118 *h = initial_h;
119 return;
120 }
121 if (frame < 50) {
122 *w = initial_w * 3 / 4;
123 *h = initial_h * 3 / 4;
124 return;
125 }
126 if (frame < 60) {
127 *w = initial_w / 2;
128 *h = initial_h / 2;
129 return;
130 }
131 if (frame < 70) {
132 *w = initial_w;
133 *h = initial_h;
134 return;
135 }
136 if (frame < 80) {
137 *w = initial_w * 3 / 4;
138 *h = initial_h * 3 / 4;
139 return;
140 }
141 if (frame < 90) {
142 *w = initial_w / 2;
143 *h = initial_h / 2;
144 return;
145 }
146 if (frame < 100) {
147 *w = initial_w * 3 / 4;
148 *h = initial_h * 3 / 4;
149 return;
150 }
151 if (frame < 110) {
152 *w = initial_w;
153 *h = initial_h;
154 return;
155 }
156 if (frame < 120) {
157 *w = initial_w * 3 / 4;
158 *h = initial_h * 3 / 4;
159 return;
160 }
161 if (frame < 130) {
162 *w = initial_w / 2;
163 *h = initial_h / 2;
164 return;
165 }
166 if (frame < 140) {
167 *w = initial_w * 3 / 4;
168 *h = initial_h * 3 / 4;
169 return;
170 }
171 if (frame < 150) {
172 *w = initial_w;
173 *h = initial_h;
174 return;
175 }
176 if (frame < 160) {
177 *w = initial_w * 3 / 4;
178 *h = initial_h * 3 / 4;
179 return;
180 }
181 if (frame < 170) {
182 *w = initial_w / 2;
183 *h = initial_h / 2;
184 return;
185 }
186 if (frame < 180) {
187 *w = initial_w * 3 / 4;
188 *h = initial_h * 3 / 4;
189 return;
190 }
191 if (frame < 190) {
192 *w = initial_w;
193 *h = initial_h;
194 return;
195 }
196 if (frame < 200) {
197 *w = initial_w * 3 / 4;
198 *h = initial_h * 3 / 4;
199 return;
200 }
201 if (frame < 210) {
202 *w = initial_w / 2;
203 *h = initial_h / 2;
204 return;
205 }
206 if (frame < 220) {
207 *w = initial_w * 3 / 4;
208 *h = initial_h * 3 / 4;
209 return;
210 }
211 if (frame < 230) {
212 *w = initial_w;
213 *h = initial_h;
214 return;
215 }
216 if (frame < 240) {
217 *w = initial_w * 3 / 4;
218 *h = initial_h * 3 / 4;
219 return;
220 }
221 if (frame < 250) {
222 *w = initial_w / 2;
223 *h = initial_h / 2;
224 return;
225 }
226 if (frame < 260) {
227 *w = initial_w;
228 *h = initial_h;
229 return;
230 }
231 // Go down very low.
232 if (frame < 270) {
233 *w = initial_w / 4;
234 *h = initial_h / 4;
235 return;
236 }
237 if (flag_codec == 1) {
238 // Cases that only works for VP9.
239 // For VP9: Swap width and height of original.
240 if (frame < 320) {
241 *w = initial_h;
242 *h = initial_w;
243 return;
244 }
245 }
246 *w = initial_w;
247 *h = initial_h;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700248}
249
250class ResizingVideoSource : public ::libvpx_test::DummyVideoSource {
251 public:
252 ResizingVideoSource() {
253 SetSize(kInitialWidth, kInitialHeight);
Marco3cbc26f2016-02-10 11:39:04 -0800254 limit_ = 350;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700255 }
Marco3cbc26f2016-02-10 11:39:04 -0800256 int flag_codec_;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700257 virtual ~ResizingVideoSource() {}
258
John Koleszar2fb29ff2012-05-23 12:55:27 -0700259 protected:
260 virtual void Next() {
261 ++frame_;
Marco3cbc26f2016-02-10 11:39:04 -0800262 unsigned int width;
263 unsigned int height;
264 ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height,
265 flag_codec_);
266 SetSize(width, height);
John Koleszar2fb29ff2012-05-23 12:55:27 -0700267 FillFrame();
268 }
269};
270
271class ResizeTest : public ::libvpx_test::EncoderTest,
John Koleszar706cafe2013-01-18 11:51:12 -0800272 public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
John Koleszar2fb29ff2012-05-23 12:55:27 -0700273 protected:
John Koleszar706cafe2013-01-18 11:51:12 -0800274 ResizeTest() : EncoderTest(GET_PARAM(0)) {}
275
Adrian Grange88c8ff22013-09-12 09:35:04 -0700276 virtual ~ResizeTest() {}
277
John Koleszar2fb29ff2012-05-23 12:55:27 -0700278 virtual void SetUp() {
279 InitializeConfig();
John Koleszar706cafe2013-01-18 11:51:12 -0800280 SetMode(GET_PARAM(1));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700281 }
282
John Koleszar88f99f42013-02-06 12:44:20 -0800283 virtual void DecompressedFrameHook(const vpx_image_t &img,
284 vpx_codec_pts_t pts) {
285 frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700286 }
287
288 std::vector< FrameInfo > frame_info_list_;
289};
290
291TEST_P(ResizeTest, TestExternalResizeWorks) {
292 ResizingVideoSource video;
Marco3cbc26f2016-02-10 11:39:04 -0800293 video.flag_codec_ = 0;
Alex Converse910ca852015-01-12 16:26:05 -0800294 cfg_.g_lag_in_frames = 0;
John Koleszar2fb29ff2012-05-23 12:55:27 -0700295 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
296
James Zernbb061382014-01-31 20:11:55 -0800297 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
John Koleszar2fb29ff2012-05-23 12:55:27 -0700298 info != frame_info_list_.end(); ++info) {
James Zern17b89932014-01-31 20:10:28 -0800299 const unsigned int frame = static_cast<unsigned>(info->pts);
Marco3cbc26f2016-02-10 11:39:04 -0800300 unsigned int expected_w;
301 unsigned int expected_h;
302 ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
303 &expected_w, &expected_h, 0);
John Koleszar2fb29ff2012-05-23 12:55:27 -0700304 EXPECT_EQ(expected_w, info->w)
Alex Converse910ca852015-01-12 16:26:05 -0800305 << "Frame " << frame << " had unexpected width";
John Koleszar2fb29ff2012-05-23 12:55:27 -0700306 EXPECT_EQ(expected_h, info->h)
Alex Converse910ca852015-01-12 16:26:05 -0800307 << "Frame " << frame << " had unexpected height";
John Koleszar2fb29ff2012-05-23 12:55:27 -0700308 }
309}
310
Adrian Grange88c8ff22013-09-12 09:35:04 -0700311const unsigned int kStepDownFrame = 3;
312const unsigned int kStepUpFrame = 6;
313
John Koleszar88f99f42013-02-06 12:44:20 -0800314class ResizeInternalTest : public ResizeTest {
315 protected:
Adrian Grange88c8ff22013-09-12 09:35:04 -0700316#if WRITE_COMPRESSED_STREAM
317 ResizeInternalTest()
318 : ResizeTest(),
319 frame0_psnr_(0.0),
320 outfile_(NULL),
321 out_frames_(0) {}
322#else
John Koleszarb683eec2013-02-21 10:38:27 -0800323 ResizeInternalTest() : ResizeTest(), frame0_psnr_(0.0) {}
Adrian Grange88c8ff22013-09-12 09:35:04 -0700324#endif
325
326 virtual ~ResizeInternalTest() {}
327
328 virtual void BeginPassHook(unsigned int /*pass*/) {
329#if WRITE_COMPRESSED_STREAM
330 outfile_ = fopen("vp90-2-05-resize.ivf", "wb");
331#endif
332 }
333
334 virtual void EndPassHook() {
335#if WRITE_COMPRESSED_STREAM
336 if (outfile_) {
337 if (!fseek(outfile_, 0, SEEK_SET))
338 write_ivf_file_header(&cfg_, out_frames_, outfile_);
339 fclose(outfile_);
340 outfile_ = NULL;
341 }
342#endif
343 }
John Koleszar88f99f42013-02-06 12:44:20 -0800344
345 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
346 libvpx_test::Encoder *encoder) {
jackychen55f092d2015-09-21 09:37:46 -0700347 if (change_config_) {
348 int new_q = 60;
349 if (video->frame() == 0) {
350 struct vpx_scaling_mode mode = {VP8E_ONETWO, VP8E_ONETWO};
351 encoder->Control(VP8E_SET_SCALEMODE, &mode);
352 }
353 if (video->frame() == 1) {
354 struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
355 encoder->Control(VP8E_SET_SCALEMODE, &mode);
356 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
357 encoder->Config(&cfg_);
358 }
359 } else {
360 if (video->frame() == kStepDownFrame) {
361 struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE};
362 encoder->Control(VP8E_SET_SCALEMODE, &mode);
363 }
364 if (video->frame() == kStepUpFrame) {
365 struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
366 encoder->Control(VP8E_SET_SCALEMODE, &mode);
367 }
John Koleszarb683eec2013-02-21 10:38:27 -0800368 }
John Koleszar88f99f42013-02-06 12:44:20 -0800369 }
John Koleszarb683eec2013-02-21 10:38:27 -0800370
371 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
James Zern60be7932016-07-22 13:11:07 -0700372 if (frame0_psnr_ == 0.)
John Koleszarb683eec2013-02-21 10:38:27 -0800373 frame0_psnr_ = pkt->data.psnr.psnr[0];
Deb Mukherjee3cd37df2014-01-17 12:56:36 -0800374 EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
John Koleszarb683eec2013-02-21 10:38:27 -0800375 }
376
Adrian Grange88c8ff22013-09-12 09:35:04 -0700377#if WRITE_COMPRESSED_STREAM
James Zerndbe69172014-08-22 12:11:42 -0700378 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
Adrian Grange88c8ff22013-09-12 09:35:04 -0700379 ++out_frames_;
380
381 // Write initial file header if first frame.
382 if (pkt->data.frame.pts == 0)
383 write_ivf_file_header(&cfg_, 0, outfile_);
384
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
399TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
400 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
John Koleszarb683eec2013-02-21 10:38:27 -0800401 30, 1, 0, 10);
402 init_flags_ = VPX_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) {
417 const vpx_codec_pts_t pts = info->pts;
Adrian Grange88c8ff22013-09-12 09:35:04 -0700418 if (pts >= kStepDownFrame && pts < kStepUpFrame) {
John Koleszar88f99f42013-02-06 12:44:20 -0800419 ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
420 ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
421 } else {
422 EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
423 EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
424 }
425 }
426}
427
jackychen55f092d2015-09-21 09:37:46 -0700428TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) {
429 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
430 30, 1, 0, 10);
431 cfg_.g_w = 352;
432 cfg_.g_h = 288;
433 change_config_ = true;
434 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
435}
436
jackychen55c88432015-11-09 14:58:14 -0800437class ResizeRealtimeTest : public ::libvpx_test::EncoderTest,
jackychen9ac42bc2015-09-15 14:17:04 -0700438 public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
439 protected:
jackychen55c88432015-11-09 14:58:14 -0800440 ResizeRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
441 virtual ~ResizeRealtimeTest() {}
jackychen9ac42bc2015-09-15 14:17:04 -0700442
443 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
444 libvpx_test::Encoder *encoder) {
445 if (video->frame() == 0) {
446 encoder->Control(VP9E_SET_AQ_MODE, 3);
447 encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
448 }
jackychenca8f8fd2015-09-15 15:47:11 -0700449
450 if (change_bitrate_ && video->frame() == 120) {
451 change_bitrate_ = false;
452 cfg_.rc_target_bitrate = 500;
453 encoder->Config(&cfg_);
454 }
jackychen9ac42bc2015-09-15 14:17:04 -0700455 }
456
457 virtual void SetUp() {
458 InitializeConfig();
459 SetMode(GET_PARAM(1));
460 set_cpu_used_ = GET_PARAM(2);
461 }
462
463 virtual void DecompressedFrameHook(const vpx_image_t &img,
464 vpx_codec_pts_t pts) {
465 frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
466 }
467
Marcob9cb9552016-03-07 16:58:06 -0800468 virtual void MismatchHook(const vpx_image_t *img1,
469 const vpx_image_t *img2) {
470 double mismatch_psnr = compute_psnr(img1, img2);
471 mismatch_psnr_ += mismatch_psnr;
472 ++mismatch_nframes_;
473 }
474
475 unsigned int GetMismatchFrames() {
476 return mismatch_nframes_;
477 }
478
jackychen9ac42bc2015-09-15 14:17:04 -0700479 void DefaultConfig() {
jackychen9ac42bc2015-09-15 14:17:04 -0700480 cfg_.rc_buf_initial_sz = 500;
481 cfg_.rc_buf_optimal_sz = 600;
482 cfg_.rc_buf_sz = 1000;
483 cfg_.rc_min_quantizer = 2;
484 cfg_.rc_max_quantizer = 56;
485 cfg_.rc_undershoot_pct = 50;
486 cfg_.rc_overshoot_pct = 50;
487 cfg_.rc_end_usage = VPX_CBR;
488 cfg_.kf_mode = VPX_KF_AUTO;
489 cfg_.g_lag_in_frames = 0;
490 cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
491 // Enable dropped frames.
492 cfg_.rc_dropframe_thresh = 1;
493 // Enable error_resilience mode.
494 cfg_.g_error_resilient = 1;
495 // Enable dynamic resizing.
496 cfg_.rc_resize_allowed = 1;
497 // Run at low bitrate.
498 cfg_.rc_target_bitrate = 200;
499 }
500
501 std::vector< FrameInfo > frame_info_list_;
502 int set_cpu_used_;
jackychenca8f8fd2015-09-15 15:47:11 -0700503 bool change_bitrate_;
Marcob9cb9552016-03-07 16:58:06 -0800504 double mismatch_psnr_;
505 int mismatch_nframes_;
jackychen9ac42bc2015-09-15 14:17:04 -0700506};
507
jackychen55c88432015-11-09 14:58:14 -0800508TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
509 ResizingVideoSource video;
Marco3cbc26f2016-02-10 11:39:04 -0800510 video.flag_codec_ = 1;
jackychen55c88432015-11-09 14:58:14 -0800511 DefaultConfig();
Marco34d12d12016-02-10 16:59:09 -0800512 // Disable internal resize for this test.
513 cfg_.rc_resize_allowed = 0;
jackychen55c88432015-11-09 14:58:14 -0800514 change_bitrate_ = false;
Marcob9cb9552016-03-07 16:58:06 -0800515 mismatch_psnr_ = 0.0;
516 mismatch_nframes_ = 0;
jackychen55c88432015-11-09 14:58:14 -0800517 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
518
519 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
520 info != frame_info_list_.end(); ++info) {
521 const unsigned int frame = static_cast<unsigned>(info->pts);
Marco3cbc26f2016-02-10 11:39:04 -0800522 unsigned int expected_w;
523 unsigned int expected_h;
524 ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
525 &expected_w, &expected_h, 1);
jackychen55c88432015-11-09 14:58:14 -0800526 EXPECT_EQ(expected_w, info->w)
527 << "Frame " << frame << " had unexpected width";
528 EXPECT_EQ(expected_h, info->h)
529 << "Frame " << frame << " had unexpected height";
Marcob9cb9552016-03-07 16:58:06 -0800530 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
jackychen55c88432015-11-09 14:58:14 -0800531 }
532}
533
jackychen9ac42bc2015-09-15 14:17:04 -0700534// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
535// Run at low bitrate, with resize_allowed = 1, and verify that we get
536// one resize down event.
jackychen55c88432015-11-09 14:58:14 -0800537TEST_P(ResizeRealtimeTest, TestInternalResizeDown) {
jackychen9ac42bc2015-09-15 14:17:04 -0700538 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
539 30, 1, 0, 299);
540 DefaultConfig();
jackychen55c88432015-11-09 14:58:14 -0800541 cfg_.g_w = 352;
542 cfg_.g_h = 288;
jackychenca8f8fd2015-09-15 15:47:11 -0700543 change_bitrate_ = false;
Marcob9cb9552016-03-07 16:58:06 -0800544 mismatch_psnr_ = 0.0;
545 mismatch_nframes_ = 0;
jackychen9ac42bc2015-09-15 14:17:04 -0700546 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
547
548 unsigned int last_w = cfg_.g_w;
549 unsigned int last_h = cfg_.g_h;
550 int resize_count = 0;
551 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
552 info != frame_info_list_.end(); ++info) {
553 if (info->w != last_w || info->h != last_h) {
554 // Verify that resize down occurs.
555 ASSERT_LT(info->w, last_w);
556 ASSERT_LT(info->h, last_h);
557 last_w = info->w;
558 last_h = info->h;
559 resize_count++;
560 }
561 }
562
James Zern0616fa62016-04-26 19:56:44 -0700563#if CONFIG_VP9_DECODER
jackychen9ac42bc2015-09-15 14:17:04 -0700564 // Verify that we get 1 resize down event in this test.
565 ASSERT_EQ(1, resize_count) << "Resizing should occur.";
Marcob9cb9552016-03-07 16:58:06 -0800566 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
James Zern0616fa62016-04-26 19:56:44 -0700567#else
568 printf("Warning: VP9 decoder unavailable, unable to check resize count!\n");
569#endif
jackychen9ac42bc2015-09-15 14:17:04 -0700570}
571
jackychenca8f8fd2015-09-15 15:47:11 -0700572// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
573// Start at low target bitrate, raise the bitrate in the middle of the clip,
574// scaling-up should occur after bitrate changed.
jackychen55c88432015-11-09 14:58:14 -0800575TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
jackychenca8f8fd2015-09-15 15:47:11 -0700576 ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
jackychen0465aa42015-11-09 14:04:58 -0800577 30, 1, 0, 359);
jackychenca8f8fd2015-09-15 15:47:11 -0700578 DefaultConfig();
jackychen55c88432015-11-09 14:58:14 -0800579 cfg_.g_w = 352;
580 cfg_.g_h = 288;
jackychenca8f8fd2015-09-15 15:47:11 -0700581 change_bitrate_ = true;
Marcob9cb9552016-03-07 16:58:06 -0800582 mismatch_psnr_ = 0.0;
583 mismatch_nframes_ = 0;
jackychenca8f8fd2015-09-15 15:47:11 -0700584 // Disable dropped frames.
585 cfg_.rc_dropframe_thresh = 0;
586 // Starting bitrate low.
jackychen204cde52015-11-13 16:02:43 -0800587 cfg_.rc_target_bitrate = 80;
jackychenca8f8fd2015-09-15 15:47:11 -0700588 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
589
590 unsigned int last_w = cfg_.g_w;
591 unsigned int last_h = cfg_.g_h;
592 int resize_count = 0;
593 for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
594 info != frame_info_list_.end(); ++info) {
595 if (info->w != last_w || info->h != last_h) {
596 resize_count++;
597 if (resize_count == 1) {
598 // Verify that resize down occurs.
599 ASSERT_LT(info->w, last_w);
600 ASSERT_LT(info->h, last_h);
601 } else if (resize_count == 2) {
602 // Verify that resize up occurs.
603 ASSERT_GT(info->w, last_w);
604 ASSERT_GT(info->h, last_h);
605 }
606 last_w = info->w;
607 last_h = info->h;
608 }
609 }
610
James Zern0616fa62016-04-26 19:56:44 -0700611#if CONFIG_VP9_DECODER
jackychen204cde52015-11-13 16:02:43 -0800612 // Verify that we get 2 resize events in this test.
613 ASSERT_EQ(resize_count, 2) << "Resizing should occur twice.";
Marcob9cb9552016-03-07 16:58:06 -0800614 EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
James Zern0616fa62016-04-26 19:56:44 -0700615#else
616 printf("Warning: VP9 decoder unavailable, unable to check resize count!\n");
617#endif
jackychenca8f8fd2015-09-15 15:47:11 -0700618}
619
Alex Converse797a2552015-01-15 13:56:55 -0800620vpx_img_fmt_t CspForFrameNumber(int frame) {
621 if (frame < 10)
622 return VPX_IMG_FMT_I420;
623 if (frame < 20)
624 return VPX_IMG_FMT_I444;
625 return VPX_IMG_FMT_I420;
626}
627
628class ResizeCspTest : public ResizeTest {
629 protected:
630#if WRITE_COMPRESSED_STREAM
631 ResizeCspTest()
632 : ResizeTest(),
633 frame0_psnr_(0.0),
634 outfile_(NULL),
635 out_frames_(0) {}
636#else
637 ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
638#endif
639
640 virtual ~ResizeCspTest() {}
641
642 virtual void BeginPassHook(unsigned int /*pass*/) {
643#if WRITE_COMPRESSED_STREAM
644 outfile_ = fopen("vp91-2-05-cspchape.ivf", "wb");
645#endif
646 }
647
648 virtual void EndPassHook() {
649#if WRITE_COMPRESSED_STREAM
650 if (outfile_) {
651 if (!fseek(outfile_, 0, SEEK_SET))
652 write_ivf_file_header(&cfg_, out_frames_, outfile_);
653 fclose(outfile_);
654 outfile_ = NULL;
655 }
656#endif
657 }
658
659 virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
660 libvpx_test::Encoder *encoder) {
661 if (CspForFrameNumber(video->frame()) != VPX_IMG_FMT_I420 &&
662 cfg_.g_profile != 1) {
663 cfg_.g_profile = 1;
664 encoder->Config(&cfg_);
665 }
666 if (CspForFrameNumber(video->frame()) == VPX_IMG_FMT_I420 &&
667 cfg_.g_profile != 0) {
668 cfg_.g_profile = 0;
669 encoder->Config(&cfg_);
670 }
671 }
672
673 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
James Zern60be7932016-07-22 13:11:07 -0700674 if (frame0_psnr_ == 0.)
Alex Converse797a2552015-01-15 13:56:55 -0800675 frame0_psnr_ = pkt->data.psnr.psnr[0];
676 EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
677 }
678
679#if WRITE_COMPRESSED_STREAM
680 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
681 ++out_frames_;
682
683 // Write initial file header if first frame.
684 if (pkt->data.frame.pts == 0)
685 write_ivf_file_header(&cfg_, 0, outfile_);
686
687 // Write frame header and data.
688 write_ivf_frame_header(pkt, outfile_);
689 (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
690 }
691#endif
692
693 double frame0_psnr_;
694#if WRITE_COMPRESSED_STREAM
695 FILE *outfile_;
696 unsigned int out_frames_;
697#endif
698};
699
700class ResizingCspVideoSource : public ::libvpx_test::DummyVideoSource {
701 public:
702 ResizingCspVideoSource() {
703 SetSize(kInitialWidth, kInitialHeight);
704 limit_ = 30;
705 }
706
707 virtual ~ResizingCspVideoSource() {}
708
709 protected:
710 virtual void Next() {
711 ++frame_;
712 SetImageFormat(CspForFrameNumber(frame_));
713 FillFrame();
714 }
715};
716
717TEST_P(ResizeCspTest, TestResizeCspWorks) {
718 ResizingCspVideoSource video;
James Zern40f177a2015-02-26 20:31:59 -0800719 init_flags_ = VPX_CODEC_USE_PSNR;
Alex Converse797a2552015-01-15 13:56:55 -0800720 cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
721 cfg_.g_lag_in_frames = 0;
722 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
723}
724
Yaowu Xu3fa28d52016-07-27 15:52:42 -0700725VP10_INSTANTIATE_TEST_CASE(ResizeTest,
Alex Converse910ca852015-01-12 16:26:05 -0800726 ::testing::Values(::libvpx_test::kRealTime));
Yaowu Xu3fa28d52016-07-27 15:52:42 -0700727VP10_INSTANTIATE_TEST_CASE(ResizeInternalTest,
John Koleszar88f99f42013-02-06 12:44:20 -0800728 ::testing::Values(::libvpx_test::kOnePassBest));
Yaowu Xu3fa28d52016-07-27 15:52:42 -0700729VP10_INSTANTIATE_TEST_CASE(ResizeRealtimeTest,
jackychen9ac42bc2015-09-15 14:17:04 -0700730 ::testing::Values(::libvpx_test::kRealTime),
731 ::testing::Range(5, 9));
Yaowu Xu3fa28d52016-07-27 15:52:42 -0700732VP10_INSTANTIATE_TEST_CASE(ResizeCspTest,
Alex Converse797a2552015-01-15 13:56:55 -0800733 ::testing::Values(::libvpx_test::kRealTime));
John Koleszar2fb29ff2012-05-23 12:55:27 -0700734} // namespace