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