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