blob: ede21e554d72648a99005e8a77d9cbda9f6a725e [file] [log] [blame]
pbos@webrtc.org9115cde2014-12-09 10:36:40 +00001/* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +02002 *
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
5 * tree. An additional intellectual property rights grant can be found
6 * in the file PATENTS. All contributing project authors may
7 * be found in the AUTHORS file in the root of the source tree.
8 */
pbos@webrtc.org9115cde2014-12-09 10:36:40 +00009
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "modules/video_coding/codecs/vp8/screenshare_layers.h"
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000011
12#include <stdlib.h>
13
philipelcce46fc2015-12-21 03:04:49 -080014#include <algorithm>
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +020015#include <memory>
philipelcce46fc2015-12-21 03:04:49 -080016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/video_coding/include/video_codec_interface.h"
18#include "rtc_base/checks.h"
Ilya Nikolaevskiy58662912017-10-04 15:07:09 +020019#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "system_wrappers/include/clock.h"
21#include "system_wrappers/include/metrics.h"
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000022
23namespace webrtc {
Erik Språng59021ba2018-10-03 11:05:16 +020024namespace {
Erik Språng2c4c9142015-06-24 11:24:44 +020025static const int kOneSecond90Khz = 90000;
Erik Språng13044c12017-10-05 12:20:36 +020026static const int kMinTimeBetweenSyncs = kOneSecond90Khz * 2;
27static const int kMaxTimeBetweenSyncs = kOneSecond90Khz * 4;
Erik Språng2c4c9142015-06-24 11:24:44 +020028static const int kQpDeltaThresholdForSync = 8;
sprang916170a2017-05-23 07:47:55 -070029static const int kMinBitrateKbpsForQpBoost = 500;
Erik Språng59021ba2018-10-03 11:05:16 +020030} // namespace
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000031
sprang@webrtc.org70f74f32014-12-17 10:57:10 +000032const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5;
33const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
34
sprang429600d2017-01-26 06:12:26 -080035constexpr int ScreenshareLayers::kMaxNumTemporalLayers;
36
sprangafe1f742016-04-12 02:45:13 -070037// Always emit a frame with certain interval, even if bitrate targets have
sprang916170a2017-05-23 07:47:55 -070038// been exceeded. This prevents needless keyframe requests.
sprang6c4bbfa2017-05-30 10:08:23 -070039const int ScreenshareLayers::kMaxFrameIntervalMs = 2750;
sprangafe1f742016-04-12 02:45:13 -070040
Erik Språng59021ba2018-10-03 11:05:16 +020041ScreenshareLayers::ScreenshareLayers(int num_temporal_layers, Clock* clock)
sprangb0fdfea2016-03-01 05:51:16 -080042 : clock_(clock),
sprang429600d2017-01-26 06:12:26 -080043 number_of_temporal_layers_(
44 std::min(kMaxNumTemporalLayers, num_temporal_layers)),
Erik Språng2c4c9142015-06-24 11:24:44 +020045 active_layer_(-1),
46 last_timestamp_(-1),
47 last_sync_timestamp_(-1),
sprangafe1f742016-04-12 02:45:13 -070048 last_emitted_tl0_timestamp_(-1),
Erik Språng27a457d2018-01-12 11:00:21 +010049 last_frame_time_ms_(-1),
Erik Språng2c4c9142015-06-24 11:24:44 +020050 min_qp_(-1),
51 max_qp_(-1),
52 max_debt_bytes_(0),
sprangac4a90d2016-12-28 05:58:07 -080053 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale.
Erik Språng59021ba2018-10-03 11:05:16 +020054 bitrate_updated_(false),
55 checker_(TemporalLayersChecker::CreateTemporalLayersChecker(
Erik Språng4529fbc2018-10-12 10:30:31 +020056 Vp8TemporalLayersType::kBitrateDynamic,
Erik Språng59021ba2018-10-03 11:05:16 +020057 num_temporal_layers)) {
sprang429600d2017-01-26 06:12:26 -080058 RTC_CHECK_GT(number_of_temporal_layers_, 0);
59 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000060}
61
sprangb0fdfea2016-03-01 05:51:16 -080062ScreenshareLayers::~ScreenshareLayers() {
63 UpdateHistograms();
64}
65
Erik Språngfb2a66a2018-09-10 10:48:01 +020066bool ScreenshareLayers::SupportsEncoderFrameDropping() const {
67 // Frame dropping is handled internally by this class.
68 return false;
69}
70
Erik Språng4529fbc2018-10-12 10:30:31 +020071Vp8TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
pbos18ad1d42017-05-04 05:04:46 -070072 uint32_t timestamp) {
Erik Språng59021ba2018-10-03 11:05:16 +020073 auto it = pending_frame_configs_.find(timestamp);
74 if (it != pending_frame_configs_.end()) {
75 // Drop and re-encode, reuse the previous config.
76 return it->second;
77 }
78
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000079 if (number_of_temporal_layers_ <= 1) {
80 // No flags needed for 1 layer screenshare.
Peter Boström1436c832017-03-27 15:01:49 -040081 // TODO(pbos): Consider updating only last, and not all buffers.
Erik Språng4529fbc2018-10-12 10:30:31 +020082 Vp8TemporalLayers::FrameConfig tl_config(
pbos51f083c2017-05-04 06:39:04 -070083 kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate);
Erik Språng59021ba2018-10-03 11:05:16 +020084 pending_frame_configs_[timestamp] = tl_config;
pbos51f083c2017-05-04 06:39:04 -070085 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000086 }
Erik Språng2c4c9142015-06-24 11:24:44 +020087
sprangac4a90d2016-12-28 05:58:07 -080088 const int64_t now_ms = clock_->TimeInMilliseconds();
sprangb0fdfea2016-03-01 05:51:16 -080089
Erik Språng2c4c9142015-06-24 11:24:44 +020090 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
sprang916170a2017-05-23 07:47:55 -070091 int64_t ts_diff;
92 if (last_timestamp_ == -1) {
93 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
94 } else {
95 ts_diff = unwrapped_timestamp - last_timestamp_;
96 }
Erik Språng27a457d2018-01-12 11:00:21 +010097
98 if (target_framerate_) {
99 // If input frame rate exceeds target frame rate, either over a one second
100 // averaging window, or if frame interval is below 90% of desired value,
101 // drop frame.
Erik Språng27a457d2018-01-12 11:00:21 +0100102 if (encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_)
Erik Språng4529fbc2018-10-12 10:30:31 +0200103 return Vp8TemporalLayers::FrameConfig(kNone, kNone, kNone);
Erik Språng27a457d2018-01-12 11:00:21 +0100104
Erik Språngdb9e9d52018-01-22 09:23:11 -0800105 // Primarily check if frame interval is too short using frame timestamps,
106 // as if they are correct they won't be affected by queuing in webrtc.
107 const int64_t expected_frame_interval_90khz =
108 kOneSecond90Khz / *target_framerate_;
109 if (last_timestamp_ != -1 && ts_diff > 0) {
110 if (ts_diff < 85 * expected_frame_interval_90khz / 100) {
Erik Språng4529fbc2018-10-12 10:30:31 +0200111 return Vp8TemporalLayers::FrameConfig(kNone, kNone, kNone);
Erik Språngdb9e9d52018-01-22 09:23:11 -0800112 }
113 } else {
114 // Timestamps looks off, use realtime clock here instead.
115 const int64_t expected_frame_interval_ms = 1000 / *target_framerate_;
116 if (last_frame_time_ms_ != -1 &&
117 now_ms - last_frame_time_ms_ <
118 (85 * expected_frame_interval_ms) / 100) {
Erik Språng4529fbc2018-10-12 10:30:31 +0200119 return Vp8TemporalLayers::FrameConfig(kNone, kNone, kNone);
Erik Språngdb9e9d52018-01-22 09:23:11 -0800120 }
Erik Språng27a457d2018-01-12 11:00:21 +0100121 }
122 }
123
124 if (stats_.first_frame_time_ms_ == -1)
125 stats_.first_frame_time_ms_ = now_ms;
126
sprang916170a2017-05-23 07:47:55 -0700127 // Make sure both frame droppers leak out bits.
128 layers_[0].UpdateDebt(ts_diff / 90);
129 layers_[1].UpdateDebt(ts_diff / 90);
130 last_timestamp_ = timestamp;
Erik Språng27a457d2018-01-12 11:00:21 +0100131 last_frame_time_ms_ = now_ms;
sprang916170a2017-05-23 07:47:55 -0700132
133 TemporalLayerState layer_state = TemporalLayerState::kDrop;
134
Erik Språng2c4c9142015-06-24 11:24:44 +0200135 if (active_layer_ == -1 ||
136 layers_[active_layer_].state != TemporalLayer::State::kDropped) {
sprangafe1f742016-04-12 02:45:13 -0700137 if (last_emitted_tl0_timestamp_ != -1 &&
138 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
139 kMaxFrameIntervalMs) {
140 // Too long time has passed since the last frame was emitted, cancel
141 // enough debt to allow a single frame.
142 layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
143 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200144 if (layers_[0].debt_bytes_ > max_debt_bytes_) {
145 // Must drop TL0, encode TL1 instead.
146 if (layers_[1].debt_bytes_ > max_debt_bytes_) {
147 // Must drop both TL0 and TL1.
148 active_layer_ = -1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000149 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200150 active_layer_ = 1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000151 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200152 } else {
153 active_layer_ = 0;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000154 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000155 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200156
157 switch (active_layer_) {
158 case 0:
sprang916170a2017-05-23 07:47:55 -0700159 layer_state = TemporalLayerState::kTl0;
sprangafe1f742016-04-12 02:45:13 -0700160 last_emitted_tl0_timestamp_ = unwrapped_timestamp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200161 break;
162 case 1:
sprangf03ea042017-07-13 03:53:51 -0700163 if (layers_[1].state != TemporalLayer::State::kDropped) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200164 if (TimeToSync(unwrapped_timestamp) ||
165 layers_[1].state == TemporalLayer::State::kKeyFrame) {
sprangf03ea042017-07-13 03:53:51 -0700166 last_sync_timestamp_ = unwrapped_timestamp;
167 layer_state = TemporalLayerState::kTl1Sync;
168 } else {
169 layer_state = TemporalLayerState::kTl1;
170 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200171 } else {
sprangf03ea042017-07-13 03:53:51 -0700172 layer_state = last_sync_timestamp_ == unwrapped_timestamp
173 ? TemporalLayerState::kTl1Sync
174 : TemporalLayerState::kTl1;
Erik Språng2c4c9142015-06-24 11:24:44 +0200175 }
176 break;
177 case -1:
sprang916170a2017-05-23 07:47:55 -0700178 layer_state = TemporalLayerState::kDrop;
sprangb0fdfea2016-03-01 05:51:16 -0800179 ++stats_.num_dropped_frames_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200180 break;
181 default:
Erik Språng2c4c9142015-06-24 11:24:44 +0200182 RTC_NOTREACHED();
183 }
184
Erik Språng4529fbc2018-10-12 10:30:31 +0200185 Vp8TemporalLayers::FrameConfig tl_config;
Peter Boström1436c832017-03-27 15:01:49 -0400186 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
187 // layers.
188 switch (layer_state) {
sprang916170a2017-05-23 07:47:55 -0700189 case TemporalLayerState::kDrop:
Erik Språng4529fbc2018-10-12 10:30:31 +0200190 tl_config = Vp8TemporalLayers::FrameConfig(kNone, kNone, kNone);
pbos51f083c2017-05-04 06:39:04 -0700191 break;
sprang916170a2017-05-23 07:47:55 -0700192 case TemporalLayerState::kTl0:
Peter Boström1436c832017-03-27 15:01:49 -0400193 // TL0 only references and updates 'last'.
pbos51f083c2017-05-04 06:39:04 -0700194 tl_config =
Erik Språng4529fbc2018-10-12 10:30:31 +0200195 Vp8TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700196 tl_config.packetizer_temporal_idx = 0;
pbos51f083c2017-05-04 06:39:04 -0700197 break;
sprang916170a2017-05-23 07:47:55 -0700198 case TemporalLayerState::kTl1:
Peter Boström1436c832017-03-27 15:01:49 -0400199 // TL1 references both 'last' and 'golden' but only updates 'golden'.
Erik Språng4529fbc2018-10-12 10:30:31 +0200200 tl_config = Vp8TemporalLayers::FrameConfig(kReference,
201 kReferenceAndUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700202 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700203 break;
sprang916170a2017-05-23 07:47:55 -0700204 case TemporalLayerState::kTl1Sync:
Peter Boström1436c832017-03-27 15:01:49 -0400205 // Predict from only TL0 to allow participants to switch to the high
206 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
207 // and update 'golden' from this point on.
Erik Språng4529fbc2018-10-12 10:30:31 +0200208 tl_config = Vp8TemporalLayers::FrameConfig(kReference, kUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700209 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700210 break;
Peter Boström1436c832017-03-27 15:01:49 -0400211 }
pbos51f083c2017-05-04 06:39:04 -0700212
pbos1777c5f2017-07-19 17:04:02 -0700213 tl_config.layer_sync = layer_state == TemporalLayerState::kTl1Sync;
Erik Språng59021ba2018-10-03 11:05:16 +0200214 pending_frame_configs_[timestamp] = tl_config;
pbos51f083c2017-05-04 06:39:04 -0700215 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000216}
217
Erik Språngbb60a3a2018-03-19 18:25:10 +0100218void ScreenshareLayers::OnRatesUpdated(
219 const std::vector<uint32_t>& bitrates_bps,
220 int framerate_fps) {
221 RTC_DCHECK_GT(framerate_fps, 0);
222 RTC_DCHECK_GE(bitrates_bps.size(), 1);
223 RTC_DCHECK_LE(bitrates_bps.size(), 2);
224
225 // |bitrates_bps| uses individual rates per layer, but we want to use the
226 // accumulated rate here.
227 uint32_t tl0_kbps = bitrates_bps[0] / 1000;
228 uint32_t tl1_kbps = tl0_kbps;
229 if (bitrates_bps.size() > 1) {
230 tl1_kbps += bitrates_bps[1] / 1000;
231 }
232
sprangac4a90d2016-12-28 05:58:07 -0800233 if (!target_framerate_) {
Erik Språngbb60a3a2018-03-19 18:25:10 +0100234 // First OnRatesUpdated() is called during construction, with the
235 // configured targets as parameters.
236 target_framerate_ = framerate_fps;
sprang0ad0de62017-01-11 05:01:32 -0800237 capture_framerate_ = target_framerate_;
sprangac4a90d2016-12-28 05:58:07 -0800238 bitrate_updated_ = true;
239 } else {
Erik Språnge624d072018-04-11 16:47:27 +0200240 if ((capture_framerate_ &&
241 framerate_fps != static_cast<int>(*capture_framerate_)) ||
242 (tl0_kbps != layers_[0].target_rate_kbps_) ||
243 (tl1_kbps != layers_[1].target_rate_kbps_)) {
244 bitrate_updated_ = true;
245 }
Erik Språngbb60a3a2018-03-19 18:25:10 +0100246
247 if (framerate_fps < 0) {
sprang0ad0de62017-01-11 05:01:32 -0800248 capture_framerate_.reset();
sprangac4a90d2016-12-28 05:58:07 -0800249 } else {
Erik Språngbb60a3a2018-03-19 18:25:10 +0100250 capture_framerate_ = framerate_fps;
sprangac4a90d2016-12-28 05:58:07 -0800251 }
252 }
253
Erik Språngbb60a3a2018-03-19 18:25:10 +0100254 layers_[0].target_rate_kbps_ = tl0_kbps;
255 layers_[1].target_rate_kbps_ = tl1_kbps;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000256}
257
Erik Språng59021ba2018-10-03 11:05:16 +0200258void ScreenshareLayers::OnEncodeDone(uint32_t rtp_timestamp,
259 size_t size_bytes,
260 bool is_keyframe,
261 int qp,
262 CodecSpecificInfoVP8* vp8_info) {
263 if (size_bytes == 0) {
Erik Språng2c4c9142015-06-24 11:24:44 +0200264 layers_[active_layer_].state = TemporalLayer::State::kDropped;
sprangb0fdfea2016-03-01 05:51:16 -0800265 ++stats_.num_overshoots_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200266 return;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000267 }
sprangef7228c2015-08-05 02:01:29 -0700268
Erik Språng59021ba2018-10-03 11:05:16 +0200269 absl::optional<FrameConfig> frame_config;
270 auto it = pending_frame_configs_.find(rtp_timestamp);
271 if (it != pending_frame_configs_.end()) {
272 frame_config = it->second;
273 pending_frame_configs_.erase(it);
274
275 if (checker_) {
276 RTC_DCHECK(checker_->CheckTemporalConfig(is_keyframe, *frame_config));
277 }
278 }
279
280 if (number_of_temporal_layers_ == 1) {
281 vp8_info->temporalIdx = kNoTemporalIdx;
282 vp8_info->layerSync = false;
283 } else {
284 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(rtp_timestamp);
285 if (frame_config) {
286 vp8_info->temporalIdx = frame_config->packetizer_temporal_idx;
287 vp8_info->layerSync = frame_config->layer_sync;
288 } else {
289 // Frame requested to be dropped, but was not. Fall back to base-layer.
290 vp8_info->temporalIdx = 0;
291 vp8_info->layerSync = false;
292 }
293 if (is_keyframe) {
294 vp8_info->temporalIdx = 0;
295 last_sync_timestamp_ = unwrapped_timestamp;
296 vp8_info->layerSync = true;
297 layers_[0].state = TemporalLayer::State::kKeyFrame;
298 layers_[1].state = TemporalLayer::State::kKeyFrame;
299 active_layer_ = 1;
300 }
301 }
302
303 encode_framerate_.Update(1, clock_->TimeInMilliseconds());
304
305 if (number_of_temporal_layers_ == 1)
306 return;
307
308 RTC_DCHECK_NE(-1, active_layer_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200309 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
310 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
311 }
312
313 if (qp != -1)
314 layers_[active_layer_].last_qp = qp;
315
316 if (active_layer_ == 0) {
Erik Språng59021ba2018-10-03 11:05:16 +0200317 layers_[0].debt_bytes_ += size_bytes;
318 layers_[1].debt_bytes_ += size_bytes;
sprangb0fdfea2016-03-01 05:51:16 -0800319 ++stats_.num_tl0_frames_;
320 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
321 stats_.tl0_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200322 } else if (active_layer_ == 1) {
Erik Språng59021ba2018-10-03 11:05:16 +0200323 layers_[1].debt_bytes_ += size_bytes;
sprangb0fdfea2016-03-01 05:51:16 -0800324 ++stats_.num_tl1_frames_;
325 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
326 stats_.tl1_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200327 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000328}
329
Erik Språng2c4c9142015-06-24 11:24:44 +0200330bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
sprang2ddb8bd2016-02-04 03:59:52 -0800331 RTC_DCHECK_EQ(1, active_layer_);
henrikg91d6ede2015-09-17 00:24:34 -0700332 RTC_DCHECK_NE(-1, layers_[0].last_qp);
Erik Språng2c4c9142015-06-24 11:24:44 +0200333 if (layers_[1].last_qp == -1) {
334 // First frame in TL1 should only depend on TL0 since there are no
335 // previous frames in TL1.
336 return true;
337 }
338
henrikg91d6ede2015-09-17 00:24:34 -0700339 RTC_DCHECK_NE(-1, last_sync_timestamp_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200340 int64_t timestamp_diff = timestamp - last_sync_timestamp_;
341 if (timestamp_diff > kMaxTimeBetweenSyncs) {
342 // After a certain time, force a sync frame.
343 return true;
344 } else if (timestamp_diff < kMinTimeBetweenSyncs) {
345 // If too soon from previous sync frame, don't issue a new one.
346 return false;
347 }
348 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too
349 // large.
350 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync)
351 return true;
352 return false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000353}
354
sprangc7805db2016-11-25 08:09:43 -0800355uint32_t ScreenshareLayers::GetCodecTargetBitrateKbps() const {
356 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
357
358 if (number_of_temporal_layers_ > 1) {
359 // Calculate a codec target bitrate. This may be higher than TL0, gaining
360 // quality at the expense of frame rate at TL0. Constraints:
361 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
362 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
363 target_bitrate_kbps =
364 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
365 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
366 }
367
368 return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
369}
370
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100371bool ScreenshareLayers::UpdateConfiguration(Vp8EncoderConfig* cfg) {
Erik Språngf1414702018-09-12 15:04:08 +0200372 if (min_qp_ == -1 || max_qp_ == -1) {
373 // Store the valid qp range. This must not change during the lifetime of
374 // this class.
375 min_qp_ = cfg->rc_min_quantizer;
376 max_qp_ = cfg->rc_max_quantizer;
377 }
378
Erik Språng08127a92016-11-16 16:41:30 +0100379 bool cfg_updated = false;
sprangc7805db2016-11-25 08:09:43 -0800380 uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
Erik Språng27a457d2018-01-12 11:00:21 +0100381
382 // TODO(sprang): We _really_ need to make an overhaul of this class. :(
383 // If we're dropping frames in order to meet a target framerate, adjust the
384 // bitrate assigned to the encoder so the total average bitrate is correct.
385 float encoder_config_bitrate_kbps = target_bitrate_kbps;
386 if (target_framerate_ && capture_framerate_ &&
387 *target_framerate_ < *capture_framerate_) {
388 encoder_config_bitrate_kbps *=
389 static_cast<float>(*capture_framerate_) / *target_framerate_;
390 }
391
392 if (bitrate_updated_ ||
393 cfg->rc_target_bitrate != encoder_config_bitrate_kbps) {
394 cfg->rc_target_bitrate = encoder_config_bitrate_kbps;
Erik Språng08127a92016-11-16 16:41:30 +0100395
396 // Don't reconfigure qp limits during quality boost frames.
397 if (active_layer_ == -1 ||
398 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
Erik Språng08127a92016-11-16 16:41:30 +0100399 // After a dropped frame, a frame with max qp will be encoded and the
400 // quality will then ramp up from there. To boost the speed of recovery,
sprang916170a2017-05-23 07:47:55 -0700401 // encode the next frame with lower max qp, if there is sufficient
402 // bandwidth to do so without causing excessive delay.
403 // TL0 is the most important to improve since the errors in this layer
404 // will propagate to TL1.
Erik Språng08127a92016-11-16 16:41:30 +0100405 // Currently, reduce max qp by 20% for TL0 and 15% for TL1.
sprang916170a2017-05-23 07:47:55 -0700406 if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
407 layers_[0].enhanced_max_qp =
408 min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
409 layers_[1].enhanced_max_qp =
410 min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
411 } else {
412 layers_[0].enhanced_max_qp = -1;
413 layers_[1].enhanced_max_qp = -1;
414 }
Erik Språng08127a92016-11-16 16:41:30 +0100415 }
416
sprang0ad0de62017-01-11 05:01:32 -0800417 if (capture_framerate_) {
sprangac4a90d2016-12-28 05:58:07 -0800418 int avg_frame_size =
sprang0ad0de62017-01-11 05:01:32 -0800419 (target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
sprang916170a2017-05-23 07:47:55 -0700420 // Allow max debt to be the size of a single optimal frame.
421 // TODO(sprang): Determine if this needs to be adjusted by some factor.
422 // (Lower values may cause more frame drops, higher may lead to queuing
423 // delays.)
424 max_debt_bytes_ = avg_frame_size;
Erik Språng08127a92016-11-16 16:41:30 +0100425 }
426
427 bitrate_updated_ = false;
428 cfg_updated = true;
429 }
430
431 // Don't try to update boosts state if not active yet.
432 if (active_layer_ == -1)
433 return cfg_updated;
434
sprangef7228c2015-08-05 02:01:29 -0700435 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1)
Erik Språng08127a92016-11-16 16:41:30 +0100436 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200437
438 // If layer is in the quality boost state (following a dropped frame), update
439 // the configuration with the adjusted (lower) qp and set the state back to
440 // normal.
Erik Språngf1414702018-09-12 15:04:08 +0200441 unsigned int adjusted_max_qp = max_qp_; // Set the normal max qp.
442 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost) {
443 if (layers_[active_layer_].enhanced_max_qp != -1) {
444 // Bitrate is high enough for quality boost, update max qp.
445 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
446 }
447 // Regardless of qp, reset the boost state for the next frame.
Erik Språng2c4c9142015-06-24 11:24:44 +0200448 layers_[active_layer_].state = TemporalLayer::State::kNormal;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000449 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200450
451 if (adjusted_max_qp == cfg->rc_max_quantizer)
Erik Språng08127a92016-11-16 16:41:30 +0100452 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200453
454 cfg->rc_max_quantizer = adjusted_max_qp;
Erik Språng08127a92016-11-16 16:41:30 +0100455 cfg_updated = true;
sprangc7805db2016-11-25 08:09:43 -0800456
Erik Språng08127a92016-11-16 16:41:30 +0100457 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200458}
459
460void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
461 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
462 if (debt_reduction_bytes >= debt_bytes_) {
463 debt_bytes_ = 0;
464 } else {
465 debt_bytes_ -= debt_reduction_bytes;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000466 }
467}
sprang@webrtc.org70f74f32014-12-17 10:57:10 +0000468
sprangb0fdfea2016-03-01 05:51:16 -0800469void ScreenshareLayers::UpdateHistograms() {
470 if (stats_.first_frame_time_ms_ == -1)
471 return;
472 int64_t duration_sec =
473 (clock_->TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) / 1000;
474 if (duration_sec >= metrics::kMinRunTimeInSeconds) {
475 RTC_HISTOGRAM_COUNTS_10000(
476 "WebRTC.Video.Screenshare.Layer0.FrameRate",
477 (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
478 RTC_HISTOGRAM_COUNTS_10000(
479 "WebRTC.Video.Screenshare.Layer1.FrameRate",
480 (stats_.num_tl1_frames_ + (duration_sec / 2)) / duration_sec);
481 int total_frames = stats_.num_tl0_frames_ + stats_.num_tl1_frames_;
asapersson58d992e2016-03-29 02:15:06 -0700482 RTC_HISTOGRAM_COUNTS_10000(
483 "WebRTC.Video.Screenshare.FramesPerDrop",
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200484 (stats_.num_dropped_frames_ == 0
485 ? 0
486 : total_frames / stats_.num_dropped_frames_));
asapersson58d992e2016-03-29 02:15:06 -0700487 RTC_HISTOGRAM_COUNTS_10000(
488 "WebRTC.Video.Screenshare.FramesPerOvershoot",
489 (stats_.num_overshoots_ == 0 ? 0
490 : total_frames / stats_.num_overshoots_));
sprangb0fdfea2016-03-01 05:51:16 -0800491 if (stats_.num_tl0_frames_ > 0) {
492 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer0.Qp",
493 stats_.tl0_qp_sum_ / stats_.num_tl0_frames_);
494 RTC_HISTOGRAM_COUNTS_10000(
495 "WebRTC.Video.Screenshare.Layer0.TargetBitrate",
496 stats_.tl0_target_bitrate_sum_ / stats_.num_tl0_frames_);
497 }
498 if (stats_.num_tl1_frames_ > 0) {
499 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
500 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
501 RTC_HISTOGRAM_COUNTS_10000(
502 "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
503 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
504 }
505 }
506}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000507} // namespace webrtc