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 29 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |