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