blob: d81447bb5d849b6275860f0762731adf0b22f771 [file] [log] [blame]
pbos@webrtc.org9115cde2014-12-09 10:36:40 +00001/* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
2*
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*/
9
10#include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h"
11
12#include <stdlib.h>
13
philipelcce46fc2015-12-21 03:04:49 -080014#include <algorithm>
15
Henrik Kjellanderdca1e092017-07-01 16:42:22 +020016#include "vpx/vp8cx.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020017#include "vpx/vpx_encoder.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010018#include "webrtc/modules/video_coding/include/video_codec_interface.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/rtc_base/checks.h"
sprangb0fdfea2016-03-01 05:51:16 -080020#include "webrtc/system_wrappers/include/clock.h"
21#include "webrtc/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;
26static const int kMinTimeBetweenSyncs = kOneSecond90Khz * 5;
27static const int kMaxTimeBetweenSyncs = kOneSecond90Khz * 10;
28static 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
Erik Språng08127a92016-11-16 16:41:30 +010040webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create(
41 int simulcast_id,
42 int num_temporal_layers,
43 uint8_t initial_tl0_pic_idx) const {
sprang429600d2017-01-26 06:12:26 -080044 webrtc::TemporalLayers* tl;
45 if (simulcast_id == 0) {
46 tl = new webrtc::ScreenshareLayers(num_temporal_layers, rand(),
47 webrtc::Clock::GetRealTimeClock());
48 } else {
sprang5271ea62017-03-01 01:58:17 -080049 TemporalLayersFactory rt_tl_factory;
sprang429600d2017-01-26 06:12:26 -080050 tl = rt_tl_factory.Create(simulcast_id, num_temporal_layers, rand());
51 }
Erik Språng08127a92016-11-16 16:41:30 +010052 if (listener_)
53 listener_->OnTemporalLayersCreated(simulcast_id, tl);
54 return tl;
55}
56
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000057ScreenshareLayers::ScreenshareLayers(int num_temporal_layers,
sprangb0fdfea2016-03-01 05:51:16 -080058 uint8_t initial_tl0_pic_idx,
59 Clock* clock)
60 : clock_(clock),
sprang429600d2017-01-26 06:12:26 -080061 number_of_temporal_layers_(
62 std::min(kMaxNumTemporalLayers, num_temporal_layers)),
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000063 last_base_layer_sync_(false),
64 tl0_pic_idx_(initial_tl0_pic_idx),
Erik Språng2c4c9142015-06-24 11:24:44 +020065 active_layer_(-1),
66 last_timestamp_(-1),
67 last_sync_timestamp_(-1),
sprangafe1f742016-04-12 02:45:13 -070068 last_emitted_tl0_timestamp_(-1),
Erik Språng2c4c9142015-06-24 11:24:44 +020069 min_qp_(-1),
70 max_qp_(-1),
71 max_debt_bytes_(0),
sprangac4a90d2016-12-28 05:58:07 -080072 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale.
Erik Språng08127a92016-11-16 16:41:30 +010073 bitrate_updated_(false) {
sprang429600d2017-01-26 06:12:26 -080074 RTC_CHECK_GT(number_of_temporal_layers_, 0);
75 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000076}
77
sprangb0fdfea2016-03-01 05:51:16 -080078ScreenshareLayers::~ScreenshareLayers() {
79 UpdateHistograms();
80}
81
brandtr080830c2017-05-03 03:25:53 -070082uint8_t ScreenshareLayers::Tl0PicIdx() const {
83 return tl0_pic_idx_;
84}
85
pbos18ad1d42017-05-04 05:04:46 -070086TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
87 uint32_t timestamp) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000088 if (number_of_temporal_layers_ <= 1) {
89 // No flags needed for 1 layer screenshare.
Peter Boström1436c832017-03-27 15:01:49 -040090 // TODO(pbos): Consider updating only last, and not all buffers.
pbos51f083c2017-05-04 06:39:04 -070091 TemporalLayers::FrameConfig tl_config(
92 kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate);
pbos51f083c2017-05-04 06:39:04 -070093 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000094 }
Erik Språng2c4c9142015-06-24 11:24:44 +020095
sprangac4a90d2016-12-28 05:58:07 -080096 const int64_t now_ms = clock_->TimeInMilliseconds();
97 if (target_framerate_.value_or(0) > 0 &&
98 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) {
99 // Max framerate exceeded, drop frame.
pbos18ad1d42017-05-04 05:04:46 -0700100 return TemporalLayers::FrameConfig(kNone, kNone, kNone);
sprangac4a90d2016-12-28 05:58:07 -0800101 }
102
sprangb0fdfea2016-03-01 05:51:16 -0800103 if (stats_.first_frame_time_ms_ == -1)
sprangac4a90d2016-12-28 05:58:07 -0800104 stats_.first_frame_time_ms_ = now_ms;
sprangb0fdfea2016-03-01 05:51:16 -0800105
Erik Språng2c4c9142015-06-24 11:24:44 +0200106 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
sprang916170a2017-05-23 07:47:55 -0700107 int64_t ts_diff;
108 if (last_timestamp_ == -1) {
109 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
110 } else {
111 ts_diff = unwrapped_timestamp - last_timestamp_;
112 }
113 // 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;
117
118 TemporalLayerState layer_state = TemporalLayerState::kDrop;
119
Erik Språng2c4c9142015-06-24 11:24:44 +0200120 if (active_layer_ == -1 ||
121 layers_[active_layer_].state != TemporalLayer::State::kDropped) {
sprangafe1f742016-04-12 02:45:13 -0700122 if (last_emitted_tl0_timestamp_ != -1 &&
123 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
124 kMaxFrameIntervalMs) {
125 // Too long time has passed since the last frame was emitted, cancel
126 // enough debt to allow a single frame.
127 layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
128 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200129 if (layers_[0].debt_bytes_ > max_debt_bytes_) {
130 // Must drop TL0, encode TL1 instead.
131 if (layers_[1].debt_bytes_ > max_debt_bytes_) {
132 // Must drop both TL0 and TL1.
133 active_layer_ = -1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000134 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200135 active_layer_ = 1;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000136 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200137 } else {
138 active_layer_ = 0;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000139 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000140 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200141
142 switch (active_layer_) {
143 case 0:
sprang916170a2017-05-23 07:47:55 -0700144 layer_state = TemporalLayerState::kTl0;
sprangafe1f742016-04-12 02:45:13 -0700145 last_emitted_tl0_timestamp_ = unwrapped_timestamp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200146 break;
147 case 1:
sprangf03ea042017-07-13 03:53:51 -0700148 if (layers_[1].state != TemporalLayer::State::kDropped) {
149 if (TimeToSync(unwrapped_timestamp)) {
150 last_sync_timestamp_ = unwrapped_timestamp;
151 layer_state = TemporalLayerState::kTl1Sync;
152 } else {
153 layer_state = TemporalLayerState::kTl1;
154 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200155 } else {
sprangf03ea042017-07-13 03:53:51 -0700156 layer_state = last_sync_timestamp_ == unwrapped_timestamp
157 ? TemporalLayerState::kTl1Sync
158 : TemporalLayerState::kTl1;
Erik Språng2c4c9142015-06-24 11:24:44 +0200159 }
160 break;
161 case -1:
sprang916170a2017-05-23 07:47:55 -0700162 layer_state = TemporalLayerState::kDrop;
sprangb0fdfea2016-03-01 05:51:16 -0800163 ++stats_.num_dropped_frames_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200164 break;
165 default:
Erik Språng2c4c9142015-06-24 11:24:44 +0200166 RTC_NOTREACHED();
167 }
168
pbos51f083c2017-05-04 06:39:04 -0700169 TemporalLayers::FrameConfig tl_config;
Peter Boström1436c832017-03-27 15:01:49 -0400170 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
171 // layers.
172 switch (layer_state) {
sprang916170a2017-05-23 07:47:55 -0700173 case TemporalLayerState::kDrop:
pbos51f083c2017-05-04 06:39:04 -0700174 tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone);
175 break;
sprang916170a2017-05-23 07:47:55 -0700176 case TemporalLayerState::kTl0:
Peter Boström1436c832017-03-27 15:01:49 -0400177 // TL0 only references and updates 'last'.
pbos51f083c2017-05-04 06:39:04 -0700178 tl_config =
179 TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700180 tl_config.packetizer_temporal_idx = 0;
pbos51f083c2017-05-04 06:39:04 -0700181 break;
sprang916170a2017-05-23 07:47:55 -0700182 case TemporalLayerState::kTl1:
Peter Boström1436c832017-03-27 15:01:49 -0400183 // TL1 references both 'last' and 'golden' but only updates 'golden'.
pbos51f083c2017-05-04 06:39:04 -0700184 tl_config =
185 TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700186 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700187 break;
sprang916170a2017-05-23 07:47:55 -0700188 case TemporalLayerState::kTl1Sync:
Peter Boström1436c832017-03-27 15:01:49 -0400189 // Predict from only TL0 to allow participants to switch to the high
190 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
191 // and update 'golden' from this point on.
pbos51f083c2017-05-04 06:39:04 -0700192 tl_config = TemporalLayers::FrameConfig(kReference, kUpdate, kNone);
pbos1777c5f2017-07-19 17:04:02 -0700193 tl_config.packetizer_temporal_idx = 1;
pbos51f083c2017-05-04 06:39:04 -0700194 break;
Peter Boström1436c832017-03-27 15:01:49 -0400195 }
pbos51f083c2017-05-04 06:39:04 -0700196
pbos1777c5f2017-07-19 17:04:02 -0700197 tl_config.layer_sync = layer_state == TemporalLayerState::kTl1Sync;
pbos51f083c2017-05-04 06:39:04 -0700198 return tl_config;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000199}
200
Erik Språng08127a92016-11-16 16:41:30 +0100201std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps,
202 int max_bitrate_kbps,
203 int framerate) {
sprangac4a90d2016-12-28 05:58:07 -0800204 RTC_DCHECK_GT(framerate, 0);
205 if (!target_framerate_) {
206 // First OnRatesUpdated() is called during construction, with the configured
207 // targets as parameters.
208 target_framerate_.emplace(framerate);
sprang0ad0de62017-01-11 05:01:32 -0800209 capture_framerate_ = target_framerate_;
sprangac4a90d2016-12-28 05:58:07 -0800210 bitrate_updated_ = true;
211 } else {
212 bitrate_updated_ =
213 bitrate_kbps != static_cast<int>(layers_[0].target_rate_kbps_) ||
214 max_bitrate_kbps != static_cast<int>(layers_[1].target_rate_kbps_) ||
sprang0ad0de62017-01-11 05:01:32 -0800215 (capture_framerate_ &&
216 framerate != static_cast<int>(*capture_framerate_));
sprangac4a90d2016-12-28 05:58:07 -0800217 if (framerate < 0) {
sprang0ad0de62017-01-11 05:01:32 -0800218 capture_framerate_.reset();
sprangac4a90d2016-12-28 05:58:07 -0800219 } else {
sprang0ad0de62017-01-11 05:01:32 -0800220 capture_framerate_.emplace(framerate);
sprangac4a90d2016-12-28 05:58:07 -0800221 }
222 }
223
Erik Språng2c4c9142015-06-24 11:24:44 +0200224 layers_[0].target_rate_kbps_ = bitrate_kbps;
225 layers_[1].target_rate_kbps_ = max_bitrate_kbps;
pbos@webrtc.org89042902015-03-20 12:49:38 +0000226
Erik Språng08127a92016-11-16 16:41:30 +0100227 std::vector<uint32_t> allocation;
228 allocation.push_back(bitrate_kbps);
229 if (max_bitrate_kbps > bitrate_kbps)
230 allocation.push_back(max_bitrate_kbps - bitrate_kbps);
231 return allocation;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000232}
233
Peter Boström1436c832017-03-27 15:01:49 -0400234void ScreenshareLayers::FrameEncoded(unsigned int size, int qp) {
sprangac4a90d2016-12-28 05:58:07 -0800235 if (size > 0)
236 encode_framerate_.Update(1, clock_->TimeInMilliseconds());
237
sprang2ddb8bd2016-02-04 03:59:52 -0800238 if (number_of_temporal_layers_ == 1)
239 return;
240
241 RTC_DCHECK_NE(-1, active_layer_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200242 if (size == 0) {
243 layers_[active_layer_].state = TemporalLayer::State::kDropped;
sprangb0fdfea2016-03-01 05:51:16 -0800244 ++stats_.num_overshoots_;
Erik Språng2c4c9142015-06-24 11:24:44 +0200245 return;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000246 }
sprangef7228c2015-08-05 02:01:29 -0700247
Erik Språng2c4c9142015-06-24 11:24:44 +0200248 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
249 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
250 }
251
252 if (qp != -1)
253 layers_[active_layer_].last_qp = qp;
254
255 if (active_layer_ == 0) {
256 layers_[0].debt_bytes_ += size;
257 layers_[1].debt_bytes_ += size;
sprangb0fdfea2016-03-01 05:51:16 -0800258 ++stats_.num_tl0_frames_;
259 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
260 stats_.tl0_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200261 } else if (active_layer_ == 1) {
262 layers_[1].debt_bytes_ += size;
sprangb0fdfea2016-03-01 05:51:16 -0800263 ++stats_.num_tl1_frames_;
264 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
265 stats_.tl1_qp_sum_ += qp;
Erik Språng2c4c9142015-06-24 11:24:44 +0200266 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000267}
268
pbos18ad1d42017-05-04 05:04:46 -0700269void ScreenshareLayers::PopulateCodecSpecific(
270 bool frame_is_keyframe,
271 const TemporalLayers::FrameConfig& tl_config,
272 CodecSpecificInfoVP8* vp8_info,
273 uint32_t timestamp) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000274 if (number_of_temporal_layers_ == 1) {
275 vp8_info->temporalIdx = kNoTemporalIdx;
276 vp8_info->layerSync = false;
277 vp8_info->tl0PicIdx = kNoTl0PicIdx;
278 } else {
pbos1777c5f2017-07-19 17:04:02 -0700279 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
280 vp8_info->temporalIdx = tl_config.packetizer_temporal_idx;
281 vp8_info->layerSync = tl_config.layer_sync;
Peter Boström1436c832017-03-27 15:01:49 -0400282 if (frame_is_keyframe) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000283 vp8_info->temporalIdx = 0;
Erik Språng2c4c9142015-06-24 11:24:44 +0200284 last_sync_timestamp_ = unwrapped_timestamp;
pbos1777c5f2017-07-19 17:04:02 -0700285 vp8_info->layerSync = true;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000286 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
287 // Regardless of pattern the frame after a base layer sync will always
288 // be a layer sync.
Erik Språng2c4c9142015-06-24 11:24:44 +0200289 last_sync_timestamp_ = unwrapped_timestamp;
pbos1777c5f2017-07-19 17:04:02 -0700290 vp8_info->layerSync = true;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000291 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000292 if (vp8_info->temporalIdx == 0) {
293 tl0_pic_idx_++;
294 }
Peter Boström1436c832017-03-27 15:01:49 -0400295 last_base_layer_sync_ = frame_is_keyframe;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000296 vp8_info->tl0PicIdx = tl0_pic_idx_;
297 }
298}
299
Erik Språng2c4c9142015-06-24 11:24:44 +0200300bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
sprang2ddb8bd2016-02-04 03:59:52 -0800301 RTC_DCHECK_EQ(1, active_layer_);
henrikg91d6ede2015-09-17 00:24:34 -0700302 RTC_DCHECK_NE(-1, layers_[0].last_qp);
Erik Språng2c4c9142015-06-24 11:24:44 +0200303 if (layers_[1].last_qp == -1) {
304 // First frame in TL1 should only depend on TL0 since there are no
305 // previous frames in TL1.
306 return true;
307 }
308
henrikg91d6ede2015-09-17 00:24:34 -0700309 RTC_DCHECK_NE(-1, last_sync_timestamp_);
Erik Språng2c4c9142015-06-24 11:24:44 +0200310 int64_t timestamp_diff = timestamp - last_sync_timestamp_;
311 if (timestamp_diff > kMaxTimeBetweenSyncs) {
312 // After a certain time, force a sync frame.
313 return true;
314 } else if (timestamp_diff < kMinTimeBetweenSyncs) {
315 // If too soon from previous sync frame, don't issue a new one.
316 return false;
317 }
318 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too
319 // large.
320 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync)
321 return true;
322 return false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000323}
324
sprangc7805db2016-11-25 08:09:43 -0800325uint32_t ScreenshareLayers::GetCodecTargetBitrateKbps() const {
326 uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
327
328 if (number_of_temporal_layers_ > 1) {
329 // Calculate a codec target bitrate. This may be higher than TL0, gaining
330 // quality at the expense of frame rate at TL0. Constraints:
331 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
332 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
333 target_bitrate_kbps =
334 std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
335 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
336 }
337
338 return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
339}
340
Erik Språng2c4c9142015-06-24 11:24:44 +0200341bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
Erik Språng08127a92016-11-16 16:41:30 +0100342 bool cfg_updated = false;
sprangc7805db2016-11-25 08:09:43 -0800343 uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
344 if (bitrate_updated_ || cfg->rc_target_bitrate != target_bitrate_kbps) {
345 cfg->rc_target_bitrate = target_bitrate_kbps;
Erik Språng08127a92016-11-16 16:41:30 +0100346
347 // Don't reconfigure qp limits during quality boost frames.
348 if (active_layer_ == -1 ||
349 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
350 min_qp_ = cfg->rc_min_quantizer;
351 max_qp_ = cfg->rc_max_quantizer;
352 // After a dropped frame, a frame with max qp will be encoded and the
353 // quality will then ramp up from there. To boost the speed of recovery,
sprang916170a2017-05-23 07:47:55 -0700354 // encode the next frame with lower max qp, if there is sufficient
355 // bandwidth to do so without causing excessive delay.
356 // TL0 is the most important to improve since the errors in this layer
357 // will propagate to TL1.
Erik Språng08127a92016-11-16 16:41:30 +0100358 // Currently, reduce max qp by 20% for TL0 and 15% for TL1.
sprang916170a2017-05-23 07:47:55 -0700359 if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
360 layers_[0].enhanced_max_qp =
361 min_qp_ + (((max_qp_ - min_qp_) * 80) / 100);
362 layers_[1].enhanced_max_qp =
363 min_qp_ + (((max_qp_ - min_qp_) * 85) / 100);
364 } else {
365 layers_[0].enhanced_max_qp = -1;
366 layers_[1].enhanced_max_qp = -1;
367 }
Erik Språng08127a92016-11-16 16:41:30 +0100368 }
369
sprang0ad0de62017-01-11 05:01:32 -0800370 if (capture_framerate_) {
sprangac4a90d2016-12-28 05:58:07 -0800371 int avg_frame_size =
sprang0ad0de62017-01-11 05:01:32 -0800372 (target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
sprang916170a2017-05-23 07:47:55 -0700373 // Allow max debt to be the size of a single optimal frame.
374 // TODO(sprang): Determine if this needs to be adjusted by some factor.
375 // (Lower values may cause more frame drops, higher may lead to queuing
376 // delays.)
377 max_debt_bytes_ = avg_frame_size;
Erik Språng08127a92016-11-16 16:41:30 +0100378 }
379
380 bitrate_updated_ = false;
381 cfg_updated = true;
382 }
383
384 // Don't try to update boosts state if not active yet.
385 if (active_layer_ == -1)
386 return cfg_updated;
387
sprangef7228c2015-08-05 02:01:29 -0700388 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1)
Erik Språng08127a92016-11-16 16:41:30 +0100389 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200390
391 // If layer is in the quality boost state (following a dropped frame), update
392 // the configuration with the adjusted (lower) qp and set the state back to
393 // normal.
394 unsigned int adjusted_max_qp;
395 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost &&
396 layers_[active_layer_].enhanced_max_qp != -1) {
397 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
398 layers_[active_layer_].state = TemporalLayer::State::kNormal;
399 } else {
Erik Språng2c4c9142015-06-24 11:24:44 +0200400 adjusted_max_qp = max_qp_; // Set the normal max qp.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000401 }
Erik Språng2c4c9142015-06-24 11:24:44 +0200402
403 if (adjusted_max_qp == cfg->rc_max_quantizer)
Erik Språng08127a92016-11-16 16:41:30 +0100404 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200405
406 cfg->rc_max_quantizer = adjusted_max_qp;
Erik Språng08127a92016-11-16 16:41:30 +0100407 cfg_updated = true;
sprangc7805db2016-11-25 08:09:43 -0800408
Erik Språng08127a92016-11-16 16:41:30 +0100409 return cfg_updated;
Erik Språng2c4c9142015-06-24 11:24:44 +0200410}
411
412void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
413 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
414 if (debt_reduction_bytes >= debt_bytes_) {
415 debt_bytes_ = 0;
416 } else {
417 debt_bytes_ -= debt_reduction_bytes;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000418 }
419}
sprang@webrtc.org70f74f32014-12-17 10:57:10 +0000420
sprangb0fdfea2016-03-01 05:51:16 -0800421void ScreenshareLayers::UpdateHistograms() {
422 if (stats_.first_frame_time_ms_ == -1)
423 return;
424 int64_t duration_sec =
425 (clock_->TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) / 1000;
426 if (duration_sec >= metrics::kMinRunTimeInSeconds) {
427 RTC_HISTOGRAM_COUNTS_10000(
428 "WebRTC.Video.Screenshare.Layer0.FrameRate",
429 (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
430 RTC_HISTOGRAM_COUNTS_10000(
431 "WebRTC.Video.Screenshare.Layer1.FrameRate",
432 (stats_.num_tl1_frames_ + (duration_sec / 2)) / duration_sec);
433 int total_frames = stats_.num_tl0_frames_ + stats_.num_tl1_frames_;
asapersson58d992e2016-03-29 02:15:06 -0700434 RTC_HISTOGRAM_COUNTS_10000(
435 "WebRTC.Video.Screenshare.FramesPerDrop",
436 (stats_.num_dropped_frames_ == 0 ? 0 : total_frames /
437 stats_.num_dropped_frames_));
438 RTC_HISTOGRAM_COUNTS_10000(
439 "WebRTC.Video.Screenshare.FramesPerOvershoot",
440 (stats_.num_overshoots_ == 0 ? 0
441 : total_frames / stats_.num_overshoots_));
sprangb0fdfea2016-03-01 05:51:16 -0800442 if (stats_.num_tl0_frames_ > 0) {
443 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer0.Qp",
444 stats_.tl0_qp_sum_ / stats_.num_tl0_frames_);
445 RTC_HISTOGRAM_COUNTS_10000(
446 "WebRTC.Video.Screenshare.Layer0.TargetBitrate",
447 stats_.tl0_target_bitrate_sum_ / stats_.num_tl0_frames_);
448 }
449 if (stats_.num_tl1_frames_ > 0) {
450 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
451 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
452 RTC_HISTOGRAM_COUNTS_10000(
453 "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
454 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
455 }
456 }
457}
458
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000459} // namespace webrtc