/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#ifndef TEST_ENCODE_TEST_DRIVER_H_
#define TEST_ENCODE_TEST_DRIVER_H_

#include <string>
#include <vector>

#include "./vpx_config.h"
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "vpx/vpx_encoder.h"
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
#include "vpx/vp8cx.h"
#endif

namespace libvpx_test {

class CodecFactory;
class VideoSource;

enum TestMode {
  kRealTime,
  kOnePassGood,
  kOnePassBest,
  kTwoPassGood,
  kTwoPassBest
};
#define ALL_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
                                         ::libvpx_test::kOnePassGood, \
                                         ::libvpx_test::kOnePassBest, \
                                         ::libvpx_test::kTwoPassGood, \
                                         ::libvpx_test::kTwoPassBest)

#define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
                                              ::libvpx_test::kOnePassGood, \
                                              ::libvpx_test::kOnePassBest)

#define TWO_PASS_TEST_MODES ::testing::Values(::libvpx_test::kTwoPassGood, \
                                              ::libvpx_test::kTwoPassBest)


// Provides an object to handle the libvpx get_cx_data() iteration pattern
class CxDataIterator {
 public:
  explicit CxDataIterator(vpx_codec_ctx_t *encoder)
      : encoder_(encoder), iter_(NULL) {}

  const vpx_codec_cx_pkt_t *Next() {
    return vpx_codec_get_cx_data(encoder_, &iter_);
  }

 private:
  vpx_codec_ctx_t  *encoder_;
  vpx_codec_iter_t  iter_;
};

// Implements an in-memory store for libvpx twopass statistics
class TwopassStatsStore {
 public:
  void Append(const vpx_codec_cx_pkt_t &pkt) {
    buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
                   pkt.data.twopass_stats.sz);
  }

  vpx_fixed_buf_t buf() {
    const vpx_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
    return buf;
  }

  void Reset() {
    buffer_.clear();
  }

 protected:
  std::string  buffer_;
};


// Provides a simplified interface to manage one video encoding pass, given
// a configuration and video source.
//
// TODO(jkoleszar): The exact services it provides and the appropriate
// level of abstraction will be fleshed out as more tests are written.
class Encoder {
 public:
  Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
          const unsigned long init_flags, TwopassStatsStore *stats)
      : cfg_(cfg), deadline_(deadline), init_flags_(init_flags), stats_(stats) {
    memset(&encoder_, 0, sizeof(encoder_));
  }

  virtual ~Encoder() {
    vpx_codec_destroy(&encoder_);
  }

  CxDataIterator GetCxData() {
    return CxDataIterator(&encoder_);
  }

  void InitEncoder(VideoSource *video);

  const vpx_image_t *GetPreviewFrame() {
    return vpx_codec_get_preview_frame(&encoder_);
  }
  // This is a thin wrapper around vpx_codec_encode(), so refer to
  // vpx_encoder.h for its semantics.
  void EncodeFrame(VideoSource *video, const unsigned long frame_flags);

  // Convenience wrapper for EncodeFrame()
  void EncodeFrame(VideoSource *video) {
    EncodeFrame(video, 0);
  }

  void Control(int ctrl_id, int arg) {
    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
  }

  void Control(int ctrl_id, struct vpx_scaling_mode *arg) {
    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
  }

  void Control(int ctrl_id, struct vpx_svc_layer_id *arg) {
    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
  }

#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
  void Control(int ctrl_id, vpx_active_map_t *arg) {
    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
  }
#endif

  void set_deadline(unsigned long deadline) {
    deadline_ = deadline;
  }

 protected:
  virtual vpx_codec_iface_t* CodecInterface() const = 0;

  const char *EncoderError() {
    const char *detail = vpx_codec_error_detail(&encoder_);
    return detail ? detail : vpx_codec_error(&encoder_);
  }

  // Encode an image
  void EncodeFrameInternal(const VideoSource &video,
                           const unsigned long frame_flags);

  // Flush the encoder on EOS
  void Flush();

  vpx_codec_ctx_t      encoder_;
  vpx_codec_enc_cfg_t  cfg_;
  unsigned long        deadline_;
  unsigned long        init_flags_;
  TwopassStatsStore   *stats_;
};

// Common test functionality for all Encoder tests.
//
// This class is a mixin which provides the main loop common to all
// encoder tests. It provides hooks which can be overridden by subclasses
// to implement each test's specific behavior, while centralizing the bulk
// of the boilerplate. Note that it doesn't inherit the gtest testing
// classes directly, so that tests can be parameterized differently.
class EncoderTest {
 protected:
  explicit EncoderTest(const CodecFactory *codec)
      : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0),
        last_pts_(0) {}

  virtual ~EncoderTest() {}

  // Initialize the cfg_ member with the default configuration.
  void InitializeConfig();

  // Map the TestMode enum to the deadline_ and passes_ variables.
  void SetMode(TestMode mode);

  // Set encoder flag.
  void set_init_flags(unsigned long flag) {  // NOLINT(runtime/int)
    init_flags_ = flag;
  }

  // Main loop
  virtual void RunLoop(VideoSource *video);

  // Hook to be called at the beginning of a pass.
  virtual void BeginPassHook(unsigned int /*pass*/) {}

  // Hook to be called at the end of a pass.
  virtual void EndPassHook() {}

  // Hook to be called before encoding a frame.
  virtual void PreEncodeFrameHook(VideoSource* /*video*/) {}
  virtual void PreEncodeFrameHook(VideoSource* /*video*/,
                                  Encoder* /*encoder*/) {}

  // Hook to be called on every compressed data packet.
  virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}

  // Hook to be called on every PSNR packet.
  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}

  // Hook to determine whether the encode loop should continue.
  virtual bool Continue() const {
    return !(::testing::Test::HasFatalFailure() || abort_);
  }

  const CodecFactory   *codec_;
  // Hook to determine whether to decode frame after encoding
  virtual bool DoDecode() const { return 1; }

  // Hook to handle encode/decode mismatch
  virtual void MismatchHook(const vpx_image_t *img1,
                            const vpx_image_t *img2);

  // Hook to be called on every decompressed frame.
  virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
                                     vpx_codec_pts_t /*pts*/) {}

  // Hook to be called to handle decode result. Return true to continue.
  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
                                  const VideoSource& /*video*/,
                                  Decoder *decoder) {
    EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
    return VPX_CODEC_OK == res_dec;
  }

  // Hook that can modify the encoder's output data
  virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook(
      const vpx_codec_cx_pkt_t *pkt) {
    return pkt;
  }

  bool                 abort_;
  vpx_codec_enc_cfg_t  cfg_;
  vpx_codec_dec_cfg_t  dec_cfg_;
  unsigned int         passes_;
  unsigned long        deadline_;
  TwopassStatsStore    stats_;
  unsigned long        init_flags_;
  unsigned long        frame_flags_;
  vpx_codec_pts_t      last_pts_;
};

}  // namespace libvpx_test

#endif  // TEST_ENCODE_TEST_DRIVER_H_
