2 * Copyright (c) 2013 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.
12 #include "test/codec_factory.h"
13 #include "test/decode_test_driver.h"
14 #include "test/encode_test_driver.h"
15 #include "test/i420_video_source.h"
16 #include "test/ivf_video_source.h"
17 #include "test/md5_helper.h"
18 #include "test/util.h"
19 #include "test/webm_video_source.h"
20 #include "vpx_ports/vpx_timer.h"
22 #include "./vpx_version.h"
24 using std::tr1::make_tuple;
31 const int kMaxPsnr = 100;
32 const double kUsecsInSec = 1000000.0;
33 const char kNewEncodeOutputFile[] = "new_encode.ivf";
36 DecodePerfTest takes a tuple of filename + number of threads to decode with
38 typedef std::tr1::tuple<const char *, unsigned> DecodePerfParam;
40 const DecodePerfParam kVP9DecodePerfVectors[] = {
41 make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),
42 make_tuple("vp90-2-bbb_640x360_tile_1x2_337kbps.webm", 2),
43 make_tuple("vp90-2-bbb_854x480_tile_1x2_651kbps.webm", 2),
44 make_tuple("vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm", 4),
45 make_tuple("vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm", 1),
46 make_tuple("vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm", 4),
47 make_tuple("vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm", 4),
48 make_tuple("vp90-2-sintel_426x182_tile_1x1_171kbps.webm", 1),
49 make_tuple("vp90-2-sintel_640x272_tile_1x2_318kbps.webm", 2),
50 make_tuple("vp90-2-sintel_854x364_tile_1x2_621kbps.webm", 2),
51 make_tuple("vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm", 4),
52 make_tuple("vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm", 4),
53 make_tuple("vp90-2-tos_426x178_tile_1x1_181kbps.webm", 1),
54 make_tuple("vp90-2-tos_640x266_tile_1x2_336kbps.webm", 2),
55 make_tuple("vp90-2-tos_854x356_tile_1x2_656kbps.webm", 2),
56 make_tuple("vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm", 2),
57 make_tuple("vp90-2-tos_1280x534_tile_1x4_1306kbps.webm", 4),
58 make_tuple("vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm", 4),
59 make_tuple("vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm", 4),
63 In order to reflect real world performance as much as possible, Perf tests
64 *DO NOT* do any correctness checks. Please run them alongside correctness
65 tests to ensure proper codec integrity. Furthermore, in this test we
66 deliberately limit the amount of system calls we make to avoid OS
69 TODO(joshualitt) create a more detailed perf measurement test to collect
70 power/temp/min max frame decode times/etc
73 class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {
76 TEST_P(DecodePerfTest, PerfTest) {
77 const char *const video_name = GET_PARAM(VIDEO_NAME);
78 const unsigned threads = GET_PARAM(THREADS);
80 libvpx_test::WebMVideoSource video(video_name);
83 vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
84 cfg.threads = threads;
85 libvpx_test::VP9Decoder decoder(cfg, 0);
88 vpx_usec_timer_start(&t);
90 for (video.Begin(); video.cxdata() != NULL; video.Next()) {
91 decoder.DecodeFrame(video.cxdata(), video.frame_size());
94 vpx_usec_timer_mark(&t);
95 const double elapsed_secs = double(vpx_usec_timer_elapsed(&t))
97 const unsigned frames = video.frame_number();
98 const double fps = double(frames) / elapsed_secs;
101 printf("\t\"type\" : \"decode_perf_test\",\n");
102 printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
103 printf("\t\"videoName\" : \"%s\",\n", video_name);
104 printf("\t\"threadCount\" : %u,\n", threads);
105 printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
106 printf("\t\"totalFrames\" : %u,\n", frames);
107 printf("\t\"framesPerSecond\" : %f\n", fps);
111 INSTANTIATE_TEST_CASE_P(VP9, DecodePerfTest,
112 ::testing::ValuesIn(kVP9DecodePerfVectors));
114 class VP9NewEncodeDecodePerfTest :
115 public ::libvpx_test::EncoderTest,
116 public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
118 VP9NewEncodeDecodePerfTest()
119 : EncoderTest(GET_PARAM(0)),
120 encoding_mode_(GET_PARAM(1)),
126 virtual ~VP9NewEncodeDecodePerfTest() {}
128 virtual void SetUp() {
130 SetMode(encoding_mode_);
132 cfg_.g_lag_in_frames = 25;
133 cfg_.rc_min_quantizer = 2;
134 cfg_.rc_max_quantizer = 56;
135 cfg_.rc_dropframe_thresh = 0;
136 cfg_.rc_undershoot_pct = 50;
137 cfg_.rc_overshoot_pct = 50;
138 cfg_.rc_buf_sz = 1000;
139 cfg_.rc_buf_initial_sz = 500;
140 cfg_.rc_buf_optimal_sz = 600;
141 cfg_.rc_resize_allowed = 0;
142 cfg_.rc_end_usage = VPX_VBR;
145 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
146 ::libvpx_test::Encoder *encoder) {
147 if (video->frame() == 1) {
148 encoder->Control(VP8E_SET_CPUUSED, speed_);
149 encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
150 encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
154 virtual void BeginPassHook(unsigned int /*pass*/) {
155 const std::string data_path = getenv("LIBVPX_TEST_DATA_PATH");
156 const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile;
157 outfile_ = fopen(path_to_source.c_str(), "wb");
158 ASSERT_TRUE(outfile_ != NULL);
161 virtual void EndPassHook() {
162 if (outfile_ != NULL) {
163 if (!fseek(outfile_, 0, SEEK_SET))
164 ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
170 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
173 // Write initial file header if first frame.
174 if (pkt->data.frame.pts == 0)
175 ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
177 // Write frame header and data.
178 ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz);
179 ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_),
183 virtual bool DoDecode() { return false; }
185 void set_speed(unsigned int speed) {
190 libvpx_test::TestMode encoding_mode_;
193 uint32_t out_frames_;
196 struct EncodePerfTestVideo {
197 EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
198 uint32_t bitrate_, int frames_)
211 const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
212 EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
215 TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
218 // TODO(JBB): Make this work by going through the set of given files.
220 const vpx_rational timebase = { 33333333, 1000000000 };
221 cfg_.g_timebase = timebase;
222 cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
224 init_flags_ = VPX_CODEC_USE_PSNR;
226 const char *video_name = kVP9EncodePerfTestVectors[i].name;
227 libvpx_test::I420VideoSource video(
229 kVP9EncodePerfTestVectors[i].width,
230 kVP9EncodePerfTestVectors[i].height,
231 timebase.den, timebase.num, 0,
232 kVP9EncodePerfTestVectors[i].frames);
235 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
237 const uint32_t threads = 4;
239 libvpx_test::IVFVideoSource decode_video(kNewEncodeOutputFile);
242 vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
243 cfg.threads = threads;
244 libvpx_test::VP9Decoder decoder(cfg, 0);
247 vpx_usec_timer_start(&t);
249 for (decode_video.Begin(); decode_video.cxdata() != NULL;
250 decode_video.Next()) {
251 decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size());
254 vpx_usec_timer_mark(&t);
255 const double elapsed_secs =
256 static_cast<double>(vpx_usec_timer_elapsed(&t)) / kUsecsInSec;
257 const unsigned decode_frames = decode_video.frame_number();
258 const double fps = static_cast<double>(decode_frames) / elapsed_secs;
261 printf("\t\"type\" : \"decode_perf_test\",\n");
262 printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
263 printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile);
264 printf("\t\"threadCount\" : %u,\n", threads);
265 printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
266 printf("\t\"totalFrames\" : %u,\n", decode_frames);
267 printf("\t\"framesPerSecond\" : %f\n", fps);
271 VP9_INSTANTIATE_TEST_CASE(
272 VP9NewEncodeDecodePerfTest, ::testing::Values(::libvpx_test::kTwoPassGood));