]> granicus.if.org Git - libvpx/blob - test/decode_perf_test.cc
Merge "endian_inl.h: fix mips32 android build"
[libvpx] / test / decode_perf_test.cc
1 /*
2  *  Copyright (c) 2013 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  */
10
11 #include <string>
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"
21 #include "./ivfenc.h"
22 #include "./vpx_version.h"
23
24 using std::tr1::make_tuple;
25
26 namespace {
27
28 #define VIDEO_NAME 0
29 #define THREADS 1
30
31 const int kMaxPsnr = 100;
32 const double kUsecsInSec = 1000000.0;
33 const char kNewEncodeOutputFile[] = "new_encode.ivf";
34
35 /*
36  DecodePerfTest takes a tuple of filename + number of threads to decode with
37  */
38 typedef std::tr1::tuple<const char *, unsigned> DecodePerfParam;
39
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),
60 };
61
62 /*
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
67  preemption.
68
69  TODO(joshualitt) create a more detailed perf measurement test to collect
70    power/temp/min max frame decode times/etc
71  */
72
73 class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {
74 };
75
76 TEST_P(DecodePerfTest, PerfTest) {
77   const char *const video_name = GET_PARAM(VIDEO_NAME);
78   const unsigned threads = GET_PARAM(THREADS);
79
80   libvpx_test::WebMVideoSource video(video_name);
81   video.Init();
82
83   vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
84   cfg.threads = threads;
85   libvpx_test::VP9Decoder decoder(cfg, 0);
86
87   vpx_usec_timer t;
88   vpx_usec_timer_start(&t);
89
90   for (video.Begin(); video.cxdata() != NULL; video.Next()) {
91     decoder.DecodeFrame(video.cxdata(), video.frame_size());
92   }
93
94   vpx_usec_timer_mark(&t);
95   const double elapsed_secs = double(vpx_usec_timer_elapsed(&t))
96                               / kUsecsInSec;
97   const unsigned frames = video.frame_number();
98   const double fps = double(frames) / elapsed_secs;
99
100   printf("{\n");
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);
108   printf("}\n");
109 }
110
111 INSTANTIATE_TEST_CASE_P(VP9, DecodePerfTest,
112                         ::testing::ValuesIn(kVP9DecodePerfVectors));
113
114 class VP9NewEncodeDecodePerfTest :
115     public ::libvpx_test::EncoderTest,
116     public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
117  protected:
118   VP9NewEncodeDecodePerfTest()
119       : EncoderTest(GET_PARAM(0)),
120         encoding_mode_(GET_PARAM(1)),
121         speed_(0),
122         outfile_(0),
123         out_frames_(0) {
124   }
125
126   virtual ~VP9NewEncodeDecodePerfTest() {}
127
128   virtual void SetUp() {
129     InitializeConfig();
130     SetMode(encoding_mode_);
131
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;
143   }
144
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);
151     }
152   }
153
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);
159   }
160
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_);
165       fclose(outfile_);
166       outfile_ = NULL;
167     }
168   }
169
170   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
171     ++out_frames_;
172
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_);
176
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_),
180               pkt->data.frame.sz);
181   }
182
183   virtual bool DoDecode() { return false; }
184
185   void set_speed(unsigned int speed) {
186     speed_ = speed;
187   }
188
189  private:
190   libvpx_test::TestMode encoding_mode_;
191   uint32_t speed_;
192   FILE *outfile_;
193   uint32_t out_frames_;
194 };
195
196 struct EncodePerfTestVideo {
197   EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
198                       uint32_t bitrate_, int frames_)
199       : name(name_),
200         width(width_),
201         height(height_),
202         bitrate(bitrate_),
203         frames(frames_) {}
204   const char *name;
205   uint32_t width;
206   uint32_t height;
207   uint32_t bitrate;
208   int frames;
209 };
210
211 const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
212   EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
213 };
214
215 TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
216   SetUp();
217
218   // TODO(JBB): Make this work by going through the set of given files.
219   const int i = 0;
220   const vpx_rational timebase = { 33333333, 1000000000 };
221   cfg_.g_timebase = timebase;
222   cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
223
224   init_flags_ = VPX_CODEC_USE_PSNR;
225
226   const char *video_name = kVP9EncodePerfTestVectors[i].name;
227   libvpx_test::I420VideoSource video(
228       video_name,
229       kVP9EncodePerfTestVectors[i].width,
230       kVP9EncodePerfTestVectors[i].height,
231       timebase.den, timebase.num, 0,
232       kVP9EncodePerfTestVectors[i].frames);
233   set_speed(2);
234
235   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
236
237   const uint32_t threads = 4;
238
239   libvpx_test::IVFVideoSource decode_video(kNewEncodeOutputFile);
240   decode_video.Init();
241
242   vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
243   cfg.threads = threads;
244   libvpx_test::VP9Decoder decoder(cfg, 0);
245
246   vpx_usec_timer t;
247   vpx_usec_timer_start(&t);
248
249   for (decode_video.Begin(); decode_video.cxdata() != NULL;
250        decode_video.Next()) {
251     decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size());
252   }
253
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;
259
260   printf("{\n");
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);
268   printf("}\n");
269 }
270
271 VP9_INSTANTIATE_TEST_CASE(
272   VP9NewEncodeDecodePerfTest, ::testing::Values(::libvpx_test::kTwoPassGood));
273 }  // namespace