Bug 1882465 - Update .hg-annotate-ignore-revs and .git-blame-ignore-revs to reflect...
[gecko.git] / third_party / aom / test / encode_test_driver.h
blobd1e6615cd70aba0b8dc4a1eb4ed6f1c415381609
1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
11 #ifndef AOM_TEST_ENCODE_TEST_DRIVER_H_
12 #define AOM_TEST_ENCODE_TEST_DRIVER_H_
14 #include <string>
15 #include <vector>
17 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
19 #include "config/aom_config.h"
21 #if CONFIG_AV1_ENCODER
22 #include "aom/aomcx.h"
23 #endif
24 #include "aom/aom_encoder.h"
26 namespace libaom_test {
28 class CodecFactory;
29 class VideoSource;
31 enum TestMode { kRealTime, kOnePassGood, kTwoPassGood, kAllIntra };
32 #define ALL_TEST_MODES \
33 ::testing::Values(::libaom_test::kRealTime, ::libaom_test::kOnePassGood, \
34 ::libaom_test::kTwoPassGood)
36 #define ONE_PASS_TEST_MODES \
37 ::testing::Values(::libaom_test::kRealTime, ::libaom_test::kOnePassGood)
39 #define TWO_PASS_TEST_MODES ::testing::Values(::libaom_test::kTwoPassGood)
41 #define NONREALTIME_TEST_MODES \
42 ::testing::Values(::libaom_test::kOnePassGood, ::libaom_test::kTwoPassGood)
44 // Provides an object to handle the libaom get_cx_data() iteration pattern
45 class CxDataIterator {
46 public:
47 explicit CxDataIterator(aom_codec_ctx_t *encoder)
48 : encoder_(encoder), iter_(nullptr) {}
50 const aom_codec_cx_pkt_t *Next() {
51 return aom_codec_get_cx_data(encoder_, &iter_);
54 private:
55 aom_codec_ctx_t *encoder_;
56 aom_codec_iter_t iter_;
59 // Implements an in-memory store for libaom twopass statistics
60 class TwopassStatsStore {
61 public:
62 void Append(const aom_codec_cx_pkt_t &pkt) {
63 buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
64 pkt.data.twopass_stats.sz);
67 aom_fixed_buf_t buf() {
68 const aom_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
69 return buf;
72 void Reset() { buffer_.clear(); }
74 protected:
75 std::string buffer_;
78 // Provides a simplified interface to manage one video encoding pass, given
79 // a configuration and video source.
81 // TODO(jkoleszar): The exact services it provides and the appropriate
82 // level of abstraction will be fleshed out as more tests are written.
83 class Encoder {
84 public:
85 Encoder(aom_codec_enc_cfg_t cfg, const aom_codec_flags_t init_flags,
86 TwopassStatsStore *stats)
87 : cfg_(cfg), init_flags_(init_flags), stats_(stats) {
88 memset(&encoder_, 0, sizeof(encoder_));
91 virtual ~Encoder() { aom_codec_destroy(&encoder_); }
93 CxDataIterator GetCxData() { return CxDataIterator(&encoder_); }
95 void InitEncoder(VideoSource *video);
97 const aom_image_t *GetPreviewFrame() {
98 return aom_codec_get_preview_frame(&encoder_);
100 // This is a thin wrapper around aom_codec_encode(), so refer to
101 // aom_encoder.h for its semantics.
102 void EncodeFrame(VideoSource *video, aom_enc_frame_flags_t frame_flags);
104 // Convenience wrapper for EncodeFrame()
105 void EncodeFrame(VideoSource *video) { EncodeFrame(video, 0); }
107 void Control(int ctrl_id, int arg) {
108 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
109 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
112 void Control(int ctrl_id, int *arg) {
113 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
114 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
117 void Control(int ctrl_id, struct aom_scaling_mode *arg) {
118 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
119 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
122 void Control(int ctrl_id, struct aom_svc_layer_id *arg) {
123 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
124 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
127 void Control(int ctrl_id, struct aom_svc_ref_frame_config *arg) {
128 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
129 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
132 void Control(int ctrl_id, struct aom_svc_ref_frame_comp_pred *arg) {
133 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
134 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
137 void Control(int ctrl_id, struct aom_svc_params *arg) {
138 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
139 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
142 void Control(int ctrl_id, struct aom_ext_part_funcs *arg) {
143 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
144 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
147 #if CONFIG_AV1_ENCODER
148 void Control(int ctrl_id, aom_active_map_t *arg) {
149 const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
150 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
152 #endif
154 void SetOption(const char *name, const char *value) {
155 const aom_codec_err_t res = aom_codec_set_option(&encoder_, name, value);
156 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
159 void Config(const aom_codec_enc_cfg_t *cfg) {
160 const aom_codec_err_t res = aom_codec_enc_config_set(&encoder_, cfg);
161 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
162 cfg_ = *cfg;
165 protected:
166 virtual aom_codec_iface_t *CodecInterface() const = 0;
168 const char *EncoderError() {
169 const char *detail = aom_codec_error_detail(&encoder_);
170 return detail ? detail : aom_codec_error(&encoder_);
173 // Encode an image
174 void EncodeFrameInternal(const VideoSource &video,
175 aom_enc_frame_flags_t frame_flags);
177 // Flush the encoder on EOS
178 void Flush();
180 aom_codec_ctx_t encoder_;
181 aom_codec_enc_cfg_t cfg_;
182 aom_codec_flags_t init_flags_;
183 TwopassStatsStore *stats_;
186 // Common test functionality for all Encoder tests.
188 // This class is a mixin which provides the main loop common to all
189 // encoder tests. It provides hooks which can be overridden by subclasses
190 // to implement each test's specific behavior, while centralizing the bulk
191 // of the boilerplate. Note that it doesn't inherit the gtest testing
192 // classes directly, so that tests can be parameterized differently.
193 class EncoderTest {
194 protected:
195 explicit EncoderTest(const CodecFactory *codec)
196 : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0),
197 mode_(kRealTime) {
198 // Default to 1 thread.
199 cfg_.g_threads = 1;
202 virtual ~EncoderTest() = default;
204 // Initialize the cfg_ member with the default configuration for the
205 // TestMode enum and maps the TestMode enum to the passes_ variable.
206 void InitializeConfig(TestMode mode);
208 // Set encoder flag.
209 void set_init_flags(aom_codec_flags_t flag) { init_flags_ = flag; }
211 // Main loop
212 virtual void RunLoop(VideoSource *video);
214 // Hook to be called at the beginning of a pass.
215 virtual void BeginPassHook(unsigned int /*pass*/) {}
217 // Hook to be called at the end of a pass.
218 virtual void EndPassHook() {}
220 // Hook to be called before encoding a frame.
221 virtual void PreEncodeFrameHook(VideoSource * /*video*/,
222 Encoder * /*encoder*/) {}
224 virtual void PostEncodeFrameHook(Encoder * /*encoder*/) {}
226 // Hook to be called on every compressed data packet.
227 virtual void FramePktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
229 // Hook to be called on every PSNR packet.
230 virtual void PSNRPktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
232 // Hook to be called on every first pass stats packet.
233 virtual void StatsPktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
235 // Calculates SSIM at frame level.
236 virtual void CalculateFrameLevelSSIM(const aom_image_t * /*img_src*/,
237 const aom_image_t * /*img_enc*/,
238 aom_bit_depth_t /*bit_depth*/,
239 unsigned int /*input_bit_depth*/) {}
241 // Hook to determine whether the encode loop should continue.
242 virtual bool Continue() const {
243 return !(::testing::Test::HasFatalFailure() || abort_);
246 // Hook to determine whether to decode frame after encoding
247 virtual bool DoDecode() const { return true; }
249 // Hook to determine whether to decode invisible frames after encoding
250 virtual bool DoDecodeInvisible() const { return true; }
252 // Hook to handle encode/decode mismatch
253 virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2);
255 // Hook to be called on every decompressed frame.
256 virtual void DecompressedFrameHook(const aom_image_t & /*img*/,
257 aom_codec_pts_t /*pts*/) {}
259 // Hook to be called to handle decode result. Return true to continue.
260 virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
261 Decoder *decoder) {
262 EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
263 return AOM_CODEC_OK == res_dec;
266 virtual int GetNumSpatialLayers() { return 1; }
268 // Hook that can modify the encoder's output data
269 virtual const aom_codec_cx_pkt_t *MutateEncoderOutputHook(
270 const aom_codec_cx_pkt_t *pkt) {
271 return pkt;
274 const CodecFactory *codec_;
275 bool abort_;
276 aom_codec_enc_cfg_t cfg_;
277 unsigned int passes_;
278 TwopassStatsStore stats_;
279 aom_codec_flags_t init_flags_;
280 aom_enc_frame_flags_t frame_flags_;
281 TestMode mode_;
284 } // namespace libaom_test
286 #endif // AOM_TEST_ENCODE_TEST_DRIVER_H_