xref: /aosp_15_r20/external/libaom/test/datarate_test.h (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2019, 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 "config/aom_config.h"
13 
14 #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"
21 
22 namespace datarate_test {
23 namespace {
24 class DatarateTest : public ::libaom_test::EncoderTest {
25  public:
DatarateTest(const::libaom_test::CodecFactory * codec)26   explicit DatarateTest(const ::libaom_test::CodecFactory *codec)
27       : EncoderTest(codec), set_cpu_used_(0), aq_mode_(0),
28         speed_change_test_(false) {}
29 
30  protected:
31   ~DatarateTest() override = default;
32 
ResetModel()33   virtual void ResetModel() {
34     last_pts_ = 0;
35     bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
36     frame_number_ = 0;
37     tot_frame_number_ = 0;
38     first_drop_ = 0;
39     num_drops_ = 0;
40     // Denoiser is off by default.
41     denoiser_on_ = 0;
42     bits_total_ = 0;
43     denoiser_offon_test_ = 0;
44     denoiser_offon_period_ = -1;
45     tile_columns_ = 0;
46     tile_rows_ = 0;
47     auto_tiles_ = false;
48     screen_mode_ = false;
49     max_perc_spike_ = 1.0;
50     max_perc_spike_high_ = 1.0;
51     num_spikes_ = 0;
52     num_spikes_high_ = 0;
53     frame_update_bitrate_ = 0;
54     for (int i = 0; i < 3; i++) {
55       target_bitrate_update_[i] = 0;
56       frame_number_dynamic_[i] = 0;
57       bits_total_dynamic_[i] = 0;
58       effective_datarate_dynamic_[i] = 0.0;
59     }
60   }
61 
PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)62   void PreEncodeFrameHook(::libaom_test::VideoSource *video,
63                           ::libaom_test::Encoder *encoder) override {
64     if (video->frame() == 0) {
65       encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
66       encoder->Control(AV1E_SET_AQ_MODE, aq_mode_);
67       if (auto_tiles_) {
68         encoder->Control(AV1E_SET_AUTO_TILES, 1);
69       } else {
70         encoder->Control(AV1E_SET_TILE_COLUMNS, tile_columns_);
71         encoder->Control(AV1E_SET_TILE_ROWS, tile_rows_);
72       }
73       encoder->Control(AV1E_SET_ROW_MT, 1);
74       if (cfg_.g_usage == AOM_USAGE_REALTIME) {
75         encoder->Control(AV1E_SET_ENABLE_GLOBAL_MOTION, 0);
76         encoder->Control(AV1E_SET_ENABLE_WARPED_MOTION, 0);
77         encoder->Control(AV1E_SET_ENABLE_RESTORATION, 0);
78         encoder->Control(AV1E_SET_ENABLE_OBMC, 0);
79         encoder->Control(AV1E_SET_DELTAQ_MODE, 0);
80         encoder->Control(AV1E_SET_ENABLE_TPL_MODEL, 0);
81         encoder->Control(AV1E_SET_ENABLE_CDEF, 1);
82         encoder->Control(AV1E_SET_COEFF_COST_UPD_FREQ, 2);
83         encoder->Control(AV1E_SET_MODE_COST_UPD_FREQ, 2);
84         encoder->Control(AV1E_SET_MV_COST_UPD_FREQ, 2);
85         encoder->Control(AV1E_SET_DV_COST_UPD_FREQ, 2);
86         encoder->Control(AV1E_SET_POSTENCODE_DROP_RTC, 1);
87       }
88       if (screen_mode_) {
89         encoder->Control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_SCREEN);
90         encoder->Control(AV1E_SET_ENABLE_PALETTE, 1);
91         encoder->Control(AV1E_SET_ENABLE_INTRABC, 0);
92       }
93     }
94 
95     if (speed_change_test_) {
96       if (video->frame() == 0) {
97         encoder->Control(AOME_SET_CPUUSED, 8);
98       } else if (video->frame() == 30) {
99         encoder->Control(AOME_SET_CPUUSED, 7);
100       } else if (video->frame() == 60) {
101         encoder->Control(AOME_SET_CPUUSED, 6);
102       } else if (video->frame() == 90) {
103         encoder->Control(AOME_SET_CPUUSED, 7);
104       }
105     }
106 
107     if (frame_update_bitrate_ > 0) {
108       if (frame_number_ == frame_update_bitrate_) {
109         cfg_.rc_target_bitrate = target_bitrate_update_[1];
110         encoder->Config(&cfg_);
111       } else if (frame_number_ == 2 * frame_update_bitrate_) {
112         cfg_.rc_target_bitrate = target_bitrate_update_[2];
113         encoder->Config(&cfg_);
114       }
115     }
116 
117     if (denoiser_offon_test_) {
118       ASSERT_GT(denoiser_offon_period_, 0)
119           << "denoiser_offon_period_ is not positive.";
120       if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
121         // Flip denoiser_on_ periodically
122         denoiser_on_ ^= 1;
123       }
124     }
125 
126     encoder->Control(AV1E_SET_NOISE_SENSITIVITY, denoiser_on_);
127 
128     const aom_rational_t tb = video->timebase();
129     timebase_ = static_cast<double>(tb.num) / tb.den;
130     duration_ = 0;
131   }
132 
FramePktHook(const aom_codec_cx_pkt_t * pkt)133   void FramePktHook(const aom_codec_cx_pkt_t *pkt) override {
134     // Time since last timestamp = duration.
135     aom_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
136 
137     if (duration > 1) {
138       // If first drop not set and we have a drop set it to this time.
139       if (!first_drop_) first_drop_ = last_pts_ + 1;
140       // Update the number of frame drops.
141       num_drops_ += static_cast<int>(duration - 1);
142       // Update counter for total number of frames (#frames input to encoder).
143       // Needed for setting the proper layer_id below.
144       tot_frame_number_ += static_cast<int>(duration - 1);
145     }
146 
147     // Add to the buffer the bits we'd expect from a constant bitrate server.
148     bits_in_buffer_model_ += static_cast<int64_t>(
149         duration * timebase_ * cfg_.rc_target_bitrate * 1000);
150 
151     // Buffer should not go negative.
152     ASSERT_GE(bits_in_buffer_model_, 0)
153         << "Buffer Underrun at frame " << pkt->data.frame.pts;
154 
155     const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
156 
157     // Update the total encoded bits.
158     bits_total_ += frame_size_in_bits;
159 
160     // Update the most recent pts.
161     last_pts_ = pkt->data.frame.pts;
162     ++frame_number_;
163     ++tot_frame_number_;
164     const int per_frame_bandwidth = (cfg_.rc_target_bitrate * 1000) / 30;
165     if (frame_size_in_bits > max_perc_spike_ * per_frame_bandwidth &&
166         frame_number_ > 1)
167       num_spikes_++;
168     if (frame_size_in_bits > max_perc_spike_high_ * per_frame_bandwidth &&
169         frame_number_ > 1)
170       num_spikes_high_++;
171 
172     if (frame_update_bitrate_ > 0) {
173       if (frame_number_ < frame_update_bitrate_) {
174         bits_total_dynamic_[0] += frame_size_in_bits;
175         frame_number_dynamic_[0]++;
176       } else if (frame_number_ >= frame_update_bitrate_ &&
177                  frame_number_ < 2 * frame_update_bitrate_) {
178         bits_total_dynamic_[1] += frame_size_in_bits;
179         frame_number_dynamic_[1]++;
180       } else {
181         bits_total_dynamic_[2] += frame_size_in_bits;
182         frame_number_dynamic_[2]++;
183       }
184     }
185   }
186 
EndPassHook()187   void EndPassHook() override {
188     duration_ = (last_pts_ + 1) * timebase_;
189     // Effective file datarate:
190     effective_datarate_ = (bits_total_ / 1000.0) / duration_;
191     if (frame_update_bitrate_ > 0) {
192       for (int i = 0; i < 3; i++)
193         effective_datarate_dynamic_[i] =
194             30 * (bits_total_dynamic_[i] / 1000.0) / frame_number_dynamic_[i];
195     }
196   }
197 
198   aom_codec_pts_t last_pts_;
199   double timebase_;
200   int frame_number_;      // Counter for number of non-dropped/encoded frames.
201   int tot_frame_number_;  // Counter for total number of input frames.
202   int64_t bits_total_;
203   double duration_;
204   double effective_datarate_;
205   int set_cpu_used_;
206   int64_t bits_in_buffer_model_;
207   aom_codec_pts_t first_drop_;
208   int num_drops_;
209   int denoiser_on_;
210   int denoiser_offon_test_;
211   int denoiser_offon_period_;
212   unsigned int aq_mode_;
213   bool speed_change_test_;
214   int tile_columns_;
215   int tile_rows_;
216   bool auto_tiles_;
217   bool screen_mode_;
218   double max_perc_spike_;
219   double max_perc_spike_high_;
220   int num_spikes_;
221   int num_spikes_high_;
222   // These are use for test with dynamic bitrate change.
223   // Used to verify that the encoder can respond and hit bitrate that is updated
224   // during the sequence.
225   int frame_update_bitrate_;
226   int target_bitrate_update_[3];
227   double effective_datarate_dynamic_[3];
228   int64_t bits_total_dynamic_[3];
229   int frame_number_dynamic_[3];
230 };
231 
232 }  // namespace
233 }  // namespace datarate_test
234