decode_multithreaded_test.cc (6643B)
1 /* 2 * Copyright (c) 2018, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <cstdio> 13 #include <cstdlib> 14 #include <string> 15 16 #include "aom_mem/aom_mem.h" 17 #include "gtest/gtest.h" 18 #include "test/codec_factory.h" 19 #include "test/encode_test_driver.h" 20 #include "test/i420_video_source.h" 21 #include "test/md5_helper.h" 22 #include "test/util.h" 23 24 namespace { 25 26 static const int kNumMultiThreadDecoders = 3; 27 28 class AV1DecodeMultiThreadedTest 29 : public ::libaom_test::CodecTestWith5Params<int, int, int, int, int>, 30 public ::libaom_test::EncoderTest { 31 protected: 32 AV1DecodeMultiThreadedTest() 33 : EncoderTest(GET_PARAM(0)), md5_single_thread_(), md5_multi_thread_(), 34 n_tile_cols_(GET_PARAM(1)), n_tile_rows_(GET_PARAM(2)), 35 n_tile_groups_(GET_PARAM(3)), set_cpu_used_(GET_PARAM(4)), 36 row_mt_(GET_PARAM(5)) { 37 init_flags_ = AOM_CODEC_USE_PSNR; 38 aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t(); 39 cfg.w = 704; 40 cfg.h = 576; 41 cfg.threads = 1; 42 cfg.allow_lowbitdepth = 1; 43 single_thread_dec_ = codec_->CreateDecoder(cfg, 0); 44 45 // Test cfg.threads == powers of 2. 46 for (int i = 0; i < kNumMultiThreadDecoders; ++i) { 47 cfg.threads <<= 1; 48 multi_thread_dec_[i] = codec_->CreateDecoder(cfg, 0); 49 multi_thread_dec_[i]->Control(AV1D_SET_ROW_MT, row_mt_); 50 } 51 52 if (single_thread_dec_->IsAV1()) { 53 single_thread_dec_->Control(AV1D_EXT_TILE_DEBUG, 1); 54 single_thread_dec_->Control(AV1_SET_DECODE_TILE_ROW, -1); 55 single_thread_dec_->Control(AV1_SET_DECODE_TILE_COL, -1); 56 } 57 for (int i = 0; i < kNumMultiThreadDecoders; ++i) { 58 if (multi_thread_dec_[i]->IsAV1()) { 59 multi_thread_dec_[i]->Control(AV1D_EXT_TILE_DEBUG, 1); 60 multi_thread_dec_[i]->Control(AV1_SET_DECODE_TILE_ROW, -1); 61 multi_thread_dec_[i]->Control(AV1_SET_DECODE_TILE_COL, -1); 62 } 63 } 64 } 65 66 ~AV1DecodeMultiThreadedTest() override { 67 delete single_thread_dec_; 68 for (int i = 0; i < kNumMultiThreadDecoders; ++i) 69 delete multi_thread_dec_[i]; 70 } 71 72 void SetUp() override { InitializeConfig(libaom_test::kTwoPassGood); } 73 74 void PreEncodeFrameHook(libaom_test::VideoSource *video, 75 libaom_test::Encoder *encoder) override { 76 if (video->frame() == 0) { 77 encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_); 78 encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_); 79 encoder->Control(AV1E_SET_NUM_TG, n_tile_groups_); 80 encoder->Control(AOME_SET_CPUUSED, set_cpu_used_); 81 } 82 } 83 84 void UpdateMD5(::libaom_test::Decoder *dec, const aom_codec_cx_pkt_t *pkt, 85 ::libaom_test::MD5 *md5) { 86 const aom_codec_err_t res = dec->DecodeFrame( 87 reinterpret_cast<uint8_t *>(pkt->data.frame.buf), pkt->data.frame.sz); 88 if (res != AOM_CODEC_OK) { 89 abort_ = true; 90 ASSERT_EQ(AOM_CODEC_OK, res); 91 } 92 const aom_image_t *img = dec->GetDxData().Next(); 93 md5->Add(img); 94 } 95 96 void FramePktHook(const aom_codec_cx_pkt_t *pkt) override { 97 UpdateMD5(single_thread_dec_, pkt, &md5_single_thread_); 98 99 for (int i = 0; i < kNumMultiThreadDecoders; ++i) 100 UpdateMD5(multi_thread_dec_[i], pkt, &md5_multi_thread_[i]); 101 } 102 103 void DoTest() { 104 const aom_rational timebase = { 33333333, 1000000000 }; 105 cfg_.g_timebase = timebase; 106 cfg_.rc_target_bitrate = 500; 107 cfg_.g_lag_in_frames = 12; 108 cfg_.rc_end_usage = AOM_VBR; 109 110 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 704, 576, 111 timebase.den, timebase.num, 0, 2); 112 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 113 114 const char *md5_single_thread_str = md5_single_thread_.Get(); 115 116 for (int i = 0; i < kNumMultiThreadDecoders; ++i) { 117 const char *md5_multi_thread_str = md5_multi_thread_[i].Get(); 118 ASSERT_STREQ(md5_single_thread_str, md5_multi_thread_str); 119 } 120 } 121 122 ::libaom_test::MD5 md5_single_thread_; 123 ::libaom_test::MD5 md5_multi_thread_[kNumMultiThreadDecoders]; 124 ::libaom_test::Decoder *single_thread_dec_; 125 ::libaom_test::Decoder *multi_thread_dec_[kNumMultiThreadDecoders]; 126 127 private: 128 int n_tile_cols_; 129 int n_tile_rows_; 130 int n_tile_groups_; 131 int set_cpu_used_; 132 int row_mt_; 133 }; 134 135 // run an encode and do the decode both in single thread 136 // and multi thread. Ensure that the MD5 of the output in both cases 137 // is identical. If so, the test passes. 138 TEST_P(AV1DecodeMultiThreadedTest, MD5Match) { 139 cfg_.large_scale_tile = 0; 140 single_thread_dec_->Control(AV1_SET_TILE_MODE, 0); 141 for (int i = 0; i < kNumMultiThreadDecoders; ++i) 142 multi_thread_dec_[i]->Control(AV1_SET_TILE_MODE, 0); 143 DoTest(); 144 } 145 146 class AV1DecodeMultiThreadedTestLarge : public AV1DecodeMultiThreadedTest {}; 147 148 TEST_P(AV1DecodeMultiThreadedTestLarge, MD5Match) { 149 cfg_.large_scale_tile = 0; 150 single_thread_dec_->Control(AV1_SET_TILE_MODE, 0); 151 for (int i = 0; i < kNumMultiThreadDecoders; ++i) 152 multi_thread_dec_[i]->Control(AV1_SET_TILE_MODE, 0); 153 DoTest(); 154 } 155 156 // TODO(ranjit): More tests have to be added using pre-generated MD5. 157 AV1_INSTANTIATE_TEST_SUITE(AV1DecodeMultiThreadedTest, ::testing::Values(1, 2), 158 ::testing::Values(1, 2), ::testing::Values(1), 159 ::testing::Values(3), ::testing::Values(0, 1)); 160 AV1_INSTANTIATE_TEST_SUITE(AV1DecodeMultiThreadedTestLarge, 161 ::testing::Values(0, 1, 2, 6), 162 ::testing::Values(0, 1, 2, 6), 163 ::testing::Values(1, 4), ::testing::Values(0), 164 ::testing::Values(0, 1)); 165 166 class AV1DecodeMultiThreadedLSTestLarge 167 : public AV1DecodeMultiThreadedTestLarge {}; 168 169 TEST_P(AV1DecodeMultiThreadedLSTestLarge, MD5Match) { 170 cfg_.large_scale_tile = 1; 171 single_thread_dec_->Control(AV1_SET_TILE_MODE, 1); 172 for (int i = 0; i < kNumMultiThreadDecoders; ++i) 173 multi_thread_dec_[i]->Control(AV1_SET_TILE_MODE, 1); 174 DoTest(); 175 } 176 177 AV1_INSTANTIATE_TEST_SUITE(AV1DecodeMultiThreadedLSTestLarge, 178 ::testing::Values(6), ::testing::Values(6), 179 ::testing::Values(1), ::testing::Values(0, 3), 180 ::testing::Values(0, 1)); 181 182 } // namespace