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

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

Issue 1869003002: Make sure temporal layered screenshare frames are sent in at least 2s. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Make sure ScreenshareLayers allows a frame every 2s Created 4 years, 8 months 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 29 matching lines...) Expand all
40 const int ScreenshareLayers::kTl1Flags = 40 const int ScreenshareLayers::kTl1Flags =
41 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; 41 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
42 42
43 // Allow predicting from only TL0 to allow participants to switch to the high 43 // Allow predicting from only TL0 to allow participants to switch to the high
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
51 // been exceeded.
52 const int ScreenshareLayers::kMaxFrameIntervalMs = 2000;
53
50 ScreenshareLayers::ScreenshareLayers(int num_temporal_layers, 54 ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
51 uint8_t initial_tl0_pic_idx, 55 uint8_t initial_tl0_pic_idx,
52 Clock* clock) 56 Clock* clock)
53 : clock_(clock), 57 : clock_(clock),
54 number_of_temporal_layers_(num_temporal_layers), 58 number_of_temporal_layers_(num_temporal_layers),
55 last_base_layer_sync_(false), 59 last_base_layer_sync_(false),
56 tl0_pic_idx_(initial_tl0_pic_idx), 60 tl0_pic_idx_(initial_tl0_pic_idx),
57 active_layer_(-1), 61 active_layer_(-1),
58 last_timestamp_(-1), 62 last_timestamp_(-1),
59 last_sync_timestamp_(-1), 63 last_sync_timestamp_(-1),
(...skipping 18 matching lines...) Expand all
78 if (number_of_temporal_layers_ <= 1) { 82 if (number_of_temporal_layers_ <= 1) {
79 // No flags needed for 1 layer screenshare. 83 // No flags needed for 1 layer screenshare.
80 return 0; 84 return 0;
81 } 85 }
82 86
83 if (stats_.first_frame_time_ms_ == -1) 87 if (stats_.first_frame_time_ms_ == -1)
84 stats_.first_frame_time_ms_ = clock_->TimeInMilliseconds(); 88 stats_.first_frame_time_ms_ = clock_->TimeInMilliseconds();
85 89
86 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); 90 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
87 int flags = 0; 91 int flags = 0;
88
89 if (active_layer_ == -1 || 92 if (active_layer_ == -1 ||
90 layers_[active_layer_].state != TemporalLayer::State::kDropped) { 93 layers_[active_layer_].state != TemporalLayer::State::kDropped) {
94 layers_[0].CheckFrameInterval(unwrapped_timestamp);
91 if (layers_[0].debt_bytes_ > max_debt_bytes_) { 95 if (layers_[0].debt_bytes_ > max_debt_bytes_) {
92 // Must drop TL0, encode TL1 instead. 96 // Must drop TL0, encode TL1 instead.
97 layers_[1].CheckFrameInterval(unwrapped_timestamp);
stefan-webrtc 2016/04/07 12:53:12 Do we want the same behavior in TL1, or should we
sprang_webrtc 2016/04/07 13:03:32 Yeah, I think only doing it for TL0 makes sense.
93 if (layers_[1].debt_bytes_ > max_debt_bytes_) { 98 if (layers_[1].debt_bytes_ > max_debt_bytes_) {
94 // Must drop both TL0 and TL1. 99 // Must drop both TL0 and TL1.
95 active_layer_ = -1; 100 active_layer_ = -1;
96 } else { 101 } else {
97 active_layer_ = 1; 102 active_layer_ = 1;
98 } 103 }
99 } else { 104 } else {
100 active_layer_ = 0; 105 active_layer_ = 0;
101 } 106 }
102 } 107 }
103 108
104 switch (active_layer_) { 109 switch (active_layer_) {
105 case 0: 110 case 0:
106 flags = kTl0Flags; 111 flags = kTl0Flags;
112 layers_[0].last_emitted_timsetamp_ = unwrapped_timestamp;
stefan-webrtc 2016/04/07 12:53:12 last_emitted_timestamp
sprang_webrtc 2016/04/07 13:03:32 Done.
107 break; 113 break;
108 case 1: 114 case 1:
109 if (TimeToSync(unwrapped_timestamp)) { 115 if (TimeToSync(unwrapped_timestamp)) {
110 last_sync_timestamp_ = unwrapped_timestamp; 116 last_sync_timestamp_ = unwrapped_timestamp;
111 flags = kTl1SyncFlags; 117 flags = kTl1SyncFlags;
112 } else { 118 } else {
113 flags = kTl1Flags; 119 flags = kTl1Flags;
114 } 120 }
121 layers_[1].last_emitted_timsetamp_ = unwrapped_timestamp;
115 break; 122 break;
116 case -1: 123 case -1:
117 flags = -1; 124 flags = -1;
118 ++stats_.num_dropped_frames_; 125 ++stats_.num_dropped_frames_;
119 break; 126 break;
120 default: 127 default:
121 flags = -1; 128 flags = -1;
122 RTC_NOTREACHED(); 129 RTC_NOTREACHED();
123 } 130 }
124 131
125 // Make sure both frame droppers leak out bits.
126 int64_t ts_diff; 132 int64_t ts_diff;
127 if (last_timestamp_ == -1) { 133 if (last_timestamp_ == -1) {
128 ts_diff = kOneSecond90Khz / (frame_rate_ <= 0 ? 5 : frame_rate_); 134 ts_diff = kOneSecond90Khz / (frame_rate_ <= 0 ? 5 : frame_rate_);
129 } else { 135 } else {
130 ts_diff = unwrapped_timestamp - last_timestamp_; 136 ts_diff = unwrapped_timestamp - last_timestamp_;
131 } 137 }
132 138 // Make sure both frame droppers leak out bits.
133 layers_[0].UpdateDebt(ts_diff / 90); 139 layers_[0].UpdateDebt(ts_diff / 90);
134 layers_[1].UpdateDebt(ts_diff / 90); 140 layers_[1].UpdateDebt(ts_diff / 90);
135 last_timestamp_ = timestamp; 141 last_timestamp_ = timestamp;
136 return flags; 142 return flags;
137 } 143 }
138 144
139 bool ScreenshareLayers::ConfigureBitrates(int bitrate_kbps, 145 bool ScreenshareLayers::ConfigureBitrates(int bitrate_kbps,
140 int max_bitrate_kbps, 146 int max_bitrate_kbps,
141 int framerate, 147 int framerate,
142 vpx_codec_enc_cfg_t* cfg) { 148 vpx_codec_enc_cfg_t* cfg) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 301
296 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { 302 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
297 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; 303 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
298 if (debt_reduction_bytes >= debt_bytes_) { 304 if (debt_reduction_bytes >= debt_bytes_) {
299 debt_bytes_ = 0; 305 debt_bytes_ = 0;
300 } else { 306 } else {
301 debt_bytes_ -= debt_reduction_bytes; 307 debt_bytes_ -= debt_reduction_bytes;
302 } 308 }
303 } 309 }
304 310
311 void ScreenshareLayers::TemporalLayer::CheckFrameInterval(int64_t timestamp) {
312 if (last_emitted_timsetamp_ != -1 &&
313 (timestamp - last_emitted_timsetamp_) / 90 > kMaxFrameIntervalMs) {
314 // Too long time has passed since the last frame was emitted, cancel debt.
315 debt_bytes_ = 0;
316 }
317 }
318
305 void ScreenshareLayers::UpdateHistograms() { 319 void ScreenshareLayers::UpdateHistograms() {
306 if (stats_.first_frame_time_ms_ == -1) 320 if (stats_.first_frame_time_ms_ == -1)
307 return; 321 return;
308 int64_t duration_sec = 322 int64_t duration_sec =
309 (clock_->TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) / 1000; 323 (clock_->TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) / 1000;
310 if (duration_sec >= metrics::kMinRunTimeInSeconds) { 324 if (duration_sec >= metrics::kMinRunTimeInSeconds) {
311 RTC_HISTOGRAM_COUNTS_10000( 325 RTC_HISTOGRAM_COUNTS_10000(
312 "WebRTC.Video.Screenshare.Layer0.FrameRate", 326 "WebRTC.Video.Screenshare.Layer0.FrameRate",
313 (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec); 327 (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
314 RTC_HISTOGRAM_COUNTS_10000( 328 RTC_HISTOGRAM_COUNTS_10000(
(...skipping 19 matching lines...) Expand all
334 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", 348 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
335 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); 349 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
336 RTC_HISTOGRAM_COUNTS_10000( 350 RTC_HISTOGRAM_COUNTS_10000(
337 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", 351 "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
338 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); 352 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
339 } 353 }
340 } 354 }
341 } 355 }
342 356
343 } // namespace webrtc 357 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698