blob: dac16ebe70bb76570f40eafb64c214f240b699f4 [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"
19#include "system_wrappers/include/clock.h"
20#include "system_wrappers/include/metrics.h"
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +020021#include "vpx/vp8cx.h"
22#include "vpx/vpx_encoder.h"
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000023
24namespace webrtc {
25
Erik Språng2c4c9142015-06-24 11:24:44 +020026static const int kOneSecond90Khz = 90000;
27static const int kMinTimeBetweenSyncs = kOneSecond90Khz * 5;
28static const int kMaxTimeBetweenSyncs = kOneSecond90Khz * 10;
29static const int kQpDeltaThresholdForSync = 8;
sprang916170a2017-05-23 07:47:55 -070030static const int kMinBitrateKbpsForQpBoost = 500;
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ång08127a92016-11-16 16:41:30 +010041webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create(
42 int simulcast_id,
43 int num_temporal_layers,
44 uint8_t initial_tl0_pic_idx) const {
sprang429600d2017-01-26 06:12:26 -080045 webrtc::TemporalLayers* tl;
46 if (simulcast_id == 0) {
47 tl = new webrtc::ScreenshareLayers(num_temporal_layers, rand(),
48 webrtc::Clock::GetRealTimeClock());
49 } else {
sprang5271ea62017-03-01 01:58:17 -080050 TemporalLayersFactory rt_tl_factory;
sprang429600d2017-01-26 06:12:26 -080051 tl = rt_tl_factory.Create(simulcast_id, num_temporal_layers, rand());
52 }
Erik Språng08127a92016-11-16 16:41:30 +010053 if (listener_)
54 listener_->OnTemporalLayersCreated(simulcast_id, tl);
55 return tl;
56}
57
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +020058std::unique_ptr<webrtc::TemporalLayersChecker>
59ScreenshareTemporalLayersFactory::CreateChecker(
60 int simulcast_id,
61 int temporal_layers,
62 uint8_t initial_tl0_pic_idx) const {
63 webrtc::TemporalLayersChecker* tlc;
64 if (simulcast_id == 0) {
65 tlc = new webrtc::ScreenshareTemporalLayersChecker(temporal_layers,
66 initial_tl0_pic_idx);
67 } else {
68 TemporalLayersFactory rt_tl_factory;
69 return rt_tl_factory.CreateChecker(simulcast_id, temporal_layers,
70 initial_tl0_pic_idx);
71 }
72 return std::unique_ptr<webrtc::TemporalLayersChecker>(tlc);
73}
74
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000075ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
sprangb0fdfea2016-03-01 05:51:16 -080076 uint8_t initial_tl0_pic_idx,
77 Clock* clock)
78 : clock_(clock),
sprang429600d2017-01-26 06:12:26 -080079 number_of_temporal_layers_(
80 std::min(kMaxNumTemporalLayers, num_temporal_layers)),
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000081 last_base_layer_sync_(false),
82 tl0_pic_idx_(initial_tl0_pic_idx),
Erik Språng2c4c9142015-06-24 11:24:44 +020083 active_layer_(-1),
84 last_timestamp_(-1),
85 last_sync_timestamp_(-1),
sprangafe1f742016-04-12 02:45:13 -070086 last_emitted_tl0_timestamp_(-1),
Erik Språng2c4c9142015-06-24 11:24:44 +020087 min_qp_(-1),
88 max_qp_(-1),
89 max_debt_bytes_(0),
sprangac4a90d2016-12-28 05:58:07 -080090 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale.
Erik Språng08127a92016-11-16 16:41:30 +010091 bitrate_updated_(false) {
sprang429600d2017-01-26 06:12:26 -080092 RTC_CHECK_GT(number_of_temporal_layers_, 0);
93 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000094}
95
sprangb0fdfea2016-03-01 05:51:16 -080096ScreenshareLayers::~ScreenshareLayers() {
97 UpdateHistograms();
98}
99
brandtr080830c2017-05-03 03:25:53 -0700100uint8_t ScreenshareLayers::Tl0PicIdx() const {
101 return tl0_pic_idx_;
102}
103
pbos18ad1d42017-05-04 05:04:46 -0700104TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
105 uint32_t timestamp) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000106 if (number_of_temporal_layers_ <= 1) {
107 // No flags needed for 1 layer screenshare.
Peter Boström1436c832017-03-27 15:01:49 -0400108 // TODO(pbos): Consider updating only last, and not all buffers.
pbos51f083c2017-05-04 06:39:04 -0700109 TemporalLayers::FrameConfig tl_config(
110 kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate);
pbos51f083c2017-05-04 06:39:04 -0700111 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000112 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200113
sprangac4a90d2016-12-28 05:58:07 -0800114 const int64_t now_ms = clock_->TimeInMilliseconds();
115 if (target_framerate_.value_or(0) > 0 &&
116 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) {
117 // Max framerate exceeded, drop frame.
pbos18ad1d42017-05-04 05:04:46 -0700118 return TemporalLayers::FrameConfig(kNone, kNone, kNone);
sprangac4a90d2016-12-28 05:58:07 -0800119 }
120
sprangb0fdfea2016-03-01 05:51:16 -0800121 if (stats_.first_frame_time_ms_ == -1)
sprangac4a90d2016-12-28 05:58:07 -0800122 stats_.first_frame_time_ms_ = now_ms;
sprangb0fdfea2016-03-01 05:51:16 -0800123
Erik Språng2c4c9142015-06-24 11:24:44 +0200124 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
sprang916170a2017-05-23 07:47:55 -0700125 int64_t ts_diff;
126 if (last_timestamp_ == -1) {
127 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
128 } else {
129 ts_diff = unwrapped_timestamp - last_timestamp_;
130 }
131 // Make sure both frame droppers leak out bits.
132 layers_[0].UpdateDebt(ts_diff / 90);
133 layers_[1].UpdateDebt(ts_diff / 90);
134 last_timestamp_ = timestamp;
135
136 TemporalLayerState layer_state = TemporalLayerState::kDrop;
137
Erik Språng2c4c9142015-06-24 11:24:44 +0200138 if (active_layer_ == -1 ||
139 layers_[active_layer_].state != TemporalLayer::State::kDropped) {
sprangafe1f742016-04-12 02:45:13 -0700140 if (last_emitted_tl0_timestamp_ != -1 &&
141 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
142 kMaxFrameIntervalMs) {
143 // Too long time has passed since the last frame was emitted, cancel
144 // enough debt to allow a single frame.
145 layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
146 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200147 if (layers_[0].debt_bytes_ > max_debt_bytes_) {
148 // Must drop TL0, encode TL1 instead.
149 if (layers_[1].debt_bytes_ > max_debt_bytes_) {
150 // Must drop both TL0 and TL1.
151 active_layer_ = -1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000152 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200153 active_layer_ = 1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000154 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200155 } else {
156 active_layer_ = 0;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000157 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000158 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200159
160 switch (active_layer_) {
161 case 0:
sprang916170a2017-05-23 07:47:55 -0700162 layer_state = TemporalLayerState::kTl0;
sprangafe1f742016-04-12 02:45:13 -0700163 last_emitted_tl0_timestamp_ = unwrapped_timestamp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200164 break;
165 case 1:
sprangf03ea042017-07-13 03:53:51 -0700166 if (layers_[1].state != TemporalLayer::State::kDropped) {
167 if (TimeToSync(unwrapped_timestamp)) {
168 last_sync_timestamp_ = unwrapped_timestamp;
169 layer_state = TemporalLayerState::kTl1Sync;
170 } else {
171 layer_state = TemporalLayerState::kTl1;
172 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200173 } else {
sprangf03ea042017-07-13 03:53:51 -0700174 layer_state = last_sync_timestamp_ == unwrapped_timestamp
175 ? TemporalLayerState::kTl1Sync
176 : TemporalLayerState::kTl1;
Erik Språng2c4c9142015-06-24 11:24:44 +0200177 }
178 break;
179 case -1:
sprang916170a2017-05-23 07:47:55 -0700180 layer_state = TemporalLayerState::kDrop;
sprangb0fdfea2016-03-01 05:51:16 -0800181 ++stats_.num_dropped_frames_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200182 break;
183 default:
Erik Språng2c4c9142015-06-24 11:24:44 +0200184 RTC_NOTREACHED();
185 }
186
pbos51f083c2017-05-04 06:39:04 -0700187 TemporalLayers::FrameConfig tl_config;
Peter Boström1436c832017-03-27 15:01:49 -0400188 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
189 // layers.
190 switch (layer_state) {
sprang916170a2017-05-23 07:47:55 -0700191 case TemporalLayerState::kDrop:
pbos51f083c2017-05-04 06:39:04 -0700192 tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone);
193 break;
sprang916170a2017-05-23 07:47:55 -0700194 case TemporalLayerState::kTl0:
Peter Boström1436c832017-03-27 15:01:49 -0400195 // TL0 only references and updates 'last'.
pbos51f083c2017-05-04 06:39:04 -0700196 tl_config =
197 TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700198 tl_config.packetizer_temporal_idx = 0;
pbos51f083c2017-05-04 06:39:04 -0700199 break;
sprang916170a2017-05-23 07:47:55 -0700200 case TemporalLayerState::kTl1:
Peter Boström1436c832017-03-27 15:01:49 -0400201 // TL1 references both 'last' and 'golden' but only updates 'golden'.
pbos51f083c2017-05-04 06:39:04 -0700202 tl_config =
203 TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700204 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700205 break;
sprang916170a2017-05-23 07:47:55 -0700206 case TemporalLayerState::kTl1Sync:
Peter Boström1436c832017-03-27 15:01:49 -0400207 // Predict from only TL0 to allow participants to switch to the high
208 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
209 // and update 'golden' from this point on.
pbos51f083c2017-05-04 06:39:04 -0700210 tl_config = TemporalLayers::FrameConfig(kReference, kUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700211 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700212 break;
Peter Boström1436c832017-03-27 15:01:49 -0400213 }
pbos51f083c2017-05-04 06:39:04 -0700214
pbos1777c5f2017-07-19 17:04:02 -0700215 tl_config.layer_sync = layer_state == TemporalLayerState::kTl1Sync;
pbos51f083c2017-05-04 06:39:04 -0700216 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000217}
218
Erik Språng08127a92016-11-16 16:41:30 +0100219std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps,
220 int max_bitrate_kbps,
221 int framerate) {
sprangac4a90d2016-12-28 05:58:07 -0800222 RTC_DCHECK_GT(framerate, 0);
223 if (!target_framerate_) {
224 // First OnRatesUpdated() is called during construction, with the configured
225 // targets as parameters.
226 target_framerate_.emplace(framerate);
sprang0ad0de62017-01-11 05:01:32 -0800227 capture_framerate_ = target_framerate_;
sprangac4a90d2016-12-28 05:58:07 -0800228 bitrate_updated_ = true;
229 } else {
230 bitrate_updated_ =
231 bitrate_kbps != static_cast<int>(layers_[0].target_rate_kbps_) ||
232 max_bitrate_kbps != static_cast<int>(layers_[1].target_rate_kbps_) ||
sprang0ad0de62017-01-11 05:01:32 -0800233 (capture_framerate_ &&
234 framerate != static_cast<int>(*capture_framerate_));
sprangac4a90d2016-12-28 05:58:07 -0800235 if (framerate < 0) {
sprang0ad0de62017-01-11 05:01:32 -0800236 capture_framerate_.reset();
sprangac4a90d2016-12-28 05:58:07 -0800237 } else {
sprang0ad0de62017-01-11 05:01:32 -0800238 capture_framerate_.emplace(framerate);
sprangac4a90d2016-12-28 05:58:07 -0800239 }
240 }
241
Erik Språng2c4c9142015-06-24 11:24:44 +0200242 layers_[0].target_rate_kbps_ = bitrate_kbps;
243 layers_[1].target_rate_kbps_ = max_bitrate_kbps;
pbos@webrtc.org89042902015-03-20 12:49:38 +0000244
Erik Språng08127a92016-11-16 16:41:30 +0100245 std::vector<uint32_t> allocation;
246 allocation.push_back(bitrate_kbps);
247 if (max_bitrate_kbps > bitrate_kbps)
248 allocation.push_back(max_bitrate_kbps - bitrate_kbps);
249 return allocation;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000250}
251
Peter Boström1436c832017-03-27 15:01:49 -0400252void ScreenshareLayers::FrameEncoded(unsigned int size, int qp) {
sprangac4a90d2016-12-28 05:58:07 -0800253 if (size > 0)
254 encode_framerate_.Update(1, clock_->TimeInMilliseconds());
255
sprang2ddb8bd2016-02-04 03:59:52 -0800256 if (number_of_temporal_layers_ == 1)
257 return;
258
259 RTC_DCHECK_NE(-1, active_layer_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200260 if (size == 0) {
261 layers_[active_layer_].state = TemporalLayer::State::kDropped;
sprangb0fdfea2016-03-01 05:51:16 -0800262 ++stats_.num_overshoots_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200263 return;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000264 }
sprangef7228c2015-08-05 02:01:29 -0700265
Erik Språng2c4c9142015-06-24 11:24:44 +0200266 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
267 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
268 }
269
270 if (qp != -1)
271 layers_[active_layer_].last_qp = qp;
272
273 if (active_layer_ == 0) {
274 layers_[0].debt_bytes_ += size;
275 layers_[1].debt_bytes_ += size;
sprangb0fdfea2016-03-01 05:51:16 -0800276 ++stats_.num_tl0_frames_;
277 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
278 stats_.tl0_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200279 } else if (active_layer_ == 1) {
280 layers_[1].debt_bytes_ += size;
sprangb0fdfea2016-03-01 05:51:16 -0800281 ++stats_.num_tl1_frames_;
282 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
283 stats_.tl1_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200284 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000285}
286
pbos18ad1d42017-05-04 05:04:46 -0700287void ScreenshareLayers::PopulateCodecSpecific(
288 bool frame_is_keyframe,
289 const TemporalLayers::FrameConfig& tl_config,
290 CodecSpecificInfoVP8* vp8_info,
291 uint32_t timestamp) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000292 if (number_of_temporal_layers_ == 1) {
293 vp8_info->temporalIdx = kNoTemporalIdx;
294 vp8_info->layerSync = false;
295 vp8_info->tl0PicIdx = kNoTl0PicIdx;
296 } else {
pbos1777c5f2017-07-19 17:04:02 -0700297 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
298 vp8_info->temporalIdx = tl_config.packetizer_temporal_idx;
299 vp8_info->layerSync = tl_config.layer_sync;
Peter Boström1436c832017-03-27 15:01:49 -0400300 if (frame_is_keyframe) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000301 vp8_info->temporalIdx = 0;
Erik Språng2c4c9142015-06-24 11:24:44 +0200302 last_sync_timestamp_ = unwrapped_timestamp;
pbos1777c5f2017-07-19 17:04:02 -0700303 vp8_info->layerSync = true;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000304 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
305 // Regardless of pattern the frame after a base layer sync will always
306 // be a layer sync.
Erik Språng2c4c9142015-06-24 11:24:44 +0200307 last_sync_timestamp_ = unwrapped_timestamp;
pbos1777c5f2017-07-19 17:04:02 -0700308 vp8_info->layerSync = true;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000309 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000310 if (vp8_info->temporalIdx == 0) {
311 tl0_pic_idx_++;
312 }
Peter Boström1436c832017-03-27 15:01:49 -0400313 last_base_layer_sync_ = frame_is_keyframe;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000314 vp8_info->tl0PicIdx = tl0_pic_idx_;
315 }
316}
317
Erik Språng2c4c9142015-06-24 11:24:44 +0200318bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
sprang2ddb8bd2016-02-04 03:59:52 -0800319 RTC_DCHECK_EQ(1, active_layer_);
henrikg91d6ede2015-09-17 00:24:34 -0700320 RTC_DCHECK_NE(-1, layers_[0].last_qp);
Erik Språng2c4c9142015-06-24 11:24:44 +0200321 if (layers_[1].last_qp == -1) {
322 // First frame in TL1 should only depend on TL0 since there are no
323 // previous frames in TL1.
324 return true;
325 }
326
henrikg91d6ede2015-09-17 00:24:34 -0700327 RTC_DCHECK_NE(-1, last_sync_timestamp_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200328 int64_t timestamp_diff = timestamp - last_sync_timestamp_;
329 if (timestamp_diff > kMaxTimeBetweenSyncs) {
330 // After a certain time, force a sync frame.
331 return true;
332 } else if (timestamp_diff < kMinTimeBetweenSyncs) {
333 // If too soon from previous sync frame, don't issue a new one.
334 return false;
335 }
336 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too
337 // large.
338 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync)
339 return true;
340 return false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000341}
342
sprangc7805db2016-11-25 08:09:43 -0800343uint32_t ScreenshareLayers::GetCodecTargetBitrateKbps() const {
344 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
345
346 if (number_of_temporal_layers_ > 1) {
347 // Calculate a codec target bitrate. This may be higher than TL0, gaining
348 // quality at the expense of frame rate at TL0. Constraints:
349 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
350 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
351 target_bitrate_kbps =
352 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
353 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
354 }
355
356 return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
357}
358
Erik Språng2c4c9142015-06-24 11:24:44 +0200359bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
Erik Språng08127a92016-11-16 16:41:30 +0100360 bool cfg_updated = false;
sprangc7805db2016-11-25 08:09:43 -0800361 uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
362 if (bitrate_updated_ || cfg->rc_target_bitrate != target_bitrate_kbps) {
363 cfg->rc_target_bitrate = target_bitrate_kbps;
Erik Språng08127a92016-11-16 16:41:30 +0100364
365 // Don't reconfigure qp limits during quality boost frames.
366 if (active_layer_ == -1 ||
367 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
368 min_qp_ = cfg->rc_min_quantizer;
369 max_qp_ = cfg->rc_max_quantizer;
370 // After a dropped frame, a frame with max qp will be encoded and the
371 // quality will then ramp up from there. To boost the speed of recovery,
sprang916170a2017-05-23 07:47:55 -0700372 // encode the next frame with lower max qp, if there is sufficient
373 // bandwidth to do so without causing excessive delay.
374 // TL0 is the most important to improve since the errors in this layer
375 // will propagate to TL1.
Erik Språng08127a92016-11-16 16:41:30 +0100376 // Currently, reduce max qp by 20% for TL0 and 15% for TL1.
sprang916170a2017-05-23 07:47:55 -0700377 if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
378 layers_[0].enhanced_max_qp =
379 min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
380 layers_[1].enhanced_max_qp =
381 min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
382 } else {
383 layers_[0].enhanced_max_qp = -1;
384 layers_[1].enhanced_max_qp = -1;
385 }
Erik Språng08127a92016-11-16 16:41:30 +0100386 }
387
sprang0ad0de62017-01-11 05:01:32 -0800388 if (capture_framerate_) {
sprangac4a90d2016-12-28 05:58:07 -0800389 int avg_frame_size =
sprang0ad0de62017-01-11 05:01:32 -0800390 (target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
sprang916170a2017-05-23 07:47:55 -0700391 // Allow max debt to be the size of a single optimal frame.
392 // TODO(sprang): Determine if this needs to be adjusted by some factor.
393 // (Lower values may cause more frame drops, higher may lead to queuing
394 // delays.)
395 max_debt_bytes_ = avg_frame_size;
Erik Språng08127a92016-11-16 16:41:30 +0100396 }
397
398 bitrate_updated_ = false;
399 cfg_updated = true;
400 }
401
402 // Don't try to update boosts state if not active yet.
403 if (active_layer_ == -1)
404 return cfg_updated;
405
sprangef7228c2015-08-05 02:01:29 -0700406 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1)
Erik Språng08127a92016-11-16 16:41:30 +0100407 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200408
409 // If layer is in the quality boost state (following a dropped frame), update
410 // the configuration with the adjusted (lower) qp and set the state back to
411 // normal.
412 unsigned int adjusted_max_qp;
413 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost &&
414 layers_[active_layer_].enhanced_max_qp != -1) {
415 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
416 layers_[active_layer_].state = TemporalLayer::State::kNormal;
417 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200418 adjusted_max_qp = max_qp_; // Set the normal max qp.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000419 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200420
421 if (adjusted_max_qp == cfg->rc_max_quantizer)
Erik Språng08127a92016-11-16 16:41:30 +0100422 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200423
424 cfg->rc_max_quantizer = adjusted_max_qp;
Erik Språng08127a92016-11-16 16:41:30 +0100425 cfg_updated = true;
sprangc7805db2016-11-25 08:09:43 -0800426
Erik Språng08127a92016-11-16 16:41:30 +0100427 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200428}
429
430void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
431 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
432 if (debt_reduction_bytes >= debt_bytes_) {
433 debt_bytes_ = 0;
434 } else {
435 debt_bytes_ -= debt_reduction_bytes;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000436 }
437}
sprang@webrtc.org70f74f32014-12-17 10:57:10 +0000438
sprangb0fdfea2016-03-01 05:51:16 -0800439void ScreenshareLayers::UpdateHistograms() {
440 if (stats_.first_frame_time_ms_ == -1)
441 return;
442 int64_t duration_sec =
443 (clock_->TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) / 1000;
444 if (duration_sec >= metrics::kMinRunTimeInSeconds) {
445 RTC_HISTOGRAM_COUNTS_10000(
446 "WebRTC.Video.Screenshare.Layer0.FrameRate",
447 (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
448 RTC_HISTOGRAM_COUNTS_10000(
449 "WebRTC.Video.Screenshare.Layer1.FrameRate",
450 (stats_.num_tl1_frames_ + (duration_sec / 2)) / duration_sec);
451 int total_frames = stats_.num_tl0_frames_ + stats_.num_tl1_frames_;
asapersson58d992e2016-03-29 02:15:06 -0700452 RTC_HISTOGRAM_COUNTS_10000(
453 "WebRTC.Video.Screenshare.FramesPerDrop",
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200454 (stats_.num_dropped_frames_ == 0
455 ? 0
456 : total_frames / stats_.num_dropped_frames_));
asapersson58d992e2016-03-29 02:15:06 -0700457 RTC_HISTOGRAM_COUNTS_10000(
458 "WebRTC.Video.Screenshare.FramesPerOvershoot",
459 (stats_.num_overshoots_ == 0 ? 0
460 : total_frames / stats_.num_overshoots_));
sprangb0fdfea2016-03-01 05:51:16 -0800461 if (stats_.num_tl0_frames_ > 0) {
462 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer0.Qp",
463 stats_.tl0_qp_sum_ / stats_.num_tl0_frames_);
464 RTC_HISTOGRAM_COUNTS_10000(
465 "WebRTC.Video.Screenshare.Layer0.TargetBitrate",
466 stats_.tl0_target_bitrate_sum_ / stats_.num_tl0_frames_);
467 }
468 if (stats_.num_tl1_frames_ > 0) {
469 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
470 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
471 RTC_HISTOGRAM_COUNTS_10000(
472 "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
473 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
474 }
475 }
476}
477
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200478ScreenshareTemporalLayersChecker::ScreenshareTemporalLayersChecker(
479 int /*num_temporal_layers*/,
480 uint8_t /*initial_tl0_pic_idx*/) {}
481
482// TODO(ilnik): Implement layers dependency checks here. Keep track of
483// last/golden/arf buffers and sync bits.
484bool ScreenshareTemporalLayersChecker::CheckTemporalConfig(
485 bool /*frame_is_keyframe*/,
486 const TemporalLayers::FrameConfig& /*frame_config*/) {
487 return true;
488}
489
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000490} // namespace webrtc