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 framerate_(-1), | 68 frame_rate_(-1) { |
69 bitrate_updated_(false) { | |
70 RTC_CHECK_GT(num_temporal_layers, 0); | 69 RTC_CHECK_GT(num_temporal_layers, 0); |
71 RTC_CHECK_LE(num_temporal_layers, 2); | 70 RTC_CHECK_LE(num_temporal_layers, 2); |
72 } | 71 } |
73 | 72 |
74 ScreenshareLayers::~ScreenshareLayers() { | 73 ScreenshareLayers::~ScreenshareLayers() { |
75 UpdateHistograms(); | 74 UpdateHistograms(); |
76 } | 75 } |
77 | 76 |
78 int ScreenshareLayers::CurrentLayerId() const { | 77 int ScreenshareLayers::CurrentLayerId() const { |
79 // Codec does not use temporal layers for screenshare. | 78 // Codec does not use temporal layers for screenshare. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 flags = -1; | 129 flags = -1; |
131 ++stats_.num_dropped_frames_; | 130 ++stats_.num_dropped_frames_; |
132 break; | 131 break; |
133 default: | 132 default: |
134 flags = -1; | 133 flags = -1; |
135 RTC_NOTREACHED(); | 134 RTC_NOTREACHED(); |
136 } | 135 } |
137 | 136 |
138 int64_t ts_diff; | 137 int64_t ts_diff; |
139 if (last_timestamp_ == -1) { | 138 if (last_timestamp_ == -1) { |
140 ts_diff = kOneSecond90Khz / (framerate_ <= 0 ? 5 : framerate_); | 139 ts_diff = kOneSecond90Khz / (frame_rate_ <= 0 ? 5 : frame_rate_); |
141 } else { | 140 } else { |
142 ts_diff = unwrapped_timestamp - last_timestamp_; | 141 ts_diff = unwrapped_timestamp - last_timestamp_; |
143 } | 142 } |
144 // Make sure both frame droppers leak out bits. | 143 // Make sure both frame droppers leak out bits. |
145 layers_[0].UpdateDebt(ts_diff / 90); | 144 layers_[0].UpdateDebt(ts_diff / 90); |
146 layers_[1].UpdateDebt(ts_diff / 90); | 145 layers_[1].UpdateDebt(ts_diff / 90); |
147 last_timestamp_ = timestamp; | 146 last_timestamp_ = timestamp; |
148 return flags; | 147 return flags; |
149 } | 148 } |
150 | 149 |
151 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, | 150 bool ScreenshareLayers::ConfigureBitrates(int bitrate_kbps, |
152 int max_bitrate_kbps, | 151 int max_bitrate_kbps, |
153 int framerate) { | 152 int framerate, |
| 153 vpx_codec_enc_cfg_t* cfg) { |
154 layers_[0].target_rate_kbps_ = bitrate_kbps; | 154 layers_[0].target_rate_kbps_ = bitrate_kbps; |
155 layers_[1].target_rate_kbps_ = max_bitrate_kbps; | 155 layers_[1].target_rate_kbps_ = max_bitrate_kbps; |
156 framerate_ = framerate; | |
157 bitrate_updated_ = true; | |
158 | 156 |
159 std::vector<uint32_t> allocation; | 157 int target_bitrate_kbps = bitrate_kbps; |
160 allocation.push_back(bitrate_kbps); | 158 |
161 if (max_bitrate_kbps > bitrate_kbps) | 159 if (cfg != nullptr) { |
162 allocation.push_back(max_bitrate_kbps - bitrate_kbps); | 160 if (number_of_temporal_layers_ > 1) { |
163 return allocation; | 161 // Calculate a codec target bitrate. This may be higher than TL0, gaining |
| 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; |
164 } | 191 } |
165 | 192 |
166 void ScreenshareLayers::FrameEncoded(unsigned int size, | 193 void ScreenshareLayers::FrameEncoded(unsigned int size, |
167 uint32_t timestamp, | 194 uint32_t timestamp, |
168 int qp) { | 195 int qp) { |
169 if (number_of_temporal_layers_ == 1) | 196 if (number_of_temporal_layers_ == 1) |
170 return; | 197 return; |
171 | 198 |
172 RTC_DCHECK_NE(-1, active_layer_); | 199 RTC_DCHECK_NE(-1, active_layer_); |
173 if (size == 0) { | 200 if (size == 0) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 return false; | 272 return false; |
246 } | 273 } |
247 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too | 274 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too |
248 // large. | 275 // large. |
249 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) | 276 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) |
250 return true; | 277 return true; |
251 return false; | 278 return false; |
252 } | 279 } |
253 | 280 |
254 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { | 281 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { |
255 bool cfg_updated = false; | |
256 if (bitrate_updated_) { | |
257 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_; | |
258 | |
259 if (number_of_temporal_layers_ > 1) { | |
260 // Calculate a codec target bitrate. This may be higher than TL0, gaining | |
261 // quality at the expense of frame rate at TL0. Constraints: | |
262 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction. | |
263 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate. | |
264 target_bitrate_kbps = | |
265 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction, | |
266 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot); | |
267 | |
268 cfg->rc_target_bitrate = | |
269 std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps); | |
270 } | |
271 | |
272 // Don't reconfigure qp limits during quality boost frames. | |
273 if (active_layer_ == -1 || | |
274 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) { | |
275 min_qp_ = cfg->rc_min_quantizer; | |
276 max_qp_ = cfg->rc_max_quantizer; | |
277 // After a dropped frame, a frame with max qp will be encoded and the | |
278 // quality will then ramp up from there. To boost the speed of recovery, | |
279 // encode the next frame with lower max qp. TL0 is the most important to | |
280 // improve since the errors in this layer will propagate to TL1. | |
281 // Currently, reduce max qp by 20% for TL0 and 15% for TL1. | |
282 layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100); | |
283 layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100); | |
284 } | |
285 | |
286 if (framerate_ > 0) { | |
287 int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate_); | |
288 max_debt_bytes_ = 4 * avg_frame_size; | |
289 } | |
290 | |
291 bitrate_updated_ = false; | |
292 cfg_updated = true; | |
293 } | |
294 | |
295 // Don't try to update boosts state if not active yet. | |
296 if (active_layer_ == -1) | |
297 return cfg_updated; | |
298 | |
299 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) | 282 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) |
300 return cfg_updated; | 283 return false; |
| 284 RTC_DCHECK_NE(-1, active_layer_); |
301 | 285 |
302 // If layer is in the quality boost state (following a dropped frame), update | 286 // If layer is in the quality boost state (following a dropped frame), update |
303 // the configuration with the adjusted (lower) qp and set the state back to | 287 // the configuration with the adjusted (lower) qp and set the state back to |
304 // normal. | 288 // normal. |
305 unsigned int adjusted_max_qp; | 289 unsigned int adjusted_max_qp; |
306 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && | 290 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && |
307 layers_[active_layer_].enhanced_max_qp != -1) { | 291 layers_[active_layer_].enhanced_max_qp != -1) { |
308 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; | 292 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; |
309 layers_[active_layer_].state = TemporalLayer::State::kNormal; | 293 layers_[active_layer_].state = TemporalLayer::State::kNormal; |
310 } else { | 294 } else { |
311 if (max_qp_ == -1) | 295 if (max_qp_ == -1) |
312 return cfg_updated; | 296 return false; |
313 adjusted_max_qp = max_qp_; // Set the normal max qp. | 297 adjusted_max_qp = max_qp_; // Set the normal max qp. |
314 } | 298 } |
315 | 299 |
316 if (adjusted_max_qp == cfg->rc_max_quantizer) | 300 if (adjusted_max_qp == cfg->rc_max_quantizer) |
317 return cfg_updated; | 301 return false; |
318 | 302 |
319 cfg->rc_max_quantizer = adjusted_max_qp; | 303 cfg->rc_max_quantizer = adjusted_max_qp; |
320 cfg_updated = true; | 304 return true; |
321 return cfg_updated; | |
322 } | 305 } |
323 | 306 |
324 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { | 307 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { |
325 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; | 308 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; |
326 if (debt_reduction_bytes >= debt_bytes_) { | 309 if (debt_reduction_bytes >= debt_bytes_) { |
327 debt_bytes_ = 0; | 310 debt_bytes_ = 0; |
328 } else { | 311 } else { |
329 debt_bytes_ -= debt_reduction_bytes; | 312 debt_bytes_ -= debt_reduction_bytes; |
330 } | 313 } |
331 } | 314 } |
(...skipping 30 matching lines...) Expand all Loading... |
362 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", | 345 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", |
363 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); | 346 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); |
364 RTC_HISTOGRAM_COUNTS_10000( | 347 RTC_HISTOGRAM_COUNTS_10000( |
365 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", | 348 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", |
366 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); | 349 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); |
367 } | 350 } |
368 } | 351 } |
369 } | 352 } |
370 | 353 |
371 } // namespace webrtc | 354 } // namespace webrtc |
OLD | NEW |