blob: 6d0a72f9804c27f4699545ebe87b8cd229e26be7 [file] [log] [blame]
John Koleszarb9180fc2012-05-16 15:27:00 -07001/*
2 * Copyright (c) 2012 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#ifndef TEST_ENCODE_TEST_DRIVER_H_
11#define TEST_ENCODE_TEST_DRIVER_H_
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080012
John Koleszarb9180fc2012-05-16 15:27:00 -070013#include <string>
14#include <vector>
James Zern51b7fd02013-05-03 19:08:08 -070015
John Koleszarb9180fc2012-05-16 15:27:00 -070016#include "third_party/googletest/src/include/gtest/gtest.h"
Jingning Han097d59c2015-07-29 14:51:36 -070017
18#include "./vpx_config.h"
Jingning Han3ee6db62015-08-05 19:00:31 -070019#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
Alex Conversea5654692014-03-11 16:40:57 -070020#include "vpx/vp8cx.h"
21#endif
Jingning Han097d59c2015-07-29 14:51:36 -070022#include "vpx/vpx_encoder.h"
John Koleszarb9180fc2012-05-16 15:27:00 -070023
24namespace libvpx_test {
25
John Koleszar706cafe2013-01-18 11:51:12 -080026class CodecFactory;
John Koleszarb9180fc2012-05-16 15:27:00 -070027class VideoSource;
28
29enum TestMode {
30 kRealTime,
31 kOnePassGood,
32 kOnePassBest,
33 kTwoPassGood,
34 kTwoPassBest
35};
36#define ALL_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
37 ::libvpx_test::kOnePassGood, \
38 ::libvpx_test::kOnePassBest, \
39 ::libvpx_test::kTwoPassGood, \
40 ::libvpx_test::kTwoPassBest)
41
John Koleszar2fb29ff2012-05-23 12:55:27 -070042#define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
43 ::libvpx_test::kOnePassGood, \
44 ::libvpx_test::kOnePassBest)
45
John Koleszar706cafe2013-01-18 11:51:12 -080046#define TWO_PASS_TEST_MODES ::testing::Values(::libvpx_test::kTwoPassGood, \
47 ::libvpx_test::kTwoPassBest)
48
John Koleszarb9180fc2012-05-16 15:27:00 -070049
50// Provides an object to handle the libvpx get_cx_data() iteration pattern
51class CxDataIterator {
52 public:
53 explicit CxDataIterator(vpx_codec_ctx_t *encoder)
James Zern51b7fd02013-05-03 19:08:08 -070054 : encoder_(encoder), iter_(NULL) {}
John Koleszarb9180fc2012-05-16 15:27:00 -070055
56 const vpx_codec_cx_pkt_t *Next() {
57 return vpx_codec_get_cx_data(encoder_, &iter_);
58 }
59
60 private:
61 vpx_codec_ctx_t *encoder_;
62 vpx_codec_iter_t iter_;
63};
64
John Koleszarb9180fc2012-05-16 15:27:00 -070065// Implements an in-memory store for libvpx twopass statistics
66class TwopassStatsStore {
67 public:
68 void Append(const vpx_codec_cx_pkt_t &pkt) {
69 buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
70 pkt.data.twopass_stats.sz);
71 }
72
73 vpx_fixed_buf_t buf() {
74 const vpx_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
75 return buf;
76 }
77
Adrian Grange30f58b52012-10-02 09:36:41 -070078 void Reset() {
79 buffer_.clear();
80 }
81
John Koleszarb9180fc2012-05-16 15:27:00 -070082 protected:
83 std::string buffer_;
84};
85
86
87// Provides a simplified interface to manage one video encoding pass, given
88// a configuration and video source.
89//
90// TODO(jkoleszar): The exact services it provides and the appropriate
91// level of abstraction will be fleshed out as more tests are written.
92class Encoder {
93 public:
94 Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
Adrian Grange4206c6d2012-10-02 11:03:09 -070095 const unsigned long init_flags, TwopassStatsStore *stats)
John Koleszar706cafe2013-01-18 11:51:12 -080096 : cfg_(cfg), deadline_(deadline), init_flags_(init_flags), stats_(stats) {
John Koleszarb9180fc2012-05-16 15:27:00 -070097 memset(&encoder_, 0, sizeof(encoder_));
98 }
99
James Zern51b7fd02013-05-03 19:08:08 -0700100 virtual ~Encoder() {
John Koleszarb9180fc2012-05-16 15:27:00 -0700101 vpx_codec_destroy(&encoder_);
102 }
103
104 CxDataIterator GetCxData() {
105 return CxDataIterator(&encoder_);
106 }
107
Yunqing Wang36664782014-12-12 14:34:30 -0800108 void InitEncoder(VideoSource *video);
109
Yaowu Xuc953aea2012-08-30 13:43:15 -0700110 const vpx_image_t *GetPreviewFrame() {
111 return vpx_codec_get_preview_frame(&encoder_);
112 }
John Koleszarb9180fc2012-05-16 15:27:00 -0700113 // This is a thin wrapper around vpx_codec_encode(), so refer to
114 // vpx_encoder.h for its semantics.
Adrian Grange4206c6d2012-10-02 11:03:09 -0700115 void EncodeFrame(VideoSource *video, const unsigned long frame_flags);
John Koleszarb9180fc2012-05-16 15:27:00 -0700116
117 // Convenience wrapper for EncodeFrame()
118 void EncodeFrame(VideoSource *video) {
119 EncodeFrame(video, 0);
120 }
121
John Koleszar606ac452012-07-10 15:43:44 -0700122 void Control(int ctrl_id, int arg) {
123 const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
124 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
125 }
126
Yaowu Xu7c514e22015-09-28 15:55:46 -0700127 void Control(int ctrl_id, int *arg) {
128 const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
129 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
130 }
131
John Koleszar88f99f42013-02-06 12:44:20 -0800132 void Control(int ctrl_id, struct vpx_scaling_mode *arg) {
133 const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
134 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
135 }
136
Marco Paniconi4864ab22014-02-06 09:23:17 -0800137 void Control(int ctrl_id, struct vpx_svc_layer_id *arg) {
138 const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
139 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
140 }
141
Marcoc139b812015-05-21 16:15:37 -0700142 void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
143 const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
144 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
145 }
Jingning Han3ee6db62015-08-05 19:00:31 -0700146#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
Alex Conversea5654692014-03-11 16:40:57 -0700147 void Control(int ctrl_id, vpx_active_map_t *arg) {
148 const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
149 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
150 }
151#endif
152
Alex Converse797a2552015-01-15 13:56:55 -0800153 void Config(const vpx_codec_enc_cfg_t *cfg) {
154 const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg);
155 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
156 cfg_ = *cfg;
157 }
158
John Koleszarb9180fc2012-05-16 15:27:00 -0700159 void set_deadline(unsigned long deadline) {
160 deadline_ = deadline;
161 }
162
163 protected:
James Zern4a703572014-01-31 16:32:42 -0800164 virtual vpx_codec_iface_t* CodecInterface() const = 0;
John Koleszar706cafe2013-01-18 11:51:12 -0800165
John Koleszarb9180fc2012-05-16 15:27:00 -0700166 const char *EncoderError() {
167 const char *detail = vpx_codec_error_detail(&encoder_);
168 return detail ? detail : vpx_codec_error(&encoder_);
169 }
170
171 // Encode an image
Adrian Grange4206c6d2012-10-02 11:03:09 -0700172 void EncodeFrameInternal(const VideoSource &video,
173 const unsigned long frame_flags);
John Koleszarb9180fc2012-05-16 15:27:00 -0700174
175 // Flush the encoder on EOS
176 void Flush();
177
178 vpx_codec_ctx_t encoder_;
179 vpx_codec_enc_cfg_t cfg_;
180 unsigned long deadline_;
Adrian Grange4206c6d2012-10-02 11:03:09 -0700181 unsigned long init_flags_;
John Koleszarb9180fc2012-05-16 15:27:00 -0700182 TwopassStatsStore *stats_;
183};
184
John Koleszarb9180fc2012-05-16 15:27:00 -0700185// Common test functionality for all Encoder tests.
186//
187// This class is a mixin which provides the main loop common to all
188// encoder tests. It provides hooks which can be overridden by subclasses
189// to implement each test's specific behavior, while centralizing the bulk
190// of the boilerplate. Note that it doesn't inherit the gtest testing
191// classes directly, so that tests can be parameterized differently.
192class EncoderTest {
193 protected:
John Koleszar706cafe2013-01-18 11:51:12 -0800194 explicit EncoderTest(const CodecFactory *codec)
195 : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0),
Frank Galligan45f9ee22015-04-14 15:01:56 -0700196 last_pts_(0) {
197 // Default to 1 thread.
198 cfg_.g_threads = 1;
199 }
John Koleszarb9180fc2012-05-16 15:27:00 -0700200
201 virtual ~EncoderTest() {}
202
203 // Initialize the cfg_ member with the default configuration.
John Koleszar706cafe2013-01-18 11:51:12 -0800204 void InitializeConfig();
John Koleszarb9180fc2012-05-16 15:27:00 -0700205
206 // Map the TestMode enum to the deadline_ and passes_ variables.
207 void SetMode(TestMode mode);
208
hkuang93536072014-11-20 15:39:56 -0800209 // Set encoder flag.
210 void set_init_flags(unsigned long flag) { // NOLINT(runtime/int)
211 init_flags_ = flag;
212 }
213
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800214 // Main loop
John Koleszarb9180fc2012-05-16 15:27:00 -0700215 virtual void RunLoop(VideoSource *video);
216
217 // Hook to be called at the beginning of a pass.
James Zerncae810a2014-08-22 11:58:48 -0700218 virtual void BeginPassHook(unsigned int /*pass*/) {}
John Koleszarb9180fc2012-05-16 15:27:00 -0700219
220 // Hook to be called at the end of a pass.
221 virtual void EndPassHook() {}
222
223 // Hook to be called before encoding a frame.
James Zerncae810a2014-08-22 11:58:48 -0700224 virtual void PreEncodeFrameHook(VideoSource* /*video*/) {}
225 virtual void PreEncodeFrameHook(VideoSource* /*video*/,
226 Encoder* /*encoder*/) {}
John Koleszarb9180fc2012-05-16 15:27:00 -0700227
228 // Hook to be called on every compressed data packet.
James Zerncae810a2014-08-22 11:58:48 -0700229 virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}
John Koleszarb9180fc2012-05-16 15:27:00 -0700230
Adrian Grangee6109db2012-10-02 11:27:29 -0700231 // Hook to be called on every PSNR packet.
James Zerncae810a2014-08-22 11:58:48 -0700232 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}
Adrian Grangee6109db2012-10-02 11:27:29 -0700233
John Koleszarb9180fc2012-05-16 15:27:00 -0700234 // Hook to determine whether the encode loop should continue.
James Zern1c05e9d2013-06-25 17:53:20 -0700235 virtual bool Continue() const {
236 return !(::testing::Test::HasFatalFailure() || abort_);
237 }
John Koleszarb9180fc2012-05-16 15:27:00 -0700238
John Koleszar706cafe2013-01-18 11:51:12 -0800239 const CodecFactory *codec_;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800240 // Hook to determine whether to decode frame after encoding
241 virtual bool DoDecode() const { return 1; }
242
243 // Hook to handle encode/decode mismatch
244 virtual void MismatchHook(const vpx_image_t *img1,
245 const vpx_image_t *img2);
246
John Koleszar88f99f42013-02-06 12:44:20 -0800247 // Hook to be called on every decompressed frame.
James Zerncae810a2014-08-22 11:58:48 -0700248 virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
249 vpx_codec_pts_t /*pts*/) {}
John Koleszar88f99f42013-02-06 12:44:20 -0800250
Jim Bankoski943e4322014-07-17 06:31:50 -0700251 // Hook to be called to handle decode result. Return true to continue.
252 virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
James Zerncae810a2014-08-22 11:58:48 -0700253 const VideoSource& /*video*/,
Jim Bankoski943e4322014-07-17 06:31:50 -0700254 Decoder *decoder) {
255 EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
256 return VPX_CODEC_OK == res_dec;
257 }
258
John Koleszar522d4bf2013-03-05 12:23:34 -0800259 // Hook that can modify the encoder's output data
James Zerncae810a2014-08-22 11:58:48 -0700260 virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook(
John Koleszar522d4bf2013-03-05 12:23:34 -0800261 const vpx_codec_cx_pkt_t *pkt) {
262 return pkt;
263 }
264
John Koleszarb9180fc2012-05-16 15:27:00 -0700265 bool abort_;
266 vpx_codec_enc_cfg_t cfg_;
Jim Bankoskibe7a2852014-12-07 11:28:51 -0800267 vpx_codec_dec_cfg_t dec_cfg_;
John Koleszarb9180fc2012-05-16 15:27:00 -0700268 unsigned int passes_;
269 unsigned long deadline_;
270 TwopassStatsStore stats_;
Adrian Grange4206c6d2012-10-02 11:03:09 -0700271 unsigned long init_flags_;
272 unsigned long frame_flags_;
James Zern51ebb9a2012-08-08 14:16:08 -0700273 vpx_codec_pts_t last_pts_;
John Koleszarb9180fc2012-05-16 15:27:00 -0700274};
275
276} // namespace libvpx_test
277
John Koleszarb9180fc2012-05-16 15:27:00 -0700278#endif // TEST_ENCODE_TEST_DRIVER_H_