2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
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.
10 #ifndef TEST_ENCODE_TEST_DRIVER_H_
11 #define TEST_ENCODE_TEST_DRIVER_H_
16 #include "third_party/googletest/src/include/gtest/gtest.h"
18 #include "./vpx_config.h"
19 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
20 #include "vpx/vp8cx.h"
22 #include "vpx/vpx_encoder.h"
24 namespace libvpx_test
{
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)
42 #define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
43 ::libvpx_test::kOnePassGood, \
44 ::libvpx_test::kOnePassBest)
46 #define TWO_PASS_TEST_MODES ::testing::Values(::libvpx_test::kTwoPassGood, \
47 ::libvpx_test::kTwoPassBest)
50 // Provides an object to handle the libvpx get_cx_data() iteration pattern
51 class CxDataIterator
{
53 explicit CxDataIterator(vpx_codec_ctx_t
*encoder
)
54 : encoder_(encoder
), iter_(NULL
) {}
56 const vpx_codec_cx_pkt_t
*Next() {
57 return vpx_codec_get_cx_data(encoder_
, &iter_
);
61 vpx_codec_ctx_t
*encoder_
;
62 vpx_codec_iter_t iter_
;
65 // Implements an in-memory store for libvpx twopass statistics
66 class TwopassStatsStore
{
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
);
73 vpx_fixed_buf_t
buf() {
74 const vpx_fixed_buf_t buf
= { &buffer_
[0], buffer_
.size() };
87 // Provides a simplified interface to manage one video encoding pass, given
88 // a configuration and video source.
90 // TODO(jkoleszar): The exact services it provides and the appropriate
91 // level of abstraction will be fleshed out as more tests are written.
94 Encoder(vpx_codec_enc_cfg_t cfg
, unsigned long deadline
,
95 const unsigned long init_flags
, TwopassStatsStore
*stats
)
96 : cfg_(cfg
), deadline_(deadline
), init_flags_(init_flags
), stats_(stats
) {
97 memset(&encoder_
, 0, sizeof(encoder_
));
101 vpx_codec_destroy(&encoder_
);
104 CxDataIterator
GetCxData() {
105 return CxDataIterator(&encoder_
);
108 void InitEncoder(VideoSource
*video
);
110 const vpx_image_t
*GetPreviewFrame() {
111 return vpx_codec_get_preview_frame(&encoder_
);
113 // This is a thin wrapper around vpx_codec_encode(), so refer to
114 // vpx_encoder.h for its semantics.
115 void EncodeFrame(VideoSource
*video
, const unsigned long frame_flags
);
117 // Convenience wrapper for EncodeFrame()
118 void EncodeFrame(VideoSource
*video
) {
119 EncodeFrame(video
, 0);
122 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();
127 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();
132 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();
137 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();
142 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();
146 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
147 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();
153 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();
159 void set_deadline(unsigned long deadline
) {
160 deadline_
= deadline
;
164 virtual vpx_codec_iface_t
* CodecInterface() const = 0;
166 const char *EncoderError() {
167 const char *detail
= vpx_codec_error_detail(&encoder_
);
168 return detail
? detail
: vpx_codec_error(&encoder_
);
172 void EncodeFrameInternal(const VideoSource
&video
,
173 const unsigned long frame_flags
);
175 // Flush the encoder on EOS
178 vpx_codec_ctx_t encoder_
;
179 vpx_codec_enc_cfg_t cfg_
;
180 unsigned long deadline_
;
181 unsigned long init_flags_
;
182 TwopassStatsStore
*stats_
;
185 // Common test functionality for all Encoder tests.
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.
194 explicit EncoderTest(const CodecFactory
*codec
)
195 : codec_(codec
), abort_(false), init_flags_(0), frame_flags_(0),
197 // Default to 1 thread.
201 virtual ~EncoderTest() {}
203 // Initialize the cfg_ member with the default configuration.
204 void InitializeConfig();
206 // Map the TestMode enum to the deadline_ and passes_ variables.
207 void SetMode(TestMode mode
);
210 void set_init_flags(unsigned long flag
) { // NOLINT(runtime/int)
215 virtual void RunLoop(VideoSource
*video
);
217 // Hook to be called at the beginning of a pass.
218 virtual void BeginPassHook(unsigned int /*pass*/) {}
220 // Hook to be called at the end of a pass.
221 virtual void EndPassHook() {}
223 // Hook to be called before encoding a frame.
224 virtual void PreEncodeFrameHook(VideoSource
* /*video*/) {}
225 virtual void PreEncodeFrameHook(VideoSource
* /*video*/,
226 Encoder
* /*encoder*/) {}
228 // Hook to be called on every compressed data packet.
229 virtual void FramePktHook(const vpx_codec_cx_pkt_t
* /*pkt*/) {}
231 // Hook to be called on every PSNR packet.
232 virtual void PSNRPktHook(const vpx_codec_cx_pkt_t
* /*pkt*/) {}
234 // Hook to determine whether the encode loop should continue.
235 virtual bool Continue() const {
236 return !(::testing::Test::HasFatalFailure() || abort_
);
239 const CodecFactory
*codec_
;
240 // Hook to determine whether to decode frame after encoding
241 virtual bool DoDecode() const { return 1; }
243 // Hook to handle encode/decode mismatch
244 virtual void MismatchHook(const vpx_image_t
*img1
,
245 const vpx_image_t
*img2
);
247 // Hook to be called on every decompressed frame.
248 virtual void DecompressedFrameHook(const vpx_image_t
& /*img*/,
249 vpx_codec_pts_t
/*pts*/) {}
251 // Hook to be called to handle decode result. Return true to continue.
252 virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec
,
253 const VideoSource
& /*video*/,
255 EXPECT_EQ(VPX_CODEC_OK
, res_dec
) << decoder
->DecodeError();
256 return VPX_CODEC_OK
== res_dec
;
259 // Hook that can modify the encoder's output data
260 virtual const vpx_codec_cx_pkt_t
*MutateEncoderOutputHook(
261 const vpx_codec_cx_pkt_t
*pkt
) {
266 vpx_codec_enc_cfg_t cfg_
;
267 vpx_codec_dec_cfg_t dec_cfg_
;
268 unsigned int passes_
;
269 unsigned long deadline_
;
270 TwopassStatsStore stats_
;
271 unsigned long init_flags_
;
272 unsigned long frame_flags_
;
273 vpx_codec_pts_t last_pts_
;
276 } // namespace libvpx_test
278 #endif // TEST_ENCODE_TEST_DRIVER_H_