1 /*
2 * Copyright (c) 2016, 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 #include "gtest/gtest.h"
16 #include "test/codec_factory.h"
17 #include "test/encode_test_driver.h"
18 #include "test/i420_video_source.h"
19 #include "test/util.h"
20 #include "test/md5_helper.h"
21 #include "aom_mem/aom_mem.h"
22
23 namespace {
24 class TileIndependenceTest
25 : public ::libaom_test::CodecTestWith3Params<int, int, int>,
26 public ::libaom_test::EncoderTest {
27 protected:
TileIndependenceTest()28 TileIndependenceTest()
29 : EncoderTest(GET_PARAM(0)), md5_fw_order_(), md5_inv_order_(),
30 n_tile_cols_(GET_PARAM(1)), n_tile_rows_(GET_PARAM(2)),
31 n_tile_groups_(GET_PARAM(3)) {
32 init_flags_ = AOM_CODEC_USE_PSNR;
33 aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t();
34 cfg.w = 704;
35 cfg.h = 576;
36 cfg.threads = 1;
37 cfg.allow_lowbitdepth = 1;
38 fw_dec_ = codec_->CreateDecoder(cfg, 0);
39 inv_dec_ = codec_->CreateDecoder(cfg, 0);
40 inv_dec_->Control(AV1_INVERT_TILE_DECODE_ORDER, 1);
41
42 if (fw_dec_->IsAV1() && inv_dec_->IsAV1()) {
43 fw_dec_->Control(AV1_SET_DECODE_TILE_ROW, -1);
44 fw_dec_->Control(AV1_SET_DECODE_TILE_COL, -1);
45 inv_dec_->Control(AV1_SET_DECODE_TILE_ROW, -1);
46 inv_dec_->Control(AV1_SET_DECODE_TILE_COL, -1);
47 }
48 }
49
~TileIndependenceTest()50 ~TileIndependenceTest() override {
51 delete fw_dec_;
52 delete inv_dec_;
53 }
54
SetUp()55 void SetUp() override { InitializeConfig(libaom_test::kTwoPassGood); }
56
PreEncodeFrameHook(libaom_test::VideoSource * video,libaom_test::Encoder * encoder)57 void PreEncodeFrameHook(libaom_test::VideoSource *video,
58 libaom_test::Encoder *encoder) override {
59 if (video->frame() == 0) {
60 encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_);
61 encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_);
62 SetCpuUsed(encoder);
63 } else if (video->frame() == 3) {
64 encoder->Control(AV1E_SET_NUM_TG, n_tile_groups_);
65 }
66 }
67
SetCpuUsed(libaom_test::Encoder * encoder)68 virtual void SetCpuUsed(libaom_test::Encoder *encoder) {
69 static const int kCpuUsed = 3;
70 encoder->Control(AOME_SET_CPUUSED, kCpuUsed);
71 }
72
UpdateMD5(::libaom_test::Decoder * dec,const aom_codec_cx_pkt_t * pkt,::libaom_test::MD5 * md5)73 void UpdateMD5(::libaom_test::Decoder *dec, const aom_codec_cx_pkt_t *pkt,
74 ::libaom_test::MD5 *md5) {
75 const aom_codec_err_t res = dec->DecodeFrame(
76 reinterpret_cast<uint8_t *>(pkt->data.frame.buf), pkt->data.frame.sz);
77 if (res != AOM_CODEC_OK) {
78 abort_ = true;
79 ASSERT_EQ(AOM_CODEC_OK, res);
80 }
81 const aom_image_t *img = dec->GetDxData().Next();
82 md5->Add(img);
83 }
84
FramePktHook(const aom_codec_cx_pkt_t * pkt)85 void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {
86 UpdateMD5(fw_dec_, pkt, &md5_fw_order_);
87 UpdateMD5(inv_dec_, pkt, &md5_inv_order_);
88 }
89
DoTest()90 void DoTest() {
91 const aom_rational timebase = { 33333333, 1000000000 };
92 cfg_.g_timebase = timebase;
93 cfg_.rc_target_bitrate = 500;
94 cfg_.g_lag_in_frames = 12;
95 cfg_.rc_end_usage = AOM_VBR;
96
97 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 704, 576,
98 timebase.den, timebase.num, 0, 5);
99 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
100
101 const char *md5_fw_str = md5_fw_order_.Get();
102 const char *md5_inv_str = md5_inv_order_.Get();
103 ASSERT_STREQ(md5_fw_str, md5_inv_str);
104 }
105
106 ::libaom_test::MD5 md5_fw_order_, md5_inv_order_;
107 ::libaom_test::Decoder *fw_dec_, *inv_dec_;
108
109 private:
110 int n_tile_cols_;
111 int n_tile_rows_;
112 int n_tile_groups_;
113 };
114
115 // run an encode with 2 or 4 tiles, and do the decode both in normal and
116 // inverted tile ordering. Ensure that the MD5 of the output in both cases
117 // is identical. If so, tiles are considered independent and the test passes.
TEST_P(TileIndependenceTest,MD5Match)118 TEST_P(TileIndependenceTest, MD5Match) {
119 cfg_.large_scale_tile = 0;
120 fw_dec_->Control(AV1_SET_TILE_MODE, 0);
121 inv_dec_->Control(AV1_SET_TILE_MODE, 0);
122 DoTest();
123 }
124
125 class TileIndependenceTestLarge : public TileIndependenceTest {
SetCpuUsed(libaom_test::Encoder * encoder)126 void SetCpuUsed(libaom_test::Encoder *encoder) override {
127 static const int kCpuUsed = 0;
128 encoder->Control(AOME_SET_CPUUSED, kCpuUsed);
129 }
130 };
131
TEST_P(TileIndependenceTestLarge,MD5Match)132 TEST_P(TileIndependenceTestLarge, MD5Match) {
133 cfg_.large_scale_tile = 0;
134 fw_dec_->Control(AV1_SET_TILE_MODE, 0);
135 inv_dec_->Control(AV1_SET_TILE_MODE, 0);
136 DoTest();
137 }
138
139 AV1_INSTANTIATE_TEST_SUITE(TileIndependenceTest, ::testing::Values(0, 1),
140 ::testing::Values(0, 1), ::testing::Values(1, 2, 4));
141 AV1_INSTANTIATE_TEST_SUITE(TileIndependenceTestLarge, ::testing::Values(0, 1),
142 ::testing::Values(0, 1), ::testing::Values(1, 2, 4));
143
144 class TileIndependenceLSTest : public TileIndependenceTest {};
145
TEST_P(TileIndependenceLSTest,MD5Match)146 TEST_P(TileIndependenceLSTest, MD5Match) {
147 cfg_.large_scale_tile = 1;
148 fw_dec_->Control(AV1_SET_TILE_MODE, 1);
149 fw_dec_->Control(AV1D_EXT_TILE_DEBUG, 1);
150 inv_dec_->Control(AV1_SET_TILE_MODE, 1);
151 inv_dec_->Control(AV1D_EXT_TILE_DEBUG, 1);
152 DoTest();
153 }
154
155 class TileIndependenceLSTestLarge : public TileIndependenceTestLarge {};
156
TEST_P(TileIndependenceLSTestLarge,MD5Match)157 TEST_P(TileIndependenceLSTestLarge, MD5Match) {
158 cfg_.large_scale_tile = 1;
159 fw_dec_->Control(AV1_SET_TILE_MODE, 1);
160 fw_dec_->Control(AV1D_EXT_TILE_DEBUG, 1);
161 inv_dec_->Control(AV1_SET_TILE_MODE, 1);
162 inv_dec_->Control(AV1D_EXT_TILE_DEBUG, 1);
163 DoTest();
164 }
165
166 AV1_INSTANTIATE_TEST_SUITE(TileIndependenceLSTest, ::testing::Values(6),
167 ::testing::Values(6), ::testing::Values(1));
168 AV1_INSTANTIATE_TEST_SUITE(TileIndependenceLSTestLarge, ::testing::Values(6),
169 ::testing::Values(6), ::testing::Values(1));
170 } // namespace
171