2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
12 #include "config/aom_config.h"
14 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
15 #include "test/codec_factory.h"
16 #include "test/encode_test_driver.h"
17 #include "test/i420_video_source.h"
18 #include "test/util.h"
19 #include "test/y4m_video_source.h"
20 #include "aom/aom_codec.h"
24 class DatarateTestLarge
25 : public ::libaom_test::CodecTestWith2Params
<libaom_test::TestMode
, int>,
26 public ::libaom_test::EncoderTest
{
28 DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
31 virtual ~DatarateTestLarge() {}
33 virtual void SetUp() {
35 SetMode(GET_PARAM(1));
36 set_cpu_used_
= GET_PARAM(2);
40 virtual void ResetModel() {
42 bits_in_buffer_model_
= cfg_
.rc_target_bitrate
* cfg_
.rc_buf_initial_sz
;
44 tot_frame_number_
= 0;
47 // Denoiser is off by default.
50 denoiser_offon_test_
= 0;
51 denoiser_offon_period_
= -1;
54 virtual void PreEncodeFrameHook(::libaom_test::VideoSource
*video
,
55 ::libaom_test::Encoder
*encoder
) {
56 if (video
->frame() == 0) encoder
->Control(AOME_SET_CPUUSED
, set_cpu_used_
);
58 if (denoiser_offon_test_
) {
59 ASSERT_GT(denoiser_offon_period_
, 0)
60 << "denoiser_offon_period_ is not positive.";
61 if ((video
->frame() + 1) % denoiser_offon_period_
== 0) {
62 // Flip denoiser_on_ periodically
67 encoder
->Control(AV1E_SET_NOISE_SENSITIVITY
, denoiser_on_
);
69 const aom_rational_t tb
= video
->timebase();
70 timebase_
= static_cast<double>(tb
.num
) / tb
.den
;
74 virtual void FramePktHook(const aom_codec_cx_pkt_t
*pkt
) {
75 // Time since last timestamp = duration.
76 aom_codec_pts_t duration
= pkt
->data
.frame
.pts
- last_pts_
;
79 // If first drop not set and we have a drop set it to this time.
80 if (!first_drop_
) first_drop_
= last_pts_
+ 1;
81 // Update the number of frame drops.
82 num_drops_
+= static_cast<int>(duration
- 1);
83 // Update counter for total number of frames (#frames input to encoder).
84 // Needed for setting the proper layer_id below.
85 tot_frame_number_
+= static_cast<int>(duration
- 1);
88 // Add to the buffer the bits we'd expect from a constant bitrate server.
89 bits_in_buffer_model_
+= static_cast<int64_t>(
90 duration
* timebase_
* cfg_
.rc_target_bitrate
* 1000);
92 // Buffer should not go negative.
93 ASSERT_GE(bits_in_buffer_model_
, 0)
94 << "Buffer Underrun at frame " << pkt
->data
.frame
.pts
;
96 const size_t frame_size_in_bits
= pkt
->data
.frame
.sz
* 8;
98 // Update the total encoded bits.
99 bits_total_
+= frame_size_in_bits
;
101 // Update the most recent pts.
102 last_pts_
= pkt
->data
.frame
.pts
;
107 virtual void EndPassHook(void) {
108 duration_
= (last_pts_
+ 1) * timebase_
;
109 // Effective file datarate:
110 effective_datarate_
= (bits_total_
/ 1000.0) / duration_
;
113 aom_codec_pts_t last_pts_
;
115 int frame_number_
; // Counter for number of non-dropped/encoded frames.
116 int tot_frame_number_
; // Counter for total number of input frames.
119 double effective_datarate_
;
121 int64_t bits_in_buffer_model_
;
122 aom_codec_pts_t first_drop_
;
125 int denoiser_offon_test_
;
126 int denoiser_offon_period_
;
129 // Check basic rate targeting for VBR mode.
130 TEST_P(DatarateTestLarge
, BasicRateTargetingVBR
) {
131 cfg_
.rc_min_quantizer
= 0;
132 cfg_
.rc_max_quantizer
= 63;
133 cfg_
.g_error_resilient
= 0;
134 cfg_
.rc_end_usage
= AOM_VBR
;
135 cfg_
.g_lag_in_frames
= 0;
137 ::libaom_test::I420VideoSource
video("hantro_collage_w352h288.yuv", 352, 288,
139 for (int i
= 400; i
<= 800; i
+= 400) {
140 cfg_
.rc_target_bitrate
= i
;
142 ASSERT_NO_FATAL_FAILURE(RunLoop(&video
));
143 ASSERT_GE(effective_datarate_
, cfg_
.rc_target_bitrate
* 0.75)
144 << " The datarate for the file is lower than target by too much!";
145 ASSERT_LE(effective_datarate_
, cfg_
.rc_target_bitrate
* 1.25)
146 << " The datarate for the file is greater than target by too much!";
150 // Check basic rate targeting for CBR,
151 TEST_P(DatarateTestLarge
, BasicRateTargeting
) {
152 cfg_
.rc_buf_initial_sz
= 500;
153 cfg_
.rc_buf_optimal_sz
= 500;
154 cfg_
.rc_buf_sz
= 1000;
155 cfg_
.rc_dropframe_thresh
= 1;
156 cfg_
.rc_min_quantizer
= 0;
157 cfg_
.rc_max_quantizer
= 63;
158 cfg_
.rc_end_usage
= AOM_CBR
;
159 cfg_
.g_lag_in_frames
= 0;
161 ::libaom_test::I420VideoSource
video("hantro_collage_w352h288.yuv", 352, 288,
163 for (int i
= 150; i
< 800; i
+= 400) {
164 cfg_
.rc_target_bitrate
= i
;
166 ASSERT_NO_FATAL_FAILURE(RunLoop(&video
));
167 ASSERT_GE(effective_datarate_
, cfg_
.rc_target_bitrate
* 0.85)
168 << " The datarate for the file is lower than target by too much!";
169 ASSERT_LE(effective_datarate_
, cfg_
.rc_target_bitrate
* 1.15)
170 << " The datarate for the file is greater than target by too much!";
174 // Check basic rate targeting for CBR.
175 TEST_P(DatarateTestLarge
, BasicRateTargeting444
) {
176 ::libaom_test::Y4mVideoSource
video("rush_hour_444.y4m", 0, 140);
179 cfg_
.g_timebase
= video
.timebase();
181 cfg_
.rc_buf_initial_sz
= 500;
182 cfg_
.rc_buf_optimal_sz
= 500;
183 cfg_
.rc_buf_sz
= 1000;
184 cfg_
.rc_dropframe_thresh
= 1;
185 cfg_
.rc_min_quantizer
= 0;
186 cfg_
.rc_max_quantizer
= 63;
187 cfg_
.rc_end_usage
= AOM_CBR
;
189 for (int i
= 250; i
< 900; i
+= 400) {
190 cfg_
.rc_target_bitrate
= i
;
192 ASSERT_NO_FATAL_FAILURE(RunLoop(&video
));
193 ASSERT_GE(static_cast<double>(cfg_
.rc_target_bitrate
),
194 effective_datarate_
* 0.85)
195 << " The datarate for the file exceeds the target by too much!";
196 ASSERT_LE(static_cast<double>(cfg_
.rc_target_bitrate
),
197 effective_datarate_
* 1.15)
198 << " The datarate for the file missed the target!"
199 << cfg_
.rc_target_bitrate
<< " " << effective_datarate_
;
203 // Check that (1) the first dropped frame gets earlier and earlier
204 // as the drop frame threshold is increased, and (2) that the total number of
205 // frame drops does not decrease as we increase frame drop threshold.
206 // Use a lower qp-max to force some frame drops.
207 TEST_P(DatarateTestLarge
, ChangingDropFrameThresh
) {
208 cfg_
.rc_buf_initial_sz
= 500;
209 cfg_
.rc_buf_optimal_sz
= 500;
210 cfg_
.rc_buf_sz
= 1000;
211 cfg_
.rc_undershoot_pct
= 20;
212 cfg_
.rc_undershoot_pct
= 20;
213 cfg_
.rc_dropframe_thresh
= 10;
214 cfg_
.rc_min_quantizer
= 0;
215 cfg_
.rc_max_quantizer
= 50;
216 cfg_
.rc_end_usage
= AOM_CBR
;
217 cfg_
.rc_target_bitrate
= 200;
218 cfg_
.g_lag_in_frames
= 0;
219 cfg_
.g_error_resilient
= 1;
220 // TODO(marpan): Investigate datarate target failures with a smaller keyframe
222 cfg_
.kf_max_dist
= 9999;
224 ::libaom_test::I420VideoSource
video("hantro_collage_w352h288.yuv", 352, 288,
227 const int kDropFrameThreshTestStep
= 30;
228 aom_codec_pts_t last_drop
= 140;
229 int last_num_drops
= 0;
230 for (int i
= 40; i
< 100; i
+= kDropFrameThreshTestStep
) {
231 cfg_
.rc_dropframe_thresh
= i
;
233 ASSERT_NO_FATAL_FAILURE(RunLoop(&video
));
234 ASSERT_GE(effective_datarate_
, cfg_
.rc_target_bitrate
* 0.85)
235 << " The datarate for the file is lower than target by too much!";
236 ASSERT_LE(effective_datarate_
, cfg_
.rc_target_bitrate
* 1.15)
237 << " The datarate for the file is greater than target by too much!";
238 ASSERT_LE(first_drop_
, last_drop
)
239 << " The first dropped frame for drop_thresh " << i
240 << " > first dropped frame for drop_thresh "
241 << i
- kDropFrameThreshTestStep
;
242 ASSERT_GE(num_drops_
, last_num_drops
* 0.85)
243 << " The number of dropped frames for drop_thresh " << i
244 << " < number of dropped frames for drop_thresh "
245 << i
- kDropFrameThreshTestStep
;
246 last_drop
= first_drop_
;
247 last_num_drops
= num_drops_
;
251 AV1_INSTANTIATE_TEST_CASE(DatarateTestLarge
,
252 ::testing::Values(::libaom_test::kOnePassGood
,
253 ::libaom_test::kRealTime
),
254 ::testing::Values(2, 5));