/*
 *  Copyright (c) 2014 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.
 */
#include <memory>

#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/register_state_check.h"
#include "test/video_source.h"

namespace {

class EncoderWithExpectedError : public ::libvpx_test::Encoder {
 public:
  EncoderWithExpectedError(vpx_codec_enc_cfg_t cfg,
                           unsigned long deadline,          // NOLINT
                           const unsigned long init_flags,  // NOLINT
                           ::libvpx_test::TwopassStatsStore *stats)
      : ::libvpx_test::Encoder(cfg, deadline, init_flags, stats) {}
  // This overrides with expected error code.
  void EncodeFrame(::libvpx_test::VideoSource *video,
                   const unsigned long frame_flags,  // NOLINT
                   const vpx_codec_err_t expected_err) {
    if (video->img()) {
      EncodeFrameInternal(*video, frame_flags, expected_err);
    } else {
      Flush();
    }

    // Handle twopass stats
    ::libvpx_test::CxDataIterator iter = GetCxData();

    while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
      if (pkt->kind != VPX_CODEC_STATS_PKT) continue;

      stats_->Append(*pkt);
    }
  }

 protected:
  void EncodeFrameInternal(const ::libvpx_test::VideoSource &video,
                           const unsigned long frame_flags,  // NOLINT
                           const vpx_codec_err_t expected_err) {
    vpx_codec_err_t res;
    const vpx_image_t *img = video.img();

    // Handle frame resizing
    if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) {
      cfg_.g_w = img->d_w;
      cfg_.g_h = img->d_h;
      res = vpx_codec_enc_config_set(&encoder_, &cfg_);
      ASSERT_EQ(res, VPX_CODEC_OK) << EncoderError();
    }

    // Encode the frame
    API_REGISTER_STATE_CHECK(res = vpx_codec_encode(&encoder_, img, video.pts(),
                                                    video.duration(),
                                                    frame_flags, deadline_));
    ASSERT_EQ(expected_err, res) << EncoderError();
  }

  virtual vpx_codec_iface_t *CodecInterface() const {
#if CONFIG_VP9_ENCODER
    return &vpx_codec_vp9_cx_algo;
#else
    return nullptr;
#endif
  }
};

class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest,
                               public ::testing::Test {
 protected:
  VP9FrameSizeTestsLarge()
      : EncoderTest(&::libvpx_test::kVP9), expected_res_(VPX_CODEC_OK) {}
  virtual ~VP9FrameSizeTestsLarge() {}

  virtual void SetUp() {
    InitializeConfig();
    SetMode(::libvpx_test::kRealTime);
  }

  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
                                  const libvpx_test::VideoSource & /*video*/,
                                  libvpx_test::Decoder *decoder) {
    EXPECT_EQ(expected_res_, res_dec) << decoder->DecodeError();
    return !::testing::Test::HasFailure();
  }

  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
                                  ::libvpx_test::Encoder *encoder) {
    if (video->frame() == 0) {
      encoder->Control(VP8E_SET_CPUUSED, 7);
      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
      encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
      encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
      encoder->Control(VP8E_SET_ARNR_TYPE, 3);
    }
  }

  using ::libvpx_test::EncoderTest::RunLoop;
  virtual void RunLoop(::libvpx_test::VideoSource *video,
                       const vpx_codec_err_t expected_err) {
    stats_.Reset();

    ASSERT_TRUE(passes_ == 1 || passes_ == 2);
    for (unsigned int pass = 0; pass < passes_; pass++) {
      last_pts_ = 0;

      if (passes_ == 1) {
        cfg_.g_pass = VPX_RC_ONE_PASS;
      } else if (pass == 0) {
        cfg_.g_pass = VPX_RC_FIRST_PASS;
      } else {
        cfg_.g_pass = VPX_RC_LAST_PASS;
      }

      BeginPassHook(pass);
      std::unique_ptr<EncoderWithExpectedError> encoder(
          new EncoderWithExpectedError(cfg_, deadline_, init_flags_, &stats_));
      ASSERT_NE(encoder.get(), nullptr);

      ASSERT_NO_FATAL_FAILURE(video->Begin());
      encoder->InitEncoder(video);
      ASSERT_FALSE(::testing::Test::HasFatalFailure());
      for (bool again = true; again; video->Next()) {
        again = (video->img() != nullptr);

        PreEncodeFrameHook(video, encoder.get());
        encoder->EncodeFrame(video, frame_flags_, expected_err);

        PostEncodeFrameHook(encoder.get());

        ::libvpx_test::CxDataIterator iter = encoder->GetCxData();

        while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
          pkt = MutateEncoderOutputHook(pkt);
          again = true;
          switch (pkt->kind) {
            case VPX_CODEC_CX_FRAME_PKT:
              ASSERT_GE(pkt->data.frame.pts, last_pts_);
              last_pts_ = pkt->data.frame.pts;
              FramePktHook(pkt);
              break;

            case VPX_CODEC_PSNR_PKT: PSNRPktHook(pkt); break;
            case VPX_CODEC_STATS_PKT: StatsPktHook(pkt); break;
            default: break;
          }
        }

        if (!Continue()) break;
      }

      EndPassHook();

      if (!Continue()) break;
    }
  }

  vpx_codec_err_t expected_res_;
};

TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) {
  ::libvpx_test::RandomVideoSource video;

#if CONFIG_SIZE_LIMIT
  video.SetSize(DECODE_WIDTH_LIMIT + 16, DECODE_HEIGHT_LIMIT + 16);
  video.set_limit(2);
  expected_res_ = VPX_CODEC_MEM_ERROR;
  ASSERT_NO_FATAL_FAILURE(RunLoop(&video, expected_res_));
#endif
}

TEST_F(VP9FrameSizeTestsLarge, ValidSizes) {
  ::libvpx_test::RandomVideoSource video;

#if CONFIG_SIZE_LIMIT
  video.SetSize(DECODE_WIDTH_LIMIT, DECODE_HEIGHT_LIMIT);
  video.set_limit(2);
  expected_res_ = VPX_CODEC_OK;
  ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
#else
// This test produces a pretty large single frame allocation,  (roughly
// 25 megabits). The encoder allocates a good number of these frames
// one for each lag in frames (for 2 pass), and then one for each possible
// reference buffer (8) - we can end up with up to 30 buffers of roughly this
// size or almost 1 gig of memory.
// In total the allocations will exceed 2GiB which may cause a failure with
// mingw + wine, use a smaller size in that case.
#if defined(_WIN32) && !defined(_WIN64) || defined(__OS2__)
  video.SetSize(4096, 3072);
#else
  video.SetSize(4096, 4096);
#endif
  video.set_limit(2);
  expected_res_ = VPX_CODEC_OK;
  ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
#endif
}

TEST_F(VP9FrameSizeTestsLarge, OneByOneVideo) {
  ::libvpx_test::RandomVideoSource video;

  video.SetSize(1, 1);
  video.set_limit(2);
  expected_res_ = VPX_CODEC_OK;
  ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
}
}  // namespace
