| /* | 
 |  * 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/googletest/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], ¯oblockd_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 |