/*
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 3-Clause Clear License
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
 * License was not distributed with this source code in the LICENSE file, you
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  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
 * aomedia.org/license/patent-license/.
 */

#include <memory>

#include "third_party/googletest/src/googletest/include/gtest/gtest.h"

#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/util.h"
#include "test/yuv_video_source.h"

#include "aom/aom_decoder.h"
#include "av1/decoder/decoder.h"

namespace {

struct ParamPassingTestVideo {
  const char *name;
  uint32_t width;
  uint32_t height;
  uint32_t bitrate;
  int frames;
};

const ParamPassingTestVideo kAV1ParamPassingTestVector = {
  "niklas_640_480_30.yuv", 640, 480, 600, 3
};

struct EncodeParameters {
  int32_t lossless;
  aom_color_primaries_t color_primaries;
  aom_transfer_characteristics_t transfer_characteristics;
  aom_matrix_coefficients_t matrix_coefficients;
  aom_color_range_t color_range;
  aom_chroma_sample_position_t chroma_sample_position;
  int32_t render_size[2];
};

const EncodeParameters kAV1EncodeParameterSet[] = {
  { 1,
    AOM_CICP_CP_BT_709,
    AOM_CICP_TC_BT_709,
    AOM_CICP_MC_BT_709,
    AOM_CR_STUDIO_RANGE,
    AOM_CSP_UNKNOWN,
    { 0, 0 } },
  { 0,
    AOM_CICP_CP_BT_470_M,
    AOM_CICP_TC_BT_470_M,
    AOM_CICP_MC_BT_470_B_G,
    AOM_CR_FULL_RANGE,
    AOM_CSP_VERTICAL,
    { 0, 0 } },
  { 1,
    AOM_CICP_CP_BT_601,
    AOM_CICP_TC_BT_601,
    AOM_CICP_MC_BT_601,
    AOM_CR_STUDIO_RANGE,
    AOM_CSP_COLOCATED,
    { 0, 0 } },
  { 0,
    AOM_CICP_CP_BT_2020,
    AOM_CICP_TC_BT_2020_10_BIT,
    AOM_CICP_MC_BT_2020_NCL,
    AOM_CR_FULL_RANGE,
    AOM_CSP_RESERVED,
    { 320, 240 } },
};

class AVxEncoderParmsGetToDecoder
    : public ::libaom_test::EncoderTest,
      public ::libaom_test::CodecTestWithParam<EncodeParameters> {
 protected:
  AVxEncoderParmsGetToDecoder()
      : EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {}

  virtual ~AVxEncoderParmsGetToDecoder() {}

  virtual void SetUp() {
    InitializeConfig();
    SetMode(::libaom_test::kOnePassGood);
    cfg_.g_lag_in_frames = 25;
    test_video_ = kAV1ParamPassingTestVector;
    cfg_.rc_end_usage = AOM_Q;
  }

  virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
                                  ::libaom_test::Encoder *encoder) {
    if (video->frame() == 0) {
      encoder->Control(AOME_SET_CPUUSED, 5);
      encoder->Control(AOME_SET_QP, 210);
      encoder->Control(AV1E_SET_COLOR_PRIMARIES, encode_parms.color_primaries);
      encoder->Control(AV1E_SET_TRANSFER_CHARACTERISTICS,
                       encode_parms.transfer_characteristics);
      encoder->Control(AV1E_SET_MATRIX_COEFFICIENTS,
                       encode_parms.matrix_coefficients);
      encoder->Control(AV1E_SET_COLOR_RANGE, encode_parms.color_range);
      encoder->Control(AV1E_SET_CHROMA_SAMPLE_POSITION,
                       encode_parms.chroma_sample_position);
      encoder->Control(AV1E_SET_LOSSLESS, encode_parms.lossless);
      if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) {
        encoder->Control(AV1E_SET_RENDER_SIZE, encode_parms.render_size);
      }
    }
  }

  virtual void DecompressedFrameHook(const aom_image_t &img,
                                     aom_codec_pts_t pts) {
    (void)pts;
    if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) {
      EXPECT_EQ(encode_parms.render_size[0], (int)img.r_w);
      EXPECT_EQ(encode_parms.render_size[1], (int)img.r_h);
    }
    EXPECT_EQ(encode_parms.color_primaries, img.cp);
    EXPECT_EQ(encode_parms.transfer_characteristics, img.tc);
    EXPECT_EQ(encode_parms.matrix_coefficients, img.mc);
    EXPECT_EQ(encode_parms.color_range, img.range);
    EXPECT_EQ(encode_parms.chroma_sample_position, img.csp);
  }

  virtual void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) {
    if (encode_parms.lossless) {
      const double lossless_psnr =
          get_lossless_psnr(test_video_.width, test_video_.height, 8, false);
      EXPECT_EQ(lossless_psnr, pkt->data.psnr.psnr[0]);
    }
  }

  virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
                                  libaom_test::Decoder *decoder) {
    EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
    return AOM_CODEC_OK == res_dec;
  }

  ParamPassingTestVideo test_video_;

 private:
  EncodeParameters encode_parms;
};

TEST_P(AVxEncoderParmsGetToDecoder, BitstreamParms) {
  init_flags_ = AOM_CODEC_USE_PSNR;

  std::unique_ptr<libaom_test::VideoSource> video(
      new libaom_test::YUVVideoSource(test_video_.name, AOM_IMG_FMT_I420,
                                      test_video_.width, test_video_.height, 30,
                                      1, 0, test_video_.frames));
  ASSERT_TRUE(video.get() != NULL);

  ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
}

AV1_INSTANTIATE_TEST_SUITE(AVxEncoderParmsGetToDecoder,
                           ::testing::ValuesIn(kAV1EncodeParameterSet));
}  // namespace
