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 "gtest/gtest.h"
13
14 #include "config/aom_config.h"
15
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/y4m_video_source.h"
21
22 namespace {
23
24 const int kMaxPsnr = 100;
25
26 class LosslessTestLarge
27 : public ::libaom_test::CodecTestWith3Params<libaom_test::TestMode,
28 aom_rc_mode, int>,
29 public ::libaom_test::EncoderTest {
30 protected:
LosslessTestLarge()31 LosslessTestLarge()
32 : EncoderTest(GET_PARAM(0)), psnr_(kMaxPsnr), nframes_(0),
33 encoding_mode_(GET_PARAM(1)), rc_end_usage_(GET_PARAM(2)),
34 cpu_used_(GET_PARAM(3)) {}
35
36 ~LosslessTestLarge() override = default;
37
SetUp()38 void SetUp() override {
39 InitializeConfig(encoding_mode_);
40 cfg_.rc_end_usage = rc_end_usage_;
41 }
42
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)43 void PreEncodeFrameHook(::libaom_test::VideoSource *video,
44 ::libaom_test::Encoder *encoder) override {
45 if (video->frame() == 0) {
46 // Only call Control if quantizer > 0 to verify that using quantizer
47 // alone will activate lossless
48 if (cfg_.rc_max_quantizer > 0 || cfg_.rc_min_quantizer > 0) {
49 encoder->Control(AV1E_SET_LOSSLESS, 1);
50 }
51 encoder->Control(AOME_SET_CPUUSED, cpu_used_);
52 }
53 }
54
BeginPassHook(unsigned int)55 void BeginPassHook(unsigned int /*pass*/) override {
56 psnr_ = kMaxPsnr;
57 nframes_ = 0;
58 }
59
PSNRPktHook(const aom_codec_cx_pkt_t * pkt)60 void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) override {
61 if (pkt->data.psnr.psnr[0] < psnr_) psnr_ = pkt->data.psnr.psnr[0];
62 }
63
GetMinPsnr() const64 double GetMinPsnr() const { return psnr_; }
65
HandleDecodeResult(const aom_codec_err_t res_dec,libaom_test::Decoder * decoder)66 bool HandleDecodeResult(const aom_codec_err_t res_dec,
67 libaom_test::Decoder *decoder) override {
68 EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
69 if (AOM_CODEC_OK == res_dec) {
70 aom_codec_ctx_t *ctx_dec = decoder->GetDecoder();
71 AOM_CODEC_CONTROL_TYPECHECKED(ctx_dec, AOMD_GET_LAST_QUANTIZER,
72 &base_qindex_);
73 EXPECT_EQ(base_qindex_, 0)
74 << "Error: Base_qindex is non zero for lossless coding";
75 }
76 return AOM_CODEC_OK == res_dec;
77 }
78
79 void TestLosslessEncoding();
80 void TestLosslessEncodingVGALag0();
81 void TestLosslessEncoding444();
82 void TestLosslessEncodingCtrl();
83
84 private:
85 double psnr_;
86 unsigned int nframes_;
87 libaom_test::TestMode encoding_mode_;
88 aom_rc_mode rc_end_usage_;
89 int cpu_used_;
90 int base_qindex_;
91 };
92
TestLosslessEncoding()93 void LosslessTestLarge::TestLosslessEncoding() {
94 const aom_rational timebase = { 33333333, 1000000000 };
95 cfg_.g_timebase = timebase;
96 cfg_.rc_target_bitrate = 2000;
97 cfg_.g_lag_in_frames = 25;
98 cfg_.rc_min_quantizer = 0;
99 cfg_.rc_max_quantizer = 0;
100
101 init_flags_ = AOM_CODEC_USE_PSNR;
102
103 // intentionally changed the dimension for better testing coverage
104 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
105 timebase.den, timebase.num, 0, 5);
106 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
107 const double psnr_lossless = GetMinPsnr();
108 EXPECT_GE(psnr_lossless, kMaxPsnr);
109 }
110
TestLosslessEncodingVGALag0()111 void LosslessTestLarge::TestLosslessEncodingVGALag0() {
112 const aom_rational timebase = { 33333333, 1000000000 };
113 cfg_.g_timebase = timebase;
114 cfg_.rc_target_bitrate = 2000;
115 cfg_.g_lag_in_frames = 0;
116 cfg_.rc_min_quantizer = 0;
117 cfg_.rc_max_quantizer = 0;
118
119 init_flags_ = AOM_CODEC_USE_PSNR;
120
121 libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480,
122 timebase.den, timebase.num, 0, 30);
123 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
124 const double psnr_lossless = GetMinPsnr();
125 EXPECT_GE(psnr_lossless, kMaxPsnr);
126 }
127
TestLosslessEncoding444()128 void LosslessTestLarge::TestLosslessEncoding444() {
129 libaom_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 5);
130
131 cfg_.g_profile = 1;
132 cfg_.g_timebase = video.timebase();
133 cfg_.rc_target_bitrate = 2000;
134 cfg_.g_lag_in_frames = 25;
135 cfg_.rc_min_quantizer = 0;
136 cfg_.rc_max_quantizer = 0;
137
138 init_flags_ = AOM_CODEC_USE_PSNR;
139
140 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
141 const double psnr_lossless = GetMinPsnr();
142 EXPECT_GE(psnr_lossless, kMaxPsnr);
143 }
144
TestLosslessEncodingCtrl()145 void LosslessTestLarge::TestLosslessEncodingCtrl() {
146 const aom_rational timebase = { 33333333, 1000000000 };
147 cfg_.g_timebase = timebase;
148 cfg_.rc_target_bitrate = 2000;
149 cfg_.g_lag_in_frames = 25;
150 // Intentionally set Q > 0, to make sure control can be used to activate
151 // lossless
152 cfg_.rc_min_quantizer = 10;
153 cfg_.rc_max_quantizer = 20;
154
155 init_flags_ = AOM_CODEC_USE_PSNR;
156
157 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
158 timebase.den, timebase.num, 0, 5);
159 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
160 const double psnr_lossless = GetMinPsnr();
161 EXPECT_GE(psnr_lossless, kMaxPsnr);
162 }
163
TEST_P(LosslessTestLarge,TestLosslessEncoding)164 TEST_P(LosslessTestLarge, TestLosslessEncoding) { TestLosslessEncoding(); }
165
TEST_P(LosslessTestLarge,TestLosslessEncodingVGALag0)166 TEST_P(LosslessTestLarge, TestLosslessEncodingVGALag0) {
167 TestLosslessEncodingVGALag0();
168 }
169
TEST_P(LosslessTestLarge,TestLosslessEncoding444)170 TEST_P(LosslessTestLarge, TestLosslessEncoding444) {
171 TestLosslessEncoding444();
172 }
173
TEST_P(LosslessTestLarge,TestLosslessEncodingCtrl)174 TEST_P(LosslessTestLarge, TestLosslessEncodingCtrl) {
175 TestLosslessEncodingCtrl();
176 }
177
178 class LosslessAllIntraTestLarge : public LosslessTestLarge {};
179
TEST_P(LosslessAllIntraTestLarge,TestLosslessEncodingCtrl)180 TEST_P(LosslessAllIntraTestLarge, TestLosslessEncodingCtrl) {
181 const aom_rational timebase = { 33333333, 1000000000 };
182 cfg_.g_timebase = timebase;
183 // Intentionally set Q > 0, to make sure control can be used to activate
184 // lossless
185 cfg_.rc_min_quantizer = 10;
186 cfg_.rc_max_quantizer = 20;
187
188 init_flags_ = AOM_CODEC_USE_PSNR;
189
190 libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
191 timebase.den, timebase.num, 0, 5);
192 ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
193 const double psnr_lossless = GetMinPsnr();
194 EXPECT_GE(psnr_lossless, kMaxPsnr);
195 }
196
197 using LosslessRealtimeTestLarge = LosslessTestLarge;
198
TEST_P(LosslessRealtimeTestLarge,TestLosslessEncoding)199 TEST_P(LosslessRealtimeTestLarge, TestLosslessEncoding) {
200 TestLosslessEncoding();
201 }
202
TEST_P(LosslessRealtimeTestLarge,TestLosslessEncodingVGALag0)203 TEST_P(LosslessRealtimeTestLarge, TestLosslessEncodingVGALag0) {
204 TestLosslessEncodingVGALag0();
205 }
206
TEST_P(LosslessRealtimeTestLarge,TestLosslessEncoding444)207 TEST_P(LosslessRealtimeTestLarge, TestLosslessEncoding444) {
208 TestLosslessEncoding444();
209 }
210
TEST_P(LosslessRealtimeTestLarge,TestLosslessEncodingCtrl)211 TEST_P(LosslessRealtimeTestLarge, TestLosslessEncodingCtrl) {
212 TestLosslessEncodingCtrl();
213 }
214
215 AV1_INSTANTIATE_TEST_SUITE(LosslessTestLarge,
216 ::testing::Values(::libaom_test::kOnePassGood,
217 ::libaom_test::kTwoPassGood),
218 ::testing::Values(AOM_Q, AOM_VBR, AOM_CBR, AOM_CQ),
219 ::testing::Values(0)); // cpu_used
220
221 AV1_INSTANTIATE_TEST_SUITE(LosslessAllIntraTestLarge,
222 ::testing::Values(::libaom_test::kAllIntra),
223 ::testing::Values(AOM_Q),
224 ::testing::Values(6, 9)); // cpu_used
225
226 AV1_INSTANTIATE_TEST_SUITE(LosslessRealtimeTestLarge,
227 ::testing::Values(::libaom_test::kRealTime),
228 ::testing::Values(AOM_Q, AOM_VBR, AOM_CBR, AOM_CQ),
229 ::testing::Range(6, 11)); // cpu_used
230 } // namespace
231