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