Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(679)

Side by Side Diff: webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc

Issue 2510583002: Reland #2 of Issue 2434073003: Extract bitrate allocation ... (Closed)
Patch Set: Addressed comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698