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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 // bitrate stream. This means predicting only from the LAST reference frame, but | 44 // bitrate stream. This means predicting only from the LAST reference frame, but |
45 // only updating GF to not corrupt TL0. | 45 // only updating GF to not corrupt TL0. |
46 const int ScreenshareLayers::kTl1SyncFlags = | 46 const int ScreenshareLayers::kTl1SyncFlags = |
47 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | | 47 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | |
48 VP8_EFLAG_NO_UPD_LAST; | 48 VP8_EFLAG_NO_UPD_LAST; |
49 | 49 |
50 // Always emit a frame with certain interval, even if bitrate targets have | 50 // Always emit a frame with certain interval, even if bitrate targets have |
51 // been exceeded. | 51 // been exceeded. |
52 const int ScreenshareLayers::kMaxFrameIntervalMs = 2000; | 52 const int ScreenshareLayers::kMaxFrameIntervalMs = 2000; |
53 | 53 |
| 54 webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create( |
| 55 int simulcast_id, |
| 56 int num_temporal_layers, |
| 57 uint8_t initial_tl0_pic_idx) const { |
| 58 webrtc::TemporalLayers* tl = new webrtc::ScreenshareLayers( |
| 59 num_temporal_layers, rand(), webrtc::Clock::GetRealTimeClock()); |
| 60 if (listener_) |
| 61 listener_->OnTemporalLayersCreated(simulcast_id, tl); |
| 62 return tl; |
| 63 } |
| 64 |
54 ScreenshareLayers::ScreenshareLayers(int num_temporal_layers, | 65 ScreenshareLayers::ScreenshareLayers(int num_temporal_layers, |
55 uint8_t initial_tl0_pic_idx, | 66 uint8_t initial_tl0_pic_idx, |
56 Clock* clock) | 67 Clock* clock) |
57 : clock_(clock), | 68 : clock_(clock), |
58 number_of_temporal_layers_(num_temporal_layers), | 69 number_of_temporal_layers_(num_temporal_layers), |
59 last_base_layer_sync_(false), | 70 last_base_layer_sync_(false), |
60 tl0_pic_idx_(initial_tl0_pic_idx), | 71 tl0_pic_idx_(initial_tl0_pic_idx), |
61 active_layer_(-1), | 72 active_layer_(-1), |
62 last_timestamp_(-1), | 73 last_timestamp_(-1), |
63 last_sync_timestamp_(-1), | 74 last_sync_timestamp_(-1), |
64 last_emitted_tl0_timestamp_(-1), | 75 last_emitted_tl0_timestamp_(-1), |
65 min_qp_(-1), | 76 min_qp_(-1), |
66 max_qp_(-1), | 77 max_qp_(-1), |
67 max_debt_bytes_(0), | 78 max_debt_bytes_(0), |
68 frame_rate_(-1) { | 79 framerate_(-1), |
| 80 bitrate_updated_(false) { |
69 RTC_CHECK_GT(num_temporal_layers, 0); | 81 RTC_CHECK_GT(num_temporal_layers, 0); |
70 RTC_CHECK_LE(num_temporal_layers, 2); | 82 RTC_CHECK_LE(num_temporal_layers, 2); |
71 } | 83 } |
72 | 84 |
73 ScreenshareLayers::~ScreenshareLayers() { | 85 ScreenshareLayers::~ScreenshareLayers() { |
74 UpdateHistograms(); | 86 UpdateHistograms(); |
75 } | 87 } |
76 | 88 |
77 int ScreenshareLayers::CurrentLayerId() const { | 89 int ScreenshareLayers::CurrentLayerId() const { |
78 // Codec does not use temporal layers for screenshare. | 90 // Codec does not use temporal layers for screenshare. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 flags = -1; | 141 flags = -1; |
130 ++stats_.num_dropped_frames_; | 142 ++stats_.num_dropped_frames_; |
131 break; | 143 break; |
132 default: | 144 default: |
133 flags = -1; | 145 flags = -1; |
134 RTC_NOTREACHED(); | 146 RTC_NOTREACHED(); |
135 } | 147 } |
136 | 148 |
137 int64_t ts_diff; | 149 int64_t ts_diff; |
138 if (last_timestamp_ == -1) { | 150 if (last_timestamp_ == -1) { |
139 ts_diff = kOneSecond90Khz / (frame_rate_ <= 0 ? 5 : frame_rate_); | 151 ts_diff = kOneSecond90Khz / (framerate_ <= 0 ? 5 : framerate_); |
140 } else { | 152 } else { |
141 ts_diff = unwrapped_timestamp - last_timestamp_; | 153 ts_diff = unwrapped_timestamp - last_timestamp_; |
142 } | 154 } |
143 // Make sure both frame droppers leak out bits. | 155 // Make sure both frame droppers leak out bits. |
144 layers_[0].UpdateDebt(ts_diff / 90); | 156 layers_[0].UpdateDebt(ts_diff / 90); |
145 layers_[1].UpdateDebt(ts_diff / 90); | 157 layers_[1].UpdateDebt(ts_diff / 90); |
146 last_timestamp_ = timestamp; | 158 last_timestamp_ = timestamp; |
147 return flags; | 159 return flags; |
148 } | 160 } |
149 | 161 |
150 bool ScreenshareLayers::ConfigureBitrates(int bitrate_kbps, | 162 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, |
151 int max_bitrate_kbps, | 163 int max_bitrate_kbps, |
152 int framerate, | 164 int framerate) { |
153 vpx_codec_enc_cfg_t* cfg) { | |
154 layers_[0].target_rate_kbps_ = bitrate_kbps; | 165 layers_[0].target_rate_kbps_ = bitrate_kbps; |
155 layers_[1].target_rate_kbps_ = max_bitrate_kbps; | 166 layers_[1].target_rate_kbps_ = max_bitrate_kbps; |
| 167 framerate_ = framerate; |
| 168 bitrate_updated_ = true; |
156 | 169 |
157 int target_bitrate_kbps = bitrate_kbps; | 170 std::vector<uint32_t> allocation; |
158 | 171 allocation.push_back(bitrate_kbps); |
159 if (cfg != nullptr) { | 172 if (max_bitrate_kbps > bitrate_kbps) |
160 if (number_of_temporal_layers_ > 1) { | 173 allocation.push_back(max_bitrate_kbps - bitrate_kbps); |
161 // Calculate a codec target bitrate. This may be higher than TL0, gaining | 174 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 } | 175 } |
192 | 176 |
193 void ScreenshareLayers::FrameEncoded(unsigned int size, | 177 void ScreenshareLayers::FrameEncoded(unsigned int size, |
194 uint32_t timestamp, | 178 uint32_t timestamp, |
195 int qp) { | 179 int qp) { |
196 if (number_of_temporal_layers_ == 1) | 180 if (number_of_temporal_layers_ == 1) |
197 return; | 181 return; |
198 | 182 |
199 RTC_DCHECK_NE(-1, active_layer_); | 183 RTC_DCHECK_NE(-1, active_layer_); |
200 if (size == 0) { | 184 if (size == 0) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 return false; | 256 return false; |
273 } | 257 } |
274 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too | 258 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too |
275 // large. | 259 // large. |
276 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) | 260 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) |
277 return true; | 261 return true; |
278 return false; | 262 return false; |
279 } | 263 } |
280 | 264 |
281 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { | 265 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { |
| 266 bool cfg_updated = false; |
| 267 if (bitrate_updated_) { |
| 268 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_; |
| 269 |
| 270 if (number_of_temporal_layers_ > 1) { |
| 271 // Calculate a codec target bitrate. This may be higher than TL0, gaining |
| 272 // quality at the expense of frame rate at TL0. Constraints: |
| 273 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction. |
| 274 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate. |
| 275 target_bitrate_kbps = |
| 276 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction, |
| 277 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot); |
| 278 |
| 279 cfg->rc_target_bitrate = |
| 280 std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps); |
| 281 } |
| 282 |
| 283 // Don't reconfigure qp limits during quality boost frames. |
| 284 if (active_layer_ == -1 || |
| 285 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) { |
| 286 min_qp_ = cfg->rc_min_quantizer; |
| 287 max_qp_ = cfg->rc_max_quantizer; |
| 288 // After a dropped frame, a frame with max qp will be encoded and the |
| 289 // quality will then ramp up from there. To boost the speed of recovery, |
| 290 // encode the next frame with lower max qp. TL0 is the most important to |
| 291 // improve since the errors in this layer will propagate to TL1. |
| 292 // Currently, reduce max qp by 20% for TL0 and 15% for TL1. |
| 293 layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100); |
| 294 layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100); |
| 295 } |
| 296 |
| 297 if (framerate_ > 0) { |
| 298 int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate_); |
| 299 max_debt_bytes_ = 4 * avg_frame_size; |
| 300 } |
| 301 |
| 302 bitrate_updated_ = false; |
| 303 cfg_updated = true; |
| 304 } |
| 305 |
| 306 // Don't try to update boosts state if not active yet. |
| 307 if (active_layer_ == -1) |
| 308 return cfg_updated; |
| 309 |
282 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) | 310 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) |
283 return false; | 311 return cfg_updated; |
284 RTC_DCHECK_NE(-1, active_layer_); | |
285 | 312 |
286 // If layer is in the quality boost state (following a dropped frame), update | 313 // 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 | 314 // the configuration with the adjusted (lower) qp and set the state back to |
288 // normal. | 315 // normal. |
289 unsigned int adjusted_max_qp; | 316 unsigned int adjusted_max_qp; |
290 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && | 317 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && |
291 layers_[active_layer_].enhanced_max_qp != -1) { | 318 layers_[active_layer_].enhanced_max_qp != -1) { |
292 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; | 319 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; |
293 layers_[active_layer_].state = TemporalLayer::State::kNormal; | 320 layers_[active_layer_].state = TemporalLayer::State::kNormal; |
294 } else { | 321 } else { |
295 if (max_qp_ == -1) | 322 if (max_qp_ == -1) |
296 return false; | 323 return cfg_updated; |
297 adjusted_max_qp = max_qp_; // Set the normal max qp. | 324 adjusted_max_qp = max_qp_; // Set the normal max qp. |
298 } | 325 } |
299 | 326 |
300 if (adjusted_max_qp == cfg->rc_max_quantizer) | 327 if (adjusted_max_qp == cfg->rc_max_quantizer) |
301 return false; | 328 return cfg_updated; |
302 | 329 |
303 cfg->rc_max_quantizer = adjusted_max_qp; | 330 cfg->rc_max_quantizer = adjusted_max_qp; |
304 return true; | 331 cfg_updated = true; |
| 332 return cfg_updated; |
305 } | 333 } |
306 | 334 |
307 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { | 335 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { |
308 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; | 336 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; |
309 if (debt_reduction_bytes >= debt_bytes_) { | 337 if (debt_reduction_bytes >= debt_bytes_) { |
310 debt_bytes_ = 0; | 338 debt_bytes_ = 0; |
311 } else { | 339 } else { |
312 debt_bytes_ -= debt_reduction_bytes; | 340 debt_bytes_ -= debt_reduction_bytes; |
313 } | 341 } |
314 } | 342 } |
(...skipping 30 matching lines...) Expand all Loading... |
345 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", | 373 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", |
346 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); | 374 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); |
347 RTC_HISTOGRAM_COUNTS_10000( | 375 RTC_HISTOGRAM_COUNTS_10000( |
348 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", | 376 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", |
349 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); | 377 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); |
350 } | 378 } |
351 } | 379 } |
352 } | 380 } |
353 | 381 |
354 } // namespace webrtc | 382 } // namespace webrtc |
OLD | NEW |