• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/video_coding/svc/svc_rate_allocator.h"
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <cstddef>
16 #include <numeric>
17 #include <vector>
18 
19 #include "absl/container/inlined_vector.h"
20 #include "modules/video_coding/svc/create_scalability_structure.h"
21 #include "rtc_base/checks.h"
22 
23 namespace webrtc {
24 namespace {
25 
26 constexpr float kSpatialLayeringRateScalingFactor = 0.55f;
27 constexpr float kTemporalLayeringRateScalingFactor = 0.55f;
28 
29 struct ActiveSpatialLayers {
30   size_t first = 0;
31   size_t num = 0;
32 };
33 
GetActiveSpatialLayers(const VideoCodec & codec,size_t num_spatial_layers)34 ActiveSpatialLayers GetActiveSpatialLayers(const VideoCodec& codec,
35                                            size_t num_spatial_layers) {
36   ActiveSpatialLayers active;
37   for (active.first = 0; active.first < num_spatial_layers; ++active.first) {
38     if (codec.spatialLayers[active.first].active) {
39       break;
40     }
41   }
42 
43   size_t last_active_layer = active.first;
44   for (; last_active_layer < num_spatial_layers; ++last_active_layer) {
45     if (!codec.spatialLayers[last_active_layer].active) {
46       break;
47     }
48   }
49   active.num = last_active_layer - active.first;
50 
51   return active;
52 }
53 
AdjustAndVerify(const VideoCodec & codec,size_t first_active_layer,const std::vector<DataRate> & spatial_layer_rates)54 std::vector<DataRate> AdjustAndVerify(
55     const VideoCodec& codec,
56     size_t first_active_layer,
57     const std::vector<DataRate>& spatial_layer_rates) {
58   std::vector<DataRate> adjusted_spatial_layer_rates;
59   // Keep track of rate that couldn't be applied to the previous layer due to
60   // max bitrate constraint, try to pass it forward to the next one.
61   DataRate excess_rate = DataRate::Zero();
62   for (size_t sl_idx = 0; sl_idx < spatial_layer_rates.size(); ++sl_idx) {
63     DataRate min_rate = DataRate::KilobitsPerSec(
64         codec.spatialLayers[first_active_layer + sl_idx].minBitrate);
65     DataRate max_rate = DataRate::KilobitsPerSec(
66         codec.spatialLayers[first_active_layer + sl_idx].maxBitrate);
67 
68     DataRate layer_rate = spatial_layer_rates[sl_idx] + excess_rate;
69     if (layer_rate < min_rate) {
70       // Not enough rate to reach min bitrate for desired number of layers,
71       // abort allocation.
72       if (spatial_layer_rates.size() == 1) {
73         return spatial_layer_rates;
74       }
75       return adjusted_spatial_layer_rates;
76     }
77 
78     if (layer_rate <= max_rate) {
79       excess_rate = DataRate::Zero();
80       adjusted_spatial_layer_rates.push_back(layer_rate);
81     } else {
82       excess_rate = layer_rate - max_rate;
83       adjusted_spatial_layer_rates.push_back(max_rate);
84     }
85   }
86 
87   return adjusted_spatial_layer_rates;
88 }
89 
SplitBitrate(size_t num_layers,DataRate total_bitrate,float rate_scaling_factor)90 static std::vector<DataRate> SplitBitrate(size_t num_layers,
91                                           DataRate total_bitrate,
92                                           float rate_scaling_factor) {
93   std::vector<DataRate> bitrates;
94 
95   double denominator = 0.0;
96   for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
97     denominator += std::pow(rate_scaling_factor, layer_idx);
98   }
99 
100   double numerator = std::pow(rate_scaling_factor, num_layers - 1);
101   for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
102     bitrates.push_back(numerator * total_bitrate / denominator);
103     numerator /= rate_scaling_factor;
104   }
105 
106   const DataRate sum =
107       std::accumulate(bitrates.begin(), bitrates.end(), DataRate::Zero());
108 
109   // Keep the sum of split bitrates equal to the total bitrate by adding or
110   // subtracting bits, which were lost due to rounding, to the latest layer.
111   if (total_bitrate > sum) {
112     bitrates.back() += total_bitrate - sum;
113   } else if (total_bitrate < sum) {
114     bitrates.back() -= sum - total_bitrate;
115   }
116 
117   return bitrates;
118 }
119 
120 // Returns the minimum bitrate needed for `num_active_layers` spatial layers to
121 // become active using the configuration specified by `codec`.
FindLayerTogglingThreshold(const VideoCodec & codec,size_t first_active_layer,size_t num_active_layers)122 DataRate FindLayerTogglingThreshold(const VideoCodec& codec,
123                                     size_t first_active_layer,
124                                     size_t num_active_layers) {
125   if (num_active_layers == 1) {
126     return DataRate::KilobitsPerSec(codec.spatialLayers[0].minBitrate);
127   }
128 
129   if (codec.mode == VideoCodecMode::kRealtimeVideo) {
130     DataRate lower_bound = DataRate::Zero();
131     DataRate upper_bound = DataRate::Zero();
132     if (num_active_layers > 1) {
133       for (size_t i = 0; i < num_active_layers - 1; ++i) {
134         lower_bound += DataRate::KilobitsPerSec(
135             codec.spatialLayers[first_active_layer + i].minBitrate);
136         upper_bound += DataRate::KilobitsPerSec(
137             codec.spatialLayers[first_active_layer + i].maxBitrate);
138       }
139     }
140     upper_bound += DataRate::KilobitsPerSec(
141         codec.spatialLayers[first_active_layer + num_active_layers - 1]
142             .minBitrate);
143 
144     // Do a binary search until upper and lower bound is the highest bitrate for
145     // `num_active_layers` - 1 layers and lowest bitrate for `num_active_layers`
146     // layers respectively.
147     while (upper_bound - lower_bound > DataRate::BitsPerSec(1)) {
148       DataRate try_rate = (lower_bound + upper_bound) / 2;
149       if (AdjustAndVerify(codec, first_active_layer,
150                           SplitBitrate(num_active_layers, try_rate,
151                                        kSpatialLayeringRateScalingFactor))
152               .size() == num_active_layers) {
153         upper_bound = try_rate;
154       } else {
155         lower_bound = try_rate;
156       }
157     }
158     return upper_bound;
159   } else {
160     DataRate toggling_rate = DataRate::Zero();
161     for (size_t i = 0; i < num_active_layers - 1; ++i) {
162       toggling_rate += DataRate::KilobitsPerSec(
163           codec.spatialLayers[first_active_layer + i].targetBitrate);
164     }
165     toggling_rate += DataRate::KilobitsPerSec(
166         codec.spatialLayers[first_active_layer + num_active_layers - 1]
167             .minBitrate);
168     return toggling_rate;
169   }
170 }
171 
172 }  // namespace
173 
GetNumLayers(const VideoCodec & codec)174 SvcRateAllocator::NumLayers SvcRateAllocator::GetNumLayers(
175     const VideoCodec& codec) {
176   NumLayers layers;
177   if (absl::optional<ScalabilityMode> scalability_mode =
178           codec.GetScalabilityMode();
179       scalability_mode.has_value()) {
180     if (auto structure = CreateScalabilityStructure(*scalability_mode)) {
181       ScalableVideoController::StreamLayersConfig config =
182           structure->StreamConfig();
183       layers.spatial = config.num_spatial_layers;
184       layers.temporal = config.num_temporal_layers;
185       return layers;
186     }
187   }
188   if (codec.codecType == kVideoCodecVP9) {
189     layers.spatial = codec.VP9().numberOfSpatialLayers;
190     layers.temporal = codec.VP9().numberOfTemporalLayers;
191     return layers;
192   }
193   layers.spatial = 1;
194   layers.temporal = 1;
195   return layers;
196 }
197 
SvcRateAllocator(const VideoCodec & codec)198 SvcRateAllocator::SvcRateAllocator(const VideoCodec& codec)
199     : codec_(codec),
200       num_layers_(GetNumLayers(codec)),
201       experiment_settings_(StableTargetRateExperiment::ParseFromFieldTrials()),
202       cumulative_layer_start_bitrates_(GetLayerStartBitrates(codec)),
203       last_active_layer_count_(0) {
204   RTC_DCHECK_GT(num_layers_.spatial, 0);
205   RTC_DCHECK_LE(num_layers_.spatial, kMaxSpatialLayers);
206   RTC_DCHECK_GT(num_layers_.temporal, 0);
207   RTC_DCHECK_LE(num_layers_.temporal, 3);
208   for (size_t layer_idx = 0; layer_idx < num_layers_.spatial; ++layer_idx) {
209     // Verify min <= target <= max.
210     if (codec.spatialLayers[layer_idx].active) {
211       RTC_DCHECK_GT(codec.spatialLayers[layer_idx].maxBitrate, 0);
212       RTC_DCHECK_GE(codec.spatialLayers[layer_idx].maxBitrate,
213                     codec.spatialLayers[layer_idx].minBitrate);
214       RTC_DCHECK_GE(codec.spatialLayers[layer_idx].targetBitrate,
215                     codec.spatialLayers[layer_idx].minBitrate);
216       RTC_DCHECK_GE(codec.spatialLayers[layer_idx].maxBitrate,
217                     codec.spatialLayers[layer_idx].targetBitrate);
218     }
219   }
220 }
221 
Allocate(VideoBitrateAllocationParameters parameters)222 VideoBitrateAllocation SvcRateAllocator::Allocate(
223     VideoBitrateAllocationParameters parameters) {
224   DataRate total_bitrate = parameters.total_bitrate;
225   if (codec_.maxBitrate != 0) {
226     total_bitrate =
227         std::min(total_bitrate, DataRate::KilobitsPerSec(codec_.maxBitrate));
228   }
229 
230   if (codec_.spatialLayers[0].targetBitrate == 0) {
231     // Delegate rate distribution to encoder wrapper if bitrate thresholds
232     // are not set.
233     VideoBitrateAllocation bitrate_allocation;
234     bitrate_allocation.SetBitrate(0, 0, total_bitrate.bps());
235     return bitrate_allocation;
236   }
237 
238   const ActiveSpatialLayers active_layers =
239       GetActiveSpatialLayers(codec_, num_layers_.spatial);
240   size_t num_spatial_layers = active_layers.num;
241 
242   if (num_spatial_layers == 0) {
243     return VideoBitrateAllocation();  // All layers are deactivated.
244   }
245 
246   // Figure out how many spatial layers should be active.
247   if (experiment_settings_.IsEnabled() &&
248       parameters.stable_bitrate > DataRate::Zero()) {
249     double hysteresis_factor;
250     if (codec_.mode == VideoCodecMode::kScreensharing) {
251       hysteresis_factor = experiment_settings_.GetScreenshareHysteresisFactor();
252     } else {
253       hysteresis_factor = experiment_settings_.GetVideoHysteresisFactor();
254     }
255 
256     DataRate stable_rate =
257         std::min(parameters.total_bitrate, parameters.stable_bitrate);
258     // First check if bitrate has grown large enough to enable new layers.
259     size_t num_enabled_with_hysteresis =
260         FindNumEnabledLayers(stable_rate / hysteresis_factor);
261     if (num_enabled_with_hysteresis >= last_active_layer_count_) {
262       num_spatial_layers = num_enabled_with_hysteresis;
263     } else {
264       // We could not enable new layers, check if any should be disabled.
265       num_spatial_layers =
266           std::min(last_active_layer_count_, FindNumEnabledLayers(stable_rate));
267     }
268   } else {
269     num_spatial_layers = FindNumEnabledLayers(parameters.total_bitrate);
270   }
271   last_active_layer_count_ = num_spatial_layers;
272 
273   VideoBitrateAllocation allocation;
274   if (codec_.mode == VideoCodecMode::kRealtimeVideo) {
275     allocation = GetAllocationNormalVideo(total_bitrate, active_layers.first,
276                                           num_spatial_layers);
277   } else {
278     allocation = GetAllocationScreenSharing(total_bitrate, active_layers.first,
279                                             num_spatial_layers);
280   }
281   allocation.set_bw_limited(num_spatial_layers < active_layers.num);
282   return allocation;
283 }
284 
GetAllocationNormalVideo(DataRate total_bitrate,size_t first_active_layer,size_t num_spatial_layers) const285 VideoBitrateAllocation SvcRateAllocator::GetAllocationNormalVideo(
286     DataRate total_bitrate,
287     size_t first_active_layer,
288     size_t num_spatial_layers) const {
289   std::vector<DataRate> spatial_layer_rates;
290   if (num_spatial_layers == 0) {
291     // Not enough rate for even the base layer. Force allocation at the total
292     // bitrate anyway.
293     num_spatial_layers = 1;
294     spatial_layer_rates.push_back(total_bitrate);
295   } else {
296     spatial_layer_rates =
297         AdjustAndVerify(codec_, first_active_layer,
298                         SplitBitrate(num_spatial_layers, total_bitrate,
299                                      kSpatialLayeringRateScalingFactor));
300     RTC_DCHECK_EQ(spatial_layer_rates.size(), num_spatial_layers);
301   }
302 
303   VideoBitrateAllocation bitrate_allocation;
304 
305   for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
306     std::vector<DataRate> temporal_layer_rates =
307         SplitBitrate(num_layers_.temporal, spatial_layer_rates[sl_idx],
308                      kTemporalLayeringRateScalingFactor);
309 
310     // Distribute rate across temporal layers. Allocate more bits to lower
311     // layers since they are used for prediction of higher layers and their
312     // references are far apart.
313     if (num_layers_.temporal == 1) {
314       bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
315                                     temporal_layer_rates[0].bps());
316     } else if (num_layers_.temporal == 2) {
317       bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
318                                     temporal_layer_rates[1].bps());
319       bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
320                                     temporal_layer_rates[0].bps());
321     } else {
322       RTC_CHECK_EQ(num_layers_.temporal, 3);
323       // In case of three temporal layers the high layer has two frames and the
324       // middle layer has one frame within GOP (in between two consecutive low
325       // layer frames). Thus high layer requires more bits (comparing pure
326       // bitrate of layer, excluding bitrate of base layers) to keep quality on
327       // par with lower layers.
328       bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
329                                     temporal_layer_rates[2].bps());
330       bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
331                                     temporal_layer_rates[0].bps());
332       bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 2,
333                                     temporal_layer_rates[1].bps());
334     }
335   }
336 
337   return bitrate_allocation;
338 }
339 
340 // Bit-rate is allocated in such a way, that the highest enabled layer will have
341 // between min and max bitrate, and all others will have exactly target
342 // bit-rate allocated.
GetAllocationScreenSharing(DataRate total_bitrate,size_t first_active_layer,size_t num_spatial_layers) const343 VideoBitrateAllocation SvcRateAllocator::GetAllocationScreenSharing(
344     DataRate total_bitrate,
345     size_t first_active_layer,
346     size_t num_spatial_layers) const {
347   VideoBitrateAllocation bitrate_allocation;
348 
349   if (num_spatial_layers == 0 ||
350       total_bitrate <
351           DataRate::KilobitsPerSec(
352               codec_.spatialLayers[first_active_layer].minBitrate)) {
353     // Always enable at least one layer.
354     bitrate_allocation.SetBitrate(first_active_layer, 0, total_bitrate.bps());
355     return bitrate_allocation;
356   }
357 
358   DataRate allocated_rate = DataRate::Zero();
359   DataRate top_layer_rate = DataRate::Zero();
360   size_t sl_idx;
361   for (sl_idx = first_active_layer;
362        sl_idx < first_active_layer + num_spatial_layers; ++sl_idx) {
363     const DataRate min_rate =
364         DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx].minBitrate);
365     const DataRate target_rate =
366         DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx].targetBitrate);
367 
368     if (allocated_rate + min_rate > total_bitrate) {
369       // Use stable rate to determine if layer should be enabled.
370       break;
371     }
372 
373     top_layer_rate = std::min(target_rate, total_bitrate - allocated_rate);
374     bitrate_allocation.SetBitrate(sl_idx, 0, top_layer_rate.bps());
375     allocated_rate += top_layer_rate;
376   }
377 
378   if (sl_idx > 0 && total_bitrate - allocated_rate > DataRate::Zero()) {
379     // Add leftover to the last allocated layer.
380     top_layer_rate = std::min(
381         top_layer_rate + (total_bitrate - allocated_rate),
382         DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx - 1].maxBitrate));
383     bitrate_allocation.SetBitrate(sl_idx - 1, 0, top_layer_rate.bps());
384   }
385 
386   return bitrate_allocation;
387 }
388 
FindNumEnabledLayers(DataRate target_rate) const389 size_t SvcRateAllocator::FindNumEnabledLayers(DataRate target_rate) const {
390   if (cumulative_layer_start_bitrates_.empty()) {
391     return 0;
392   }
393 
394   size_t num_enabled_layers = 0;
395   for (DataRate start_rate : cumulative_layer_start_bitrates_) {
396     // First layer is always enabled.
397     if (num_enabled_layers == 0 || start_rate <= target_rate) {
398       ++num_enabled_layers;
399     } else {
400       break;
401     }
402   }
403 
404   return num_enabled_layers;
405 }
406 
GetMaxBitrate(const VideoCodec & codec)407 DataRate SvcRateAllocator::GetMaxBitrate(const VideoCodec& codec) {
408   const NumLayers num_layers = GetNumLayers(codec);
409   const ActiveSpatialLayers active_layers =
410       GetActiveSpatialLayers(codec, num_layers.spatial);
411 
412   DataRate max_bitrate = DataRate::Zero();
413   for (size_t sl_idx = 0; sl_idx < active_layers.num; ++sl_idx) {
414     max_bitrate += DataRate::KilobitsPerSec(
415         codec.spatialLayers[active_layers.first + sl_idx].maxBitrate);
416   }
417 
418   if (codec.maxBitrate != 0) {
419     max_bitrate =
420         std::min(max_bitrate, DataRate::KilobitsPerSec(codec.maxBitrate));
421   }
422 
423   return max_bitrate;
424 }
425 
GetPaddingBitrate(const VideoCodec & codec)426 DataRate SvcRateAllocator::GetPaddingBitrate(const VideoCodec& codec) {
427   auto start_bitrate = GetLayerStartBitrates(codec);
428   if (start_bitrate.empty()) {
429     return DataRate::Zero();  // All layers are deactivated.
430   }
431 
432   return start_bitrate.back();
433 }
434 
435 absl::InlinedVector<DataRate, kMaxSpatialLayers>
GetLayerStartBitrates(const VideoCodec & codec)436 SvcRateAllocator::GetLayerStartBitrates(const VideoCodec& codec) {
437   absl::InlinedVector<DataRate, kMaxSpatialLayers> start_bitrates;
438   const NumLayers num_layers = GetNumLayers(codec);
439   const ActiveSpatialLayers active_layers =
440       GetActiveSpatialLayers(codec, num_layers.spatial);
441   DataRate last_rate = DataRate::Zero();
442   for (size_t i = 1; i <= active_layers.num; ++i) {
443     DataRate layer_toggling_rate =
444         FindLayerTogglingThreshold(codec, active_layers.first, i);
445     start_bitrates.push_back(layer_toggling_rate);
446     RTC_DCHECK_LE(last_rate, layer_toggling_rate);
447     last_rate = layer_toggling_rate;
448   }
449   return start_bitrates;
450 }
451 
452 }  // namespace webrtc
453