• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST_P(DecodePerfTest,PerfTest)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:
VP9NewEncodeDecodePerfTest()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 
~VP9NewEncodeDecodePerfTest()126   virtual ~VP9NewEncodeDecodePerfTest() {}
127 
SetUp()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 
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)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 
BeginPassHook(unsigned int)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 
EndPassHook()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 
FramePktHook(const vpx_codec_cx_pkt_t * pkt)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 
DoDecode()183   virtual bool DoDecode() { return false; }
184 
set_speed(unsigned int speed)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 {
EncodePerfTestVideo__anonf93d29300111::EncodePerfTestVideo197   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 
TEST_P(VP9NewEncodeDecodePerfTest,PerfTest)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
274