/* * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/video_coding/svc/scalability_mode_util.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "api/video_codecs/scalability_mode.h" #include "rtc_base/checks.h" namespace webrtc { absl::optional ScalabilityModeFromString( absl::string_view mode_string) { if (mode_string == "L1T1") return ScalabilityMode::kL1T1; if (mode_string == "L1T2") return ScalabilityMode::kL1T2; if (mode_string == "L1T3") return ScalabilityMode::kL1T3; if (mode_string == "L2T1") return ScalabilityMode::kL2T1; if (mode_string == "L2T1h") return ScalabilityMode::kL2T1h; if (mode_string == "L2T1_KEY") return ScalabilityMode::kL2T1_KEY; if (mode_string == "L2T2") return ScalabilityMode::kL2T2; if (mode_string == "L2T2h") return ScalabilityMode::kL2T2h; if (mode_string == "L2T2_KEY") return ScalabilityMode::kL2T2_KEY; if (mode_string == "L2T2_KEY_SHIFT") return ScalabilityMode::kL2T2_KEY_SHIFT; if (mode_string == "L2T3") return ScalabilityMode::kL2T3; if (mode_string == "L2T3h") return ScalabilityMode::kL2T3h; if (mode_string == "L2T3_KEY") return ScalabilityMode::kL2T3_KEY; if (mode_string == "L3T1") return ScalabilityMode::kL3T1; if (mode_string == "L3T1h") return ScalabilityMode::kL3T1h; if (mode_string == "L3T1_KEY") return ScalabilityMode::kL3T1_KEY; if (mode_string == "L3T2") return ScalabilityMode::kL3T2; if (mode_string == "L3T2h") return ScalabilityMode::kL3T2h; if (mode_string == "L3T2_KEY") return ScalabilityMode::kL3T2_KEY; if (mode_string == "L3T3") return ScalabilityMode::kL3T3; if (mode_string == "L3T3h") return ScalabilityMode::kL3T3h; if (mode_string == "L3T3_KEY") return ScalabilityMode::kL3T3_KEY; if (mode_string == "S2T1") return ScalabilityMode::kS2T1; if (mode_string == "S2T1h") return ScalabilityMode::kS2T1h; if (mode_string == "S2T2") return ScalabilityMode::kS2T2; if (mode_string == "S2T2h") return ScalabilityMode::kS2T2h; if (mode_string == "S2T3") return ScalabilityMode::kS2T3; if (mode_string == "S2T3h") return ScalabilityMode::kS2T3h; if (mode_string == "S3T1") return ScalabilityMode::kS3T1; if (mode_string == "S3T1h") return ScalabilityMode::kS3T1h; if (mode_string == "S3T2") return ScalabilityMode::kS3T2; if (mode_string == "S3T2h") return ScalabilityMode::kS3T2h; if (mode_string == "S3T3") return ScalabilityMode::kS3T3; if (mode_string == "S3T3h") return ScalabilityMode::kS3T3h; return absl::nullopt; } InterLayerPredMode ScalabilityModeToInterLayerPredMode( ScalabilityMode scalability_mode) { switch (scalability_mode) { case ScalabilityMode::kL1T1: case ScalabilityMode::kL1T2: case ScalabilityMode::kL1T3: case ScalabilityMode::kL2T1: case ScalabilityMode::kL2T1h: return InterLayerPredMode::kOn; case ScalabilityMode::kL2T1_KEY: return InterLayerPredMode::kOnKeyPic; case ScalabilityMode::kL2T2: case ScalabilityMode::kL2T2h: return InterLayerPredMode::kOn; case ScalabilityMode::kL2T2_KEY: case ScalabilityMode::kL2T2_KEY_SHIFT: return InterLayerPredMode::kOnKeyPic; case ScalabilityMode::kL2T3: case ScalabilityMode::kL2T3h: return InterLayerPredMode::kOn; case ScalabilityMode::kL2T3_KEY: return InterLayerPredMode::kOnKeyPic; case ScalabilityMode::kL3T1: case ScalabilityMode::kL3T1h: return InterLayerPredMode::kOn; case ScalabilityMode::kL3T1_KEY: return InterLayerPredMode::kOnKeyPic; case ScalabilityMode::kL3T2: case ScalabilityMode::kL3T2h: return InterLayerPredMode::kOn; case ScalabilityMode::kL3T2_KEY: return InterLayerPredMode::kOnKeyPic; case ScalabilityMode::kL3T3: case ScalabilityMode::kL3T3h: return InterLayerPredMode::kOn; case ScalabilityMode::kL3T3_KEY: return InterLayerPredMode::kOnKeyPic; case ScalabilityMode::kS2T1: case ScalabilityMode::kS2T1h: case ScalabilityMode::kS2T2: case ScalabilityMode::kS2T2h: case ScalabilityMode::kS2T3: case ScalabilityMode::kS2T3h: case ScalabilityMode::kS3T1: case ScalabilityMode::kS3T1h: case ScalabilityMode::kS3T2: case ScalabilityMode::kS3T2h: case ScalabilityMode::kS3T3: case ScalabilityMode::kS3T3h: return InterLayerPredMode::kOff; } RTC_CHECK_NOTREACHED(); } int ScalabilityModeToNumSpatialLayers(ScalabilityMode scalability_mode) { switch (scalability_mode) { case ScalabilityMode::kL1T1: case ScalabilityMode::kL1T2: case ScalabilityMode::kL1T3: return 1; case ScalabilityMode::kL2T1: case ScalabilityMode::kL2T1h: case ScalabilityMode::kL2T1_KEY: case ScalabilityMode::kL2T2: case ScalabilityMode::kL2T2h: case ScalabilityMode::kL2T2_KEY: case ScalabilityMode::kL2T2_KEY_SHIFT: case ScalabilityMode::kL2T3: case ScalabilityMode::kL2T3h: case ScalabilityMode::kL2T3_KEY: return 2; case ScalabilityMode::kL3T1: case ScalabilityMode::kL3T1h: case ScalabilityMode::kL3T1_KEY: case ScalabilityMode::kL3T2: case ScalabilityMode::kL3T2h: case ScalabilityMode::kL3T2_KEY: case ScalabilityMode::kL3T3: case ScalabilityMode::kL3T3h: case ScalabilityMode::kL3T3_KEY: return 3; case ScalabilityMode::kS2T1: case ScalabilityMode::kS2T1h: case ScalabilityMode::kS2T2: case ScalabilityMode::kS2T2h: case ScalabilityMode::kS2T3: case ScalabilityMode::kS2T3h: return 2; case ScalabilityMode::kS3T1: case ScalabilityMode::kS3T1h: case ScalabilityMode::kS3T2: case ScalabilityMode::kS3T2h: case ScalabilityMode::kS3T3: case ScalabilityMode::kS3T3h: return 3; } RTC_CHECK_NOTREACHED(); } int ScalabilityModeToNumTemporalLayers(ScalabilityMode scalability_mode) { switch (scalability_mode) { case ScalabilityMode::kL1T1: return 1; case ScalabilityMode::kL1T2: return 2; case ScalabilityMode::kL1T3: return 3; case ScalabilityMode::kL2T1: case ScalabilityMode::kL2T1h: case ScalabilityMode::kL2T1_KEY: return 1; case ScalabilityMode::kL2T2: case ScalabilityMode::kL2T2h: case ScalabilityMode::kL2T2_KEY: case ScalabilityMode::kL2T2_KEY_SHIFT: return 2; case ScalabilityMode::kL2T3: case ScalabilityMode::kL2T3h: case ScalabilityMode::kL2T3_KEY: return 3; case ScalabilityMode::kL3T1: case ScalabilityMode::kL3T1h: case ScalabilityMode::kL3T1_KEY: return 1; case ScalabilityMode::kL3T2: case ScalabilityMode::kL3T2h: case ScalabilityMode::kL3T2_KEY: return 2; case ScalabilityMode::kL3T3: case ScalabilityMode::kL3T3h: case ScalabilityMode::kL3T3_KEY: return 3; case ScalabilityMode::kS2T1: case ScalabilityMode::kS2T1h: case ScalabilityMode::kS3T1: case ScalabilityMode::kS3T1h: return 1; case ScalabilityMode::kS2T2: case ScalabilityMode::kS2T2h: case ScalabilityMode::kS3T2: case ScalabilityMode::kS3T2h: return 2; case ScalabilityMode::kS2T3: case ScalabilityMode::kS2T3h: case ScalabilityMode::kS3T3: case ScalabilityMode::kS3T3h: return 3; } RTC_CHECK_NOTREACHED(); } absl::optional ScalabilityModeToResolutionRatio( ScalabilityMode scalability_mode) { switch (scalability_mode) { case ScalabilityMode::kL1T1: case ScalabilityMode::kL1T2: case ScalabilityMode::kL1T3: return absl::nullopt; case ScalabilityMode::kL2T1: case ScalabilityMode::kL2T1_KEY: case ScalabilityMode::kL2T2: case ScalabilityMode::kL2T2_KEY: case ScalabilityMode::kL2T2_KEY_SHIFT: case ScalabilityMode::kL2T3: case ScalabilityMode::kL2T3_KEY: case ScalabilityMode::kL3T1: case ScalabilityMode::kL3T1_KEY: case ScalabilityMode::kL3T2: case ScalabilityMode::kL3T2_KEY: case ScalabilityMode::kL3T3: case ScalabilityMode::kL3T3_KEY: case ScalabilityMode::kS2T1: case ScalabilityMode::kS2T2: case ScalabilityMode::kS2T3: case ScalabilityMode::kS3T1: case ScalabilityMode::kS3T2: case ScalabilityMode::kS3T3: return ScalabilityModeResolutionRatio::kTwoToOne; case ScalabilityMode::kL2T1h: case ScalabilityMode::kL2T2h: case ScalabilityMode::kL2T3h: case ScalabilityMode::kL3T1h: case ScalabilityMode::kL3T2h: case ScalabilityMode::kL3T3h: case ScalabilityMode::kS2T1h: case ScalabilityMode::kS2T2h: case ScalabilityMode::kS2T3h: case ScalabilityMode::kS3T1h: case ScalabilityMode::kS3T2h: case ScalabilityMode::kS3T3h: return ScalabilityModeResolutionRatio::kThreeToTwo; } RTC_CHECK_NOTREACHED(); } ScalabilityMode LimitNumSpatialLayers(ScalabilityMode scalability_mode, int max_spatial_layers) { int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode); if (max_spatial_layers >= num_spatial_layers) { return scalability_mode; } switch (scalability_mode) { case ScalabilityMode::kL1T1: return ScalabilityMode::kL1T1; case ScalabilityMode::kL1T2: return ScalabilityMode::kL1T2; case ScalabilityMode::kL1T3: return ScalabilityMode::kL1T3; case ScalabilityMode::kL2T1: return ScalabilityMode::kL1T1; case ScalabilityMode::kL2T1h: return ScalabilityMode::kL1T1; case ScalabilityMode::kL2T1_KEY: return ScalabilityMode::kL1T1; case ScalabilityMode::kL2T2: return ScalabilityMode::kL1T2; case ScalabilityMode::kL2T2h: return ScalabilityMode::kL1T2; case ScalabilityMode::kL2T2_KEY: return ScalabilityMode::kL1T2; case ScalabilityMode::kL2T2_KEY_SHIFT: return ScalabilityMode::kL1T2; case ScalabilityMode::kL2T3: return ScalabilityMode::kL1T3; case ScalabilityMode::kL2T3h: return ScalabilityMode::kL1T3; case ScalabilityMode::kL2T3_KEY: return ScalabilityMode::kL1T3; case ScalabilityMode::kL3T1: return max_spatial_layers == 2 ? ScalabilityMode::kL2T1 : ScalabilityMode::kL1T1; case ScalabilityMode::kL3T1h: return max_spatial_layers == 2 ? ScalabilityMode::kL2T1h : ScalabilityMode::kL1T1; case ScalabilityMode::kL3T1_KEY: return max_spatial_layers == 2 ? ScalabilityMode::kL2T1_KEY : ScalabilityMode::kL1T1; case ScalabilityMode::kL3T2: return max_spatial_layers == 2 ? ScalabilityMode::kL2T2 : ScalabilityMode::kL1T2; case ScalabilityMode::kL3T2h: return max_spatial_layers == 2 ? ScalabilityMode::kL2T2h : ScalabilityMode::kL1T2; case ScalabilityMode::kL3T2_KEY: return max_spatial_layers == 2 ? ScalabilityMode::kL2T2_KEY : ScalabilityMode::kL1T2; case ScalabilityMode::kL3T3: return max_spatial_layers == 2 ? ScalabilityMode::kL2T3 : ScalabilityMode::kL1T3; case ScalabilityMode::kL3T3h: return max_spatial_layers == 2 ? ScalabilityMode::kL2T3h : ScalabilityMode::kL1T3; case ScalabilityMode::kL3T3_KEY: return max_spatial_layers == 2 ? ScalabilityMode::kL2T3_KEY : ScalabilityMode::kL1T3; case ScalabilityMode::kS2T1: return ScalabilityMode::kL1T1; case ScalabilityMode::kS2T1h: return ScalabilityMode::kL1T1; case ScalabilityMode::kS2T2: return ScalabilityMode::kL1T2; case ScalabilityMode::kS2T2h: return ScalabilityMode::kL1T2; case ScalabilityMode::kS2T3: return ScalabilityMode::kL1T3; case ScalabilityMode::kS2T3h: return ScalabilityMode::kL1T3; case ScalabilityMode::kS3T1: return max_spatial_layers == 2 ? ScalabilityMode::kS2T1 : ScalabilityMode::kL1T1; case ScalabilityMode::kS3T1h: return max_spatial_layers == 2 ? ScalabilityMode::kS2T1h : ScalabilityMode::kL1T1; case ScalabilityMode::kS3T2: return max_spatial_layers == 2 ? ScalabilityMode::kS2T2 : ScalabilityMode::kL1T2; case ScalabilityMode::kS3T2h: return max_spatial_layers == 2 ? ScalabilityMode::kS2T2h : ScalabilityMode::kL1T2; case ScalabilityMode::kS3T3: return max_spatial_layers == 2 ? ScalabilityMode::kS2T3 : ScalabilityMode::kL1T3; case ScalabilityMode::kS3T3h: return max_spatial_layers == 2 ? ScalabilityMode::kS2T3h : ScalabilityMode::kL1T3; } RTC_CHECK_NOTREACHED(); } } // namespace webrtc