New enum ScalabilityMode.
Used instead of string representation in lower-levels of encoder configuration, to avoid string comparisons (with risk of misspelling) in lots of places.
Bug: webrtc:11607
Change-Id: I4d51c2265aac297c29976d2aa601d8ffb33b7326
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/259870
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36706}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 1d14022..88bd079 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -804,6 +804,7 @@
"../../rtc_base/synchronization:mutex",
"../../system_wrappers:field_trial",
"../rtp_rtcp:rtp_rtcp_format",
+ "svc:scalability_mode_util",
"svc:scalability_structures",
"svc:scalable_video_controller",
"svc:svc_rate_allocator",
diff --git a/modules/video_coding/codecs/av1/BUILD.gn b/modules/video_coding/codecs/av1/BUILD.gn
index 2e4d824..520ed0a 100644
--- a/modules/video_coding/codecs/av1/BUILD.gn
+++ b/modules/video_coding/codecs/av1/BUILD.gn
@@ -99,6 +99,7 @@
sources = [ "libaom_av1_encoder_supported.cc" ]
deps = [
"../../../../api/video_codecs:video_codecs_api",
+ "../../svc:scalability_mode_util",
"../../svc:scalability_structures",
"../../svc:scalable_video_controller",
]
@@ -139,6 +140,7 @@
"../../../../api/units:data_size",
"../../../../api/units:time_delta",
"../../../../api/video:video_frame",
+ "../../svc:scalability_mode_util",
"../../svc:scalability_structures",
"../../svc:scalable_video_controller",
]
diff --git a/modules/video_coding/codecs/av1/av1_svc_config.cc b/modules/video_coding/codecs/av1/av1_svc_config.cc
index abc7e69..f872372 100644
--- a/modules/video_coding/codecs/av1/av1_svc_config.cc
+++ b/modules/video_coding/codecs/av1/av1_svc_config.cc
@@ -24,16 +24,18 @@
bool SetAv1SvcConfig(VideoCodec& video_codec) {
RTC_DCHECK_EQ(video_codec.codecType, kVideoCodecAV1);
- absl::string_view scalability_mode = video_codec.ScalabilityMode();
- if (scalability_mode.empty()) {
+ absl::optional<ScalabilityMode> scalability_mode =
+ video_codec.GetScalabilityMode();
+ if (!scalability_mode.has_value()) {
RTC_LOG(LS_WARNING) << "Scalability mode is not set, using 'L1T1'.";
- scalability_mode = "L1T1";
+ scalability_mode = ScalabilityMode::kL1T1;
}
std::unique_ptr<ScalableVideoController> structure =
- CreateScalabilityStructure(scalability_mode);
+ CreateScalabilityStructure(*scalability_mode);
if (structure == nullptr) {
- RTC_LOG(LS_WARNING) << "Failed to create structure " << scalability_mode;
+ RTC_LOG(LS_WARNING) << "Failed to create structure "
+ << static_cast<int>(*scalability_mode);
return false;
}
diff --git a/modules/video_coding/codecs/av1/av1_svc_config_unittest.cc b/modules/video_coding/codecs/av1/av1_svc_config_unittest.cc
index dca1791..b4e264b 100644
--- a/modules/video_coding/codecs/av1/av1_svc_config_unittest.cc
+++ b/modules/video_coding/codecs/av1/av1_svc_config_unittest.cc
@@ -17,22 +17,10 @@
namespace webrtc {
namespace {
-TEST(Av1SvcConfigTest, RequireScalabilityMode) {
+TEST(Av1SvcConfigTest, TreatsEmptyAsL1T1) {
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
- video_codec.SetScalabilityMode("Unknown");
- EXPECT_FALSE(SetAv1SvcConfig(video_codec));
-
- video_codec.SetScalabilityMode("L1T1");
- EXPECT_TRUE(SetAv1SvcConfig(video_codec));
-}
-
-TEST(Av1SvcConfigTest, TreatsEmptyAsNone) {
- VideoCodec video_codec;
- video_codec.codecType = kVideoCodecAV1;
-
- video_codec.SetScalabilityMode("");
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
EXPECT_TRUE(video_codec.spatialLayers[0].active);
@@ -43,7 +31,7 @@
TEST(Av1SvcConfigTest, SetsActiveSpatialLayersFromScalabilityMode) {
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
- video_codec.SetScalabilityMode("L2T1");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL2T1);
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
@@ -55,7 +43,7 @@
TEST(Av1SvcConfigTest, ConfiguresDobuleResolutionRatioFromScalabilityMode) {
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
- video_codec.SetScalabilityMode("L2T1");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL2T1);
video_codec.width = 1200;
video_codec.height = 800;
@@ -71,7 +59,7 @@
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
// h mode uses 1.5:1 ratio
- video_codec.SetScalabilityMode("L2T1h");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL2T1h);
video_codec.width = 1500;
video_codec.height = 900;
@@ -87,7 +75,7 @@
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
// h mode uses 1.5:1 ratio
- video_codec.SetScalabilityMode("L2T1");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL2T1);
video_codec.maxFramerate = 27;
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
@@ -99,7 +87,7 @@
TEST(Av1SvcConfigTest, SetsNumberOfTemporalLayers) {
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
- video_codec.SetScalabilityMode("L1T3");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL1T3);
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
@@ -109,7 +97,7 @@
TEST(Av1SvcConfigTest, CopiesMinMaxBitrateForSingleSpatialLayer) {
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
- video_codec.SetScalabilityMode("L1T3");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL1T3);
video_codec.minBitrate = 100;
video_codec.maxBitrate = 500;
@@ -126,7 +114,7 @@
TEST(Av1SvcConfigTest, SetsBitratesForMultipleSpatialLayers) {
VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1;
- video_codec.SetScalabilityMode("L3T3");
+ video_codec.SetScalabilityMode(ScalabilityMode::kL3T3);
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
index 3f28abc..6408d52 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
@@ -169,15 +169,16 @@
RTC_LOG(LS_WARNING) << "Simulcast is not implemented by LibaomAv1Encoder.";
return result;
}
- absl::string_view scalability_mode = encoder_settings_.ScalabilityMode();
- if (scalability_mode.empty()) {
+ absl::optional<ScalabilityMode> scalability_mode =
+ encoder_settings_.GetScalabilityMode();
+ if (!scalability_mode.has_value()) {
RTC_LOG(LS_WARNING) << "Scalability mode is not set, using 'L1T1'.";
- scalability_mode = "L1T1";
+ scalability_mode = ScalabilityMode::kL1T1;
}
- svc_controller_ = CreateScalabilityStructure(scalability_mode);
+ svc_controller_ = CreateScalabilityStructure(*scalability_mode);
if (svc_controller_ == nullptr) {
RTC_LOG(LS_WARNING) << "Failed to set scalability mode "
- << scalability_mode;
+ << static_cast<int>(*scalability_mode);
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder_supported.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder_supported.cc
index 0bb3108..8a65da5 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder_supported.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_supported.cc
@@ -10,6 +10,7 @@
#include "modules/video_coding/codecs/av1/libaom_av1_encoder_supported.h"
#include "modules/video_coding/svc/create_scalability_structure.h"
+#include "modules/video_coding/svc/scalability_mode_util.h"
#if defined(RTC_USE_LIBAOM_AV1_ENCODER)
#include "modules/video_coding/codecs/av1/libaom_av1_encoder.h" // nogncheck
@@ -21,11 +22,14 @@
std::unique_ptr<VideoEncoder> CreateLibaomAv1EncoderIfSupported() {
return CreateLibaomAv1Encoder();
}
-bool LibaomAv1EncoderSupportsScalabilityMode(
- absl::string_view scalability_mode) {
+bool LibaomAv1EncoderSupportsScalabilityMode(absl::string_view mode_string) {
+ absl::optional<ScalabilityMode> scalability_mode =
+ ScalabilityModeFromString(mode_string);
+
// For libaom AV1, the scalability mode is supported if we can create the
// scalability structure.
- return ScalabilityStructureConfig(scalability_mode) != absl::nullopt;
+ return scalability_mode.has_value() &&
+ ScalabilityStructureConfig(*scalability_mode) != absl::nullopt;
}
#else
const bool kIsLibaomAv1EncoderSupported = false;
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
index 0c67e4d..5243edc 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
@@ -64,7 +64,7 @@
// Configure encoder with 2 temporal layers.
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
- codec_settings.SetScalabilityMode("L1T2");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL1T2);
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
@@ -90,7 +90,7 @@
SpatialScalabilityInTemporalUnitReportedAsDeltaFrame) {
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
- codec_settings.SetScalabilityMode("L2T1");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1);
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
@@ -112,7 +112,7 @@
TEST(LibaomAv1EncoderTest, NoBitrateOnTopSpatialLayerProduceDeltaFrames) {
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
- codec_settings.SetScalabilityMode("L2T1");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1);
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
@@ -140,7 +140,7 @@
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
// Configure encoder with 3 spatial layers.
- codec_settings.SetScalabilityMode("L3T1");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1);
codec_settings.maxBitrate = allocation.get_sum_kbps();
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
@@ -167,7 +167,7 @@
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
// Configure encoder with 3 spatial layers.
- codec_settings.SetScalabilityMode("L3T1");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1);
// Odd width and height values should not make encoder crash.
codec_settings.width = 623;
codec_settings.height = 405;
@@ -186,7 +186,7 @@
TEST(LibaomAv1EncoderTest, EncoderInfoProvidesFpsAllocation) {
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
- codec_settings.SetScalabilityMode("L3T3");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL3T3);
codec_settings.maxFramerate = 60;
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
@@ -208,7 +208,7 @@
codec_settings.maxBitrate = allocation.get_sum_kbps();
ASSERT_GT(codec_settings.width, 4);
// Configure encoder with 3 spatial layers.
- codec_settings.SetScalabilityMode("L3T1");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1);
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
encoder->SetRates(VideoEncoder::RateControlParameters(
diff --git a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
index 269432a..5d9c251 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_unittest.cc
@@ -28,6 +28,7 @@
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "modules/video_coding/svc/create_scalability_structure.h"
+#include "modules/video_coding/svc/scalability_mode_util.h"
#include "modules/video_coding/svc/scalable_video_controller.h"
#include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
#include "test/gmock.h"
@@ -55,7 +56,7 @@
VideoCodec DefaultCodecSettings() {
VideoCodec codec_settings;
- codec_settings.SetScalabilityMode("L1T1");
+ codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
codec_settings.width = kWidth;
codec_settings.height = kHeight;
codec_settings.maxFramerate = kFramerate;
@@ -175,6 +176,13 @@
};
struct SvcTestParam {
+ ScalabilityMode GetScalabilityMode() const {
+ absl::optional<ScalabilityMode> scalability_mode =
+ ScalabilityModeFromString(name);
+ RTC_CHECK(scalability_mode.has_value());
+ return *scalability_mode;
+ }
+
std::string name;
int num_frames_to_generate;
std::map<LayerId, DataRate> configured_bitrates;
@@ -185,7 +193,7 @@
TEST_P(LibaomAv1SvcTest, EncodeAndDecodeAllDecodeTargets) {
const SvcTestParam param = GetParam();
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(param.name);
+ CreateScalabilityStructure(param.GetScalabilityMode());
ASSERT_TRUE(svc_controller);
VideoBitrateAllocation allocation;
if (param.configured_bitrates.empty()) {
@@ -208,7 +216,7 @@
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
VideoCodec codec_settings = DefaultCodecSettings();
- codec_settings.SetScalabilityMode(GetParam().name);
+ codec_settings.SetScalabilityMode(GetParam().GetScalabilityMode());
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
WEBRTC_VIDEO_CODEC_OK);
encoder->SetRates(VideoEncoder::RateControlParameters(
@@ -278,7 +286,7 @@
std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
ASSERT_TRUE(encoder);
VideoCodec codec_settings = DefaultCodecSettings();
- codec_settings.SetScalabilityMode(param.name);
+ codec_settings.SetScalabilityMode(param.GetScalabilityMode());
codec_settings.maxBitrate = allocation.get_sum_kbps();
codec_settings.maxFramerate = 30;
ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
diff --git a/modules/video_coding/codecs/test/videocodec_test_av1.cc b/modules/video_coding/codecs/test/videocodec_test_av1.cc
index 38b90ab..7680957 100644
--- a/modules/video_coding/codecs/test/videocodec_test_av1.cc
+++ b/modules/video_coding/codecs/test/videocodec_test_av1.cc
@@ -52,7 +52,7 @@
auto config = CreateConfig("foreman_cif");
config.SetCodecSettings(cricket::kAv1CodecName, 1, 1, 1, false, true, true,
kCifWidth, kCifHeight);
- config.codec_settings.SetScalabilityMode("L1T1");
+ config.codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
config.num_frames = kNumFramesLong;
auto fixture = CreateVideoCodecTestFixture(config);
@@ -70,7 +70,7 @@
auto config = CreateConfig("foreman_cif");
config.SetCodecSettings(cricket::kAv1CodecName, 1, 1, 1, false, true, true,
kCifWidth, kCifHeight);
- config.codec_settings.SetScalabilityMode("L1T1");
+ config.codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
auto fixture = CreateVideoCodecTestFixture(config);
std::vector<RateProfile> rate_profiles = {{50, 30, 0}};
@@ -90,7 +90,7 @@
auto config = CreateConfig("ConferenceMotion_1280_720_50");
config.SetCodecSettings(cricket::kAv1CodecName, 1, 1, 1, false, true, true,
kHdWidth, kHdHeight);
- config.codec_settings.SetScalabilityMode("L1T1");
+ config.codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
config.num_frames = kNumFramesLong;
auto fixture = CreateVideoCodecTestFixture(config);
diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
index 2c9e4bc..3f9f4e9 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
@@ -27,6 +27,7 @@
#include "common_video/libyuv/include/webrtc_libyuv.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/video_coding/svc/create_scalability_structure.h"
+#include "modules/video_coding/svc/scalability_mode_util.h"
#include "modules/video_coding/svc/scalable_video_controller.h"
#include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
#include "modules/video_coding/svc/svc_rate_allocator.h"
@@ -142,7 +143,14 @@
}
}
- auto scalability_structure_controller = CreateScalabilityStructure(name);
+ absl::optional<ScalabilityMode> scalability_mode =
+ ScalabilityModeFromString(name);
+ if (!scalability_mode.has_value()) {
+ RTC_LOG(LS_WARNING) << "Invalid scalability mode " << name;
+ return nullptr;
+ }
+ auto scalability_structure_controller =
+ CreateScalabilityStructure(*scalability_mode);
if (scalability_structure_controller == nullptr) {
RTC_LOG(LS_WARNING) << "Unsupported scalability structure " << name;
} else {
diff --git a/modules/video_coding/svc/BUILD.gn b/modules/video_coding/svc/BUILD.gn
index 2eb2502..f68001a 100644
--- a/modules/video_coding/svc/BUILD.gn
+++ b/modules/video_coding/svc/BUILD.gn
@@ -8,6 +8,21 @@
import("../../../webrtc.gni")
+rtc_source_set("scalability_mode_util") {
+ sources = [
+ "scalability_mode_util.cc",
+ "scalability_mode_util.h",
+ ]
+ deps = [
+ "../../../api/video_codecs:scalability_mode",
+ "../../../rtc_base:checks",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
rtc_source_set("scalable_video_controller") {
sources = [
"scalable_video_controller.h",
@@ -43,6 +58,7 @@
":scalable_video_controller",
"../../../api/transport/rtp:dependency_descriptor",
"../../../api/video:video_bitrate_allocation",
+ "../../../api/video_codecs:scalability_mode",
"../../../common_video/generic_frame_descriptor",
"../../../rtc_base:checks",
"../../../rtc_base:logging",
@@ -75,6 +91,7 @@
rtc_source_set("scalability_structure_tests") {
testonly = true
sources = [
+ "scalability_mode_util_unittest.cc",
"scalability_structure_full_svc_unittest.cc",
"scalability_structure_key_svc_unittest.cc",
"scalability_structure_l2t2_key_shift_unittest.cc",
@@ -83,6 +100,7 @@
"scalability_structure_unittest.cc",
]
deps = [
+ ":scalability_mode_util",
":scalability_structures",
":scalable_video_controller",
"..:chain_diff_calculator",
@@ -91,10 +109,14 @@
"../../../api/transport/rtp:dependency_descriptor",
"../../../api/video:video_bitrate_allocation",
"../../../api/video:video_frame_type",
+ "../../../api/video_codecs:scalability_mode",
"../../../common_video/generic_frame_descriptor",
"../../../test:test_support",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
}
rtc_source_set("svc_rate_allocator_tests") {
diff --git a/modules/video_coding/svc/create_scalability_structure.cc b/modules/video_coding/svc/create_scalability_structure.cc
index 80df766..dfbfb14 100644
--- a/modules/video_coding/svc/create_scalability_structure.cc
+++ b/modules/video_coding/svc/create_scalability_structure.cc
@@ -11,7 +11,7 @@
#include <memory>
-#include "absl/strings/string_view.h"
+#include "api/video_codecs/scalability_mode.h"
#include "modules/video_coding/svc/scalability_structure_full_svc.h"
#include "modules/video_coding/svc/scalability_structure_key_svc.h"
#include "modules/video_coding/svc/scalability_structure_l2t2_key_shift.h"
@@ -24,7 +24,7 @@
namespace {
struct NamedStructureFactory {
- absl::string_view name;
+ ScalabilityMode name;
// Use function pointer to make NamedStructureFactory trivally destructable.
std::unique_ptr<ScalableVideoController> (*factory)();
ScalableVideoController::StreamLayersConfig config;
@@ -114,28 +114,33 @@
{4, 2, 1}};
constexpr NamedStructureFactory kFactories[] = {
- {"L1T1", Create<ScalableVideoControllerNoLayering>, kConfigL1T1},
- {"L1T2", Create<ScalabilityStructureL1T2>, kConfigL1T2},
- {"L1T3", Create<ScalabilityStructureL1T3>, kConfigL1T3},
- {"L2T1", Create<ScalabilityStructureL2T1>, kConfigL2T1},
- {"L2T1h", CreateH<ScalabilityStructureL2T1>, kConfigL2T1h},
- {"L2T1_KEY", Create<ScalabilityStructureL2T1Key>, kConfigL2T1},
- {"L2T2", Create<ScalabilityStructureL2T2>, kConfigL2T2},
- {"L2T2_KEY", Create<ScalabilityStructureL2T2Key>, kConfigL2T2},
- {"L2T2_KEY_SHIFT", Create<ScalabilityStructureL2T2KeyShift>, kConfigL2T2},
- {"L2T3_KEY", Create<ScalabilityStructureL2T3Key>, kConfigL2T3},
- {"L3T1", Create<ScalabilityStructureL3T1>, kConfigL3T1},
- {"L3T3", Create<ScalabilityStructureL3T3>, kConfigL3T3},
- {"L3T3_KEY", Create<ScalabilityStructureL3T3Key>, kConfigL3T3},
- {"S2T1", Create<ScalabilityStructureS2T1>, kConfigS2T1},
- {"S3T3", Create<ScalabilityStructureS3T3>, kConfigS3T3},
+ {ScalabilityMode::kL1T1, Create<ScalableVideoControllerNoLayering>,
+ kConfigL1T1},
+ {ScalabilityMode::kL1T2, Create<ScalabilityStructureL1T2>, kConfigL1T2},
+ {ScalabilityMode::kL1T3, Create<ScalabilityStructureL1T3>, kConfigL1T3},
+ {ScalabilityMode::kL2T1, Create<ScalabilityStructureL2T1>, kConfigL2T1},
+ {ScalabilityMode::kL2T1h, CreateH<ScalabilityStructureL2T1>, kConfigL2T1h},
+ {ScalabilityMode::kL2T1_KEY, Create<ScalabilityStructureL2T1Key>,
+ kConfigL2T1},
+ {ScalabilityMode::kL2T2, Create<ScalabilityStructureL2T2>, kConfigL2T2},
+ {ScalabilityMode::kL2T2_KEY, Create<ScalabilityStructureL2T2Key>,
+ kConfigL2T2},
+ {ScalabilityMode::kL2T2_KEY_SHIFT, Create<ScalabilityStructureL2T2KeyShift>,
+ kConfigL2T2},
+ {ScalabilityMode::kL2T3_KEY, Create<ScalabilityStructureL2T3Key>,
+ kConfigL2T3},
+ {ScalabilityMode::kL3T1, Create<ScalabilityStructureL3T1>, kConfigL3T1},
+ {ScalabilityMode::kL3T3, Create<ScalabilityStructureL3T3>, kConfigL3T3},
+ {ScalabilityMode::kL3T3_KEY, Create<ScalabilityStructureL3T3Key>,
+ kConfigL3T3},
+ {ScalabilityMode::kS2T1, Create<ScalabilityStructureS2T1>, kConfigS2T1},
+ {ScalabilityMode::kS3T3, Create<ScalabilityStructureS3T3>, kConfigS3T3},
};
} // namespace
std::unique_ptr<ScalableVideoController> CreateScalabilityStructure(
- absl::string_view name) {
- RTC_DCHECK(!name.empty());
+ ScalabilityMode name) {
for (const auto& entry : kFactories) {
if (entry.name == name) {
return entry.factory();
@@ -145,8 +150,7 @@
}
absl::optional<ScalableVideoController::StreamLayersConfig>
-ScalabilityStructureConfig(absl::string_view name) {
- RTC_DCHECK(!name.empty());
+ScalabilityStructureConfig(ScalabilityMode name) {
for (const auto& entry : kFactories) {
if (entry.name == name) {
return entry.config;
diff --git a/modules/video_coding/svc/create_scalability_structure.h b/modules/video_coding/svc/create_scalability_structure.h
index fde0344..3b67443 100644
--- a/modules/video_coding/svc/create_scalability_structure.h
+++ b/modules/video_coding/svc/create_scalability_structure.h
@@ -13,8 +13,8 @@
#include <memory>
#include <vector>
-#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
+#include "api/video_codecs/scalability_mode.h"
#include "modules/video_coding/svc/scalable_video_controller.h"
namespace webrtc {
@@ -23,12 +23,12 @@
// https://w3c.github.io/webrtc-svc/#scalabilitymodes*
// Returns nullptr for unknown name.
std::unique_ptr<ScalableVideoController> CreateScalabilityStructure(
- absl::string_view name);
+ ScalabilityMode name);
-// Returns descrption of the scalability structure identified by 'name',
+// Returns description of the scalability structure identified by 'name',
// Return nullopt for unknown name.
absl::optional<ScalableVideoController::StreamLayersConfig>
-ScalabilityStructureConfig(absl::string_view name);
+ScalabilityStructureConfig(ScalabilityMode name);
} // namespace webrtc
diff --git a/modules/video_coding/svc/scalability_mode_util.cc b/modules/video_coding/svc/scalability_mode_util.cc
new file mode 100644
index 0000000..6dc063d
--- /dev/null
+++ b/modules/video_coding/svc/scalability_mode_util.cc
@@ -0,0 +1,96 @@
+/*
+ * 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<ScalabilityMode> 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 == "L2T2_KEY")
+ return ScalabilityMode::kL2T2_KEY;
+ if (mode_string == "L2T2_KEY_SHIFT")
+ return ScalabilityMode::kL2T2_KEY_SHIFT;
+ if (mode_string == "L2T3_KEY")
+ return ScalabilityMode::kL2T3_KEY;
+
+ if (mode_string == "L3T1")
+ return ScalabilityMode::kL3T1;
+ if (mode_string == "L3T3")
+ return ScalabilityMode::kL3T3;
+ if (mode_string == "L3T3_KEY")
+ return ScalabilityMode::kL3T3_KEY;
+
+ if (mode_string == "S2T1")
+ return ScalabilityMode::kS2T1;
+ if (mode_string == "S3T3")
+ return ScalabilityMode::kS3T3;
+
+ return absl::nullopt;
+}
+
+absl::string_view ScalabilityModeToString(ScalabilityMode scalability_mode) {
+ switch (scalability_mode) {
+ case ScalabilityMode::kL1T1:
+ return "L1T1";
+ case ScalabilityMode::kL1T2:
+ return "L1T2";
+ case ScalabilityMode::kL1T3:
+ return "L1T3";
+ case ScalabilityMode::kL2T1:
+ return "L2T1";
+ case ScalabilityMode::kL2T1h:
+ return "L2T1h";
+ case ScalabilityMode::kL2T1_KEY:
+ return "L2T1_KEY";
+ case ScalabilityMode::kL2T2:
+ return "L2T2";
+ case ScalabilityMode::kL2T2_KEY:
+ return "L2T2_KEY";
+ case ScalabilityMode::kL2T2_KEY_SHIFT:
+ return "L2T2_KEY_SHIFT";
+ case ScalabilityMode::kL2T3_KEY:
+ return "L2T3_KEY";
+ case ScalabilityMode::kL3T1:
+ return "L3T1";
+ case ScalabilityMode::kL3T3:
+ return "L3T3";
+ case ScalabilityMode::kL3T3_KEY:
+ return "L3T3_KEY";
+ case ScalabilityMode::kS2T1:
+ return "S2T1";
+ case ScalabilityMode::kS3T3:
+ return "S3T3";
+ }
+ RTC_CHECK_NOTREACHED();
+}
+
+} // namespace webrtc
diff --git a/modules/video_coding/svc/scalability_mode_util.h b/modules/video_coding/svc/scalability_mode_util.h
new file mode 100644
index 0000000..363cb6e
--- /dev/null
+++ b/modules/video_coding/svc/scalability_mode_util.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#ifndef MODULES_VIDEO_CODING_SVC_SCALABILITY_MODE_UTIL_H_
+#define 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"
+
+namespace webrtc {
+
+absl::optional<ScalabilityMode> ScalabilityModeFromString(
+ absl::string_view scalability_mode_string);
+
+absl::string_view ScalabilityModeToString(ScalabilityMode scalability_mode);
+
+} // namespace webrtc
+
+#endif // MODULES_VIDEO_CODING_SVC_SCALABILITY_MODE_UTIL_H_
diff --git a/modules/video_coding/svc/scalability_mode_util_unittest.cc b/modules/video_coding/svc/scalability_mode_util_unittest.cc
new file mode 100644
index 0000000..7fb1036
--- /dev/null
+++ b/modules/video_coding/svc/scalability_mode_util_unittest.cc
@@ -0,0 +1,47 @@
+/*
+ * 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 "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+TEST(ScalabilityModeUtil, ConvertsL1T2) {
+ EXPECT_EQ(ScalabilityModeFromString("L1T2"), ScalabilityMode::kL1T2);
+ EXPECT_EQ(ScalabilityModeToString(ScalabilityMode::kL1T2), "L1T2");
+}
+
+TEST(ScalabilityModeUtil, RejectsUnknownString) {
+ EXPECT_EQ(ScalabilityModeFromString(""), absl::nullopt);
+ EXPECT_EQ(ScalabilityModeFromString("not-a-mode"), absl::nullopt);
+}
+
+// Check roundtrip conversion of all enum values.
+TEST(ScalabilityModeUtil, ConvertsAllToAndFromString) {
+ const ScalabilityMode kLastEnum = ScalabilityMode::kS3T3;
+ for (int numerical_enum = 0; numerical_enum <= static_cast<int>(kLastEnum);
+ numerical_enum++) {
+ ScalabilityMode scalability_mode =
+ static_cast<ScalabilityMode>(numerical_enum);
+ absl::string_view scalability_mode_string =
+ ScalabilityModeToString(scalability_mode);
+ EXPECT_FALSE(scalability_mode_string.empty());
+ EXPECT_EQ(ScalabilityModeFromString(scalability_mode_string),
+ scalability_mode);
+ }
+}
+
+} // namespace
+} // namespace webrtc
diff --git a/modules/video_coding/svc/scalability_structure_unittest.cc b/modules/video_coding/svc/scalability_structure_unittest.cc
index 7b6e924..ffc085d 100644
--- a/modules/video_coding/svc/scalability_structure_unittest.cc
+++ b/modules/video_coding/svc/scalability_structure_unittest.cc
@@ -19,6 +19,7 @@
#include "api/array_view.h"
#include "api/transport/rtp/dependency_descriptor.h"
#include "modules/video_coding/svc/create_scalability_structure.h"
+#include "modules/video_coding/svc/scalability_mode_util.h"
#include "modules/video_coding/svc/scalability_structure_test_helpers.h"
#include "modules/video_coding/svc/scalable_video_controller.h"
#include "test/gmock.h"
@@ -47,6 +48,13 @@
return os << param.name;
}
+ ScalabilityMode GetScalabilityMode() const {
+ absl::optional<ScalabilityMode> scalability_mode =
+ ScalabilityModeFromString(name);
+ RTC_CHECK(scalability_mode.has_value());
+ return *scalability_mode;
+ }
+
std::string name;
int num_temporal_units;
};
@@ -56,9 +64,9 @@
TEST_P(ScalabilityStructureTest,
StaticConfigMatchesConfigReturnedByController) {
std::unique_ptr<ScalableVideoController> controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
absl::optional<ScalableVideoController::StreamLayersConfig> static_config =
- ScalabilityStructureConfig(GetParam().name);
+ ScalabilityStructureConfig(GetParam().GetScalabilityMode());
ASSERT_THAT(controller, NotNull());
ASSERT_NE(static_config, absl::nullopt);
ScalableVideoController::StreamLayersConfig config =
@@ -78,7 +86,8 @@
TEST_P(ScalabilityStructureTest,
NumberOfDecodeTargetsAndChainsAreInRangeAndConsistent) {
FrameDependencyStructure structure =
- CreateScalabilityStructure(GetParam().name)->DependencyStructure();
+ CreateScalabilityStructure(GetParam().GetScalabilityMode())
+ ->DependencyStructure();
EXPECT_GT(structure.num_decode_targets, 0);
EXPECT_LE(structure.num_decode_targets,
DependencyDescriptor::kMaxDecodeTargets);
@@ -97,7 +106,8 @@
TEST_P(ScalabilityStructureTest, TemplatesAreSortedByLayerId) {
FrameDependencyStructure structure =
- CreateScalabilityStructure(GetParam().name)->DependencyStructure();
+ CreateScalabilityStructure(GetParam().GetScalabilityMode())
+ ->DependencyStructure();
ASSERT_THAT(structure.templates, Not(IsEmpty()));
const auto& first_templates = structure.templates.front();
EXPECT_EQ(first_templates.spatial_id, 0);
@@ -128,7 +138,8 @@
TEST_P(ScalabilityStructureTest, TemplatesMatchNumberOfDecodeTargetsAndChains) {
FrameDependencyStructure structure =
- CreateScalabilityStructure(GetParam().name)->DependencyStructure();
+ CreateScalabilityStructure(GetParam().GetScalabilityMode())
+ ->DependencyStructure();
EXPECT_THAT(
structure.templates,
Each(AllOf(Field(&FrameDependencyTemplate::decode_target_indications,
@@ -139,7 +150,7 @@
TEST_P(ScalabilityStructureTest, FrameInfoMatchesFrameDependencyStructure) {
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
FrameDependencyStructure structure = svc_controller->DependencyStructure();
std::vector<GenericFrameInfo> frame_infos =
ScalabilityStructureWrapper(*svc_controller)
@@ -158,7 +169,7 @@
TEST_P(ScalabilityStructureTest, ThereIsAPerfectTemplateForEachFrame) {
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
FrameDependencyStructure structure = svc_controller->DependencyStructure();
std::vector<GenericFrameInfo> frame_infos =
ScalabilityStructureWrapper(*svc_controller)
@@ -171,7 +182,7 @@
TEST_P(ScalabilityStructureTest, FrameDependsOnSameOrLowerLayer) {
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
std::vector<GenericFrameInfo> frame_infos =
ScalabilityStructureWrapper(*svc_controller)
.GenerateFrames(GetParam().num_temporal_units);
@@ -192,7 +203,7 @@
TEST_P(ScalabilityStructureTest, NoFrameDependsOnDiscardableOrNotPresent) {
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
std::vector<GenericFrameInfo> frame_infos =
ScalabilityStructureWrapper(*svc_controller)
.GenerateFrames(GetParam().num_temporal_units);
@@ -224,7 +235,7 @@
TEST_P(ScalabilityStructureTest, NoFrameDependsThroughSwitchIndication) {
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
FrameDependencyStructure structure = svc_controller->DependencyStructure();
std::vector<GenericFrameInfo> frame_infos =
ScalabilityStructureWrapper(*svc_controller)
@@ -277,7 +288,7 @@
TEST_P(ScalabilityStructureTest, ProduceNoFrameForDisabledLayers) {
std::unique_ptr<ScalableVideoController> svc_controller =
- CreateScalabilityStructure(GetParam().name);
+ CreateScalabilityStructure(GetParam().GetScalabilityMode());
ScalableVideoController::StreamLayersConfig structure =
svc_controller->StreamConfig();
diff --git a/modules/video_coding/svc/svc_rate_allocator.cc b/modules/video_coding/svc/svc_rate_allocator.cc
index 2d27d47..b6ae0d7 100644
--- a/modules/video_coding/svc/svc_rate_allocator.cc
+++ b/modules/video_coding/svc/svc_rate_allocator.cc
@@ -174,8 +174,10 @@
SvcRateAllocator::NumLayers SvcRateAllocator::GetNumLayers(
const VideoCodec& codec) {
NumLayers layers;
- if (!codec.ScalabilityMode().empty()) {
- if (auto structure = CreateScalabilityStructure(codec.ScalabilityMode())) {
+ if (absl::optional<ScalabilityMode> scalability_mode =
+ codec.GetScalabilityMode();
+ scalability_mode.has_value()) {
+ if (auto structure = CreateScalabilityStructure(*scalability_mode)) {
ScalableVideoController::StreamLayersConfig config =
structure->StreamConfig();
layers.spatial = config.num_spatial_layers;
diff --git a/modules/video_coding/svc/svc_rate_allocator_unittest.cc b/modules/video_coding/svc/svc_rate_allocator_unittest.cc
index fd22acd..b3a365d 100644
--- a/modules/video_coding/svc/svc_rate_allocator_unittest.cc
+++ b/modules/video_coding/svc/svc_rate_allocator_unittest.cc
@@ -275,7 +275,7 @@
codec.width = 640;
codec.height = 360;
codec.codecType = kVideoCodecAV1;
- codec.SetScalabilityMode("L3T3");
+ codec.SetScalabilityMode(ScalabilityMode::kL3T3);
codec.spatialLayers[0].active = true;
codec.spatialLayers[0].minBitrate = 30;
codec.spatialLayers[0].targetBitrate = 51;
@@ -304,7 +304,7 @@
codec.width = 640;
codec.height = 360;
codec.codecType = kVideoCodecAV1;
- codec.SetScalabilityMode("L3T3");
+ codec.SetScalabilityMode(ScalabilityMode::kL3T3);
codec.spatialLayers[0].active = false;
codec.spatialLayers[0].minBitrate = 30;
codec.spatialLayers[0].targetBitrate = 51;
@@ -333,7 +333,7 @@
codec.width = 640;
codec.height = 360;
codec.codecType = kVideoCodecAV1;
- codec.SetScalabilityMode("L2T2");
+ codec.SetScalabilityMode(ScalabilityMode::kL2T2);
codec.spatialLayers[0].active = true;
codec.spatialLayers[0].minBitrate = 30;
codec.spatialLayers[0].targetBitrate = 51;
diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc
index 5d06a2c..80b9dc9 100644
--- a/modules/video_coding/video_codec_initializer.cc
+++ b/modules/video_coding/video_codec_initializer.cc
@@ -94,7 +94,8 @@
int max_framerate = 0;
- absl::optional<std::string> scalability_mode = streams[0].scalability_mode;
+ absl::optional<ScalabilityMode> scalability_mode =
+ streams[0].scalability_mode;
for (size_t i = 0; i < streams.size(); ++i) {
SpatialLayer* sim_stream = &video_codec.simulcastStream[i];
RTC_DCHECK_GT(streams[i].width, 0);
diff --git a/modules/video_coding/video_codec_initializer_unittest.cc b/modules/video_coding/video_codec_initializer_unittest.cc
index 902f991..85efa46 100644
--- a/modules/video_coding/video_codec_initializer_unittest.cc
+++ b/modules/video_coding/video_codec_initializer_unittest.cc
@@ -430,7 +430,7 @@
VideoEncoderConfig config;
config.codec_type = VideoCodecType::kVideoCodecAV1;
std::vector<VideoStream> streams = {DefaultStream()};
- streams[0].scalability_mode = "L1T2";
+ streams[0].scalability_mode = ScalabilityMode::kL1T2;
VideoCodec codec;
EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
@@ -445,7 +445,7 @@
VideoEncoderConfig config;
config.codec_type = VideoCodecType::kVideoCodecAV1;
std::vector<VideoStream> streams = {DefaultStream()};
- streams[0].scalability_mode = "L2T2";
+ streams[0].scalability_mode = ScalabilityMode::kL2T2;
VideoCodec codec;
EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
@@ -465,7 +465,7 @@
VideoEncoderConfig config;
config.codec_type = VideoCodecType::kVideoCodecAV1;
std::vector<VideoStream> streams = {DefaultStream()};
- streams[0].scalability_mode = "L2T2";
+ streams[0].scalability_mode = ScalabilityMode::kL2T2;
config.spatial_layers = {};
VideoCodec codec;
@@ -479,7 +479,7 @@
VideoEncoderConfig config;
config.codec_type = VideoCodecType::kVideoCodecAV1;
std::vector<VideoStream> streams = {DefaultStream()};
- streams[0].scalability_mode = "L2T2";
+ streams[0].scalability_mode = ScalabilityMode::kL2T2;
config.spatial_layers.resize(2);
config.spatial_layers[0].active = true;
config.spatial_layers[1].active = false;