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 "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" 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: ~DatarateTest()31 virtual ~DatarateTest() {} 32 SetUp()33 virtual void SetUp() { 34 InitializeConfig(); 35 ResetModel(); 36 } 37 ResetModel()38 virtual void ResetModel() { 39 last_pts_ = 0; 40 bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz; 41 frame_number_ = 0; 42 tot_frame_number_ = 0; 43 first_drop_ = 0; 44 num_drops_ = 0; 45 // Denoiser is off by default. 46 denoiser_on_ = 0; 47 bits_total_ = 0; 48 denoiser_offon_test_ = 0; 49 denoiser_offon_period_ = -1; 50 } 51 PreEncodeFrameHook(::libaom_test::VideoSource * video,::libaom_test::Encoder * encoder)52 virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video, 53 ::libaom_test::Encoder *encoder) { 54 if (video->frame() == 0) { 55 encoder->Control(AOME_SET_CPUUSED, set_cpu_used_); 56 encoder->Control(AV1E_SET_AQ_MODE, aq_mode_); 57 encoder->Control(AV1E_SET_TILE_COLUMNS, 0); 58 if (cfg_.g_usage == AOM_USAGE_REALTIME) { 59 encoder->Control(AV1E_SET_DELTAQ_MODE, 0); 60 encoder->Control(AV1E_SET_ENABLE_TPL_MODEL, 0); 61 encoder->Control(AV1E_SET_ENABLE_CDEF, 1); 62 encoder->Control(AV1E_SET_COEFF_COST_UPD_FREQ, 2); 63 encoder->Control(AV1E_SET_MODE_COST_UPD_FREQ, 2); 64 encoder->Control(AV1E_SET_MV_COST_UPD_FREQ, 2); 65 } 66 } 67 68 if (speed_change_test_) { 69 if (video->frame() == 0) { 70 encoder->Control(AOME_SET_CPUUSED, 8); 71 } 72 if (video->frame() == 30) { 73 encoder->Control(AOME_SET_CPUUSED, 7); 74 } 75 if (video->frame() == 60) { 76 encoder->Control(AOME_SET_CPUUSED, 6); 77 } 78 if (video->frame() == 90) { 79 encoder->Control(AOME_SET_CPUUSED, 7); 80 } 81 } 82 83 if (denoiser_offon_test_) { 84 ASSERT_GT(denoiser_offon_period_, 0) 85 << "denoiser_offon_period_ is not positive."; 86 if ((video->frame() + 1) % denoiser_offon_period_ == 0) { 87 // Flip denoiser_on_ periodically 88 denoiser_on_ ^= 1; 89 } 90 } 91 92 encoder->Control(AV1E_SET_NOISE_SENSITIVITY, denoiser_on_); 93 94 const aom_rational_t tb = video->timebase(); 95 timebase_ = static_cast<double>(tb.num) / tb.den; 96 duration_ = 0; 97 } 98 FramePktHook(const aom_codec_cx_pkt_t * pkt)99 virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) { 100 // Time since last timestamp = duration. 101 aom_codec_pts_t duration = pkt->data.frame.pts - last_pts_; 102 103 if (duration > 1) { 104 // If first drop not set and we have a drop set it to this time. 105 if (!first_drop_) first_drop_ = last_pts_ + 1; 106 // Update the number of frame drops. 107 num_drops_ += static_cast<int>(duration - 1); 108 // Update counter for total number of frames (#frames input to encoder). 109 // Needed for setting the proper layer_id below. 110 tot_frame_number_ += static_cast<int>(duration - 1); 111 } 112 113 // Add to the buffer the bits we'd expect from a constant bitrate server. 114 bits_in_buffer_model_ += static_cast<int64_t>( 115 duration * timebase_ * cfg_.rc_target_bitrate * 1000); 116 117 // Buffer should not go negative. 118 ASSERT_GE(bits_in_buffer_model_, 0) 119 << "Buffer Underrun at frame " << pkt->data.frame.pts; 120 121 const size_t frame_size_in_bits = pkt->data.frame.sz * 8; 122 123 // Update the total encoded bits. 124 bits_total_ += frame_size_in_bits; 125 126 // Update the most recent pts. 127 last_pts_ = pkt->data.frame.pts; 128 ++frame_number_; 129 ++tot_frame_number_; 130 } 131 EndPassHook(void)132 virtual void EndPassHook(void) { 133 duration_ = (last_pts_ + 1) * timebase_; 134 // Effective file datarate: 135 effective_datarate_ = (bits_total_ / 1000.0) / duration_; 136 } 137 138 aom_codec_pts_t last_pts_; 139 double timebase_; 140 int frame_number_; // Counter for number of non-dropped/encoded frames. 141 int tot_frame_number_; // Counter for total number of input frames. 142 int64_t bits_total_; 143 double duration_; 144 double effective_datarate_; 145 int set_cpu_used_; 146 int64_t bits_in_buffer_model_; 147 aom_codec_pts_t first_drop_; 148 int num_drops_; 149 int denoiser_on_; 150 int denoiser_offon_test_; 151 int denoiser_offon_period_; 152 unsigned int aq_mode_; 153 bool speed_change_test_; 154 }; 155 156 } // namespace 157 } // namespace datarate_test 158