xref: /aosp_15_r20/external/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /* 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 "modules/video_coding/codecs/vp8/screenshare_layers.h"
11 
12 #include <stdlib.h>
13 
14 #include <algorithm>
15 #include <memory>
16 
17 #include "modules/video_coding/include/video_codec_interface.h"
18 #include "rtc_base/arraysize.h"
19 #include "rtc_base/checks.h"
20 #include "rtc_base/logging.h"
21 #include "rtc_base/time_utils.h"
22 #include "system_wrappers/include/metrics.h"
23 
24 namespace webrtc {
25 namespace {
26 using BufferFlags = Vp8FrameConfig::BufferFlags;
27 
28 constexpr BufferFlags kNone = Vp8FrameConfig::BufferFlags::kNone;
29 constexpr BufferFlags kReference = Vp8FrameConfig::BufferFlags::kReference;
30 constexpr BufferFlags kUpdate = Vp8FrameConfig::BufferFlags::kUpdate;
31 constexpr BufferFlags kReferenceAndUpdate =
32     Vp8FrameConfig::BufferFlags::kReferenceAndUpdate;
33 
34 constexpr int kOneSecond90Khz = 90000;
35 constexpr int kMinTimeBetweenSyncs = kOneSecond90Khz * 2;
36 constexpr int kMaxTimeBetweenSyncs = kOneSecond90Khz * 4;
37 constexpr int kQpDeltaThresholdForSync = 8;
38 constexpr int kMinBitrateKbpsForQpBoost = 500;
39 constexpr auto kSwitch = DecodeTargetIndication::kSwitch;
40 }  // namespace
41 
42 const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5;
43 const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
44 
45 constexpr int ScreenshareLayers::kMaxNumTemporalLayers;
46 
47 // Always emit a frame with certain interval, even if bitrate targets have
48 // been exceeded. This prevents needless keyframe requests.
49 const int ScreenshareLayers::kMaxFrameIntervalMs = 2750;
50 
ScreenshareLayers(int num_temporal_layers)51 ScreenshareLayers::ScreenshareLayers(int num_temporal_layers)
52     : number_of_temporal_layers_(
53           std::min(kMaxNumTemporalLayers, num_temporal_layers)),
54       active_layer_(-1),
55       last_timestamp_(-1),
56       last_sync_timestamp_(-1),
57       last_emitted_tl0_timestamp_(-1),
58       last_frame_time_ms_(-1),
59       max_debt_bytes_(0),
60       encode_framerate_(1000.0f, 1000.0f),  // 1 second window, second scale.
61       bitrate_updated_(false),
62       checker_(TemporalLayersChecker::CreateTemporalLayersChecker(
63           Vp8TemporalLayersType::kBitrateDynamic,
64           num_temporal_layers)) {
65   RTC_CHECK_GT(number_of_temporal_layers_, 0);
66   RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers);
67 }
68 
~ScreenshareLayers()69 ScreenshareLayers::~ScreenshareLayers() {
70   UpdateHistograms();
71 }
72 
SetQpLimits(size_t stream_index,int min_qp,int max_qp)73 void ScreenshareLayers::SetQpLimits(size_t stream_index,
74                                     int min_qp,
75                                     int max_qp) {
76   RTC_DCHECK_LT(stream_index, StreamCount());
77   // 0 < min_qp <= max_qp
78   RTC_DCHECK_LT(0, min_qp);
79   RTC_DCHECK_LE(min_qp, max_qp);
80 
81   RTC_DCHECK_EQ(min_qp_.has_value(), max_qp_.has_value());
82   if (!min_qp_.has_value()) {
83     min_qp_ = min_qp;
84     max_qp_ = max_qp;
85   } else {
86     RTC_DCHECK_EQ(min_qp, min_qp_.value());
87     RTC_DCHECK_EQ(max_qp, max_qp_.value());
88   }
89 }
90 
StreamCount() const91 size_t ScreenshareLayers::StreamCount() const {
92   return 1;
93 }
94 
SupportsEncoderFrameDropping(size_t stream_index) const95 bool ScreenshareLayers::SupportsEncoderFrameDropping(
96     size_t stream_index) const {
97   RTC_DCHECK_LT(stream_index, StreamCount());
98   // Frame dropping is handled internally by this class.
99   return false;
100 }
101 
NextFrameConfig(size_t stream_index,uint32_t timestamp)102 Vp8FrameConfig ScreenshareLayers::NextFrameConfig(size_t stream_index,
103                                                   uint32_t timestamp) {
104   RTC_DCHECK_LT(stream_index, StreamCount());
105 
106   auto it = pending_frame_configs_.find(timestamp);
107   if (it != pending_frame_configs_.end()) {
108     // Drop and re-encode, reuse the previous config.
109     return it->second.frame_config;
110   }
111 
112   if (number_of_temporal_layers_ <= 1) {
113     // No flags needed for 1 layer screenshare.
114     // TODO(pbos): Consider updating only last, and not all buffers.
115     DependencyInfo dependency_info{
116         "S", {kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate}};
117     pending_frame_configs_[timestamp] = dependency_info;
118     return dependency_info.frame_config;
119   }
120 
121   const int64_t now_ms = rtc::TimeMillis();
122 
123   int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
124   int64_t ts_diff;
125   if (last_timestamp_ == -1) {
126     ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
127   } else {
128     ts_diff = unwrapped_timestamp - last_timestamp_;
129   }
130 
131   if (target_framerate_) {
132     // If input frame rate exceeds target frame rate, either over a one second
133     // averaging window, or if frame interval is below 90% of desired value,
134     // drop frame.
135     if (encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_)
136       return Vp8FrameConfig(kNone, kNone, kNone);
137 
138     // Primarily check if frame interval is too short using frame timestamps,
139     // as if they are correct they won't be affected by queuing in webrtc.
140     const int64_t expected_frame_interval_90khz =
141         kOneSecond90Khz / *target_framerate_;
142     if (last_timestamp_ != -1 && ts_diff > 0) {
143       if (ts_diff < 85 * expected_frame_interval_90khz / 100) {
144         return Vp8FrameConfig(kNone, kNone, kNone);
145       }
146     } else {
147       // Timestamps looks off, use realtime clock here instead.
148       const int64_t expected_frame_interval_ms = 1000 / *target_framerate_;
149       if (last_frame_time_ms_ != -1 &&
150           now_ms - last_frame_time_ms_ <
151               (85 * expected_frame_interval_ms) / 100) {
152         return Vp8FrameConfig(kNone, kNone, kNone);
153       }
154     }
155   }
156 
157   if (stats_.first_frame_time_ms_ == -1)
158     stats_.first_frame_time_ms_ = now_ms;
159 
160   // Make sure both frame droppers leak out bits.
161   layers_[0].UpdateDebt(ts_diff / 90);
162   layers_[1].UpdateDebt(ts_diff / 90);
163   last_timestamp_ = timestamp;
164   last_frame_time_ms_ = now_ms;
165 
166   TemporalLayerState layer_state = TemporalLayerState::kDrop;
167 
168   if (active_layer_ == -1 ||
169       layers_[active_layer_].state != TemporalLayer::State::kDropped) {
170     if (last_emitted_tl0_timestamp_ != -1 &&
171         (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
172             kMaxFrameIntervalMs) {
173       // Too long time has passed since the last frame was emitted, cancel
174       // enough debt to allow a single frame.
175       layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
176     }
177     if (layers_[0].debt_bytes_ > max_debt_bytes_) {
178       // Must drop TL0, encode TL1 instead.
179       if (layers_[1].debt_bytes_ > max_debt_bytes_) {
180         // Must drop both TL0 and TL1.
181         active_layer_ = -1;
182       } else {
183         active_layer_ = 1;
184       }
185     } else {
186       active_layer_ = 0;
187     }
188   }
189 
190   switch (active_layer_) {
191     case 0:
192       layer_state = TemporalLayerState::kTl0;
193       last_emitted_tl0_timestamp_ = unwrapped_timestamp;
194       break;
195     case 1:
196       if (layers_[1].state != TemporalLayer::State::kDropped) {
197         if (TimeToSync(unwrapped_timestamp) ||
198             layers_[1].state == TemporalLayer::State::kKeyFrame) {
199           last_sync_timestamp_ = unwrapped_timestamp;
200           layer_state = TemporalLayerState::kTl1Sync;
201         } else {
202           layer_state = TemporalLayerState::kTl1;
203         }
204       } else {
205         layer_state = last_sync_timestamp_ == unwrapped_timestamp
206                           ? TemporalLayerState::kTl1Sync
207                           : TemporalLayerState::kTl1;
208       }
209       break;
210     case -1:
211       layer_state = TemporalLayerState::kDrop;
212       ++stats_.num_dropped_frames_;
213       break;
214     default:
215       RTC_DCHECK_NOTREACHED();
216   }
217 
218   DependencyInfo dependency_info;
219   // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
220   // layers.
221   switch (layer_state) {
222     case TemporalLayerState::kDrop:
223       dependency_info = {"", {kNone, kNone, kNone}};
224       break;
225     case TemporalLayerState::kTl0:
226       // TL0 only references and updates 'last'.
227       dependency_info = {"SS", {kReferenceAndUpdate, kNone, kNone}};
228       dependency_info.frame_config.packetizer_temporal_idx = 0;
229       break;
230     case TemporalLayerState::kTl1:
231       // TL1 references both 'last' and 'golden' but only updates 'golden'.
232       dependency_info = {"-R", {kReference, kReferenceAndUpdate, kNone}};
233       dependency_info.frame_config.packetizer_temporal_idx = 1;
234       break;
235     case TemporalLayerState::kTl1Sync:
236       // Predict from only TL0 to allow participants to switch to the high
237       // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
238       // and update 'golden' from this point on.
239       dependency_info = {"-S", {kReference, kUpdate, kNone}};
240       dependency_info.frame_config.packetizer_temporal_idx = 1;
241       dependency_info.frame_config.layer_sync = true;
242       break;
243   }
244 
245   pending_frame_configs_[timestamp] = dependency_info;
246   return dependency_info.frame_config;
247 }
248 
OnRatesUpdated(size_t stream_index,const std::vector<uint32_t> & bitrates_bps,int framerate_fps)249 void ScreenshareLayers::OnRatesUpdated(
250     size_t stream_index,
251     const std::vector<uint32_t>& bitrates_bps,
252     int framerate_fps) {
253   RTC_DCHECK_LT(stream_index, StreamCount());
254   RTC_DCHECK_GT(framerate_fps, 0);
255   RTC_DCHECK_GE(bitrates_bps.size(), 1);
256   RTC_DCHECK_LE(bitrates_bps.size(), 2);
257 
258   // `bitrates_bps` uses individual rates per layer, but we want to use the
259   // accumulated rate here.
260   uint32_t tl0_kbps = bitrates_bps[0] / 1000;
261   uint32_t tl1_kbps = tl0_kbps;
262   if (bitrates_bps.size() > 1) {
263     tl1_kbps += bitrates_bps[1] / 1000;
264   }
265 
266   if (!target_framerate_) {
267     // First OnRatesUpdated() is called during construction, with the
268     // configured targets as parameters.
269     target_framerate_ = framerate_fps;
270     capture_framerate_ = target_framerate_;
271     bitrate_updated_ = true;
272   } else {
273     if ((capture_framerate_ &&
274          framerate_fps != static_cast<int>(*capture_framerate_)) ||
275         (tl0_kbps != layers_[0].target_rate_kbps_) ||
276         (tl1_kbps != layers_[1].target_rate_kbps_)) {
277       bitrate_updated_ = true;
278     }
279 
280     if (framerate_fps < 0) {
281       capture_framerate_.reset();
282     } else {
283       capture_framerate_ = framerate_fps;
284     }
285   }
286 
287   layers_[0].target_rate_kbps_ = tl0_kbps;
288   layers_[1].target_rate_kbps_ = tl1_kbps;
289 }
290 
OnEncodeDone(size_t stream_index,uint32_t rtp_timestamp,size_t size_bytes,bool is_keyframe,int qp,CodecSpecificInfo * info)291 void ScreenshareLayers::OnEncodeDone(size_t stream_index,
292                                      uint32_t rtp_timestamp,
293                                      size_t size_bytes,
294                                      bool is_keyframe,
295                                      int qp,
296                                      CodecSpecificInfo* info) {
297   RTC_DCHECK_LT(stream_index, StreamCount());
298 
299   if (size_bytes == 0) {
300     RTC_LOG(LS_WARNING) << "Empty frame; treating as dropped.";
301     OnFrameDropped(stream_index, rtp_timestamp);
302     return;
303   }
304 
305   absl::optional<DependencyInfo> dependency_info;
306   auto it = pending_frame_configs_.find(rtp_timestamp);
307   if (it != pending_frame_configs_.end()) {
308     dependency_info = it->second;
309     pending_frame_configs_.erase(it);
310 
311     if (checker_) {
312       RTC_DCHECK(checker_->CheckTemporalConfig(is_keyframe,
313                                                dependency_info->frame_config));
314     }
315   }
316 
317   CodecSpecificInfoVP8& vp8_info = info->codecSpecific.VP8;
318   GenericFrameInfo& generic_frame_info = info->generic_frame_info.emplace();
319 
320   if (number_of_temporal_layers_ == 1) {
321     vp8_info.temporalIdx = kNoTemporalIdx;
322     vp8_info.layerSync = false;
323     generic_frame_info.temporal_id = 0;
324     generic_frame_info.decode_target_indications = {kSwitch};
325     generic_frame_info.encoder_buffers.emplace_back(
326         0, /*referenced=*/!is_keyframe, /*updated=*/true);
327   } else {
328     int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(rtp_timestamp);
329     if (dependency_info) {
330       vp8_info.temporalIdx =
331           dependency_info->frame_config.packetizer_temporal_idx;
332       vp8_info.layerSync = dependency_info->frame_config.layer_sync;
333       generic_frame_info.temporal_id = vp8_info.temporalIdx;
334       generic_frame_info.decode_target_indications =
335           dependency_info->decode_target_indications;
336     } else {
337       RTC_DCHECK(is_keyframe);
338     }
339 
340     if (is_keyframe) {
341       vp8_info.temporalIdx = 0;
342       last_sync_timestamp_ = unwrapped_timestamp;
343       vp8_info.layerSync = true;
344       layers_[0].state = TemporalLayer::State::kKeyFrame;
345       layers_[1].state = TemporalLayer::State::kKeyFrame;
346       active_layer_ = 1;
347       info->template_structure =
348           GetTemplateStructure(number_of_temporal_layers_);
349       generic_frame_info.temporal_id = vp8_info.temporalIdx;
350       generic_frame_info.decode_target_indications = {kSwitch, kSwitch};
351     } else if (active_layer_ >= 0 && layers_[active_layer_].state ==
352                                          TemporalLayer::State::kKeyFrame) {
353       layers_[active_layer_].state = TemporalLayer::State::kNormal;
354     }
355 
356     vp8_info.useExplicitDependencies = true;
357     RTC_DCHECK_EQ(vp8_info.referencedBuffersCount, 0u);
358     RTC_DCHECK_EQ(vp8_info.updatedBuffersCount, 0u);
359 
360     // Note that `frame_config` is not derefernced if `is_keyframe`,
361     // meaning it's never dereferenced if the optional may be unset.
362     for (int i = 0; i < static_cast<int>(Vp8FrameConfig::Buffer::kCount); ++i) {
363       bool references = false;
364       bool updates = is_keyframe;
365       if (!is_keyframe && dependency_info->frame_config.References(
366                               static_cast<Vp8FrameConfig::Buffer>(i))) {
367         RTC_DCHECK_LT(vp8_info.referencedBuffersCount,
368                       arraysize(CodecSpecificInfoVP8::referencedBuffers));
369         references = true;
370         vp8_info.referencedBuffers[vp8_info.referencedBuffersCount++] = i;
371       }
372 
373       if (is_keyframe || dependency_info->frame_config.Updates(
374                              static_cast<Vp8FrameConfig::Buffer>(i))) {
375         RTC_DCHECK_LT(vp8_info.updatedBuffersCount,
376                       arraysize(CodecSpecificInfoVP8::updatedBuffers));
377         updates = true;
378         vp8_info.updatedBuffers[vp8_info.updatedBuffersCount++] = i;
379       }
380 
381       if (references || updates)
382         generic_frame_info.encoder_buffers.emplace_back(i, references, updates);
383     }
384   }
385 
386   encode_framerate_.Update(1, rtc::TimeMillis());
387 
388   if (number_of_temporal_layers_ == 1)
389     return;
390 
391   RTC_DCHECK_NE(-1, active_layer_);
392   if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
393     layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
394   }
395 
396   if (qp != -1)
397     layers_[active_layer_].last_qp = qp;
398 
399   if (active_layer_ == 0) {
400     layers_[0].debt_bytes_ += size_bytes;
401     layers_[1].debt_bytes_ += size_bytes;
402     ++stats_.num_tl0_frames_;
403     stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
404     stats_.tl0_qp_sum_ += qp;
405   } else if (active_layer_ == 1) {
406     layers_[1].debt_bytes_ += size_bytes;
407     ++stats_.num_tl1_frames_;
408     stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
409     stats_.tl1_qp_sum_ += qp;
410   }
411 }
412 
OnFrameDropped(size_t stream_index,uint32_t rtp_timestamp)413 void ScreenshareLayers::OnFrameDropped(size_t stream_index,
414                                        uint32_t rtp_timestamp) {
415   layers_[active_layer_].state = TemporalLayer::State::kDropped;
416   ++stats_.num_overshoots_;
417 }
418 
OnPacketLossRateUpdate(float packet_loss_rate)419 void ScreenshareLayers::OnPacketLossRateUpdate(float packet_loss_rate) {}
420 
OnRttUpdate(int64_t rtt_ms)421 void ScreenshareLayers::OnRttUpdate(int64_t rtt_ms) {}
422 
OnLossNotification(const VideoEncoder::LossNotification & loss_notification)423 void ScreenshareLayers::OnLossNotification(
424     const VideoEncoder::LossNotification& loss_notification) {}
425 
GetTemplateStructure(int num_layers) const426 FrameDependencyStructure ScreenshareLayers::GetTemplateStructure(
427     int num_layers) const {
428   RTC_CHECK_LT(num_layers, 3);
429   RTC_CHECK_GT(num_layers, 0);
430 
431   FrameDependencyStructure template_structure;
432   template_structure.num_decode_targets = num_layers;
433 
434   switch (num_layers) {
435     case 1: {
436       template_structure.templates.resize(2);
437       template_structure.templates[0].T(0).Dtis("S");
438       template_structure.templates[1].T(0).Dtis("S").FrameDiffs({1});
439       return template_structure;
440     }
441     case 2: {
442       template_structure.templates.resize(3);
443       template_structure.templates[0].T(0).Dtis("SS");
444       template_structure.templates[1].T(0).Dtis("SS").FrameDiffs({1});
445       template_structure.templates[2].T(1).Dtis("-S").FrameDiffs({1});
446       return template_structure;
447     }
448     default:
449       RTC_DCHECK_NOTREACHED();
450       // To make the compiler happy!
451       return template_structure;
452   }
453 }
454 
TimeToSync(int64_t timestamp) const455 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
456   RTC_DCHECK_EQ(1, active_layer_);
457   RTC_DCHECK_NE(-1, layers_[0].last_qp);
458   if (layers_[1].last_qp == -1) {
459     // First frame in TL1 should only depend on TL0 since there are no
460     // previous frames in TL1.
461     return true;
462   }
463 
464   RTC_DCHECK_NE(-1, last_sync_timestamp_);
465   int64_t timestamp_diff = timestamp - last_sync_timestamp_;
466   if (timestamp_diff > kMaxTimeBetweenSyncs) {
467     // After a certain time, force a sync frame.
468     return true;
469   } else if (timestamp_diff < kMinTimeBetweenSyncs) {
470     // If too soon from previous sync frame, don't issue a new one.
471     return false;
472   }
473   // Issue a sync frame if difference in quality between TL0 and TL1 isn't too
474   // large.
475   if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync)
476     return true;
477   return false;
478 }
479 
GetCodecTargetBitrateKbps() const480 uint32_t ScreenshareLayers::GetCodecTargetBitrateKbps() const {
481   uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
482 
483   if (number_of_temporal_layers_ > 1) {
484     // Calculate a codec target bitrate. This may be higher than TL0, gaining
485     // quality at the expense of frame rate at TL0. Constraints:
486     // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
487     // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
488     target_bitrate_kbps =
489         std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
490                  layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
491   }
492 
493   return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
494 }
495 
UpdateConfiguration(size_t stream_index)496 Vp8EncoderConfig ScreenshareLayers::UpdateConfiguration(size_t stream_index) {
497   RTC_DCHECK_LT(stream_index, StreamCount());
498   RTC_DCHECK(min_qp_.has_value());
499   RTC_DCHECK(max_qp_.has_value());
500 
501   const uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
502 
503   // TODO(sprang): We _really_ need to make an overhaul of this class. :(
504   // If we're dropping frames in order to meet a target framerate, adjust the
505   // bitrate assigned to the encoder so the total average bitrate is correct.
506   float encoder_config_bitrate_kbps = target_bitrate_kbps;
507   if (target_framerate_ && capture_framerate_ &&
508       *target_framerate_ < *capture_framerate_) {
509     encoder_config_bitrate_kbps *=
510         static_cast<float>(*capture_framerate_) / *target_framerate_;
511   }
512 
513   if (bitrate_updated_ ||
514       encoder_config_.rc_target_bitrate !=
515           absl::make_optional(encoder_config_bitrate_kbps)) {
516     encoder_config_.rc_target_bitrate = encoder_config_bitrate_kbps;
517 
518     // Don't reconfigure qp limits during quality boost frames.
519     if (active_layer_ == -1 ||
520         layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
521       const int min_qp = min_qp_.value();
522       const int max_qp = max_qp_.value();
523 
524       // After a dropped frame, a frame with max qp will be encoded and the
525       // quality will then ramp up from there. To boost the speed of recovery,
526       // encode the next frame with lower max qp, if there is sufficient
527       // bandwidth to do so without causing excessive delay.
528       // TL0 is the most important to improve since the errors in this layer
529       // will propagate to TL1.
530       // Currently, reduce max qp by 20% for TL0 and 15% for TL1.
531       if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
532         layers_[0].enhanced_max_qp = min_qp + (((max_qp - min_qp) * 80) / 100);
533         layers_[1].enhanced_max_qp = min_qp + (((max_qp - min_qp) * 85) / 100);
534       } else {
535         layers_[0].enhanced_max_qp = -1;
536         layers_[1].enhanced_max_qp = -1;
537       }
538     }
539 
540     if (capture_framerate_) {
541       int avg_frame_size =
542           (target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
543       // Allow max debt to be the size of a single optimal frame.
544       // TODO(sprang): Determine if this needs to be adjusted by some factor.
545       // (Lower values may cause more frame drops, higher may lead to queuing
546       // delays.)
547       max_debt_bytes_ = avg_frame_size;
548     }
549 
550     bitrate_updated_ = false;
551   }
552 
553   // Don't try to update boosts state if not active yet.
554   if (active_layer_ == -1)
555     return encoder_config_;
556 
557   if (number_of_temporal_layers_ <= 1)
558     return encoder_config_;
559 
560   // If layer is in the quality boost state (following a dropped frame), update
561   // the configuration with the adjusted (lower) qp and set the state back to
562   // normal.
563   unsigned int adjusted_max_qp = max_qp_.value();  // Set the normal max qp.
564   if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost) {
565     if (layers_[active_layer_].enhanced_max_qp != -1) {
566       // Bitrate is high enough for quality boost, update max qp.
567       adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
568     }
569     // Regardless of qp, reset the boost state for the next frame.
570     layers_[active_layer_].state = TemporalLayer::State::kNormal;
571   }
572   encoder_config_.rc_max_quantizer = adjusted_max_qp;
573 
574   return encoder_config_;
575 }
576 
UpdateDebt(int64_t delta_ms)577 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
578   uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
579   if (debt_reduction_bytes >= debt_bytes_) {
580     debt_bytes_ = 0;
581   } else {
582     debt_bytes_ -= debt_reduction_bytes;
583   }
584 }
585 
UpdateHistograms()586 void ScreenshareLayers::UpdateHistograms() {
587   if (stats_.first_frame_time_ms_ == -1)
588     return;
589   int64_t duration_sec =
590       (rtc::TimeMillis() - stats_.first_frame_time_ms_ + 500) / 1000;
591   if (duration_sec >= metrics::kMinRunTimeInSeconds) {
592     RTC_HISTOGRAM_COUNTS_10000(
593         "WebRTC.Video.Screenshare.Layer0.FrameRate",
594         (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
595     RTC_HISTOGRAM_COUNTS_10000(
596         "WebRTC.Video.Screenshare.Layer1.FrameRate",
597         (stats_.num_tl1_frames_ + (duration_sec / 2)) / duration_sec);
598     int total_frames = stats_.num_tl0_frames_ + stats_.num_tl1_frames_;
599     RTC_HISTOGRAM_COUNTS_10000(
600         "WebRTC.Video.Screenshare.FramesPerDrop",
601         (stats_.num_dropped_frames_ == 0
602              ? 0
603              : total_frames / stats_.num_dropped_frames_));
604     RTC_HISTOGRAM_COUNTS_10000(
605         "WebRTC.Video.Screenshare.FramesPerOvershoot",
606         (stats_.num_overshoots_ == 0 ? 0
607                                      : total_frames / stats_.num_overshoots_));
608     if (stats_.num_tl0_frames_ > 0) {
609       RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer0.Qp",
610                                  stats_.tl0_qp_sum_ / stats_.num_tl0_frames_);
611       RTC_HISTOGRAM_COUNTS_10000(
612           "WebRTC.Video.Screenshare.Layer0.TargetBitrate",
613           stats_.tl0_target_bitrate_sum_ / stats_.num_tl0_frames_);
614     }
615     if (stats_.num_tl1_frames_ > 0) {
616       RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
617                                  stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
618       RTC_HISTOGRAM_COUNTS_10000(
619           "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
620           stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
621     }
622   }
623 }
624 }  // namespace webrtc
625