blob: cd2449052bf8fcd94d2646ec2b42151a1ccf33a6 [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 {
24
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;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000030
sprang@webrtc.org70f74f32014-12-17 10:57:10 +000031const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5;
32const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
33
sprang429600d2017-01-26 06:12:26 -080034constexpr int ScreenshareLayers::kMaxNumTemporalLayers;
35
sprangafe1f742016-04-12 02:45:13 -070036// Always emit a frame with certain interval, even if bitrate targets have
sprang916170a2017-05-23 07:47:55 -070037// been exceeded. This prevents needless keyframe requests.
sprang6c4bbfa2017-05-30 10:08:23 -070038const int ScreenshareLayers::kMaxFrameIntervalMs = 2750;
sprangafe1f742016-04-12 02:45:13 -070039
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000040ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
sprangb0fdfea2016-03-01 05:51:16 -080041 Clock* clock)
42 : clock_(clock),
sprang429600d2017-01-26 06:12:26 -080043 number_of_temporal_layers_(
44 std::min(kMaxNumTemporalLayers, num_temporal_layers)),
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000045 last_base_layer_sync_(false),
Erik Språng2c4c9142015-06-24 11:24:44 +020046 active_layer_(-1),
47 last_timestamp_(-1),
48 last_sync_timestamp_(-1),
sprangafe1f742016-04-12 02:45:13 -070049 last_emitted_tl0_timestamp_(-1),
Erik Språng27a457d2018-01-12 11:00:21 +010050 last_frame_time_ms_(-1),
Erik Språng2c4c9142015-06-24 11:24:44 +020051 min_qp_(-1),
52 max_qp_(-1),
53 max_debt_bytes_(0),
sprangac4a90d2016-12-28 05:58:07 -080054 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale.
Erik Språng08127a92016-11-16 16:41:30 +010055 bitrate_updated_(false) {
sprang429600d2017-01-26 06:12:26 -080056 RTC_CHECK_GT(number_of_temporal_layers_, 0);
57 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000058}
59
sprangb0fdfea2016-03-01 05:51:16 -080060ScreenshareLayers::~ScreenshareLayers() {
61 UpdateHistograms();
62}
63
pbos18ad1d42017-05-04 05:04:46 -070064TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
65 uint32_t timestamp) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000066 if (number_of_temporal_layers_ <= 1) {
67 // No flags needed for 1 layer screenshare.
Peter Boström1436c832017-03-27 15:01:49 -040068 // TODO(pbos): Consider updating only last, and not all buffers.
pbos51f083c2017-05-04 06:39:04 -070069 TemporalLayers::FrameConfig tl_config(
70 kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate);
pbos51f083c2017-05-04 06:39:04 -070071 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000072 }
Erik Språng2c4c9142015-06-24 11:24:44 +020073
sprangac4a90d2016-12-28 05:58:07 -080074 const int64_t now_ms = clock_->TimeInMilliseconds();
sprangb0fdfea2016-03-01 05:51:16 -080075
Erik Språng2c4c9142015-06-24 11:24:44 +020076 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
sprang916170a2017-05-23 07:47:55 -070077 int64_t ts_diff;
78 if (last_timestamp_ == -1) {
79 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
80 } else {
81 ts_diff = unwrapped_timestamp - last_timestamp_;
82 }
Erik Språng27a457d2018-01-12 11:00:21 +010083
84 if (target_framerate_) {
85 // If input frame rate exceeds target frame rate, either over a one second
86 // averaging window, or if frame interval is below 90% of desired value,
87 // drop frame.
Erik Språng27a457d2018-01-12 11:00:21 +010088 if (encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_)
89 return TemporalLayers::FrameConfig(kNone, kNone, kNone);
90
Erik Språngdb9e9d52018-01-22 09:23:11 -080091 // Primarily check if frame interval is too short using frame timestamps,
92 // as if they are correct they won't be affected by queuing in webrtc.
93 const int64_t expected_frame_interval_90khz =
94 kOneSecond90Khz / *target_framerate_;
95 if (last_timestamp_ != -1 && ts_diff > 0) {
96 if (ts_diff < 85 * expected_frame_interval_90khz / 100) {
97 return TemporalLayers::FrameConfig(kNone, kNone, kNone);
98 }
99 } else {
100 // Timestamps looks off, use realtime clock here instead.
101 const int64_t expected_frame_interval_ms = 1000 / *target_framerate_;
102 if (last_frame_time_ms_ != -1 &&
103 now_ms - last_frame_time_ms_ <
104 (85 * expected_frame_interval_ms) / 100) {
105 return TemporalLayers::FrameConfig(kNone, kNone, kNone);
106 }
Erik Språng27a457d2018-01-12 11:00:21 +0100107 }
108 }
109
110 if (stats_.first_frame_time_ms_ == -1)
111 stats_.first_frame_time_ms_ = now_ms;
112
sprang916170a2017-05-23 07:47:55 -0700113 // Make sure both frame droppers leak out bits.
114 layers_[0].UpdateDebt(ts_diff / 90);
115 layers_[1].UpdateDebt(ts_diff / 90);
116 last_timestamp_ = timestamp;
Erik Språng27a457d2018-01-12 11:00:21 +0100117 last_frame_time_ms_ = now_ms;
sprang916170a2017-05-23 07:47:55 -0700118
119 TemporalLayerState layer_state = TemporalLayerState::kDrop;
120
Erik Språng2c4c9142015-06-24 11:24:44 +0200121 if (active_layer_ == -1 ||
122 layers_[active_layer_].state != TemporalLayer::State::kDropped) {
sprangafe1f742016-04-12 02:45:13 -0700123 if (last_emitted_tl0_timestamp_ != -1 &&
124 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
125 kMaxFrameIntervalMs) {
126 // Too long time has passed since the last frame was emitted, cancel
127 // enough debt to allow a single frame.
128 layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
129 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200130 if (layers_[0].debt_bytes_ > max_debt_bytes_) {
131 // Must drop TL0, encode TL1 instead.
132 if (layers_[1].debt_bytes_ > max_debt_bytes_) {
133 // Must drop both TL0 and TL1.
134 active_layer_ = -1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000135 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200136 active_layer_ = 1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000137 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200138 } else {
139 active_layer_ = 0;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000140 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000141 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200142
143 switch (active_layer_) {
144 case 0:
sprang916170a2017-05-23 07:47:55 -0700145 layer_state = TemporalLayerState::kTl0;
sprangafe1f742016-04-12 02:45:13 -0700146 last_emitted_tl0_timestamp_ = unwrapped_timestamp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200147 break;
148 case 1:
sprangf03ea042017-07-13 03:53:51 -0700149 if (layers_[1].state != TemporalLayer::State::kDropped) {
150 if (TimeToSync(unwrapped_timestamp)) {
151 last_sync_timestamp_ = unwrapped_timestamp;
152 layer_state = TemporalLayerState::kTl1Sync;
153 } else {
154 layer_state = TemporalLayerState::kTl1;
155 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200156 } else {
sprangf03ea042017-07-13 03:53:51 -0700157 layer_state = last_sync_timestamp_ == unwrapped_timestamp
158 ? TemporalLayerState::kTl1Sync
159 : TemporalLayerState::kTl1;
Erik Språng2c4c9142015-06-24 11:24:44 +0200160 }
161 break;
162 case -1:
sprang916170a2017-05-23 07:47:55 -0700163 layer_state = TemporalLayerState::kDrop;
sprangb0fdfea2016-03-01 05:51:16 -0800164 ++stats_.num_dropped_frames_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200165 break;
166 default:
Erik Språng2c4c9142015-06-24 11:24:44 +0200167 RTC_NOTREACHED();
168 }
169
pbos51f083c2017-05-04 06:39:04 -0700170 TemporalLayers::FrameConfig tl_config;
Peter Boström1436c832017-03-27 15:01:49 -0400171 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
172 // layers.
173 switch (layer_state) {
sprang916170a2017-05-23 07:47:55 -0700174 case TemporalLayerState::kDrop:
pbos51f083c2017-05-04 06:39:04 -0700175 tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone);
176 break;
sprang916170a2017-05-23 07:47:55 -0700177 case TemporalLayerState::kTl0:
Peter Boström1436c832017-03-27 15:01:49 -0400178 // TL0 only references and updates 'last'.
pbos51f083c2017-05-04 06:39:04 -0700179 tl_config =
180 TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700181 tl_config.packetizer_temporal_idx = 0;
pbos51f083c2017-05-04 06:39:04 -0700182 break;
sprang916170a2017-05-23 07:47:55 -0700183 case TemporalLayerState::kTl1:
Peter Boström1436c832017-03-27 15:01:49 -0400184 // TL1 references both 'last' and 'golden' but only updates 'golden'.
pbos51f083c2017-05-04 06:39:04 -0700185 tl_config =
186 TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700187 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700188 break;
sprang916170a2017-05-23 07:47:55 -0700189 case TemporalLayerState::kTl1Sync:
Peter Boström1436c832017-03-27 15:01:49 -0400190 // Predict from only TL0 to allow participants to switch to the high
191 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
192 // and update 'golden' from this point on.
pbos51f083c2017-05-04 06:39:04 -0700193 tl_config = TemporalLayers::FrameConfig(kReference, kUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700194 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700195 break;
Peter Boström1436c832017-03-27 15:01:49 -0400196 }
pbos51f083c2017-05-04 06:39:04 -0700197
pbos1777c5f2017-07-19 17:04:02 -0700198 tl_config.layer_sync = layer_state == TemporalLayerState::kTl1Sync;
pbos51f083c2017-05-04 06:39:04 -0700199 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000200}
201
Erik Språngbb60a3a2018-03-19 18:25:10 +0100202void ScreenshareLayers::OnRatesUpdated(
203 const std::vector<uint32_t>& bitrates_bps,
204 int framerate_fps) {
205 RTC_DCHECK_GT(framerate_fps, 0);
206 RTC_DCHECK_GE(bitrates_bps.size(), 1);
207 RTC_DCHECK_LE(bitrates_bps.size(), 2);
208
209 // |bitrates_bps| uses individual rates per layer, but we want to use the
210 // accumulated rate here.
211 uint32_t tl0_kbps = bitrates_bps[0] / 1000;
212 uint32_t tl1_kbps = tl0_kbps;
213 if (bitrates_bps.size() > 1) {
214 tl1_kbps += bitrates_bps[1] / 1000;
215 }
216
sprangac4a90d2016-12-28 05:58:07 -0800217 if (!target_framerate_) {
Erik Språngbb60a3a2018-03-19 18:25:10 +0100218 // First OnRatesUpdated() is called during construction, with the
219 // configured targets as parameters.
220 target_framerate_ = framerate_fps;
sprang0ad0de62017-01-11 05:01:32 -0800221 capture_framerate_ = target_framerate_;
sprangac4a90d2016-12-28 05:58:07 -0800222 bitrate_updated_ = true;
223 } else {
Erik Språnge624d072018-04-11 16:47:27 +0200224 if ((capture_framerate_ &&
225 framerate_fps != static_cast<int>(*capture_framerate_)) ||
226 (tl0_kbps != layers_[0].target_rate_kbps_) ||
227 (tl1_kbps != layers_[1].target_rate_kbps_)) {
228 bitrate_updated_ = true;
229 }
Erik Språngbb60a3a2018-03-19 18:25:10 +0100230
231 if (framerate_fps < 0) {
sprang0ad0de62017-01-11 05:01:32 -0800232 capture_framerate_.reset();
sprangac4a90d2016-12-28 05:58:07 -0800233 } else {
Erik Språngbb60a3a2018-03-19 18:25:10 +0100234 capture_framerate_ = framerate_fps;
sprangac4a90d2016-12-28 05:58:07 -0800235 }
236 }
237
Erik Språngbb60a3a2018-03-19 18:25:10 +0100238 layers_[0].target_rate_kbps_ = tl0_kbps;
239 layers_[1].target_rate_kbps_ = tl1_kbps;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000240}
241
Peter Boström1436c832017-03-27 15:01:49 -0400242void ScreenshareLayers::FrameEncoded(unsigned int size, int qp) {
sprangac4a90d2016-12-28 05:58:07 -0800243 if (size > 0)
244 encode_framerate_.Update(1, clock_->TimeInMilliseconds());
245
sprang2ddb8bd2016-02-04 03:59:52 -0800246 if (number_of_temporal_layers_ == 1)
247 return;
248
249 RTC_DCHECK_NE(-1, active_layer_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200250 if (size == 0) {
251 layers_[active_layer_].state = TemporalLayer::State::kDropped;
sprangb0fdfea2016-03-01 05:51:16 -0800252 ++stats_.num_overshoots_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200253 return;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000254 }
sprangef7228c2015-08-05 02:01:29 -0700255
Erik Språng2c4c9142015-06-24 11:24:44 +0200256 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
257 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
258 }
259
260 if (qp != -1)
261 layers_[active_layer_].last_qp = qp;
262
263 if (active_layer_ == 0) {
264 layers_[0].debt_bytes_ += size;
265 layers_[1].debt_bytes_ += size;
sprangb0fdfea2016-03-01 05:51:16 -0800266 ++stats_.num_tl0_frames_;
267 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
268 stats_.tl0_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200269 } else if (active_layer_ == 1) {
270 layers_[1].debt_bytes_ += size;
sprangb0fdfea2016-03-01 05:51:16 -0800271 ++stats_.num_tl1_frames_;
272 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
273 stats_.tl1_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200274 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000275}
276
pbos18ad1d42017-05-04 05:04:46 -0700277void ScreenshareLayers::PopulateCodecSpecific(
278 bool frame_is_keyframe,
279 const TemporalLayers::FrameConfig& tl_config,
280 CodecSpecificInfoVP8* vp8_info,
281 uint32_t timestamp) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000282 if (number_of_temporal_layers_ == 1) {
283 vp8_info->temporalIdx = kNoTemporalIdx;
284 vp8_info->layerSync = false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000285 } else {
pbos1777c5f2017-07-19 17:04:02 -0700286 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
287 vp8_info->temporalIdx = tl_config.packetizer_temporal_idx;
288 vp8_info->layerSync = tl_config.layer_sync;
Peter Boström1436c832017-03-27 15:01:49 -0400289 if (frame_is_keyframe) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000290 vp8_info->temporalIdx = 0;
Erik Språng2c4c9142015-06-24 11:24:44 +0200291 last_sync_timestamp_ = unwrapped_timestamp;
pbos1777c5f2017-07-19 17:04:02 -0700292 vp8_info->layerSync = true;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000293 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
294 // Regardless of pattern the frame after a base layer sync will always
295 // be a layer sync.
Erik Språng2c4c9142015-06-24 11:24:44 +0200296 last_sync_timestamp_ = unwrapped_timestamp;
pbos1777c5f2017-07-19 17:04:02 -0700297 vp8_info->layerSync = true;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000298 }
Peter Boström1436c832017-03-27 15:01:49 -0400299 last_base_layer_sync_ = frame_is_keyframe;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000300 }
301}
302
Erik Språng2c4c9142015-06-24 11:24:44 +0200303bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
sprang2ddb8bd2016-02-04 03:59:52 -0800304 RTC_DCHECK_EQ(1, active_layer_);
henrikg91d6ede2015-09-17 00:24:34 -0700305 RTC_DCHECK_NE(-1, layers_[0].last_qp);
Erik Språng2c4c9142015-06-24 11:24:44 +0200306 if (layers_[1].last_qp == -1) {
307 // First frame in TL1 should only depend on TL0 since there are no
308 // previous frames in TL1.
309 return true;
310 }
311
henrikg91d6ede2015-09-17 00:24:34 -0700312 RTC_DCHECK_NE(-1, last_sync_timestamp_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200313 int64_t timestamp_diff = timestamp - last_sync_timestamp_;
314 if (timestamp_diff > kMaxTimeBetweenSyncs) {
315 // After a certain time, force a sync frame.
316 return true;
317 } else if (timestamp_diff < kMinTimeBetweenSyncs) {
318 // If too soon from previous sync frame, don't issue a new one.
319 return false;
320 }
321 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too
322 // large.
323 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync)
324 return true;
325 return false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000326}
327
sprangc7805db2016-11-25 08:09:43 -0800328uint32_t ScreenshareLayers::GetCodecTargetBitrateKbps() const {
329 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
330
331 if (number_of_temporal_layers_ > 1) {
332 // Calculate a codec target bitrate. This may be higher than TL0, gaining
333 // quality at the expense of frame rate at TL0. Constraints:
334 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
335 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
336 target_bitrate_kbps =
337 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
338 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
339 }
340
341 return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
342}
343
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100344bool ScreenshareLayers::UpdateConfiguration(Vp8EncoderConfig* cfg) {
Erik Språng08127a92016-11-16 16:41:30 +0100345 bool cfg_updated = false;
sprangc7805db2016-11-25 08:09:43 -0800346 uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
Erik Språng27a457d2018-01-12 11:00:21 +0100347
348 // TODO(sprang): We _really_ need to make an overhaul of this class. :(
349 // If we're dropping frames in order to meet a target framerate, adjust the
350 // bitrate assigned to the encoder so the total average bitrate is correct.
351 float encoder_config_bitrate_kbps = target_bitrate_kbps;
352 if (target_framerate_ && capture_framerate_ &&
353 *target_framerate_ < *capture_framerate_) {
354 encoder_config_bitrate_kbps *=
355 static_cast<float>(*capture_framerate_) / *target_framerate_;
356 }
357
358 if (bitrate_updated_ ||
359 cfg->rc_target_bitrate != encoder_config_bitrate_kbps) {
360 cfg->rc_target_bitrate = encoder_config_bitrate_kbps;
Erik Språng08127a92016-11-16 16:41:30 +0100361
362 // Don't reconfigure qp limits during quality boost frames.
363 if (active_layer_ == -1 ||
364 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
365 min_qp_ = cfg->rc_min_quantizer;
366 max_qp_ = cfg->rc_max_quantizer;
367 // After a dropped frame, a frame with max qp will be encoded and the
368 // quality will then ramp up from there. To boost the speed of recovery,
sprang916170a2017-05-23 07:47:55 -0700369 // encode the next frame with lower max qp, if there is sufficient
370 // bandwidth to do so without causing excessive delay.
371 // TL0 is the most important to improve since the errors in this layer
372 // will propagate to TL1.
Erik Språng08127a92016-11-16 16:41:30 +0100373 // Currently, reduce max qp by 20% for TL0 and 15% for TL1.
sprang916170a2017-05-23 07:47:55 -0700374 if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
375 layers_[0].enhanced_max_qp =
376 min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
377 layers_[1].enhanced_max_qp =
378 min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
379 } else {
380 layers_[0].enhanced_max_qp = -1;
381 layers_[1].enhanced_max_qp = -1;
382 }
Erik Språng08127a92016-11-16 16:41:30 +0100383 }
384
sprang0ad0de62017-01-11 05:01:32 -0800385 if (capture_framerate_) {
sprangac4a90d2016-12-28 05:58:07 -0800386 int avg_frame_size =
sprang0ad0de62017-01-11 05:01:32 -0800387 (target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
sprang916170a2017-05-23 07:47:55 -0700388 // Allow max debt to be the size of a single optimal frame.
389 // TODO(sprang): Determine if this needs to be adjusted by some factor.
390 // (Lower values may cause more frame drops, higher may lead to queuing
391 // delays.)
392 max_debt_bytes_ = avg_frame_size;
Erik Språng08127a92016-11-16 16:41:30 +0100393 }
394
395 bitrate_updated_ = false;
396 cfg_updated = true;
397 }
398
399 // Don't try to update boosts state if not active yet.
400 if (active_layer_ == -1)
401 return cfg_updated;
402
sprangef7228c2015-08-05 02:01:29 -0700403 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1)
Erik Språng08127a92016-11-16 16:41:30 +0100404 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200405
406 // If layer is in the quality boost state (following a dropped frame), update
407 // the configuration with the adjusted (lower) qp and set the state back to
408 // normal.
409 unsigned int adjusted_max_qp;
410 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost &&
411 layers_[active_layer_].enhanced_max_qp != -1) {
412 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
413 layers_[active_layer_].state = TemporalLayer::State::kNormal;
414 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200415 adjusted_max_qp = max_qp_; // Set the normal max qp.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000416 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200417
418 if (adjusted_max_qp == cfg->rc_max_quantizer)
Erik Språng08127a92016-11-16 16:41:30 +0100419 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200420
421 cfg->rc_max_quantizer = adjusted_max_qp;
Erik Språng08127a92016-11-16 16:41:30 +0100422 cfg_updated = true;
sprangc7805db2016-11-25 08:09:43 -0800423
Erik Språng08127a92016-11-16 16:41:30 +0100424 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200425}
426
427void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
428 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
429 if (debt_reduction_bytes >= debt_bytes_) {
430 debt_bytes_ = 0;
431 } else {
432 debt_bytes_ -= debt_reduction_bytes;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000433 }
434}
sprang@webrtc.org70f74f32014-12-17 10:57:10 +0000435
sprangb0fdfea2016-03-01 05:51:16 -0800436void ScreenshareLayers::UpdateHistograms() {
437 if (stats_.first_frame_time_ms_ == -1)
438 return;
439 int64_t duration_sec =
440 (clock_->TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) / 1000;
441 if (duration_sec >= metrics::kMinRunTimeInSeconds) {
442 RTC_HISTOGRAM_COUNTS_10000(
443 "WebRTC.Video.Screenshare.Layer0.FrameRate",
444 (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
445 RTC_HISTOGRAM_COUNTS_10000(
446 "WebRTC.Video.Screenshare.Layer1.FrameRate",
447 (stats_.num_tl1_frames_ + (duration_sec / 2)) / duration_sec);
448 int total_frames = stats_.num_tl0_frames_ + stats_.num_tl1_frames_;
asapersson58d992e2016-03-29 02:15:06 -0700449 RTC_HISTOGRAM_COUNTS_10000(
450 "WebRTC.Video.Screenshare.FramesPerDrop",
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200451 (stats_.num_dropped_frames_ == 0
452 ? 0
453 : total_frames / stats_.num_dropped_frames_));
asapersson58d992e2016-03-29 02:15:06 -0700454 RTC_HISTOGRAM_COUNTS_10000(
455 "WebRTC.Video.Screenshare.FramesPerOvershoot",
456 (stats_.num_overshoots_ == 0 ? 0
457 : total_frames / stats_.num_overshoots_));
sprangb0fdfea2016-03-01 05:51:16 -0800458 if (stats_.num_tl0_frames_ > 0) {
459 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer0.Qp",
460 stats_.tl0_qp_sum_ / stats_.num_tl0_frames_);
461 RTC_HISTOGRAM_COUNTS_10000(
462 "WebRTC.Video.Screenshare.Layer0.TargetBitrate",
463 stats_.tl0_target_bitrate_sum_ / stats_.num_tl0_frames_);
464 }
465 if (stats_.num_tl1_frames_ > 0) {
466 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
467 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
468 RTC_HISTOGRAM_COUNTS_10000(
469 "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
470 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
471 }
472 }
473}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000474} // namespace webrtc