Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util_gn/./../../../../../../../third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util.cc
Warning:line 29, column 8
Excessive padding in 'struct webrtc::(anonymous namespace)::ScalabilityModeParameters' (10 padding bytes, where 2 is optimal). Optimal fields order: name, num_spatial_layers, num_temporal_layers, inter_layer_pred, ratio, scalability_mode, shift, consider reordering the fields or adding explicit padding members

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_ability_mode_util_gn0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util_gn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util_gn -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D ABSL_ALLOCATOR_NOTHROW=1 -D PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -D RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY -D RTC_ENABLE_VP9 -D WEBRTC_DEPRECATE_PLAN_B -D WEBRTC_ENABLE_PROTOBUF=0 -D WEBRTC_ENCODER_PSNR_STATS -D WEBRTC_LIBRARY_IMPL -D WEBRTC_MOZILLA_BUILD -D WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0 -D WEBRTC_STRICT_FIELD_TRIALS=0 -D DYNAMIC_ANNOTATIONS_ENABLED=1 -D USE_AURA=1 -D USE_GLIB=1 -D USE_OZONE=1 -D USE_UDEV -D WEBRTC_LINUX -D WEBRTC_POSIX -D _FILE_OFFSET_BITS=64 -D _LARGEFILE64_SOURCE -D _LARGEFILE_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D WEBRTC_ENABLE_AVX2 -D _DEBUG -D _GNU_SOURCE -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util_gn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util_gn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/libwebrtc_overrides -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/gen -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/third_party/libwebrtc -I /root/firefox-clang/tools/profiler/public -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_ability_mode_util_gn0.cpp
1/*
2 * Copyright (c) 2022 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/scalability_mode_util.h"
12
13#include <array>
14#include <cstddef>
15#include <optional>
16#include <type_traits>
17
18#include "absl/algorithm/container.h"
19#include "absl/strings/string_view.h"
20#include "api/video/video_codec_type.h"
21#include "api/video_codecs/scalability_mode.h"
22#include "api/video_codecs/video_codec.h"
23#include "rtc_base/checks.h"
24
25namespace webrtc {
26
27namespace {
28
29struct ScalabilityModeParameters {
Excessive padding in 'struct webrtc::(anonymous namespace)::ScalabilityModeParameters' (10 padding bytes, where 2 is optimal). Optimal fields order: name, num_spatial_layers, num_temporal_layers, inter_layer_pred, ratio, scalability_mode, shift, consider reordering the fields or adding explicit padding members
30 const ScalabilityMode scalability_mode;
31 const absl::string_view name;
32 const int num_spatial_layers;
33 const int num_temporal_layers;
34 const InterLayerPredMode inter_layer_pred;
35 const std::optional<ScalabilityModeResolutionRatio> ratio =
36 ScalabilityModeResolutionRatio::kTwoToOne;
37 const bool shift = false;
38};
39
40constexpr size_t kNumScalabilityModes =
41 static_cast<size_t>(ScalabilityMode::kS3T3h) + 1;
42
43constexpr ScalabilityModeParameters kScalabilityModeParams[] = {
44 ScalabilityModeParameters{.scalability_mode = ScalabilityMode::kL1T1,
45 .name = "L1T1",
46 .num_spatial_layers = 1,
47 .num_temporal_layers = 1,
48 .inter_layer_pred = InterLayerPredMode::kOff,
49 .ratio = std::nullopt},
50 ScalabilityModeParameters{.scalability_mode = ScalabilityMode::kL1T2,
51 .name = "L1T2",
52 .num_spatial_layers = 1,
53 .num_temporal_layers = 2,
54 .inter_layer_pred = InterLayerPredMode::kOff,
55 .ratio = std::nullopt},
56 ScalabilityModeParameters{.scalability_mode = ScalabilityMode::kL1T3,
57 .name = "L1T3",
58 .num_spatial_layers = 1,
59 .num_temporal_layers = 3,
60 .inter_layer_pred = InterLayerPredMode::kOff,
61 .ratio = std::nullopt},
62 ScalabilityModeParameters{
63 .scalability_mode = ScalabilityMode::kL2T1,
64 .name = "L2T1",
65 .num_spatial_layers = 2,
66 .num_temporal_layers = 1,
67 .inter_layer_pred = InterLayerPredMode::kOn,
68 },
69 ScalabilityModeParameters{
70 .scalability_mode = ScalabilityMode::kL2T1h,
71 .name = "L2T1h",
72 .num_spatial_layers = 2,
73 .num_temporal_layers = 1,
74 .inter_layer_pred = InterLayerPredMode::kOn,
75 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
76 },
77 ScalabilityModeParameters{
78 .scalability_mode = ScalabilityMode::kL2T1_KEY,
79 .name = "L2T1_KEY",
80 .num_spatial_layers = 2,
81 .num_temporal_layers = 1,
82 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
83 },
84 ScalabilityModeParameters{
85 .scalability_mode = ScalabilityMode::kL2T2,
86 .name = "L2T2",
87 .num_spatial_layers = 2,
88 .num_temporal_layers = 2,
89 .inter_layer_pred = InterLayerPredMode::kOn,
90 },
91 ScalabilityModeParameters{
92 .scalability_mode = ScalabilityMode::kL2T2h,
93 .name = "L2T2h",
94 .num_spatial_layers = 2,
95 .num_temporal_layers = 2,
96 .inter_layer_pred = InterLayerPredMode::kOn,
97 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
98 },
99 ScalabilityModeParameters{
100 .scalability_mode = ScalabilityMode::kL2T2_KEY,
101 .name = "L2T2_KEY",
102 .num_spatial_layers = 2,
103 .num_temporal_layers = 2,
104 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
105 },
106 ScalabilityModeParameters{
107 .scalability_mode = ScalabilityMode::kL2T2_KEY_SHIFT,
108 .name = "L2T2_KEY_SHIFT",
109 .num_spatial_layers = 2,
110 .num_temporal_layers = 2,
111 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
112 .shift = true},
113 ScalabilityModeParameters{
114 .scalability_mode = ScalabilityMode::kL2T3,
115 .name = "L2T3",
116 .num_spatial_layers = 2,
117 .num_temporal_layers = 3,
118 .inter_layer_pred = InterLayerPredMode::kOn,
119 },
120 ScalabilityModeParameters{
121 .scalability_mode = ScalabilityMode::kL2T3h,
122 .name = "L2T3h",
123 .num_spatial_layers = 2,
124 .num_temporal_layers = 3,
125 .inter_layer_pred = InterLayerPredMode::kOn,
126 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
127 },
128 ScalabilityModeParameters{
129 .scalability_mode = ScalabilityMode::kL2T3_KEY,
130 .name = "L2T3_KEY",
131 .num_spatial_layers = 2,
132 .num_temporal_layers = 3,
133 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
134 },
135 ScalabilityModeParameters{
136 .scalability_mode = ScalabilityMode::kL3T1,
137 .name = "L3T1",
138 .num_spatial_layers = 3,
139 .num_temporal_layers = 1,
140 .inter_layer_pred = InterLayerPredMode::kOn,
141 },
142 ScalabilityModeParameters{
143 .scalability_mode = ScalabilityMode::kL3T1h,
144 .name = "L3T1h",
145 .num_spatial_layers = 3,
146 .num_temporal_layers = 1,
147 .inter_layer_pred = InterLayerPredMode::kOn,
148 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
149 },
150 ScalabilityModeParameters{
151 .scalability_mode = ScalabilityMode::kL3T1_KEY,
152 .name = "L3T1_KEY",
153 .num_spatial_layers = 3,
154 .num_temporal_layers = 1,
155 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
156 },
157 ScalabilityModeParameters{
158 .scalability_mode = ScalabilityMode::kL3T2,
159 .name = "L3T2",
160 .num_spatial_layers = 3,
161 .num_temporal_layers = 2,
162 .inter_layer_pred = InterLayerPredMode::kOn,
163 },
164 ScalabilityModeParameters{
165 .scalability_mode = ScalabilityMode::kL3T2h,
166 .name = "L3T2h",
167 .num_spatial_layers = 3,
168 .num_temporal_layers = 2,
169 .inter_layer_pred = InterLayerPredMode::kOn,
170 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
171 },
172 ScalabilityModeParameters{
173 .scalability_mode = ScalabilityMode::kL3T2_KEY,
174 .name = "L3T2_KEY",
175 .num_spatial_layers = 3,
176 .num_temporal_layers = 2,
177 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
178 },
179 ScalabilityModeParameters{
180 .scalability_mode = ScalabilityMode::kL3T3,
181 .name = "L3T3",
182 .num_spatial_layers = 3,
183 .num_temporal_layers = 3,
184 .inter_layer_pred = InterLayerPredMode::kOn,
185 },
186 ScalabilityModeParameters{
187 .scalability_mode = ScalabilityMode::kL3T3h,
188 .name = "L3T3h",
189 .num_spatial_layers = 3,
190 .num_temporal_layers = 3,
191 .inter_layer_pred = InterLayerPredMode::kOn,
192 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
193 },
194 ScalabilityModeParameters{
195 .scalability_mode = ScalabilityMode::kL3T3_KEY,
196 .name = "L3T3_KEY",
197 .num_spatial_layers = 3,
198 .num_temporal_layers = 3,
199 .inter_layer_pred = InterLayerPredMode::kOnKeyPic,
200 },
201 ScalabilityModeParameters{
202 .scalability_mode = ScalabilityMode::kS2T1,
203 .name = "S2T1",
204 .num_spatial_layers = 2,
205 .num_temporal_layers = 1,
206 .inter_layer_pred = InterLayerPredMode::kOff,
207 },
208 ScalabilityModeParameters{
209 .scalability_mode = ScalabilityMode::kS2T1h,
210 .name = "S2T1h",
211 .num_spatial_layers = 2,
212 .num_temporal_layers = 1,
213 .inter_layer_pred = InterLayerPredMode::kOff,
214 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
215 },
216 ScalabilityModeParameters{
217 .scalability_mode = ScalabilityMode::kS2T2,
218 .name = "S2T2",
219 .num_spatial_layers = 2,
220 .num_temporal_layers = 2,
221 .inter_layer_pred = InterLayerPredMode::kOff,
222 },
223 ScalabilityModeParameters{
224 .scalability_mode = ScalabilityMode::kS2T2h,
225 .name = "S2T2h",
226 .num_spatial_layers = 2,
227 .num_temporal_layers = 2,
228 .inter_layer_pred = InterLayerPredMode::kOff,
229 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
230 },
231 ScalabilityModeParameters{
232 .scalability_mode = ScalabilityMode::kS2T3,
233 .name = "S2T3",
234 .num_spatial_layers = 2,
235 .num_temporal_layers = 3,
236 .inter_layer_pred = InterLayerPredMode::kOff,
237 },
238 ScalabilityModeParameters{
239 .scalability_mode = ScalabilityMode::kS2T3h,
240 .name = "S2T3h",
241 .num_spatial_layers = 2,
242 .num_temporal_layers = 3,
243 .inter_layer_pred = InterLayerPredMode::kOff,
244 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
245 },
246 ScalabilityModeParameters{
247 .scalability_mode = ScalabilityMode::kS3T1,
248 .name = "S3T1",
249 .num_spatial_layers = 3,
250 .num_temporal_layers = 1,
251 .inter_layer_pred = InterLayerPredMode::kOff,
252 },
253 ScalabilityModeParameters{
254 .scalability_mode = ScalabilityMode::kS3T1h,
255 .name = "S3T1h",
256 .num_spatial_layers = 3,
257 .num_temporal_layers = 1,
258 .inter_layer_pred = InterLayerPredMode::kOff,
259 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
260 },
261 ScalabilityModeParameters{
262 .scalability_mode = ScalabilityMode::kS3T2,
263 .name = "S3T2",
264 .num_spatial_layers = 3,
265 .num_temporal_layers = 2,
266 .inter_layer_pred = InterLayerPredMode::kOff,
267 },
268 ScalabilityModeParameters{
269 .scalability_mode = ScalabilityMode::kS3T2h,
270 .name = "S3T2h",
271 .num_spatial_layers = 3,
272 .num_temporal_layers = 2,
273 .inter_layer_pred = InterLayerPredMode::kOff,
274 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
275 },
276 ScalabilityModeParameters{
277 .scalability_mode = ScalabilityMode::kS3T3,
278 .name = "S3T3",
279 .num_spatial_layers = 3,
280 .num_temporal_layers = 3,
281 .inter_layer_pred = InterLayerPredMode::kOff,
282 },
283 ScalabilityModeParameters{
284 .scalability_mode = ScalabilityMode::kS3T3h,
285 .name = "S3T3h",
286 .num_spatial_layers = 3,
287 .num_temporal_layers = 3,
288 .inter_layer_pred = InterLayerPredMode::kOff,
289 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo,
290 },
291};
292
293// This could be replaced with std::all_of in c++20.
294constexpr bool CheckScalabilityModeParams() {
295 static_assert(std::size(kScalabilityModeParams) == kNumScalabilityModes);
296 for (size_t s = 0; s < kNumScalabilityModes; ++s) {
297 if (kScalabilityModeParams[s].scalability_mode !=
298 static_cast<ScalabilityMode>(s)) {
299 return false;
300 }
301 }
302 return true;
303}
304
305static_assert(CheckScalabilityModeParams(),
306 "There is a scalability mode mismatch in the array!");
307
308constexpr auto Idx(ScalabilityMode s) {
309 const auto index = static_cast<std::underlying_type_t<ScalabilityMode>>(s);
310 RTC_CHECK_LT(index, kNumScalabilityModes)::webrtc::SafeLt((index), (kNumScalabilityModes)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "./../../../../../../../third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util.cc"
, 310, "index" " " "<" " " "kNumScalabilityModes") & ::
webrtc::webrtc_checks_impl::LogStreamer<>() << (index
) << (kNumScalabilityModes)
;
311 return index;
312}
313
314std::optional<ScalabilityModeResolutionRatio> CalculateSimulcastResolutionRatio(
315 const VideoCodec& codec) {
316 if (codec.numberOfSimulcastStreams < 2) {
317 return std::nullopt;
318 }
319
320 std::optional<ScalabilityModeResolutionRatio> ratio;
321 for (int i = 0; i < codec.numberOfSimulcastStreams - 1; ++i) {
322 ScalabilityModeResolutionRatio layer_ratio;
323 if (codec.simulcastStream[i + 1].width / codec.simulcastStream[i].width ==
324 2) {
325 layer_ratio = ScalabilityModeResolutionRatio::kTwoToOne;
326 } else if (2 * codec.simulcastStream[i + 1].width /
327 codec.simulcastStream[i].width ==
328 3) {
329 layer_ratio = ScalabilityModeResolutionRatio::kThreeToTwo;
330 } else {
331 // Unknown ratio.
332 return std::nullopt;
333 }
334
335 if (ratio.has_value() && ratio != layer_ratio) {
336 // Inconsistent layer ratios.
337 return std::nullopt;
338 }
339 ratio = layer_ratio;
340 }
341
342 return ratio;
343}
344
345std::optional<ScalabilityModeResolutionRatio> CalculateSpatialResolutionRatio(
346 const VideoCodec& codec,
347 int num_spatial_layers) {
348 if (num_spatial_layers < 2) {
349 return std::nullopt;
350 }
351
352 std::optional<ScalabilityModeResolutionRatio> ratio;
353 for (int i = 0; i < num_spatial_layers - 1; ++i) {
354 ScalabilityModeResolutionRatio layer_ratio;
355 if (codec.spatialLayers[i + 1].width / codec.spatialLayers[i].width == 2) {
356 layer_ratio = ScalabilityModeResolutionRatio::kTwoToOne;
357 } else if (2 * codec.spatialLayers[i + 1].width /
358 codec.spatialLayers[i].width ==
359 3) {
360 layer_ratio = ScalabilityModeResolutionRatio::kThreeToTwo;
361 } else {
362 // Unknown ratio.
363 return std::nullopt;
364 }
365
366 if (ratio.has_value() && ratio != layer_ratio) {
367 // Inconsistent layer ratios.
368 return std::nullopt;
369 }
370 ratio = layer_ratio;
371 }
372
373 return ratio;
374}
375} // namespace
376
377std::optional<ScalabilityMode> MakeScalabilityMode(
378 int num_spatial_layers,
379 int num_temporal_layers,
380 InterLayerPredMode inter_layer_pred,
381 std::optional<ScalabilityModeResolutionRatio> ratio,
382 bool shift) {
383 for (const auto& candidate_mode : kScalabilityModeParams) {
384 if (candidate_mode.num_spatial_layers == num_spatial_layers &&
385 candidate_mode.num_temporal_layers == num_temporal_layers) {
386 if (num_spatial_layers == 1 ||
387 (candidate_mode.inter_layer_pred == inter_layer_pred &&
388 candidate_mode.ratio == ratio && candidate_mode.shift == shift)) {
389 return candidate_mode.scalability_mode;
390 }
391 }
392 }
393 return std::nullopt;
394}
395
396std::optional<ScalabilityMode> ScalabilityModeFromString(
397 absl::string_view mode_string) {
398 const auto it =
399 absl::c_find_if(kScalabilityModeParams,
400 [&](const ScalabilityModeParameters& candidate_mode) {
401 return candidate_mode.name == mode_string;
402 });
403 if (it != std::end(kScalabilityModeParams)) {
404 return it->scalability_mode;
405 }
406 return std::nullopt;
407}
408
409InterLayerPredMode ScalabilityModeToInterLayerPredMode(
410 ScalabilityMode scalability_mode) {
411 return kScalabilityModeParams[Idx(scalability_mode)].inter_layer_pred;
412}
413
414int ScalabilityModeToNumSpatialLayers(ScalabilityMode scalability_mode) {
415 return kScalabilityModeParams[Idx(scalability_mode)].num_spatial_layers;
416}
417
418int ScalabilityModeToNumTemporalLayers(ScalabilityMode scalability_mode) {
419 return kScalabilityModeParams[Idx(scalability_mode)].num_temporal_layers;
420}
421
422std::optional<ScalabilityModeResolutionRatio> ScalabilityModeToResolutionRatio(
423 ScalabilityMode scalability_mode) {
424 return kScalabilityModeParams[Idx(scalability_mode)].ratio;
425}
426
427ScalabilityMode LimitNumSpatialLayers(ScalabilityMode scalability_mode,
428 int max_spatial_layers) {
429 int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode);
430 if (max_spatial_layers >= num_spatial_layers) {
431 return scalability_mode;
432 }
433
434 switch (scalability_mode) {
435 case ScalabilityMode::kL1T1:
436 return ScalabilityMode::kL1T1;
437 case ScalabilityMode::kL1T2:
438 return ScalabilityMode::kL1T2;
439 case ScalabilityMode::kL1T3:
440 return ScalabilityMode::kL1T3;
441 case ScalabilityMode::kL2T1:
442 return ScalabilityMode::kL1T1;
443 case ScalabilityMode::kL2T1h:
444 return ScalabilityMode::kL1T1;
445 case ScalabilityMode::kL2T1_KEY:
446 return ScalabilityMode::kL1T1;
447 case ScalabilityMode::kL2T2:
448 return ScalabilityMode::kL1T2;
449 case ScalabilityMode::kL2T2h:
450 return ScalabilityMode::kL1T2;
451 case ScalabilityMode::kL2T2_KEY:
452 return ScalabilityMode::kL1T2;
453 case ScalabilityMode::kL2T2_KEY_SHIFT:
454 return ScalabilityMode::kL1T2;
455 case ScalabilityMode::kL2T3:
456 return ScalabilityMode::kL1T3;
457 case ScalabilityMode::kL2T3h:
458 return ScalabilityMode::kL1T3;
459 case ScalabilityMode::kL2T3_KEY:
460 return ScalabilityMode::kL1T3;
461 case ScalabilityMode::kL3T1:
462 return max_spatial_layers == 2 ? ScalabilityMode::kL2T1
463 : ScalabilityMode::kL1T1;
464 case ScalabilityMode::kL3T1h:
465 return max_spatial_layers == 2 ? ScalabilityMode::kL2T1h
466 : ScalabilityMode::kL1T1;
467 case ScalabilityMode::kL3T1_KEY:
468 return max_spatial_layers == 2 ? ScalabilityMode::kL2T1_KEY
469 : ScalabilityMode::kL1T1;
470 case ScalabilityMode::kL3T2:
471 return max_spatial_layers == 2 ? ScalabilityMode::kL2T2
472 : ScalabilityMode::kL1T2;
473 case ScalabilityMode::kL3T2h:
474 return max_spatial_layers == 2 ? ScalabilityMode::kL2T2h
475 : ScalabilityMode::kL1T2;
476 case ScalabilityMode::kL3T2_KEY:
477 return max_spatial_layers == 2 ? ScalabilityMode::kL2T2_KEY
478 : ScalabilityMode::kL1T2;
479 case ScalabilityMode::kL3T3:
480 return max_spatial_layers == 2 ? ScalabilityMode::kL2T3
481 : ScalabilityMode::kL1T3;
482 case ScalabilityMode::kL3T3h:
483 return max_spatial_layers == 2 ? ScalabilityMode::kL2T3h
484 : ScalabilityMode::kL1T3;
485 case ScalabilityMode::kL3T3_KEY:
486 return max_spatial_layers == 2 ? ScalabilityMode::kL2T3_KEY
487 : ScalabilityMode::kL1T3;
488 case ScalabilityMode::kS2T1:
489 return ScalabilityMode::kL1T1;
490 case ScalabilityMode::kS2T1h:
491 return ScalabilityMode::kL1T1;
492 case ScalabilityMode::kS2T2:
493 return ScalabilityMode::kL1T2;
494 case ScalabilityMode::kS2T2h:
495 return ScalabilityMode::kL1T2;
496 case ScalabilityMode::kS2T3:
497 return ScalabilityMode::kL1T3;
498 case ScalabilityMode::kS2T3h:
499 return ScalabilityMode::kL1T3;
500 case ScalabilityMode::kS3T1:
501 return max_spatial_layers == 2 ? ScalabilityMode::kS2T1
502 : ScalabilityMode::kL1T1;
503 case ScalabilityMode::kS3T1h:
504 return max_spatial_layers == 2 ? ScalabilityMode::kS2T1h
505 : ScalabilityMode::kL1T1;
506 case ScalabilityMode::kS3T2:
507 return max_spatial_layers == 2 ? ScalabilityMode::kS2T2
508 : ScalabilityMode::kL1T2;
509 case ScalabilityMode::kS3T2h:
510 return max_spatial_layers == 2 ? ScalabilityMode::kS2T2h
511 : ScalabilityMode::kL1T2;
512 case ScalabilityMode::kS3T3:
513 return max_spatial_layers == 2 ? ScalabilityMode::kS2T3
514 : ScalabilityMode::kL1T3;
515 case ScalabilityMode::kS3T3h:
516 return max_spatial_layers == 2 ? ScalabilityMode::kS2T3h
517 : ScalabilityMode::kL1T3;
518 }
519 RTC_CHECK_NOTREACHED()do { ::webrtc::webrtc_checks_impl::UnreachableCodeReached( "./../../../../../../../third_party/libwebrtc/modules/video_coding/svc/scalability_mode_util.cc"
, 519); } while (0)
;
520}
521
522bool ScalabilityModeIsShiftMode(ScalabilityMode scalability_mode) {
523 return kScalabilityModeParams[Idx(scalability_mode)].shift;
524}
525
526ScalabilityMode GetScalabilityModeFromVideoCodec(const VideoCodec& codec) {
527 if (auto scalability_mode = codec.GetScalabilityMode()) {
528 return *scalability_mode;
529 }
530
531 int num_spatial_layers = 1;
532 int num_temporal_layers = 1;
533 InterLayerPredMode inter_layer_pred = InterLayerPredMode::kOff;
534 std::optional<ScalabilityModeResolutionRatio> ratio;
535
536 switch (codec.codecType) {
537 case kVideoCodecVP8:
538 num_temporal_layers = codec.VP8().numberOfTemporalLayers;
539 num_spatial_layers = codec.numberOfSimulcastStreams;
540 inter_layer_pred = InterLayerPredMode::kOff;
541 ratio = CalculateSimulcastResolutionRatio(codec);
542 break;
543 case kVideoCodecH264:
544 num_temporal_layers = codec.H264().numberOfTemporalLayers;
545 num_spatial_layers = codec.numberOfSimulcastStreams;
546 inter_layer_pred = InterLayerPredMode::kOff;
547 ratio = CalculateSimulcastResolutionRatio(codec);
548 break;
549 case kVideoCodecVP9:
550 // VP9 can be used with either simulcast or spatial layers.
551 if (codec.VP9().numberOfSpatialLayers > 0) {
552 num_spatial_layers = codec.VP9().numberOfSpatialLayers;
553 ratio = CalculateSpatialResolutionRatio(codec, num_spatial_layers);
554 } else {
555 num_spatial_layers = codec.numberOfSimulcastStreams;
556 ratio = CalculateSimulcastResolutionRatio(codec);
557 }
558 inter_layer_pred = codec.VP9().interLayerPred;
559 break;
560 case kVideoCodecAV1:
561 case kVideoCodecH265:
562 case kVideoCodecGeneric:
563 // All other codecs may support simulcast, but not spatial or temporal
564 // layers unless they are specified using the explicit scalability mode.
565 num_spatial_layers = codec.numberOfSimulcastStreams;
566 break;
567 }
568
569 // L1Tx modes always have InterLayerPredMode::kOff.
570 if (num_spatial_layers == 1) {
571 inter_layer_pred = InterLayerPredMode::kOff;
572 }
573
574 return MakeScalabilityMode(num_spatial_layers, num_temporal_layers,
575 inter_layer_pred, ratio,
576 /*shift=*/false)
577 .value_or(ScalabilityMode::kL1T1);
578}
579
580} // namespace webrtc