Determine scalability mode if not explicilty set for AV1.
Bug: none Change-Id: I86298b8a57300ed1d824cf6ba8f5daeec6af7315 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/262242 Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/main@{#36879}
This commit is contained in:
@ -259,7 +259,8 @@ std::vector<VideoCodec> GetPayloadTypesAndDefaultCodecs(
|
||||
|
||||
bool IsTemporalLayersSupported(const std::string& codec_name) {
|
||||
return absl::EqualsIgnoreCase(codec_name, kVp8CodecName) ||
|
||||
absl::EqualsIgnoreCase(codec_name, kVp9CodecName);
|
||||
absl::EqualsIgnoreCase(codec_name, kVp9CodecName) ||
|
||||
absl::EqualsIgnoreCase(codec_name, kAv1CodecName);
|
||||
}
|
||||
|
||||
static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
|
||||
|
@ -18,6 +18,8 @@ rtc_library("av1_svc_config") {
|
||||
"../../../../api/video_codecs:video_codecs_api",
|
||||
"../../../../rtc_base:checks",
|
||||
"../../../../rtc_base:logging",
|
||||
"../../../../rtc_base:stringutils",
|
||||
"../../svc:scalability_mode_util",
|
||||
"../../svc:scalability_structures",
|
||||
"../../svc:scalable_video_controller",
|
||||
]
|
||||
|
@ -15,11 +15,26 @@
|
||||
#include <memory>
|
||||
|
||||
#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 "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
absl::optional<ScalabilityMode> BuildScalabilityMode(int num_temporal_layers,
|
||||
int num_spatial_layers) {
|
||||
char name[20];
|
||||
rtc::SimpleStringBuilder ss(name);
|
||||
ss << "L" << num_spatial_layers << "T" << num_temporal_layers;
|
||||
if (num_spatial_layers > 1) {
|
||||
ss << "_KEY";
|
||||
}
|
||||
|
||||
return ScalabilityModeFromString(name);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool LibaomAv1EncoderSupportsScalabilityMode(ScalabilityMode scalability_mode) {
|
||||
// For libaom AV1, the scalability mode is supported if we can create the
|
||||
@ -27,14 +42,20 @@ bool LibaomAv1EncoderSupportsScalabilityMode(ScalabilityMode scalability_mode) {
|
||||
return ScalabilityStructureConfig(scalability_mode) != absl::nullopt;
|
||||
}
|
||||
|
||||
bool SetAv1SvcConfig(VideoCodec& video_codec) {
|
||||
bool SetAv1SvcConfig(VideoCodec& video_codec,
|
||||
int num_temporal_layers,
|
||||
int num_spatial_layers) {
|
||||
RTC_DCHECK_EQ(video_codec.codecType, kVideoCodecAV1);
|
||||
|
||||
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 = ScalabilityMode::kL1T1;
|
||||
scalability_mode =
|
||||
BuildScalabilityMode(num_temporal_layers, num_spatial_layers);
|
||||
if (!scalability_mode) {
|
||||
RTC_LOG(LS_WARNING) << "Scalability mode is not set, using 'L1T1'.";
|
||||
scalability_mode = ScalabilityMode::kL1T1;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ScalableVideoController> structure =
|
||||
@ -45,6 +66,8 @@ bool SetAv1SvcConfig(VideoCodec& video_codec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
video_codec.SetScalabilityMode(*scalability_mode);
|
||||
|
||||
ScalableVideoController::StreamLayersConfig info = structure->StreamConfig();
|
||||
for (int sl_idx = 0; sl_idx < info.num_spatial_layers; ++sl_idx) {
|
||||
SpatialLayer& spatial_layer = video_codec.spatialLayers[sl_idx];
|
||||
|
@ -17,7 +17,9 @@ namespace webrtc {
|
||||
bool LibaomAv1EncoderSupportsScalabilityMode(ScalabilityMode scalability_mode);
|
||||
|
||||
// Fills `video_codec.spatialLayers` using other members.
|
||||
bool SetAv1SvcConfig(VideoCodec& video_codec);
|
||||
bool SetAv1SvcConfig(VideoCodec& video_codec,
|
||||
int num_temporal_layers,
|
||||
int num_spatial_layers);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
@ -16,24 +16,48 @@
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
constexpr int kDontCare = 0;
|
||||
|
||||
TEST(Av1SvcConfigTest, TreatsEmptyAsL1T1) {
|
||||
VideoCodec video_codec;
|
||||
video_codec.codecType = kVideoCodecAV1;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_TRUE(video_codec.spatialLayers[0].active);
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 1);
|
||||
EXPECT_FALSE(video_codec.spatialLayers[1].active);
|
||||
}
|
||||
|
||||
TEST(Av1SvcConfigTest, ScalabilityModeFromNumberOfTemporalLayers) {
|
||||
VideoCodec video_codec;
|
||||
video_codec.codecType = kVideoCodecAV1;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/3,
|
||||
/*num_spatial_layers=*/1));
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 3);
|
||||
}
|
||||
|
||||
TEST(Av1SvcConfigTest, ScalabilityModeFromNumberOfSpatialLayers) {
|
||||
VideoCodec video_codec;
|
||||
video_codec.codecType = kVideoCodecAV1;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/3,
|
||||
/*num_spatial_layers=*/2));
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 3);
|
||||
EXPECT_TRUE(video_codec.spatialLayers[0].active);
|
||||
EXPECT_TRUE(video_codec.spatialLayers[1].active);
|
||||
EXPECT_FALSE(video_codec.spatialLayers[2].active);
|
||||
}
|
||||
|
||||
TEST(Av1SvcConfigTest, SetsActiveSpatialLayersFromScalabilityMode) {
|
||||
VideoCodec video_codec;
|
||||
video_codec.codecType = kVideoCodecAV1;
|
||||
video_codec.SetScalabilityMode(ScalabilityMode::kL2T1);
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_TRUE(video_codec.spatialLayers[0].active);
|
||||
EXPECT_TRUE(video_codec.spatialLayers[1].active);
|
||||
@ -47,7 +71,8 @@ TEST(Av1SvcConfigTest, ConfiguresDobuleResolutionRatioFromScalabilityMode) {
|
||||
video_codec.width = 1200;
|
||||
video_codec.height = 800;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].width, 600);
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].height, 400);
|
||||
@ -63,7 +88,8 @@ TEST(Av1SvcConfigTest, ConfiguresSmallResolutionRatioFromScalabilityMode) {
|
||||
video_codec.width = 1500;
|
||||
video_codec.height = 900;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].width, 1000);
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].height, 600);
|
||||
@ -78,7 +104,8 @@ TEST(Av1SvcConfigTest, CopiesFramrate) {
|
||||
video_codec.SetScalabilityMode(ScalabilityMode::kL2T1);
|
||||
video_codec.maxFramerate = 27;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].maxFramerate, 27);
|
||||
EXPECT_EQ(video_codec.spatialLayers[1].maxFramerate, 27);
|
||||
@ -89,7 +116,8 @@ TEST(Av1SvcConfigTest, SetsNumberOfTemporalLayers) {
|
||||
video_codec.codecType = kVideoCodecAV1;
|
||||
video_codec.SetScalabilityMode(ScalabilityMode::kL1T3);
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 3);
|
||||
}
|
||||
@ -101,7 +129,8 @@ TEST(Av1SvcConfigTest, CopiesMinMaxBitrateForSingleSpatialLayer) {
|
||||
video_codec.minBitrate = 100;
|
||||
video_codec.maxBitrate = 500;
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].minBitrate, 100u);
|
||||
EXPECT_EQ(video_codec.spatialLayers[0].maxBitrate, 500u);
|
||||
@ -116,7 +145,8 @@ TEST(Av1SvcConfigTest, SetsBitratesForMultipleSpatialLayers) {
|
||||
video_codec.codecType = kVideoCodecAV1;
|
||||
video_codec.SetScalabilityMode(ScalabilityMode::kL3T3);
|
||||
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec));
|
||||
EXPECT_TRUE(SetAv1SvcConfig(video_codec, /*num_temporal_layers=*/kDontCare,
|
||||
/*num_spatial_layers=*/kDontCare));
|
||||
|
||||
EXPECT_GT(video_codec.spatialLayers[0].minBitrate, 0u);
|
||||
EXPECT_LE(video_codec.spatialLayers[0].minBitrate,
|
||||
|
@ -263,7 +263,11 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
|
||||
break;
|
||||
}
|
||||
case kVideoCodecAV1:
|
||||
if (SetAv1SvcConfig(video_codec)) {
|
||||
if (SetAv1SvcConfig(video_codec,
|
||||
/*num_temporal_layers=*/
|
||||
streams.back().num_temporal_layers.value_or(1),
|
||||
/*num_spatial_layers=*/
|
||||
std::max<int>(config.spatial_layers.size(), 1))) {
|
||||
for (size_t i = 0; i < config.spatial_layers.size(); ++i) {
|
||||
video_codec.spatialLayers[i].active = config.spatial_layers[i].active;
|
||||
}
|
||||
|
Reference in New Issue
Block a user