tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

encode_test_driver.h (9814B)


      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 #ifndef AOM_TEST_ENCODE_TEST_DRIVER_H_
     12 #define AOM_TEST_ENCODE_TEST_DRIVER_H_
     13 
     14 #include <string>
     15 #include <vector>
     16 
     17 #include "gtest/gtest.h"
     18 
     19 #include "config/aom_config.h"
     20 
     21 #if CONFIG_AV1_ENCODER
     22 #include "aom/aomcx.h"
     23 #endif
     24 #include "aom/aom_encoder.h"
     25 
     26 namespace libaom_test {
     27 
     28 class CodecFactory;
     29 class VideoSource;
     30 
     31 enum TestMode {
     32  kRealTime,
     33  kOnePassGood,
     34  kTwoPassGood,
     35  kAllIntra,
     36  kLowComplexityDecode
     37 };
     38 #define ALL_TEST_MODES                                                     \
     39  ::testing::Values(::libaom_test::kRealTime, ::libaom_test::kOnePassGood, \
     40                    ::libaom_test::kTwoPassGood)
     41 
     42 #define ONE_PASS_TEST_MODES \
     43  ::testing::Values(::libaom_test::kRealTime, ::libaom_test::kOnePassGood)
     44 
     45 #define TWO_PASS_TEST_MODES ::testing::Values(::libaom_test::kTwoPassGood)
     46 
     47 #define NONREALTIME_TEST_MODES \
     48  ::testing::Values(::libaom_test::kOnePassGood, ::libaom_test::kTwoPassGood)
     49 
     50 // Provides an object to handle the libaom get_cx_data() iteration pattern
     51 class CxDataIterator {
     52 public:
     53  explicit CxDataIterator(aom_codec_ctx_t *encoder)
     54      : encoder_(encoder), iter_(nullptr) {}
     55 
     56  const aom_codec_cx_pkt_t *Next() {
     57    return aom_codec_get_cx_data(encoder_, &iter_);
     58  }
     59 
     60 private:
     61  aom_codec_ctx_t *encoder_;
     62  aom_codec_iter_t iter_;
     63 };
     64 
     65 // Implements an in-memory store for libaom twopass statistics
     66 class TwopassStatsStore {
     67 public:
     68  void Append(const aom_codec_cx_pkt_t &pkt) {
     69    buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
     70                   pkt.data.twopass_stats.sz);
     71  }
     72 
     73  aom_fixed_buf_t buf() {
     74    const aom_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
     75    return buf;
     76  }
     77 
     78  void Reset() { buffer_.clear(); }
     79 
     80 protected:
     81  std::string buffer_;
     82 };
     83 
     84 // Provides a simplified interface to manage one video encoding pass, given
     85 // a configuration and video source.
     86 //
     87 // TODO(jkoleszar): The exact services it provides and the appropriate
     88 // level of abstraction will be fleshed out as more tests are written.
     89 class Encoder {
     90 public:
     91  Encoder(aom_codec_enc_cfg_t cfg, const aom_codec_flags_t init_flags,
     92          TwopassStatsStore *stats)
     93      : cfg_(cfg), init_flags_(init_flags), stats_(stats) {
     94    memset(&encoder_, 0, sizeof(encoder_));
     95  }
     96 
     97  virtual ~Encoder() { aom_codec_destroy(&encoder_); }
     98 
     99  CxDataIterator GetCxData() { return CxDataIterator(&encoder_); }
    100 
    101  void InitEncoder(VideoSource *video);
    102 
    103  const aom_image_t *GetPreviewFrame() {
    104    return aom_codec_get_preview_frame(&encoder_);
    105  }
    106  // This is a thin wrapper around aom_codec_encode(), so refer to
    107  // aom_encoder.h for its semantics.
    108  void EncodeFrame(VideoSource *video, aom_enc_frame_flags_t frame_flags);
    109 
    110  // Convenience wrapper for EncodeFrame()
    111  void EncodeFrame(VideoSource *video) { EncodeFrame(video, 0); }
    112 
    113  void Control(int ctrl_id, int arg) {
    114    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    115    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    116  }
    117 
    118  void Control(int ctrl_id, int *arg) {
    119    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    120    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    121  }
    122 
    123  void Control(int ctrl_id, struct aom_scaling_mode *arg) {
    124    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    125    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    126  }
    127 
    128  void Control(int ctrl_id, struct aom_svc_layer_id *arg) {
    129    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    130    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    131  }
    132 
    133  void Control(int ctrl_id, struct aom_svc_ref_frame_config *arg) {
    134    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    135    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    136  }
    137 
    138  void Control(int ctrl_id, struct aom_svc_ref_frame_comp_pred *arg) {
    139    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    140    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    141  }
    142 
    143  void Control(int ctrl_id, struct aom_svc_params *arg) {
    144    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    145    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    146  }
    147 
    148  void Control(int ctrl_id, struct aom_ext_part_funcs *arg) {
    149    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    150    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    151  }
    152 
    153 #if CONFIG_AV1_ENCODER
    154  void Control(int ctrl_id, aom_active_map_t *arg) {
    155    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    156    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    157  }
    158  void Control(int ctrl_id, aom_roi_map_t *arg) {
    159    const aom_codec_err_t res = aom_codec_control(&encoder_, ctrl_id, arg);
    160    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    161  }
    162 #endif
    163 
    164  void SetOption(const char *name, const char *value) {
    165    const aom_codec_err_t res = aom_codec_set_option(&encoder_, name, value);
    166    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    167  }
    168 
    169  void Config(const aom_codec_enc_cfg_t *cfg) {
    170    const aom_codec_err_t res = aom_codec_enc_config_set(&encoder_, cfg);
    171    ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
    172    cfg_ = *cfg;
    173  }
    174 
    175 protected:
    176  virtual aom_codec_iface_t *CodecInterface() const = 0;
    177 
    178  const char *EncoderError() {
    179    const char *detail = aom_codec_error_detail(&encoder_);
    180    return detail ? detail : aom_codec_error(&encoder_);
    181  }
    182 
    183  // Encode an image
    184  void EncodeFrameInternal(const VideoSource &video,
    185                           aom_enc_frame_flags_t frame_flags);
    186 
    187  // Flush the encoder on EOS
    188  void Flush();
    189 
    190  aom_codec_ctx_t encoder_;
    191  aom_codec_enc_cfg_t cfg_;
    192  aom_codec_flags_t init_flags_;
    193  TwopassStatsStore *stats_;
    194 };
    195 
    196 // Common test functionality for all Encoder tests.
    197 //
    198 // This class is a mixin which provides the main loop common to all
    199 // encoder tests. It provides hooks which can be overridden by subclasses
    200 // to implement each test's specific behavior, while centralizing the bulk
    201 // of the boilerplate. Note that it doesn't inherit the gtest testing
    202 // classes directly, so that tests can be parameterized differently.
    203 class EncoderTest {
    204 protected:
    205  explicit EncoderTest(const CodecFactory *codec)
    206      : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0),
    207        mode_(kRealTime) {
    208    // Default to 1 thread.
    209    cfg_.g_threads = 1;
    210  }
    211 
    212  virtual ~EncoderTest() = default;
    213 
    214  // Initialize the cfg_ member with the default configuration for the
    215  // TestMode enum and maps the TestMode enum to the passes_ variable.
    216  void InitializeConfig(TestMode mode);
    217 
    218  // Set encoder flag.
    219  void set_init_flags(aom_codec_flags_t flag) { init_flags_ = flag; }
    220 
    221  // Main loop
    222  virtual void RunLoop(VideoSource *video);
    223 
    224  // Hook to be called at the beginning of a pass.
    225  virtual void BeginPassHook(unsigned int /*pass*/) {}
    226 
    227  // Hook to be called at the end of a pass.
    228  virtual void EndPassHook() {}
    229 
    230  // Hook to be called before encoding a frame.
    231  virtual void PreEncodeFrameHook(VideoSource * /*video*/,
    232                                  Encoder * /*encoder*/) {}
    233 
    234  virtual void PostEncodeFrameHook(Encoder * /*encoder*/) {}
    235 
    236  // Hook to be called on every compressed data packet.
    237  virtual void FramePktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
    238 
    239  // Hook to be called on every PSNR packet.
    240  virtual void PSNRPktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
    241 
    242  // Hook to be called on every first pass stats packet.
    243  virtual void StatsPktHook(const aom_codec_cx_pkt_t * /*pkt*/) {}
    244 
    245  // Calculates SSIM at frame level.
    246  virtual void CalculateFrameLevelSSIM(const aom_image_t * /*img_src*/,
    247                                       const aom_image_t * /*img_enc*/,
    248                                       aom_bit_depth_t /*bit_depth*/,
    249                                       unsigned int /*input_bit_depth*/) {}
    250 
    251  // Hook to determine whether the encode loop should continue.
    252  virtual bool Continue() const {
    253    return !(::testing::Test::HasFatalFailure() || abort_);
    254  }
    255 
    256  // Hook to determine whether to decode frame after encoding
    257  virtual bool DoDecode() const { return true; }
    258 
    259  // Hook to determine whether to decode invisible frames after encoding
    260  virtual bool DoDecodeInvisible() const { return true; }
    261 
    262  // Hook to handle encode/decode mismatch
    263  virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2);
    264 
    265  // Hook to be called on every decompressed frame.
    266  virtual void DecompressedFrameHook(const aom_image_t & /*img*/,
    267                                     aom_codec_pts_t /*pts*/) {}
    268 
    269  // Hook to be called to handle decode result. Return true to continue.
    270  virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
    271                                  Decoder *decoder) {
    272    EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
    273    return AOM_CODEC_OK == res_dec;
    274  }
    275 
    276  virtual int GetNumSpatialLayers() { return 1; }
    277 
    278  // Hook that can modify the encoder's output data
    279  virtual const aom_codec_cx_pkt_t *MutateEncoderOutputHook(
    280      const aom_codec_cx_pkt_t *pkt) {
    281    return pkt;
    282  }
    283 
    284  const CodecFactory *codec_;
    285  bool abort_;
    286  aom_codec_enc_cfg_t cfg_;
    287  unsigned int passes_;
    288  TwopassStatsStore stats_;
    289  aom_codec_flags_t init_flags_;
    290  aom_enc_frame_flags_t frame_flags_;
    291  TestMode mode_;
    292 };
    293 
    294 }  // namespace libaom_test
    295 
    296 #endif  // AOM_TEST_ENCODE_TEST_DRIVER_H_