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

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

#include "./aom_config.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "vp8/common/blockd.h"
#include "vp8/common/onyx.h"
#include "vp8/encoder/block.h"
#include "vp8/encoder/onyx_int.h"
#include "vp8/encoder/quantize.h"
#include "aom/aom_integer.h"
#include "aom_mem/aom_mem.h"

namespace {
#if !CONFIG_AOM_QM

const int kNumBlocks = 25;
const int kNumBlockEntries = 16;

typedef void (*VP8Quantize)(BLOCK *b, BLOCKD *d);

typedef std::tr1::tuple<VP8Quantize, VP8Quantize> VP8QuantizeParam;

using libaom_test::ACMRandom;
using std::tr1::make_tuple;

// Create and populate a VP8_COMP instance which has a complete set of
// quantization inputs as well as a second MACROBLOCKD for output.
class QuantizeTestBase {
 public:
  virtual ~QuantizeTestBase() {
    vp8_remove_compressor(&vp8_comp_);
    vp8_comp_ = NULL;
    aom_free(macroblockd_dst_);
    macroblockd_dst_ = NULL;
    libaom_test::ClearSystemState();
  }

 protected:
  void SetupCompressor() {
    rnd_.Reset(ACMRandom::DeterministicSeed());

    // The full configuration is necessary to generate the quantization tables.
    VP8_CONFIG vp8_config;
    memset(&vp8_config, 0, sizeof(vp8_config));

    vp8_comp_ = vp8_create_compressor(&vp8_config);

    // Set the tables based on a quantizer of 0.
    vp8_set_quantizer(vp8_comp_, 0);

    // Set up all the block/blockd pointers for the mb in vp8_comp_.
    vp8cx_frame_init_quantizer(vp8_comp_);

    // Copy macroblockd from the reference to get pre-set-up dequant values.
    macroblockd_dst_ = reinterpret_cast<MACROBLOCKD *>(
        aom_memalign(32, sizeof(*macroblockd_dst_)));
    memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_));
    // Fix block pointers - currently they point to the blocks in the reference
    // structure.
    vp8_setup_block_dptrs(macroblockd_dst_);
  }

  void UpdateQuantizer(int q) {
    vp8_set_quantizer(vp8_comp_, q);

    memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_));
    vp8_setup_block_dptrs(macroblockd_dst_);
  }

  void FillCoeffConstant(int16_t c) {
    for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) {
      vp8_comp_->mb.coeff[i] = c;
    }
  }

  void FillCoeffRandom() {
    for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) {
      vp8_comp_->mb.coeff[i] = rnd_.Rand8();
    }
  }

  void CheckOutput() {
    EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.qcoeff, macroblockd_dst_->qcoeff,
                        sizeof(*macroblockd_dst_->qcoeff) * kNumBlocks *
                            kNumBlockEntries))
        << "qcoeff mismatch";
    EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.dqcoeff, macroblockd_dst_->dqcoeff,
                        sizeof(*macroblockd_dst_->dqcoeff) * kNumBlocks *
                            kNumBlockEntries))
        << "dqcoeff mismatch";
    EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.eobs, macroblockd_dst_->eobs,
                        sizeof(*macroblockd_dst_->eobs) * kNumBlocks))
        << "eobs mismatch";
  }

  VP8_COMP *vp8_comp_;
  MACROBLOCKD *macroblockd_dst_;

 private:
  ACMRandom rnd_;
};

class QuantizeTest : public QuantizeTestBase,
                     public ::testing::TestWithParam<VP8QuantizeParam> {
 protected:
  virtual void SetUp() {
    SetupCompressor();
    asm_quant_ = GET_PARAM(0);
    c_quant_ = GET_PARAM(1);
  }

  void RunComparison() {
    for (int i = 0; i < kNumBlocks; ++i) {
      ASM_REGISTER_STATE_CHECK(
          c_quant_(&vp8_comp_->mb.block[i], &vp8_comp_->mb.e_mbd.block[i]));
      ASM_REGISTER_STATE_CHECK(
          asm_quant_(&vp8_comp_->mb.block[i], &macroblockd_dst_->block[i]));
    }

    CheckOutput();
  }

 private:
  VP8Quantize asm_quant_;
  VP8Quantize c_quant_;
};

TEST_P(QuantizeTest, TestZeroInput) {
  FillCoeffConstant(0);
  RunComparison();
}

TEST_P(QuantizeTest, TestLargeNegativeInput) {
  FillCoeffConstant(0);
  // Generate a qcoeff which contains 512/-512 (0x0100/0xFE00) to catch issues
  // like BUG=883 where the constant being compared was incorrectly initialized.
  vp8_comp_->mb.coeff[0] = -8191;
  RunComparison();
}

TEST_P(QuantizeTest, TestRandomInput) {
  FillCoeffRandom();
  RunComparison();
}

TEST_P(QuantizeTest, TestMultipleQ) {
  for (int q = 0; q < QINDEX_RANGE; ++q) {
    UpdateQuantizer(q);
    FillCoeffRandom();
    RunComparison();
  }
}

#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
    SSE2, QuantizeTest,
    ::testing::Values(
        make_tuple(&vp8_fast_quantize_b_sse2, &vp8_fast_quantize_b_c),
        make_tuple(&vp8_regular_quantize_b_sse2, &vp8_regular_quantize_b_c)));
#endif  // HAVE_SSE2

#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, QuantizeTest,
                        ::testing::Values(make_tuple(&vp8_fast_quantize_b_ssse3,
                                                     &vp8_fast_quantize_b_c)));
#endif  // HAVE_SSSE3

#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
    SSE4_1, QuantizeTest,
    ::testing::Values(make_tuple(&vp8_regular_quantize_b_sse4_1,
                                 &vp8_regular_quantize_b_c)));
#endif  // HAVE_SSE4_1

#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, QuantizeTest,
                        ::testing::Values(make_tuple(&vp8_fast_quantize_b_neon,
                                                     &vp8_fast_quantize_b_c)));
#endif  // HAVE_NEON

#if HAVE_MSA
INSTANTIATE_TEST_CASE_P(
    MSA, QuantizeTest,
    ::testing::Values(
        make_tuple(&vp8_fast_quantize_b_msa, &vp8_fast_quantize_b_c),
        make_tuple(&vp8_regular_quantize_b_msa, &vp8_regular_quantize_b_c)));
#endif  // HAVE_MSA
#endif  // CONFIG_AOM_QM
}  // namespace
