/*
 * 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.
 */

#include <string>
#include "gtest/gtest.h"

#include "aom/aom_codec.h"
#include "aom_ports/aom_timer.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/util.h"
#include "test/y4m_video_source.h"

namespace {

const int kMaxPsnr = 100;
const double kUsecsInSec = 1000000.0;

struct EncodePerfTestVideo {
  EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
                      uint32_t bitrate_, int frames_)
      : name(name_), width(width_), height(height_), bitrate(bitrate_),
        frames(frames_) {}
  const char *name;
  uint32_t width;
  uint32_t height;
  uint32_t bitrate;
  int frames;
};

const EncodePerfTestVideo kAV1EncodePerfTestVectors[] = {
  EncodePerfTestVideo("desktop_640_360_30.yuv", 640, 360, 200, 2484),
  EncodePerfTestVideo("kirland_640_480_30.yuv", 640, 480, 200, 300),
  EncodePerfTestVideo("macmarcomoving_640_480_30.yuv", 640, 480, 200, 987),
  EncodePerfTestVideo("macmarcostationary_640_480_30.yuv", 640, 480, 200, 718),
  EncodePerfTestVideo("niklas_640_480_30.yuv", 640, 480, 200, 471),
  EncodePerfTestVideo("tacomanarrows_640_480_30.yuv", 640, 480, 200, 300),
  EncodePerfTestVideo("tacomasmallcameramovement_640_480_30.yuv", 640, 480, 200,
                      300),
  EncodePerfTestVideo("thaloundeskmtg_640_480_30.yuv", 640, 480, 200, 300),
  EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
};

const int kEncodePerfTestSpeeds[] = { 5, 6, 7, 8 };
const int kEncodePerfTestThreads[] = { 1, 2, 4 };

class AV1EncodePerfTest
    : public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
      public ::libaom_test::EncoderTest {
 protected:
  AV1EncodePerfTest()
      : EncoderTest(GET_PARAM(0)), min_psnr_(kMaxPsnr), nframes_(0),
        encoding_mode_(GET_PARAM(1)), speed_(0), threads_(1) {}

  ~AV1EncodePerfTest() override = default;

  void SetUp() override {
    InitializeConfig(encoding_mode_);

    cfg_.g_lag_in_frames = 0;
    cfg_.rc_min_quantizer = 2;
    cfg_.rc_max_quantizer = 56;
    cfg_.rc_dropframe_thresh = 0;
    cfg_.rc_undershoot_pct = 50;
    cfg_.rc_overshoot_pct = 50;
    cfg_.rc_buf_sz = 1000;
    cfg_.rc_buf_initial_sz = 500;
    cfg_.rc_buf_optimal_sz = 600;
    cfg_.rc_end_usage = AOM_CBR;
    cfg_.g_error_resilient = 1;
    cfg_.g_threads = threads_;
  }

  void PreEncodeFrameHook(::libaom_test::VideoSource *video,
                          ::libaom_test::Encoder *encoder) override {
    if (video->frame() == 0) {
      const int log2_tile_columns = 3;
      encoder->Control(AOME_SET_CPUUSED, speed_);
      encoder->Control(AV1E_SET_TILE_COLUMNS, log2_tile_columns);
      encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING, 1);
      encoder->Control(AOME_SET_ENABLEAUTOALTREF, 0);
    }
  }

  void BeginPassHook(unsigned int /*pass*/) override {
    min_psnr_ = kMaxPsnr;
    nframes_ = 0;
  }

  void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) override {
    if (pkt->data.psnr.psnr[0] < min_psnr_) {
      min_psnr_ = pkt->data.psnr.psnr[0];
    }
  }

  // for performance reasons don't decode
  bool DoDecode() const override { return false; }

  double min_psnr() const { return min_psnr_; }

  void set_speed(unsigned int speed) { speed_ = speed; }

  void set_threads(unsigned int threads) { threads_ = threads; }

 private:
  double min_psnr_;
  unsigned int nframes_;
  libaom_test::TestMode encoding_mode_;
  unsigned speed_;
  unsigned int threads_;
};

TEST_P(AV1EncodePerfTest, PerfTest) {
  for (const EncodePerfTestVideo &test_video : kAV1EncodePerfTestVectors) {
    for (int speed : kEncodePerfTestSpeeds) {
      for (int threads : kEncodePerfTestThreads) {
        if (test_video.width < 512 && threads > 1)
          continue;
        else if (test_video.width < 1024 && threads > 2)
          continue;

        set_threads(threads);
        SetUp();

        const aom_rational timebase = { 33333333, 1000000000 };
        cfg_.g_timebase = timebase;
        cfg_.rc_target_bitrate = test_video.bitrate;

        init_flags_ = AOM_CODEC_USE_PSNR;

        const unsigned frames = test_video.frames;
        const char *video_name = test_video.name;
        libaom_test::I420VideoSource video(video_name, test_video.width,
                                           test_video.height, timebase.den,
                                           timebase.num, 0, test_video.frames);
        set_speed(speed);

        aom_usec_timer t;
        aom_usec_timer_start(&t);

        ASSERT_NO_FATAL_FAILURE(RunLoop(&video));

        aom_usec_timer_mark(&t);
        const double elapsed_secs = aom_usec_timer_elapsed(&t) / kUsecsInSec;
        const double fps = frames / elapsed_secs;
        const double minimum_psnr = min_psnr();
        std::string display_name(video_name);
        if (threads > 1) {
          char thread_count[32];
          snprintf(thread_count, sizeof(thread_count), "_t-%d", threads);
          display_name += thread_count;
        }

        printf("{\n");
        printf("\t\"type\" : \"encode_perf_test\",\n");
        printf("\t\"version\" : \"%s\",\n", aom_codec_version_str());
        printf("\t\"videoName\" : \"%s\",\n", display_name.c_str());
        printf("\t\"encodeTimeSecs\" : %f,\n", elapsed_secs);
        printf("\t\"totalFrames\" : %u,\n", frames);
        printf("\t\"framesPerSecond\" : %f,\n", fps);
        printf("\t\"minPsnr\" : %f,\n", minimum_psnr);
        printf("\t\"speed\" : %d,\n", speed);
        printf("\t\"threads\" : %d\n", threads);
        printf("}\n");
      }
    }
  }
}

AV1_INSTANTIATE_TEST_SUITE(AV1EncodePerfTest,
                           ::testing::Values(::libaom_test::kRealTime));
}  // namespace
