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