decode_perf_test.cc (8031B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <string> 13 #include <tuple> 14 15 #include "aom/aom_codec.h" 16 #include "aom_ports/aom_timer.h" 17 #include "common/ivfenc.h" 18 #include "test/codec_factory.h" 19 #include "test/decode_test_driver.h" 20 #include "test/encode_test_driver.h" 21 #include "test/i420_video_source.h" 22 #include "test/ivf_video_source.h" 23 #include "test/md5_helper.h" 24 #include "test/util.h" 25 #include "test/webm_video_source.h" 26 27 using std::make_tuple; 28 29 namespace { 30 31 #define VIDEO_NAME 0 32 #define THREADS 1 33 34 const double kUsecsInSec = 1000000.0; 35 const char kNewEncodeOutputFile[] = "new_encode.ivf"; 36 37 /* 38 DecodePerfTest takes a tuple of filename + number of threads to decode with 39 */ 40 using DecodePerfParam = std::tuple<const char *, unsigned int>; 41 42 // TODO(jimbankoski): Add actual test vectors here when available. 43 // const DecodePerfParam kAV1DecodePerfVectors[] = {}; 44 45 /* 46 In order to reflect real world performance as much as possible, Perf tests 47 *DO NOT* do any correctness checks. Please run them alongside correctness 48 tests to ensure proper codec integrity. Furthermore, in this test we 49 deliberately limit the amount of system calls we make to avoid OS 50 preemption. 51 52 TODO(joshualitt) create a more detailed perf measurement test to collect 53 power/temp/min max frame decode times/etc 54 */ 55 56 class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {}; 57 58 TEST_P(DecodePerfTest, PerfTest) { 59 const char *const video_name = GET_PARAM(VIDEO_NAME); 60 const unsigned threads = GET_PARAM(THREADS); 61 62 libaom_test::WebMVideoSource video(video_name); 63 video.Init(); 64 65 aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t(); 66 cfg.threads = threads; 67 cfg.allow_lowbitdepth = 1; 68 libaom_test::AV1Decoder decoder(cfg, 0); 69 70 aom_usec_timer t; 71 aom_usec_timer_start(&t); 72 73 for (video.Begin(); video.cxdata() != nullptr; video.Next()) { 74 decoder.DecodeFrame(video.cxdata(), video.frame_size()); 75 } 76 77 aom_usec_timer_mark(&t); 78 const double elapsed_secs = double(aom_usec_timer_elapsed(&t)) / kUsecsInSec; 79 const unsigned frames = video.frame_number(); 80 const double fps = double(frames) / elapsed_secs; 81 82 printf("{\n"); 83 printf("\t\"type\" : \"decode_perf_test\",\n"); 84 printf("\t\"version\" : \"%s\",\n", aom_codec_version_str()); 85 printf("\t\"videoName\" : \"%s\",\n", video_name); 86 printf("\t\"threadCount\" : %u,\n", threads); 87 printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs); 88 printf("\t\"totalFrames\" : %u,\n", frames); 89 printf("\t\"framesPerSecond\" : %f\n", fps); 90 printf("}\n"); 91 } 92 93 // TODO(jimbankoski): Enabled when we have actual AV1 Decode vectors. 94 // INSTANTIATE_TEST_SUITE_P(AV1, DecodePerfTest, 95 // ::testing::ValuesIn(kAV1DecodePerfVectors)); 96 97 class AV1NewEncodeDecodePerfTest 98 : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>, 99 public ::libaom_test::EncoderTest { 100 protected: 101 AV1NewEncodeDecodePerfTest() 102 : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)), speed_(0), 103 outfile_(nullptr), out_frames_(0) {} 104 105 ~AV1NewEncodeDecodePerfTest() override = default; 106 107 void SetUp() override { 108 InitializeConfig(encoding_mode_); 109 110 cfg_.g_lag_in_frames = 25; 111 cfg_.rc_min_quantizer = 2; 112 cfg_.rc_max_quantizer = 56; 113 cfg_.rc_dropframe_thresh = 0; 114 cfg_.rc_undershoot_pct = 50; 115 cfg_.rc_overshoot_pct = 50; 116 cfg_.rc_buf_sz = 1000; 117 cfg_.rc_buf_initial_sz = 500; 118 cfg_.rc_buf_optimal_sz = 600; 119 cfg_.rc_end_usage = AOM_VBR; 120 } 121 122 void PreEncodeFrameHook(::libaom_test::VideoSource *video, 123 ::libaom_test::Encoder *encoder) override { 124 if (video->frame() == 0) { 125 encoder->Control(AOME_SET_CPUUSED, speed_); 126 encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1); 127 encoder->Control(AV1E_SET_TILE_COLUMNS, 2); 128 } 129 } 130 131 void BeginPassHook(unsigned int /*pass*/) override { 132 const char *const env = getenv("LIBAOM_TEST_DATA_PATH"); 133 const std::string data_path(env ? env : "."); 134 const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile; 135 outfile_ = fopen(path_to_source.c_str(), "wb"); 136 ASSERT_NE(outfile_, nullptr); 137 } 138 139 void EndPassHook() override { 140 if (outfile_ != nullptr) { 141 if (!fseek(outfile_, 0, SEEK_SET)) 142 ivf_write_file_header(outfile_, &cfg_, AV1_FOURCC, out_frames_); 143 fclose(outfile_); 144 outfile_ = nullptr; 145 } 146 } 147 148 void FramePktHook(const aom_codec_cx_pkt_t *pkt) override { 149 ++out_frames_; 150 151 // Write initial file header if first frame. 152 if (pkt->data.frame.pts == 0) 153 ivf_write_file_header(outfile_, &cfg_, AV1_FOURCC, out_frames_); 154 155 // Write frame header and data. 156 ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz); 157 ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_), 158 pkt->data.frame.sz); 159 } 160 161 bool DoDecode() const override { return false; } 162 163 void set_speed(unsigned int speed) { speed_ = speed; } 164 165 private: 166 libaom_test::TestMode encoding_mode_; 167 uint32_t speed_; 168 FILE *outfile_; 169 uint32_t out_frames_; 170 }; 171 172 struct EncodePerfTestVideo { 173 EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_, 174 uint32_t bitrate_, int frames_) 175 : name(name_), width(width_), height(height_), bitrate(bitrate_), 176 frames(frames_) {} 177 const char *name; 178 uint32_t width; 179 uint32_t height; 180 uint32_t bitrate; 181 int frames; 182 }; 183 184 const EncodePerfTestVideo kAV1EncodePerfTestVectors[] = { 185 EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470), 186 }; 187 188 TEST_P(AV1NewEncodeDecodePerfTest, PerfTest) { 189 SetUp(); 190 191 // TODO(JBB): Make this work by going through the set of given files. 192 const int i = 0; 193 const aom_rational timebase = { 33333333, 1000000000 }; 194 cfg_.g_timebase = timebase; 195 cfg_.rc_target_bitrate = kAV1EncodePerfTestVectors[i].bitrate; 196 197 init_flags_ = AOM_CODEC_USE_PSNR; 198 199 const char *video_name = kAV1EncodePerfTestVectors[i].name; 200 libaom_test::I420VideoSource video( 201 video_name, kAV1EncodePerfTestVectors[i].width, 202 kAV1EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0, 203 kAV1EncodePerfTestVectors[i].frames); 204 set_speed(2); 205 206 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 207 208 const uint32_t threads = 4; 209 210 libaom_test::IVFVideoSource decode_video(kNewEncodeOutputFile); 211 decode_video.Init(); 212 213 aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t(); 214 cfg.threads = threads; 215 cfg.allow_lowbitdepth = 1; 216 libaom_test::AV1Decoder decoder(cfg, 0); 217 218 aom_usec_timer t; 219 aom_usec_timer_start(&t); 220 221 for (decode_video.Begin(); decode_video.cxdata() != nullptr; 222 decode_video.Next()) { 223 decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size()); 224 } 225 226 aom_usec_timer_mark(&t); 227 const double elapsed_secs = 228 static_cast<double>(aom_usec_timer_elapsed(&t)) / kUsecsInSec; 229 const unsigned decode_frames = decode_video.frame_number(); 230 const double fps = static_cast<double>(decode_frames) / elapsed_secs; 231 232 printf("{\n"); 233 printf("\t\"type\" : \"decode_perf_test\",\n"); 234 printf("\t\"version\" : \"%s\",\n", aom_codec_version_str()); 235 printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile); 236 printf("\t\"threadCount\" : %u,\n", threads); 237 printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs); 238 printf("\t\"totalFrames\" : %u,\n", decode_frames); 239 printf("\t\"framesPerSecond\" : %f\n", fps); 240 printf("}\n"); 241 } 242 243 AV1_INSTANTIATE_TEST_SUITE(AV1NewEncodeDecodePerfTest, 244 ::testing::Values(::libaom_test::kTwoPassGood)); 245 } // namespace