Backed out 3 changesets (bug 1790375) for causing wd failures on fetch_error.py....
[gecko.git] / third_party / aom / test / encode_test_driver.h
blob4f3f855cf90093ef7d36bf382fcbf57e1f314b36
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 };
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_(NULL) {}
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 uint32_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, const unsigned long 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 #if CONFIG_AV1_ENCODER
123 void Control(int ctrl_id, aom_active_map_t *arg) {
124 const aom_codec_err_t res = aom_codec_control_(&encoder_, ctrl_id, arg);
125 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
127 #endif
129 void Config(const aom_codec_enc_cfg_t *cfg) {
130 const aom_codec_err_t res = aom_codec_enc_config_set(&encoder_, cfg);
131 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
132 cfg_ = *cfg;
135 protected:
136 virtual aom_codec_iface_t *CodecInterface() const = 0;
138 const char *EncoderError() {
139 const char *detail = aom_codec_error_detail(&encoder_);
140 return detail ? detail : aom_codec_error(&encoder_);
143 // Encode an image
144 void EncodeFrameInternal(const VideoSource &video,
145 const unsigned long frame_flags);
147 // Flush the encoder on EOS
148 void Flush();
150 aom_codec_ctx_t encoder_;
151 aom_codec_enc_cfg_t cfg_;
152 unsigned long init_flags_;
153 TwopassStatsStore *stats_;
156 // Common test functionality for all Encoder tests.
158 // This class is a mixin which provides the main loop common to all
159 // encoder tests. It provides hooks which can be overridden by subclasses
160 // to implement each test's specific behavior, while centralizing the bulk
161 // of the boilerplate. Note that it doesn't inherit the gtest testing
162 // classes directly, so that tests can be parameterized differently.
163 class EncoderTest {
164 protected:
165 explicit EncoderTest(const CodecFactory *codec)
166 : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0),
167 last_pts_(0), mode_(kRealTime) {
168 // Default to 1 thread.
169 cfg_.g_threads = 1;
172 virtual ~EncoderTest() {}
174 // Initialize the cfg_ member with the default configuration.
175 void InitializeConfig();
177 // Map the TestMode enum to the passes_ variables.
178 void SetMode(TestMode mode);
180 // Set encoder flag.
181 void set_init_flags(unsigned long flag) { // NOLINT(runtime/int)
182 init_flags_ = flag;
185 // Main loop
186 virtual void RunLoop(VideoSource *video);
188 // Hook to be called at the beginning of a pass.
189 virtual void BeginPassHook(unsigned int /*pass*/) {}
191 // Hook to be called at the end of a pass.
192 virtual void EndPassHook() {}
194 // Hook to be called before encoding a frame.
195 virtual void PreEncodeFrameHook(VideoSource * /*video*/) {}
196 virtual void PreEncodeFrameHook(VideoSource * /*video*/,
197 Encoder * /*encoder*/) {}
199 // Hook to be called on every compressed data packet.
200 virtual void FramePktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
202 // Hook to be called on every PSNR packet.
203 virtual void PSNRPktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
205 // Hook to determine whether the encode loop should continue.
206 virtual bool Continue() const {
207 return !(::testing::Test::HasFatalFailure() || abort_);
210 // Hook to determine whether to decode frame after encoding
211 virtual bool DoDecode() const { return true; }
213 // Hook to determine whether to decode invisible frames after encoding
214 virtual bool DoDecodeInvisible() const { return true; }
216 // Hook to handle encode/decode mismatch
217 virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2);
219 // Hook to be called on every decompressed frame.
220 virtual void DecompressedFrameHook(const aom_image_t & /*img*/,
221 aom_codec_pts_t /*pts*/) {}
223 // Hook to be called to handle decode result. Return true to continue.
224 virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
225 Decoder *decoder) {
226 EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
227 return AOM_CODEC_OK == res_dec;
230 // Hook that can modify the encoder's output data
231 virtual const aom_codec_cx_pkt_t *MutateEncoderOutputHook(
232 const aom_codec_cx_pkt_t *pkt) {
233 return pkt;
236 const CodecFactory *codec_;
237 bool abort_;
238 aom_codec_enc_cfg_t cfg_;
239 unsigned int passes_;
240 TwopassStatsStore stats_;
241 unsigned long init_flags_;
242 unsigned long frame_flags_;
243 aom_codec_pts_t last_pts_;
244 TestMode mode_;
247 } // namespace libaom_test
249 #endif // AOM_TEST_ENCODE_TEST_DRIVER_H_