Add helper to query scalability structure configuration
without creating svc controller for it.
Bug: chromium:1187565
Change-Id: I219f88203e73036bf48bce04527bb8e46ccf1c33
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231128
Reviewed-by: Johannes Kron <kron@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34968}
diff --git a/modules/video_coding/svc/create_scalability_structure.cc b/modules/video_coding/svc/create_scalability_structure.cc
index 39710d8..8e5c06f 100644
--- a/modules/video_coding/svc/create_scalability_structure.cc
+++ b/modules/video_coding/svc/create_scalability_structure.cc
@@ -27,6 +27,7 @@
absl::string_view name;
// Use function pointer to make NamedStructureFactory trivally destructable.
std::unique_ptr<ScalableVideoController> (*factory)();
+ ScalableVideoController::StreamLayersConfig config;
};
// Wrap std::make_unique function to have correct return type.
@@ -44,22 +45,90 @@
return std::make_unique<T>(factor);
}
+constexpr ScalableVideoController::StreamLayersConfig kConfigNone = {
+ /*num_spatial_layers=*/1, /*num_temporal_layers=*/1,
+ /*uses_reference_scaling=*/false};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL1T2 = {
+ /*num_spatial_layers=*/1, /*num_temporal_layers=*/2,
+ /*uses_reference_scaling=*/false};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL1T3 = {
+ /*num_spatial_layers=*/1, /*num_temporal_layers=*/3,
+ /*uses_reference_scaling=*/false};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL2T1 = {
+ /*num_spatial_layers=*/2,
+ /*num_temporal_layers=*/1,
+ /*uses_reference_scaling=*/true,
+ {1, 1},
+ {2, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL2T1h = {
+ /*num_spatial_layers=*/2,
+ /*num_temporal_layers=*/1,
+ /*uses_reference_scaling=*/true,
+ {2, 1},
+ {3, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL2T2 = {
+ /*num_spatial_layers=*/2,
+ /*num_temporal_layers=*/2,
+ /*uses_reference_scaling=*/true,
+ {1, 1},
+ {2, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL2T3 = {
+ /*num_spatial_layers=*/2,
+ /*num_temporal_layers=*/3,
+ /*uses_reference_scaling=*/true,
+ {1, 1},
+ {2, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL3T1 = {
+ /*num_spatial_layers=*/3,
+ /*num_temporal_layers=*/1,
+ /*uses_reference_scaling=*/true,
+ {1, 1, 1},
+ {4, 2, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigL3T3 = {
+ /*num_spatial_layers=*/3,
+ /*num_temporal_layers=*/3,
+ /*uses_reference_scaling=*/true,
+ {1, 1, 1},
+ {4, 2, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigS2T1 = {
+ /*num_spatial_layers=*/2,
+ /*num_temporal_layers=*/1,
+ /*uses_reference_scaling=*/false,
+ {1, 1},
+ {2, 1}};
+
+constexpr ScalableVideoController::StreamLayersConfig kConfigS3T3 = {
+ /*num_spatial_layers=*/3,
+ /*num_temporal_layers=*/3,
+ /*uses_reference_scaling=*/false,
+ {1, 1, 1},
+ {4, 2, 1}};
+
constexpr NamedStructureFactory kFactories[] = {
- {"NONE", Create<ScalableVideoControllerNoLayering>},
- {"L1T2", Create<ScalabilityStructureL1T2>},
- {"L1T3", Create<ScalabilityStructureL1T3>},
- {"L2T1", Create<ScalabilityStructureL2T1>},
- {"L2T1h", CreateH<ScalabilityStructureL2T1>},
- {"L2T1_KEY", Create<ScalabilityStructureL2T1Key>},
- {"L2T2", Create<ScalabilityStructureL2T2>},
- {"L2T2_KEY", Create<ScalabilityStructureL2T2Key>},
- {"L2T2_KEY_SHIFT", Create<ScalabilityStructureL2T2KeyShift>},
- {"L2T3_KEY", Create<ScalabilityStructureL2T3Key>},
- {"L3T1", Create<ScalabilityStructureL3T1>},
- {"L3T3", Create<ScalabilityStructureL3T3>},
- {"L3T3_KEY", Create<ScalabilityStructureL3T3Key>},
- {"S2T1", Create<ScalabilityStructureS2T1>},
- {"S3T3", Create<ScalabilityStructureS3T3>},
+ {"NONE", Create<ScalableVideoControllerNoLayering>, kConfigNone},
+ {"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},
};
} // namespace
@@ -75,4 +144,15 @@
return nullptr;
}
+absl::optional<ScalableVideoController::StreamLayersConfig>
+ScalabilityStructureConfig(absl::string_view name) {
+ RTC_DCHECK(!name.empty());
+ for (const auto& entry : kFactories) {
+ if (entry.name == name) {
+ return entry.config;
+ }
+ }
+ return absl::nullopt;
+}
+
} // namespace webrtc
diff --git a/modules/video_coding/svc/create_scalability_structure.h b/modules/video_coding/svc/create_scalability_structure.h
index 9a14221..fde0344 100644
--- a/modules/video_coding/svc/create_scalability_structure.h
+++ b/modules/video_coding/svc/create_scalability_structure.h
@@ -14,6 +14,7 @@
#include <vector>
#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
#include "modules/video_coding/svc/scalable_video_controller.h"
namespace webrtc {
@@ -24,6 +25,11 @@
std::unique_ptr<ScalableVideoController> CreateScalabilityStructure(
absl::string_view name);
+// Returns descrption of the scalability structure identified by 'name',
+// Return nullopt for unknown name.
+absl::optional<ScalableVideoController::StreamLayersConfig>
+ScalabilityStructureConfig(absl::string_view name);
+
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_SVC_CREATE_SCALABILITY_STRUCTURE_H_
diff --git a/modules/video_coding/svc/scalability_structure_full_svc.cc b/modules/video_coding/svc/scalability_structure_full_svc.cc
index b89de99..9f66a5a 100644
--- a/modules/video_coding/svc/scalability_structure_full_svc.cc
+++ b/modules/video_coding/svc/scalability_structure_full_svc.cc
@@ -52,6 +52,7 @@
result.scaling_factor_den[sid - 1] =
resolution_factor_.den * result.scaling_factor_den[sid];
}
+ result.uses_reference_scaling = num_spatial_layers_ > 1;
return result;
}
diff --git a/modules/video_coding/svc/scalability_structure_key_svc.cc b/modules/video_coding/svc/scalability_structure_key_svc.cc
index 1cee80e..6cd96a6 100644
--- a/modules/video_coding/svc/scalability_structure_key_svc.cc
+++ b/modules/video_coding/svc/scalability_structure_key_svc.cc
@@ -51,6 +51,7 @@
result.scaling_factor_num[sid - 1] = 1;
result.scaling_factor_den[sid - 1] = 2 * result.scaling_factor_den[sid];
}
+ result.uses_reference_scaling = true;
return result;
}
diff --git a/modules/video_coding/svc/scalability_structure_l2t2_key_shift.cc b/modules/video_coding/svc/scalability_structure_l2t2_key_shift.cc
index c53ff8f..4d15942 100644
--- a/modules/video_coding/svc/scalability_structure_l2t2_key_shift.cc
+++ b/modules/video_coding/svc/scalability_structure_l2t2_key_shift.cc
@@ -51,6 +51,7 @@
result.num_temporal_layers = 2;
result.scaling_factor_num[0] = 1;
result.scaling_factor_den[0] = 2;
+ result.uses_reference_scaling = true;
return result;
}
diff --git a/modules/video_coding/svc/scalability_structure_simulcast.cc b/modules/video_coding/svc/scalability_structure_simulcast.cc
index c236066..0db91cc 100644
--- a/modules/video_coding/svc/scalability_structure_simulcast.cc
+++ b/modules/video_coding/svc/scalability_structure_simulcast.cc
@@ -65,6 +65,7 @@
result.scaling_factor_num[sid - 1] = 1;
result.scaling_factor_den[sid - 1] = 2 * result.scaling_factor_den[sid];
}
+ result.uses_reference_scaling = false;
return result;
}
diff --git a/modules/video_coding/svc/scalability_structure_unittest.cc b/modules/video_coding/svc/scalability_structure_unittest.cc
index 8bd933b..9368f57 100644
--- a/modules/video_coding/svc/scalability_structure_unittest.cc
+++ b/modules/video_coding/svc/scalability_structure_unittest.cc
@@ -16,6 +16,7 @@
#include <string>
#include "absl/types/optional.h"
+#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_structure_test_helpers.h"
@@ -29,12 +30,14 @@
using ::testing::AllOf;
using ::testing::Contains;
using ::testing::Each;
+using ::testing::ElementsAreArray;
using ::testing::Field;
using ::testing::Ge;
using ::testing::IsEmpty;
using ::testing::Le;
using ::testing::Lt;
using ::testing::Not;
+using ::testing::NotNull;
using ::testing::SizeIs;
using ::testing::TestWithParam;
using ::testing::Values;
@@ -51,6 +54,28 @@
class ScalabilityStructureTest : public TestWithParam<SvcTestParam> {};
TEST_P(ScalabilityStructureTest,
+ StaticConfigMatchesConfigReturnedByController) {
+ std::unique_ptr<ScalableVideoController> controller =
+ CreateScalabilityStructure(GetParam().name);
+ absl::optional<ScalableVideoController::StreamLayersConfig> static_config =
+ ScalabilityStructureConfig(GetParam().name);
+ ASSERT_THAT(controller, NotNull());
+ ASSERT_NE(static_config, absl::nullopt);
+ ScalableVideoController::StreamLayersConfig config =
+ controller->StreamConfig();
+ EXPECT_EQ(config.num_spatial_layers, static_config->num_spatial_layers);
+ EXPECT_EQ(config.num_temporal_layers, static_config->num_temporal_layers);
+ EXPECT_THAT(
+ rtc::MakeArrayView(config.scaling_factor_num, config.num_spatial_layers),
+ ElementsAreArray(static_config->scaling_factor_num,
+ static_config->num_spatial_layers));
+ EXPECT_THAT(
+ rtc::MakeArrayView(config.scaling_factor_den, config.num_spatial_layers),
+ ElementsAreArray(static_config->scaling_factor_den,
+ static_config->num_spatial_layers));
+}
+
+TEST_P(ScalabilityStructureTest,
NumberOfDecodeTargetsAndChainsAreInRangeAndConsistent) {
FrameDependencyStructure structure =
CreateScalabilityStructure(GetParam().name)->DependencyStructure();
diff --git a/modules/video_coding/svc/scalable_video_controller.h b/modules/video_coding/svc/scalable_video_controller.h
index d2d8486..c736265 100644
--- a/modules/video_coding/svc/scalable_video_controller.h
+++ b/modules/video_coding/svc/scalable_video_controller.h
@@ -27,6 +27,8 @@
struct StreamLayersConfig {
int num_spatial_layers = 1;
int num_temporal_layers = 1;
+ // Indicates if frames can reference frames of a different resolution.
+ bool uses_reference_scaling = true;
// Spatial layers scaling. Frames with spatial_id = i expected to be encoded
// with original_resolution * scaling_factor_num[i] / scaling_factor_den[i].
int scaling_factor_num[DependencyDescriptor::kMaxSpatialIds] = {1, 1, 1, 1};
diff --git a/modules/video_coding/svc/scalable_video_controller_no_layering.cc b/modules/video_coding/svc/scalable_video_controller_no_layering.cc
index 3934e57..a9d530d 100644
--- a/modules/video_coding/svc/scalable_video_controller_no_layering.cc
+++ b/modules/video_coding/svc/scalable_video_controller_no_layering.cc
@@ -25,6 +25,7 @@
StreamLayersConfig result;
result.num_spatial_layers = 1;
result.num_temporal_layers = 1;
+ result.uses_reference_scaling = false;
return result;
}