scalability_mode_util.cc (17322B)
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_codecs/scalability_mode.h" 21 #include "api/video_codecs/video_codec.h" 22 #include "rtc_base/checks.h" 23 24 namespace webrtc { 25 26 namespace { 27 28 struct ScalabilityModeParameters { 29 const ScalabilityMode scalability_mode; 30 const absl::string_view name; 31 const int num_spatial_layers; 32 const int num_temporal_layers; 33 const InterLayerPredMode inter_layer_pred; 34 const std::optional<ScalabilityModeResolutionRatio> ratio = 35 ScalabilityModeResolutionRatio::kTwoToOne; 36 const bool shift = false; 37 }; 38 39 constexpr size_t kNumScalabilityModes = 40 static_cast<size_t>(ScalabilityMode::kS3T3h) + 1; 41 42 constexpr ScalabilityModeParameters kScalabilityModeParams[] = { 43 ScalabilityModeParameters{.scalability_mode = ScalabilityMode::kL1T1, 44 .name = "L1T1", 45 .num_spatial_layers = 1, 46 .num_temporal_layers = 1, 47 .inter_layer_pred = InterLayerPredMode::kOff, 48 .ratio = std::nullopt}, 49 ScalabilityModeParameters{.scalability_mode = ScalabilityMode::kL1T2, 50 .name = "L1T2", 51 .num_spatial_layers = 1, 52 .num_temporal_layers = 2, 53 .inter_layer_pred = InterLayerPredMode::kOff, 54 .ratio = std::nullopt}, 55 ScalabilityModeParameters{.scalability_mode = ScalabilityMode::kL1T3, 56 .name = "L1T3", 57 .num_spatial_layers = 1, 58 .num_temporal_layers = 3, 59 .inter_layer_pred = InterLayerPredMode::kOff, 60 .ratio = std::nullopt}, 61 ScalabilityModeParameters{ 62 .scalability_mode = ScalabilityMode::kL2T1, 63 .name = "L2T1", 64 .num_spatial_layers = 2, 65 .num_temporal_layers = 1, 66 .inter_layer_pred = InterLayerPredMode::kOn, 67 }, 68 ScalabilityModeParameters{ 69 .scalability_mode = ScalabilityMode::kL2T1h, 70 .name = "L2T1h", 71 .num_spatial_layers = 2, 72 .num_temporal_layers = 1, 73 .inter_layer_pred = InterLayerPredMode::kOn, 74 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 75 }, 76 ScalabilityModeParameters{ 77 .scalability_mode = ScalabilityMode::kL2T1_KEY, 78 .name = "L2T1_KEY", 79 .num_spatial_layers = 2, 80 .num_temporal_layers = 1, 81 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 82 }, 83 ScalabilityModeParameters{ 84 .scalability_mode = ScalabilityMode::kL2T2, 85 .name = "L2T2", 86 .num_spatial_layers = 2, 87 .num_temporal_layers = 2, 88 .inter_layer_pred = InterLayerPredMode::kOn, 89 }, 90 ScalabilityModeParameters{ 91 .scalability_mode = ScalabilityMode::kL2T2h, 92 .name = "L2T2h", 93 .num_spatial_layers = 2, 94 .num_temporal_layers = 2, 95 .inter_layer_pred = InterLayerPredMode::kOn, 96 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 97 }, 98 ScalabilityModeParameters{ 99 .scalability_mode = ScalabilityMode::kL2T2_KEY, 100 .name = "L2T2_KEY", 101 .num_spatial_layers = 2, 102 .num_temporal_layers = 2, 103 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 104 }, 105 ScalabilityModeParameters{ 106 .scalability_mode = ScalabilityMode::kL2T2_KEY_SHIFT, 107 .name = "L2T2_KEY_SHIFT", 108 .num_spatial_layers = 2, 109 .num_temporal_layers = 2, 110 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 111 .shift = true}, 112 ScalabilityModeParameters{ 113 .scalability_mode = ScalabilityMode::kL2T3, 114 .name = "L2T3", 115 .num_spatial_layers = 2, 116 .num_temporal_layers = 3, 117 .inter_layer_pred = InterLayerPredMode::kOn, 118 }, 119 ScalabilityModeParameters{ 120 .scalability_mode = ScalabilityMode::kL2T3h, 121 .name = "L2T3h", 122 .num_spatial_layers = 2, 123 .num_temporal_layers = 3, 124 .inter_layer_pred = InterLayerPredMode::kOn, 125 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 126 }, 127 ScalabilityModeParameters{ 128 .scalability_mode = ScalabilityMode::kL2T3_KEY, 129 .name = "L2T3_KEY", 130 .num_spatial_layers = 2, 131 .num_temporal_layers = 3, 132 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 133 }, 134 ScalabilityModeParameters{ 135 .scalability_mode = ScalabilityMode::kL3T1, 136 .name = "L3T1", 137 .num_spatial_layers = 3, 138 .num_temporal_layers = 1, 139 .inter_layer_pred = InterLayerPredMode::kOn, 140 }, 141 ScalabilityModeParameters{ 142 .scalability_mode = ScalabilityMode::kL3T1h, 143 .name = "L3T1h", 144 .num_spatial_layers = 3, 145 .num_temporal_layers = 1, 146 .inter_layer_pred = InterLayerPredMode::kOn, 147 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 148 }, 149 ScalabilityModeParameters{ 150 .scalability_mode = ScalabilityMode::kL3T1_KEY, 151 .name = "L3T1_KEY", 152 .num_spatial_layers = 3, 153 .num_temporal_layers = 1, 154 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 155 }, 156 ScalabilityModeParameters{ 157 .scalability_mode = ScalabilityMode::kL3T2, 158 .name = "L3T2", 159 .num_spatial_layers = 3, 160 .num_temporal_layers = 2, 161 .inter_layer_pred = InterLayerPredMode::kOn, 162 }, 163 ScalabilityModeParameters{ 164 .scalability_mode = ScalabilityMode::kL3T2h, 165 .name = "L3T2h", 166 .num_spatial_layers = 3, 167 .num_temporal_layers = 2, 168 .inter_layer_pred = InterLayerPredMode::kOn, 169 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 170 }, 171 ScalabilityModeParameters{ 172 .scalability_mode = ScalabilityMode::kL3T2_KEY, 173 .name = "L3T2_KEY", 174 .num_spatial_layers = 3, 175 .num_temporal_layers = 2, 176 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 177 }, 178 ScalabilityModeParameters{ 179 .scalability_mode = ScalabilityMode::kL3T3, 180 .name = "L3T3", 181 .num_spatial_layers = 3, 182 .num_temporal_layers = 3, 183 .inter_layer_pred = InterLayerPredMode::kOn, 184 }, 185 ScalabilityModeParameters{ 186 .scalability_mode = ScalabilityMode::kL3T3h, 187 .name = "L3T3h", 188 .num_spatial_layers = 3, 189 .num_temporal_layers = 3, 190 .inter_layer_pred = InterLayerPredMode::kOn, 191 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 192 }, 193 ScalabilityModeParameters{ 194 .scalability_mode = ScalabilityMode::kL3T3_KEY, 195 .name = "L3T3_KEY", 196 .num_spatial_layers = 3, 197 .num_temporal_layers = 3, 198 .inter_layer_pred = InterLayerPredMode::kOnKeyPic, 199 }, 200 ScalabilityModeParameters{ 201 .scalability_mode = ScalabilityMode::kS2T1, 202 .name = "S2T1", 203 .num_spatial_layers = 2, 204 .num_temporal_layers = 1, 205 .inter_layer_pred = InterLayerPredMode::kOff, 206 }, 207 ScalabilityModeParameters{ 208 .scalability_mode = ScalabilityMode::kS2T1h, 209 .name = "S2T1h", 210 .num_spatial_layers = 2, 211 .num_temporal_layers = 1, 212 .inter_layer_pred = InterLayerPredMode::kOff, 213 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 214 }, 215 ScalabilityModeParameters{ 216 .scalability_mode = ScalabilityMode::kS2T2, 217 .name = "S2T2", 218 .num_spatial_layers = 2, 219 .num_temporal_layers = 2, 220 .inter_layer_pred = InterLayerPredMode::kOff, 221 }, 222 ScalabilityModeParameters{ 223 .scalability_mode = ScalabilityMode::kS2T2h, 224 .name = "S2T2h", 225 .num_spatial_layers = 2, 226 .num_temporal_layers = 2, 227 .inter_layer_pred = InterLayerPredMode::kOff, 228 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 229 }, 230 ScalabilityModeParameters{ 231 .scalability_mode = ScalabilityMode::kS2T3, 232 .name = "S2T3", 233 .num_spatial_layers = 2, 234 .num_temporal_layers = 3, 235 .inter_layer_pred = InterLayerPredMode::kOff, 236 }, 237 ScalabilityModeParameters{ 238 .scalability_mode = ScalabilityMode::kS2T3h, 239 .name = "S2T3h", 240 .num_spatial_layers = 2, 241 .num_temporal_layers = 3, 242 .inter_layer_pred = InterLayerPredMode::kOff, 243 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 244 }, 245 ScalabilityModeParameters{ 246 .scalability_mode = ScalabilityMode::kS3T1, 247 .name = "S3T1", 248 .num_spatial_layers = 3, 249 .num_temporal_layers = 1, 250 .inter_layer_pred = InterLayerPredMode::kOff, 251 }, 252 ScalabilityModeParameters{ 253 .scalability_mode = ScalabilityMode::kS3T1h, 254 .name = "S3T1h", 255 .num_spatial_layers = 3, 256 .num_temporal_layers = 1, 257 .inter_layer_pred = InterLayerPredMode::kOff, 258 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 259 }, 260 ScalabilityModeParameters{ 261 .scalability_mode = ScalabilityMode::kS3T2, 262 .name = "S3T2", 263 .num_spatial_layers = 3, 264 .num_temporal_layers = 2, 265 .inter_layer_pred = InterLayerPredMode::kOff, 266 }, 267 ScalabilityModeParameters{ 268 .scalability_mode = ScalabilityMode::kS3T2h, 269 .name = "S3T2h", 270 .num_spatial_layers = 3, 271 .num_temporal_layers = 2, 272 .inter_layer_pred = InterLayerPredMode::kOff, 273 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 274 }, 275 ScalabilityModeParameters{ 276 .scalability_mode = ScalabilityMode::kS3T3, 277 .name = "S3T3", 278 .num_spatial_layers = 3, 279 .num_temporal_layers = 3, 280 .inter_layer_pred = InterLayerPredMode::kOff, 281 }, 282 ScalabilityModeParameters{ 283 .scalability_mode = ScalabilityMode::kS3T3h, 284 .name = "S3T3h", 285 .num_spatial_layers = 3, 286 .num_temporal_layers = 3, 287 .inter_layer_pred = InterLayerPredMode::kOff, 288 .ratio = ScalabilityModeResolutionRatio::kThreeToTwo, 289 }, 290 }; 291 292 // This could be replaced with std::all_of in c++20. 293 constexpr bool CheckScalabilityModeParams() { 294 static_assert(std::size(kScalabilityModeParams) == kNumScalabilityModes); 295 for (size_t s = 0; s < kNumScalabilityModes; ++s) { 296 if (kScalabilityModeParams[s].scalability_mode != 297 static_cast<ScalabilityMode>(s)) { 298 return false; 299 } 300 } 301 return true; 302 } 303 304 static_assert(CheckScalabilityModeParams(), 305 "There is a scalability mode mismatch in the array!"); 306 307 constexpr auto Idx(ScalabilityMode s) { 308 const auto index = static_cast<std::underlying_type_t<ScalabilityMode>>(s); 309 RTC_CHECK_LT(index, kNumScalabilityModes); 310 return index; 311 } 312 313 } // namespace 314 315 std::optional<ScalabilityMode> MakeScalabilityMode( 316 int num_spatial_layers, 317 int num_temporal_layers, 318 InterLayerPredMode inter_layer_pred, 319 std::optional<ScalabilityModeResolutionRatio> ratio, 320 bool shift) { 321 for (const auto& candidate_mode : kScalabilityModeParams) { 322 if (candidate_mode.num_spatial_layers == num_spatial_layers && 323 candidate_mode.num_temporal_layers == num_temporal_layers) { 324 if (num_spatial_layers == 1 || 325 (candidate_mode.inter_layer_pred == inter_layer_pred && 326 candidate_mode.ratio == ratio && candidate_mode.shift == shift)) { 327 return candidate_mode.scalability_mode; 328 } 329 } 330 } 331 return std::nullopt; 332 } 333 334 std::optional<ScalabilityMode> ScalabilityModeFromString( 335 absl::string_view mode_string) { 336 const auto it = 337 absl::c_find_if(kScalabilityModeParams, 338 [&](const ScalabilityModeParameters& candidate_mode) { 339 return candidate_mode.name == mode_string; 340 }); 341 if (it != std::end(kScalabilityModeParams)) { 342 return it->scalability_mode; 343 } 344 return std::nullopt; 345 } 346 347 InterLayerPredMode ScalabilityModeToInterLayerPredMode( 348 ScalabilityMode scalability_mode) { 349 return kScalabilityModeParams[Idx(scalability_mode)].inter_layer_pred; 350 } 351 352 int ScalabilityModeToNumSpatialLayers(ScalabilityMode scalability_mode) { 353 return kScalabilityModeParams[Idx(scalability_mode)].num_spatial_layers; 354 } 355 356 int ScalabilityModeToNumTemporalLayers(ScalabilityMode scalability_mode) { 357 return kScalabilityModeParams[Idx(scalability_mode)].num_temporal_layers; 358 } 359 360 std::optional<ScalabilityModeResolutionRatio> ScalabilityModeToResolutionRatio( 361 ScalabilityMode scalability_mode) { 362 return kScalabilityModeParams[Idx(scalability_mode)].ratio; 363 } 364 365 ScalabilityMode LimitNumSpatialLayers(ScalabilityMode scalability_mode, 366 int max_spatial_layers) { 367 int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode); 368 if (max_spatial_layers >= num_spatial_layers) { 369 return scalability_mode; 370 } 371 372 switch (scalability_mode) { 373 case ScalabilityMode::kL1T1: 374 return ScalabilityMode::kL1T1; 375 case ScalabilityMode::kL1T2: 376 return ScalabilityMode::kL1T2; 377 case ScalabilityMode::kL1T3: 378 return ScalabilityMode::kL1T3; 379 case ScalabilityMode::kL2T1: 380 return ScalabilityMode::kL1T1; 381 case ScalabilityMode::kL2T1h: 382 return ScalabilityMode::kL1T1; 383 case ScalabilityMode::kL2T1_KEY: 384 return ScalabilityMode::kL1T1; 385 case ScalabilityMode::kL2T2: 386 return ScalabilityMode::kL1T2; 387 case ScalabilityMode::kL2T2h: 388 return ScalabilityMode::kL1T2; 389 case ScalabilityMode::kL2T2_KEY: 390 return ScalabilityMode::kL1T2; 391 case ScalabilityMode::kL2T2_KEY_SHIFT: 392 return ScalabilityMode::kL1T2; 393 case ScalabilityMode::kL2T3: 394 return ScalabilityMode::kL1T3; 395 case ScalabilityMode::kL2T3h: 396 return ScalabilityMode::kL1T3; 397 case ScalabilityMode::kL2T3_KEY: 398 return ScalabilityMode::kL1T3; 399 case ScalabilityMode::kL3T1: 400 return max_spatial_layers == 2 ? ScalabilityMode::kL2T1 401 : ScalabilityMode::kL1T1; 402 case ScalabilityMode::kL3T1h: 403 return max_spatial_layers == 2 ? ScalabilityMode::kL2T1h 404 : ScalabilityMode::kL1T1; 405 case ScalabilityMode::kL3T1_KEY: 406 return max_spatial_layers == 2 ? ScalabilityMode::kL2T1_KEY 407 : ScalabilityMode::kL1T1; 408 case ScalabilityMode::kL3T2: 409 return max_spatial_layers == 2 ? ScalabilityMode::kL2T2 410 : ScalabilityMode::kL1T2; 411 case ScalabilityMode::kL3T2h: 412 return max_spatial_layers == 2 ? ScalabilityMode::kL2T2h 413 : ScalabilityMode::kL1T2; 414 case ScalabilityMode::kL3T2_KEY: 415 return max_spatial_layers == 2 ? ScalabilityMode::kL2T2_KEY 416 : ScalabilityMode::kL1T2; 417 case ScalabilityMode::kL3T3: 418 return max_spatial_layers == 2 ? ScalabilityMode::kL2T3 419 : ScalabilityMode::kL1T3; 420 case ScalabilityMode::kL3T3h: 421 return max_spatial_layers == 2 ? ScalabilityMode::kL2T3h 422 : ScalabilityMode::kL1T3; 423 case ScalabilityMode::kL3T3_KEY: 424 return max_spatial_layers == 2 ? ScalabilityMode::kL2T3_KEY 425 : ScalabilityMode::kL1T3; 426 case ScalabilityMode::kS2T1: 427 return ScalabilityMode::kL1T1; 428 case ScalabilityMode::kS2T1h: 429 return ScalabilityMode::kL1T1; 430 case ScalabilityMode::kS2T2: 431 return ScalabilityMode::kL1T2; 432 case ScalabilityMode::kS2T2h: 433 return ScalabilityMode::kL1T2; 434 case ScalabilityMode::kS2T3: 435 return ScalabilityMode::kL1T3; 436 case ScalabilityMode::kS2T3h: 437 return ScalabilityMode::kL1T3; 438 case ScalabilityMode::kS3T1: 439 return max_spatial_layers == 2 ? ScalabilityMode::kS2T1 440 : ScalabilityMode::kL1T1; 441 case ScalabilityMode::kS3T1h: 442 return max_spatial_layers == 2 ? ScalabilityMode::kS2T1h 443 : ScalabilityMode::kL1T1; 444 case ScalabilityMode::kS3T2: 445 return max_spatial_layers == 2 ? ScalabilityMode::kS2T2 446 : ScalabilityMode::kL1T2; 447 case ScalabilityMode::kS3T2h: 448 return max_spatial_layers == 2 ? ScalabilityMode::kS2T2h 449 : ScalabilityMode::kL1T2; 450 case ScalabilityMode::kS3T3: 451 return max_spatial_layers == 2 ? ScalabilityMode::kS2T3 452 : ScalabilityMode::kL1T3; 453 case ScalabilityMode::kS3T3h: 454 return max_spatial_layers == 2 ? ScalabilityMode::kS2T3h 455 : ScalabilityMode::kL1T3; 456 } 457 RTC_CHECK_NOTREACHED(); 458 } 459 460 bool ScalabilityModeIsShiftMode(ScalabilityMode scalability_mode) { 461 return kScalabilityModeParams[Idx(scalability_mode)].shift; 462 } 463 464 } // namespace webrtc