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