decode_perf_test.cc 7.76 KB
Newer Older
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4
5
6
7
8
9
10
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
11

12
#include <string>
13
14
#include "test/codec_factory.h"
#include "test/decode_test_driver.h"
15
16
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
17
18
19
20
#include "test/ivf_video_source.h"
#include "test/md5_helper.h"
#include "test/util.h"
#include "test/webm_video_source.h"
Yaowu Xu's avatar
Yaowu Xu committed
21
#include "aom_ports/aom_timer.h"
22
#include "./ivfenc.h"
Yaowu Xu's avatar
Yaowu Xu committed
23
#include "./aom_version.h"
24
25
26
27
28
29
30
31

using std::tr1::make_tuple;

namespace {

#define VIDEO_NAME 0
#define THREADS 1

32
const int kMaxPsnr = 100;
33
const double kUsecsInSec = 1000000.0;
34
const char kNewEncodeOutputFile[] = "new_encode.ivf";
35
36
37
38

/*
 DecodePerfTest takes a tuple of filename + number of threads to decode with
 */
39
typedef std::tr1::tuple<const char *, unsigned> DecodePerfParam;
40

41
42
// TODO(jimbankoski): Add actual test vectors here when available.
// const DecodePerfParam kAV1DecodePerfVectors[] = {};
43
44
45
46
47
48
49
50
51
52
53
54

/*
 In order to reflect real world performance as much as possible, Perf tests
 *DO NOT* do any correctness checks. Please run them alongside correctness
 tests to ensure proper codec integrity. Furthermore, in this test we
 deliberately limit the amount of system calls we make to avoid OS
 preemption.

 TODO(joshualitt) create a more detailed perf measurement test to collect
   power/temp/min max frame decode times/etc
 */

clang-format's avatar
clang-format committed
55
class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {};
56
57
58
59
60

TEST_P(DecodePerfTest, PerfTest) {
  const char *const video_name = GET_PARAM(VIDEO_NAME);
  const unsigned threads = GET_PARAM(THREADS);

61
  libaom_test::WebMVideoSource video(video_name);
62
63
  video.Init();

Yaowu Xu's avatar
Yaowu Xu committed
64
  aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t();
65
  cfg.threads = threads;
Yaowu Xu's avatar
Yaowu Xu committed
66
  libaom_test::AV1Decoder decoder(cfg, 0);
67

Yaowu Xu's avatar
Yaowu Xu committed
68
69
  aom_usec_timer t;
  aom_usec_timer_start(&t);
70
71
72
73
74

  for (video.Begin(); video.cxdata() != NULL; video.Next()) {
    decoder.DecodeFrame(video.cxdata(), video.frame_size());
  }

Yaowu Xu's avatar
Yaowu Xu committed
75
76
  aom_usec_timer_mark(&t);
  const double elapsed_secs = double(aom_usec_timer_elapsed(&t)) / kUsecsInSec;
77
78
79
80
  const unsigned frames = video.frame_number();
  const double fps = double(frames) / elapsed_secs;

  printf("{\n");
Joshua Litt's avatar
Joshua Litt committed
81
  printf("\t\"type\" : \"decode_perf_test\",\n");
82
83
84
85
86
87
88
89
90
  printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
  printf("\t\"videoName\" : \"%s\",\n", video_name);
  printf("\t\"threadCount\" : %u,\n", threads);
  printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
  printf("\t\"totalFrames\" : %u,\n", frames);
  printf("\t\"framesPerSecond\" : %f\n", fps);
  printf("}\n");
}

91
92
93
// TODO(jimbankoski): Enabled when we have actual AV1 Decode vectors.
// INSTANTIATE_TEST_CASE_P(AV1, DecodePerfTest,
//                        ::testing::ValuesIn(kAV1DecodePerfVectors));
94

Yaowu Xu's avatar
Yaowu Xu committed
95
class AV1NewEncodeDecodePerfTest
96
97
    : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
      public ::libaom_test::EncoderTest {
98
 protected:
Yaowu Xu's avatar
Yaowu Xu committed
99
  AV1NewEncodeDecodePerfTest()
clang-format's avatar
clang-format committed
100
101
      : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)), speed_(0),
        outfile_(0), out_frames_(0) {}
102

Yaowu Xu's avatar
Yaowu Xu committed
103
  virtual ~AV1NewEncodeDecodePerfTest() {}
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

  virtual void SetUp() {
    InitializeConfig();
    SetMode(encoding_mode_);

    cfg_.g_lag_in_frames = 25;
    cfg_.rc_min_quantizer = 2;
    cfg_.rc_max_quantizer = 56;
    cfg_.rc_dropframe_thresh = 0;
    cfg_.rc_undershoot_pct = 50;
    cfg_.rc_overshoot_pct = 50;
    cfg_.rc_buf_sz = 1000;
    cfg_.rc_buf_initial_sz = 500;
    cfg_.rc_buf_optimal_sz = 600;
    cfg_.rc_resize_allowed = 0;
Yaowu Xu's avatar
Yaowu Xu committed
119
    cfg_.rc_end_usage = AOM_VBR;
120
121
  }

122
123
  virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
                                  ::libaom_test::Encoder *encoder) {
124
    if (video->frame() == 1) {
Yaowu Xu's avatar
Yaowu Xu committed
125
126
127
      encoder->Control(AOME_SET_CPUUSED, speed_);
      encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1);
      encoder->Control(AV1E_SET_TILE_COLUMNS, 2);
128
129
130
131
    }
  }

  virtual void BeginPassHook(unsigned int /*pass*/) {
132
    const std::string data_path = getenv("LIBAOM_TEST_DATA_PATH");
133
134
    const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile;
    outfile_ = fopen(path_to_source.c_str(), "wb");
135
    ASSERT_TRUE(outfile_ != NULL);
136
137
138
  }

  virtual void EndPassHook() {
139
    if (outfile_ != NULL) {
140
      if (!fseek(outfile_, 0, SEEK_SET))
Yaowu Xu's avatar
Yaowu Xu committed
141
        ivf_write_file_header(outfile_, &cfg_, AV1_FOURCC, out_frames_);
142
143
144
145
146
      fclose(outfile_);
      outfile_ = NULL;
    }
  }

Yaowu Xu's avatar
Yaowu Xu committed
147
  virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) {
148
149
150
151
    ++out_frames_;

    // Write initial file header if first frame.
    if (pkt->data.frame.pts == 0)
Yaowu Xu's avatar
Yaowu Xu committed
152
      ivf_write_file_header(outfile_, &cfg_, AV1_FOURCC, out_frames_);
153
154
155

    // Write frame header and data.
    ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz);
156
157
    ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_),
              pkt->data.frame.sz);
158
159
  }

160
  virtual bool DoDecode() { return false; }
161

clang-format's avatar
clang-format committed
162
  void set_speed(unsigned int speed) { speed_ = speed; }
163
164

 private:
165
  libaom_test::TestMode encoding_mode_;
166
167
168
169
170
171
172
173
  uint32_t speed_;
  FILE *outfile_;
  uint32_t out_frames_;
};

struct EncodePerfTestVideo {
  EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
                      uint32_t bitrate_, int frames_)
clang-format's avatar
clang-format committed
174
      : name(name_), width(width_), height(height_), bitrate(bitrate_),
175
176
177
178
179
180
181
182
        frames(frames_) {}
  const char *name;
  uint32_t width;
  uint32_t height;
  uint32_t bitrate;
  int frames;
};

Yaowu Xu's avatar
Yaowu Xu committed
183
const EncodePerfTestVideo kAV1EncodePerfTestVectors[] = {
184
185
186
  EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
};

Yaowu Xu's avatar
Yaowu Xu committed
187
TEST_P(AV1NewEncodeDecodePerfTest, PerfTest) {
188
189
190
191
  SetUp();

  // TODO(JBB): Make this work by going through the set of given files.
  const int i = 0;
Yaowu Xu's avatar
Yaowu Xu committed
192
  const aom_rational timebase = { 33333333, 1000000000 };
193
  cfg_.g_timebase = timebase;
Yaowu Xu's avatar
Yaowu Xu committed
194
  cfg_.rc_target_bitrate = kAV1EncodePerfTestVectors[i].bitrate;
195

Yaowu Xu's avatar
Yaowu Xu committed
196
  init_flags_ = AOM_CODEC_USE_PSNR;
197

Yaowu Xu's avatar
Yaowu Xu committed
198
  const char *video_name = kAV1EncodePerfTestVectors[i].name;
199
  libaom_test::I420VideoSource video(
Yaowu Xu's avatar
Yaowu Xu committed
200
201
202
      video_name, kAV1EncodePerfTestVectors[i].width,
      kAV1EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0,
      kAV1EncodePerfTestVectors[i].frames);
203
204
205
206
207
208
  set_speed(2);

  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));

  const uint32_t threads = 4;

209
  libaom_test::IVFVideoSource decode_video(kNewEncodeOutputFile);
210
211
  decode_video.Init();

Yaowu Xu's avatar
Yaowu Xu committed
212
  aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t();
213
  cfg.threads = threads;
Yaowu Xu's avatar
Yaowu Xu committed
214
  libaom_test::AV1Decoder decoder(cfg, 0);
215

Yaowu Xu's avatar
Yaowu Xu committed
216
217
  aom_usec_timer t;
  aom_usec_timer_start(&t);
218
219
220
221
222
223

  for (decode_video.Begin(); decode_video.cxdata() != NULL;
       decode_video.Next()) {
    decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size());
  }

Yaowu Xu's avatar
Yaowu Xu committed
224
  aom_usec_timer_mark(&t);
225
  const double elapsed_secs =
Yaowu Xu's avatar
Yaowu Xu committed
226
      static_cast<double>(aom_usec_timer_elapsed(&t)) / kUsecsInSec;
227
  const unsigned decode_frames = decode_video.frame_number();
228
  const double fps = static_cast<double>(decode_frames) / elapsed_secs;
229
230
231
232
233
234
235
236
237
238
239
240

  printf("{\n");
  printf("\t\"type\" : \"decode_perf_test\",\n");
  printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
  printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile);
  printf("\t\"threadCount\" : %u,\n", threads);
  printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
  printf("\t\"totalFrames\" : %u,\n", decode_frames);
  printf("\t\"framesPerSecond\" : %f\n", fps);
  printf("}\n");
}

Yaowu Xu's avatar
Yaowu Xu committed
241
242
AV1_INSTANTIATE_TEST_CASE(AV1NewEncodeDecodePerfTest,
                          ::testing::Values(::libaom_test::kTwoPassGood));
243
}  // namespace