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.
14 #include "test/codec_factory.h"
15 #include "test/decode_test_driver.h"
16 #include "test/encode_test_driver.h"
17 #include "test/i420_video_source.h"
18 #include "test/ivf_video_source.h"
19 #include "test/md5_helper.h"
20 #include "test/util.h"
21 #include "test/webm_video_source.h"
22 #include "vpx_ports/vpx_timer.h"
24 #include "./vpx_version.h"
26 using std::make_tuple;
33 const double kUsecsInSec = 1000000.0;
34 const char kNewEncodeOutputFile[] = "new_encode.ivf";
37 DecodePerfTest takes a tuple of filename + number of threads to decode with
39 typedef std::tuple<const char *, unsigned> DecodePerfParam;
41 const DecodePerfParam kVP9DecodePerfVectors[] = {
42 make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),
43 make_tuple("vp90-2-bbb_640x360_tile_1x2_337kbps.webm", 2),
44 make_tuple("vp90-2-bbb_854x480_tile_1x2_651kbps.webm", 2),
45 make_tuple("vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm", 4),
46 make_tuple("vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm", 1),
47 make_tuple("vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm", 4),
48 make_tuple("vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm", 4),
49 make_tuple("vp90-2-sintel_426x182_tile_1x1_171kbps.webm", 1),
50 make_tuple("vp90-2-sintel_640x272_tile_1x2_318kbps.webm", 2),
51 make_tuple("vp90-2-sintel_854x364_tile_1x2_621kbps.webm", 2),
52 make_tuple("vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm", 4),
53 make_tuple("vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm", 4),
54 make_tuple("vp90-2-tos_426x178_tile_1x1_181kbps.webm", 1),
55 make_tuple("vp90-2-tos_640x266_tile_1x2_336kbps.webm", 2),
56 make_tuple("vp90-2-tos_854x356_tile_1x2_656kbps.webm", 2),
57 make_tuple("vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm", 2),
58 make_tuple("vp90-2-tos_1280x534_tile_1x4_1306kbps.webm", 4),
59 make_tuple("vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm", 4),
60 make_tuple("vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm", 4),
64 In order to reflect real world performance as much as possible, Perf tests
65 *DO NOT* do any correctness checks. Please run them alongside correctness
66 tests to ensure proper codec integrity. Furthermore, in this test we
67 deliberately limit the amount of system calls we make to avoid OS
70 TODO(joshualitt) create a more detailed perf measurement test to collect
71 power/temp/min max frame decode times/etc
74 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() != nullptr; 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)) / kUsecsInSec;
96 const unsigned frames = video.frame_number();
97 const double fps = double(frames) / elapsed_secs;
100 printf("\t\"type\" : \"decode_perf_test\",\n");
101 printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
102 printf("\t\"videoName\" : \"%s\",\n", video_name);
103 printf("\t\"threadCount\" : %u,\n", threads);
104 printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
105 printf("\t\"totalFrames\" : %u,\n", frames);
106 printf("\t\"framesPerSecond\" : %f\n", fps);
110 INSTANTIATE_TEST_SUITE_P(VP9, DecodePerfTest,
111 ::testing::ValuesIn(kVP9DecodePerfVectors));
113 class VP9NewEncodeDecodePerfTest
114 : public ::libvpx_test::EncoderTest,
115 public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
117 VP9NewEncodeDecodePerfTest()
118 : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)), speed_(0),
119 outfile_(0), out_frames_(0) {}
121 virtual ~VP9NewEncodeDecodePerfTest() {}
123 virtual void SetUp() {
125 SetMode(encoding_mode_);
127 cfg_.g_lag_in_frames = 25;
128 cfg_.rc_min_quantizer = 2;
129 cfg_.rc_max_quantizer = 56;
130 cfg_.rc_dropframe_thresh = 0;
131 cfg_.rc_undershoot_pct = 50;
132 cfg_.rc_overshoot_pct = 50;
133 cfg_.rc_buf_sz = 1000;
134 cfg_.rc_buf_initial_sz = 500;
135 cfg_.rc_buf_optimal_sz = 600;
136 cfg_.rc_resize_allowed = 0;
137 cfg_.rc_end_usage = VPX_VBR;
140 virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
141 ::libvpx_test::Encoder *encoder) {
142 if (video->frame() == 0) {
143 encoder->Control(VP8E_SET_CPUUSED, speed_);
144 encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
145 encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
149 virtual void BeginPassHook(unsigned int /*pass*/) {
150 const std::string data_path = getenv("LIBVPX_TEST_DATA_PATH");
151 const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile;
152 outfile_ = fopen(path_to_source.c_str(), "wb");
153 ASSERT_NE(outfile_, nullptr);
156 virtual void EndPassHook() {
157 if (outfile_ != nullptr) {
158 if (!fseek(outfile_, 0, SEEK_SET)) {
159 ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
166 virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
169 // Write initial file header if first frame.
170 if (pkt->data.frame.pts == 0) {
171 ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
174 // Write frame header and data.
175 ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz);
176 ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_),
180 virtual bool DoDecode() const { return false; }
182 void set_speed(unsigned int speed) { speed_ = speed; }
185 libvpx_test::TestMode encoding_mode_;
188 uint32_t out_frames_;
191 struct EncodePerfTestVideo {
192 EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
193 uint32_t bitrate_, int frames_)
194 : name(name_), width(width_), height(height_), bitrate(bitrate_),
203 const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
204 EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
207 TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
210 // TODO(JBB): Make this work by going through the set of given files.
212 const vpx_rational timebase = { 33333333, 1000000000 };
213 cfg_.g_timebase = timebase;
214 cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
216 init_flags_ = VPX_CODEC_USE_PSNR;
218 const char *video_name = kVP9EncodePerfTestVectors[i].name;
219 libvpx_test::I420VideoSource video(
220 video_name, kVP9EncodePerfTestVectors[i].width,
221 kVP9EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0,
222 kVP9EncodePerfTestVectors[i].frames);
225 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
227 const uint32_t threads = 4;
229 libvpx_test::IVFVideoSource decode_video(kNewEncodeOutputFile);
232 vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
233 cfg.threads = threads;
234 libvpx_test::VP9Decoder decoder(cfg, 0);
237 vpx_usec_timer_start(&t);
239 for (decode_video.Begin(); decode_video.cxdata() != nullptr;
240 decode_video.Next()) {
241 decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size());
244 vpx_usec_timer_mark(&t);
245 const double elapsed_secs =
246 static_cast<double>(vpx_usec_timer_elapsed(&t)) / kUsecsInSec;
247 const unsigned decode_frames = decode_video.frame_number();
248 const double fps = static_cast<double>(decode_frames) / elapsed_secs;
251 printf("\t\"type\" : \"decode_perf_test\",\n");
252 printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
253 printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile);
254 printf("\t\"threadCount\" : %u,\n", threads);
255 printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
256 printf("\t\"totalFrames\" : %u,\n", decode_frames);
257 printf("\t\"framesPerSecond\" : %f\n", fps);
261 VP9_INSTANTIATE_TEST_SUITE(VP9NewEncodeDecodePerfTest,
262 ::testing::Values(::libvpx_test::kTwoPassGood));