| OLD | NEW |
| 1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 2 * | 2 * |
| 3 * Use of this source code is governed by a BSD-style license | 3 * Use of this source code is governed by a BSD-style license |
| 4 * that can be found in the LICENSE file in the root of the source | 4 * that can be found in the LICENSE file in the root of the source |
| 5 * tree. An additional intellectual property rights grant can be found | 5 * tree. An additional intellectual property rights grant can be found |
| 6 * in the file PATENTS. All contributing project authors may | 6 * in the file PATENTS. All contributing project authors may |
| 7 * be found in the AUTHORS file in the root of the source tree. | 7 * be found in the AUTHORS file in the root of the source tree. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" | 10 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 number_of_temporal_layers_(num_temporal_layers), | 58 number_of_temporal_layers_(num_temporal_layers), |
| 59 last_base_layer_sync_(false), | 59 last_base_layer_sync_(false), |
| 60 tl0_pic_idx_(initial_tl0_pic_idx), | 60 tl0_pic_idx_(initial_tl0_pic_idx), |
| 61 active_layer_(-1), | 61 active_layer_(-1), |
| 62 last_timestamp_(-1), | 62 last_timestamp_(-1), |
| 63 last_sync_timestamp_(-1), | 63 last_sync_timestamp_(-1), |
| 64 last_emitted_tl0_timestamp_(-1), | 64 last_emitted_tl0_timestamp_(-1), |
| 65 min_qp_(-1), | 65 min_qp_(-1), |
| 66 max_qp_(-1), | 66 max_qp_(-1), |
| 67 max_debt_bytes_(0), | 67 max_debt_bytes_(0), |
| 68 frame_rate_(-1) { | 68 frame_rate_(-1), |
| 69 bitrate_updated_(false) { |
| 69 RTC_CHECK_GT(num_temporal_layers, 0); | 70 RTC_CHECK_GT(num_temporal_layers, 0); |
| 70 RTC_CHECK_LE(num_temporal_layers, 2); | 71 RTC_CHECK_LE(num_temporal_layers, 2); |
| 71 } | 72 } |
| 72 | 73 |
| 73 ScreenshareLayers::~ScreenshareLayers() { | 74 ScreenshareLayers::~ScreenshareLayers() { |
| 74 UpdateHistograms(); | 75 UpdateHistograms(); |
| 75 } | 76 } |
| 76 | 77 |
| 77 int ScreenshareLayers::CurrentLayerId() const { | 78 int ScreenshareLayers::CurrentLayerId() const { |
| 78 // Codec does not use temporal layers for screenshare. | 79 // Codec does not use temporal layers for screenshare. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 } else { | 141 } else { |
| 141 ts_diff = unwrapped_timestamp - last_timestamp_; | 142 ts_diff = unwrapped_timestamp - last_timestamp_; |
| 142 } | 143 } |
| 143 // Make sure both frame droppers leak out bits. | 144 // Make sure both frame droppers leak out bits. |
| 144 layers_[0].UpdateDebt(ts_diff / 90); | 145 layers_[0].UpdateDebt(ts_diff / 90); |
| 145 layers_[1].UpdateDebt(ts_diff / 90); | 146 layers_[1].UpdateDebt(ts_diff / 90); |
| 146 last_timestamp_ = timestamp; | 147 last_timestamp_ = timestamp; |
| 147 return flags; | 148 return flags; |
| 148 } | 149 } |
| 149 | 150 |
| 150 bool ScreenshareLayers::ConfigureBitrates(int bitrate_kbps, | 151 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbit, |
| 151 int max_bitrate_kbps, | 152 int max_bitrate_kbit, |
| 152 int framerate, | 153 int framerate) { |
| 153 vpx_codec_enc_cfg_t* cfg) { | 154 layers_[0].target_rate_kbps_ = bitrate_kbit; |
| 154 layers_[0].target_rate_kbps_ = bitrate_kbps; | 155 layers_[1].target_rate_kbps_ = max_bitrate_kbit; |
| 155 layers_[1].target_rate_kbps_ = max_bitrate_kbps; | 156 frame_rate_ = framerate; |
| 157 bitrate_updated_ = true; |
| 156 | 158 |
| 157 int target_bitrate_kbps = bitrate_kbps; | 159 std::vector<uint32_t> allocation; |
| 158 | 160 allocation.push_back(bitrate_kbit); |
| 159 if (cfg != nullptr) { | 161 if (max_bitrate_kbit > bitrate_kbit) |
| 160 if (number_of_temporal_layers_ > 1) { | 162 allocation.push_back(max_bitrate_kbit - bitrate_kbit); |
| 161 // Calculate a codec target bitrate. This may be higher than TL0, gaining | 163 return allocation; |
| 162 // quality at the expense of frame rate at TL0. Constraints: | |
| 163 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction. | |
| 164 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate. | |
| 165 target_bitrate_kbps = | |
| 166 std::min(bitrate_kbps * kMaxTL0FpsReduction, | |
| 167 max_bitrate_kbps / kAcceptableTargetOvershoot); | |
| 168 | |
| 169 cfg->rc_target_bitrate = std::max(bitrate_kbps, target_bitrate_kbps); | |
| 170 } | |
| 171 | |
| 172 // Don't reconfigure qp limits during quality boost frames. | |
| 173 if (active_layer_ == -1 || | |
| 174 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) { | |
| 175 min_qp_ = cfg->rc_min_quantizer; | |
| 176 max_qp_ = cfg->rc_max_quantizer; | |
| 177 // After a dropped frame, a frame with max qp will be encoded and the | |
| 178 // quality will then ramp up from there. To boost the speed of recovery, | |
| 179 // encode the next frame with lower max qp. TL0 is the most important to | |
| 180 // improve since the errors in this layer will propagate to TL1. | |
| 181 // Currently, reduce max qp by 20% for TL0 and 15% for TL1. | |
| 182 layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100); | |
| 183 layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate); | |
| 188 max_debt_bytes_ = 4 * avg_frame_size; | |
| 189 | |
| 190 return true; | |
| 191 } | 164 } |
| 192 | 165 |
| 193 void ScreenshareLayers::FrameEncoded(unsigned int size, | 166 void ScreenshareLayers::FrameEncoded(unsigned int size, |
| 194 uint32_t timestamp, | 167 uint32_t timestamp, |
| 195 int qp) { | 168 int qp) { |
| 196 if (number_of_temporal_layers_ == 1) | 169 if (number_of_temporal_layers_ == 1) |
| 197 return; | 170 return; |
| 198 | 171 |
| 199 RTC_DCHECK_NE(-1, active_layer_); | 172 RTC_DCHECK_NE(-1, active_layer_); |
| 200 if (size == 0) { | 173 if (size == 0) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 return false; | 245 return false; |
| 273 } | 246 } |
| 274 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too | 247 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too |
| 275 // large. | 248 // large. |
| 276 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) | 249 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) |
| 277 return true; | 250 return true; |
| 278 return false; | 251 return false; |
| 279 } | 252 } |
| 280 | 253 |
| 281 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { | 254 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { |
| 255 if (bitrate_updated_) { |
| 256 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_; |
| 257 |
| 258 if (number_of_temporal_layers_ > 1) { |
| 259 // Calculate a codec target bitrate. This may be higher than TL0, gaining |
| 260 // quality at the expense of frame rate at TL0. Constraints: |
| 261 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction. |
| 262 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate. |
| 263 target_bitrate_kbps = |
| 264 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction, |
| 265 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot); |
| 266 |
| 267 cfg->rc_target_bitrate = |
| 268 std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps); |
| 269 } |
| 270 |
| 271 // Don't reconfigure qp limits during quality boost frames. |
| 272 if (active_layer_ == -1 || |
| 273 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) { |
| 274 min_qp_ = cfg->rc_min_quantizer; |
| 275 max_qp_ = cfg->rc_max_quantizer; |
| 276 // After a dropped frame, a frame with max qp will be encoded and the |
| 277 // quality will then ramp up from there. To boost the speed of recovery, |
| 278 // encode the next frame with lower max qp. TL0 is the most important to |
| 279 // improve since the errors in this layer will propagate to TL1. |
| 280 // Currently, reduce max qp by 20% for TL0 and 15% for TL1. |
| 281 layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100); |
| 282 layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100); |
| 283 } |
| 284 |
| 285 int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * frame_rate_); |
| 286 max_debt_bytes_ = 4 * avg_frame_size; |
| 287 |
| 288 bitrate_updated_ = false; |
| 289 |
| 290 // Don't try to update boosts state if not active yet. |
| 291 if (active_layer_ == -1) |
| 292 return true; |
| 293 } |
| 294 |
| 295 RTC_DCHECK_NE(-1, active_layer_); |
| 282 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) | 296 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) |
| 283 return false; | 297 return false; |
| 284 RTC_DCHECK_NE(-1, active_layer_); | |
| 285 | 298 |
| 286 // If layer is in the quality boost state (following a dropped frame), update | 299 // If layer is in the quality boost state (following a dropped frame), update |
| 287 // the configuration with the adjusted (lower) qp and set the state back to | 300 // the configuration with the adjusted (lower) qp and set the state back to |
| 288 // normal. | 301 // normal. |
| 289 unsigned int adjusted_max_qp; | 302 unsigned int adjusted_max_qp; |
| 290 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && | 303 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && |
| 291 layers_[active_layer_].enhanced_max_qp != -1) { | 304 layers_[active_layer_].enhanced_max_qp != -1) { |
| 292 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; | 305 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; |
| 293 layers_[active_layer_].state = TemporalLayer::State::kNormal; | 306 layers_[active_layer_].state = TemporalLayer::State::kNormal; |
| 294 } else { | 307 } else { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", | 358 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", |
| 346 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); | 359 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); |
| 347 RTC_HISTOGRAM_COUNTS_10000( | 360 RTC_HISTOGRAM_COUNTS_10000( |
| 348 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", | 361 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", |
| 349 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); | 362 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); |
| 350 } | 363 } |
| 351 } | 364 } |
| 352 } | 365 } |
| 353 | 366 |
| 354 } // namespace webrtc | 367 } // namespace webrtc |
| OLD | NEW |