1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
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.
10  */
11 
12 #ifndef AOM_TEST_DECODE_TEST_DRIVER_H_
13 #define AOM_TEST_DECODE_TEST_DRIVER_H_
14 #include <cstring>
15 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
16 
17 #include "config/aom_config.h"
18 
19 #include "aom/aom_decoder.h"
20 
21 namespace libaom_test {
22 
23 class CodecFactory;
24 class CompressedVideoSource;
25 
26 // Provides an object to handle decoding output
27 class DxDataIterator {
28  public:
DxDataIterator(aom_codec_ctx_t * decoder)29   explicit DxDataIterator(aom_codec_ctx_t *decoder)
30       : decoder_(decoder), iter_(NULL) {}
31 
Next()32   const aom_image_t *Next() { return aom_codec_get_frame(decoder_, &iter_); }
33 
34  private:
35   aom_codec_ctx_t *decoder_;
36   aom_codec_iter_t iter_;
37 };
38 
39 // Provides a simplified interface to manage one video decoding.
40 // Similar to Encoder class, the exact services should be added
41 // as more tests are added.
42 class Decoder {
43  public:
Decoder(aom_codec_dec_cfg_t cfg)44   explicit Decoder(aom_codec_dec_cfg_t cfg)
45       : cfg_(cfg), flags_(0), init_done_(false) {
46     memset(&decoder_, 0, sizeof(decoder_));
47   }
48 
Decoder(aom_codec_dec_cfg_t cfg,const aom_codec_flags_t flag)49   Decoder(aom_codec_dec_cfg_t cfg, const aom_codec_flags_t flag)
50       : cfg_(cfg), flags_(flag), init_done_(false) {
51     memset(&decoder_, 0, sizeof(decoder_));
52   }
53 
~Decoder()54   virtual ~Decoder() { aom_codec_destroy(&decoder_); }
55 
56   aom_codec_err_t PeekStream(const uint8_t *cxdata, size_t size,
57                              aom_codec_stream_info_t *stream_info);
58 
59   aom_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size);
60 
61   aom_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size,
62                               void *user_priv);
63 
GetDxData()64   DxDataIterator GetDxData() { return DxDataIterator(&decoder_); }
65 
Control(int ctrl_id,int arg)66   void Control(int ctrl_id, int arg) { Control(ctrl_id, arg, AOM_CODEC_OK); }
67 
Control(int ctrl_id,const void * arg)68   void Control(int ctrl_id, const void *arg) {
69     InitOnce();
70     const aom_codec_err_t res = aom_codec_control_(&decoder_, ctrl_id, arg);
71     ASSERT_EQ(AOM_CODEC_OK, res) << DecodeError();
72   }
73 
Control(int ctrl_id,int arg,aom_codec_err_t expected_value)74   void Control(int ctrl_id, int arg, aom_codec_err_t expected_value) {
75     InitOnce();
76     const aom_codec_err_t res = aom_codec_control_(&decoder_, ctrl_id, arg);
77     ASSERT_EQ(expected_value, res) << DecodeError();
78   }
79 
DecodeError()80   const char *DecodeError() {
81     const char *detail = aom_codec_error_detail(&decoder_);
82     return detail ? detail : aom_codec_error(&decoder_);
83   }
84 
85   // Passes the external frame buffer information to libaom.
SetFrameBufferFunctions(aom_get_frame_buffer_cb_fn_t cb_get,aom_release_frame_buffer_cb_fn_t cb_release,void * user_priv)86   aom_codec_err_t SetFrameBufferFunctions(
87       aom_get_frame_buffer_cb_fn_t cb_get,
88       aom_release_frame_buffer_cb_fn_t cb_release, void *user_priv) {
89     InitOnce();
90     return aom_codec_set_frame_buffer_functions(&decoder_, cb_get, cb_release,
91                                                 user_priv);
92   }
93 
GetDecoderName()94   const char *GetDecoderName() const {
95     return aom_codec_iface_name(CodecInterface());
96   }
97 
98   bool IsAV1() const;
99 
GetDecoder()100   aom_codec_ctx_t *GetDecoder() { return &decoder_; }
101 
102  protected:
103   virtual aom_codec_iface_t *CodecInterface() const = 0;
104 
InitOnce()105   void InitOnce() {
106     if (!init_done_) {
107       const aom_codec_err_t res =
108           aom_codec_dec_init(&decoder_, CodecInterface(), &cfg_, flags_);
109       ASSERT_EQ(AOM_CODEC_OK, res) << DecodeError();
110       init_done_ = true;
111     }
112   }
113 
114   aom_codec_ctx_t decoder_;
115   aom_codec_dec_cfg_t cfg_;
116   aom_codec_flags_t flags_;
117   bool init_done_;
118 };
119 
120 // Common test functionality for all Decoder tests.
121 class DecoderTest {
122  public:
123   // Main decoding loop
124   virtual void RunLoop(CompressedVideoSource *video);
125   virtual void RunLoop(CompressedVideoSource *video,
126                        const aom_codec_dec_cfg_t &dec_cfg);
127 
128   virtual void set_cfg(const aom_codec_dec_cfg_t &dec_cfg);
129   virtual void set_flags(const aom_codec_flags_t flags);
130 
131   // Hook to be called before decompressing every frame.
PreDecodeFrameHook(const CompressedVideoSource &,Decoder *)132   virtual void PreDecodeFrameHook(const CompressedVideoSource & /*video*/,
133                                   Decoder * /*decoder*/) {}
134 
135   // Hook to be called to handle decode result. Return true to continue.
HandleDecodeResult(const aom_codec_err_t res_dec,const CompressedVideoSource &,Decoder * decoder)136   virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
137                                   const CompressedVideoSource & /*video*/,
138                                   Decoder *decoder) {
139     EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
140     return AOM_CODEC_OK == res_dec;
141   }
142 
143   // Hook to be called on every decompressed frame.
DecompressedFrameHook(const aom_image_t &,const unsigned int)144   virtual void DecompressedFrameHook(const aom_image_t & /*img*/,
145                                      const unsigned int /*frame_number*/) {}
146 
147   // Hook to be called on peek result
148   virtual void HandlePeekResult(Decoder *const decoder,
149                                 CompressedVideoSource *video,
150                                 const aom_codec_err_t res_peek);
151 
152  protected:
DecoderTest(const CodecFactory * codec)153   explicit DecoderTest(const CodecFactory *codec)
154       : codec_(codec), cfg_(), flags_(0) {}
155 
~DecoderTest()156   virtual ~DecoderTest() {}
157 
158   const CodecFactory *codec_;
159   aom_codec_dec_cfg_t cfg_;
160   aom_codec_flags_t flags_;
161 };
162 
163 }  // namespace libaom_test
164 
165 #endif  // AOM_TEST_DECODE_TEST_DRIVER_H_
166