|  | /* | 
|  | * Copyright (c) 2016, Alliance for Open Media. All rights reserved. | 
|  | * | 
|  | * This source code is subject to the terms of the BSD 2 Clause License and | 
|  | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | 
|  | * was not distributed with this source code in the LICENSE file, you can | 
|  | * obtain it at www.aomedia.org/license/software. If the Alliance for Open | 
|  | * Media Patent License 1.0 was not distributed with this source code in the | 
|  | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. | 
|  | */ | 
|  |  | 
|  | #ifndef AOM_TEST_DECODE_TEST_DRIVER_H_ | 
|  | #define AOM_TEST_DECODE_TEST_DRIVER_H_ | 
|  | #include <cstring> | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | #include "config/aom_config.h" | 
|  |  | 
|  | #include "aom/aom_decoder.h" | 
|  |  | 
|  | namespace libaom_test { | 
|  |  | 
|  | class CodecFactory; | 
|  | class CompressedVideoSource; | 
|  |  | 
|  | // Provides an object to handle decoding output | 
|  | class DxDataIterator { | 
|  | public: | 
|  | explicit DxDataIterator(aom_codec_ctx_t *decoder) | 
|  | : decoder_(decoder), iter_(nullptr) {} | 
|  |  | 
|  | const aom_image_t *Next() { return aom_codec_get_frame(decoder_, &iter_); } | 
|  |  | 
|  | private: | 
|  | aom_codec_ctx_t *decoder_; | 
|  | aom_codec_iter_t iter_; | 
|  | }; | 
|  |  | 
|  | // Provides a simplified interface to manage one video decoding. | 
|  | // Similar to Encoder class, the exact services should be added | 
|  | // as more tests are added. | 
|  | class Decoder { | 
|  | public: | 
|  | explicit Decoder(aom_codec_dec_cfg_t cfg) | 
|  | : cfg_(cfg), flags_(0), init_done_(false) { | 
|  | memset(&decoder_, 0, sizeof(decoder_)); | 
|  | } | 
|  |  | 
|  | Decoder(aom_codec_dec_cfg_t cfg, const aom_codec_flags_t flag) | 
|  | : cfg_(cfg), flags_(flag), init_done_(false) { | 
|  | memset(&decoder_, 0, sizeof(decoder_)); | 
|  | } | 
|  |  | 
|  | virtual ~Decoder() { aom_codec_destroy(&decoder_); } | 
|  |  | 
|  | aom_codec_err_t PeekStream(const uint8_t *cxdata, size_t size, | 
|  | aom_codec_stream_info_t *stream_info); | 
|  |  | 
|  | aom_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size); | 
|  |  | 
|  | aom_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size, | 
|  | void *user_priv); | 
|  |  | 
|  | DxDataIterator GetDxData() { return DxDataIterator(&decoder_); } | 
|  |  | 
|  | void Control(int ctrl_id, int arg) { Control(ctrl_id, arg, AOM_CODEC_OK); } | 
|  |  | 
|  | void Control(int ctrl_id, const void *arg) { | 
|  | InitOnce(); | 
|  | const aom_codec_err_t res = aom_codec_control(&decoder_, ctrl_id, arg); | 
|  | ASSERT_EQ(AOM_CODEC_OK, res) << DecodeError(); | 
|  | } | 
|  |  | 
|  | void Control(int ctrl_id, int arg, aom_codec_err_t expected_value) { | 
|  | InitOnce(); | 
|  | const aom_codec_err_t res = aom_codec_control(&decoder_, ctrl_id, arg); | 
|  | ASSERT_EQ(expected_value, res) << DecodeError(); | 
|  | } | 
|  |  | 
|  | const char *DecodeError() { | 
|  | const char *detail = aom_codec_error_detail(&decoder_); | 
|  | return detail ? detail : aom_codec_error(&decoder_); | 
|  | } | 
|  |  | 
|  | // Passes the external frame buffer information to libaom. | 
|  | aom_codec_err_t SetFrameBufferFunctions( | 
|  | aom_get_frame_buffer_cb_fn_t cb_get, | 
|  | aom_release_frame_buffer_cb_fn_t cb_release, void *user_priv) { | 
|  | InitOnce(); | 
|  | return aom_codec_set_frame_buffer_functions(&decoder_, cb_get, cb_release, | 
|  | user_priv); | 
|  | } | 
|  |  | 
|  | const char *GetDecoderName() const { | 
|  | return aom_codec_iface_name(CodecInterface()); | 
|  | } | 
|  |  | 
|  | bool IsAV1() const; | 
|  |  | 
|  | aom_codec_ctx_t *GetDecoder() { return &decoder_; } | 
|  |  | 
|  | protected: | 
|  | virtual aom_codec_iface_t *CodecInterface() const = 0; | 
|  |  | 
|  | void InitOnce() { | 
|  | if (!init_done_) { | 
|  | const aom_codec_err_t res = | 
|  | aom_codec_dec_init(&decoder_, CodecInterface(), &cfg_, flags_); | 
|  | ASSERT_EQ(AOM_CODEC_OK, res) << DecodeError(); | 
|  | init_done_ = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | aom_codec_ctx_t decoder_; | 
|  | aom_codec_dec_cfg_t cfg_; | 
|  | aom_codec_flags_t flags_; | 
|  | bool init_done_; | 
|  | }; | 
|  |  | 
|  | // Common test functionality for all Decoder tests. | 
|  | class DecoderTest { | 
|  | public: | 
|  | // Main decoding loop | 
|  | virtual void RunLoop(CompressedVideoSource *video); | 
|  | virtual void RunLoop(CompressedVideoSource *video, | 
|  | const aom_codec_dec_cfg_t &dec_cfg); | 
|  |  | 
|  | virtual void set_cfg(const aom_codec_dec_cfg_t &dec_cfg); | 
|  | virtual void set_flags(const aom_codec_flags_t flags); | 
|  |  | 
|  | // Hook to be called before decompressing every frame. | 
|  | virtual void PreDecodeFrameHook(const CompressedVideoSource & /*video*/, | 
|  | Decoder * /*decoder*/) {} | 
|  |  | 
|  | // Hook to be called to handle decode result. Return true to continue. | 
|  | virtual bool HandleDecodeResult(const aom_codec_err_t res_dec, | 
|  | const CompressedVideoSource & /*video*/, | 
|  | Decoder *decoder) { | 
|  | EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError(); | 
|  | return AOM_CODEC_OK == res_dec; | 
|  | } | 
|  |  | 
|  | // Hook to be called on every decompressed frame. | 
|  | virtual void DecompressedFrameHook(const aom_image_t & /*img*/, | 
|  | const unsigned int /*frame_number*/) {} | 
|  |  | 
|  | // Hook to be called on peek result | 
|  | virtual void HandlePeekResult(Decoder *const decoder, | 
|  | CompressedVideoSource *video, | 
|  | const aom_codec_err_t res_peek); | 
|  |  | 
|  | protected: | 
|  | explicit DecoderTest(const CodecFactory *codec) | 
|  | : codec_(codec), cfg_(), flags_(0) {} | 
|  |  | 
|  | virtual ~DecoderTest() = default; | 
|  |  | 
|  | const CodecFactory *codec_; | 
|  | aom_codec_dec_cfg_t cfg_; | 
|  | aom_codec_flags_t flags_; | 
|  | }; | 
|  |  | 
|  | }  // namespace libaom_test | 
|  |  | 
|  | #endif  // AOM_TEST_DECODE_TEST_DRIVER_H_ |