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:
philipel
2022-05-13 13:16:44 +02:00
committed by WebRTC LUCI CQ
parent c8a6fb2bb8
commit 9437529d4b
6 changed files with 76 additions and 14 deletions

View File

@ -259,7 +259,8 @@ std::vector<VideoCodec> GetPayloadTypesAndDefaultCodecs(
bool IsTemporalLayersSupported(const std::string& codec_name) { bool IsTemporalLayersSupported(const std::string& codec_name) {
return absl::EqualsIgnoreCase(codec_name, kVp8CodecName) || 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) { static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {

View File

@ -18,6 +18,8 @@ rtc_library("av1_svc_config") {
"../../../../api/video_codecs:video_codecs_api", "../../../../api/video_codecs:video_codecs_api",
"../../../../rtc_base:checks", "../../../../rtc_base:checks",
"../../../../rtc_base:logging", "../../../../rtc_base:logging",
"../../../../rtc_base:stringutils",
"../../svc:scalability_mode_util",
"../../svc:scalability_structures", "../../svc:scalability_structures",
"../../svc:scalable_video_controller", "../../svc:scalable_video_controller",
] ]

View File

@ -15,11 +15,26 @@
#include <memory> #include <memory>
#include "modules/video_coding/svc/create_scalability_structure.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.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc { 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) { bool LibaomAv1EncoderSupportsScalabilityMode(ScalabilityMode scalability_mode) {
// For libaom AV1, the scalability mode is supported if we can create the // 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; 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); RTC_DCHECK_EQ(video_codec.codecType, kVideoCodecAV1);
absl::optional<ScalabilityMode> scalability_mode = absl::optional<ScalabilityMode> scalability_mode =
video_codec.GetScalabilityMode(); video_codec.GetScalabilityMode();
if (!scalability_mode.has_value()) { if (!scalability_mode.has_value()) {
RTC_LOG(LS_WARNING) << "Scalability mode is not set, using 'L1T1'."; scalability_mode =
scalability_mode = ScalabilityMode::kL1T1; 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 = std::unique_ptr<ScalableVideoController> structure =
@ -45,6 +66,8 @@ bool SetAv1SvcConfig(VideoCodec& video_codec) {
return false; return false;
} }
video_codec.SetScalabilityMode(*scalability_mode);
ScalableVideoController::StreamLayersConfig info = structure->StreamConfig(); ScalableVideoController::StreamLayersConfig info = structure->StreamConfig();
for (int sl_idx = 0; sl_idx < info.num_spatial_layers; ++sl_idx) { for (int sl_idx = 0; sl_idx < info.num_spatial_layers; ++sl_idx) {
SpatialLayer& spatial_layer = video_codec.spatialLayers[sl_idx]; SpatialLayer& spatial_layer = video_codec.spatialLayers[sl_idx];

View File

@ -17,7 +17,9 @@ namespace webrtc {
bool LibaomAv1EncoderSupportsScalabilityMode(ScalabilityMode scalability_mode); bool LibaomAv1EncoderSupportsScalabilityMode(ScalabilityMode scalability_mode);
// Fills `video_codec.spatialLayers` using other members. // 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 } // namespace webrtc

View File

@ -16,24 +16,48 @@
namespace webrtc { namespace webrtc {
namespace { namespace {
constexpr int kDontCare = 0;
TEST(Av1SvcConfigTest, TreatsEmptyAsL1T1) { TEST(Av1SvcConfigTest, TreatsEmptyAsL1T1) {
VideoCodec video_codec; VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1; 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_TRUE(video_codec.spatialLayers[0].active);
EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 1); EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 1);
EXPECT_FALSE(video_codec.spatialLayers[1].active); 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) { TEST(Av1SvcConfigTest, SetsActiveSpatialLayersFromScalabilityMode) {
VideoCodec video_codec; VideoCodec video_codec;
video_codec.codecType = kVideoCodecAV1; video_codec.codecType = kVideoCodecAV1;
video_codec.SetScalabilityMode(ScalabilityMode::kL2T1); 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[0].active);
EXPECT_TRUE(video_codec.spatialLayers[1].active); EXPECT_TRUE(video_codec.spatialLayers[1].active);
@ -47,7 +71,8 @@ TEST(Av1SvcConfigTest, ConfiguresDobuleResolutionRatioFromScalabilityMode) {
video_codec.width = 1200; video_codec.width = 1200;
video_codec.height = 800; 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].width, 600);
EXPECT_EQ(video_codec.spatialLayers[0].height, 400); EXPECT_EQ(video_codec.spatialLayers[0].height, 400);
@ -63,7 +88,8 @@ TEST(Av1SvcConfigTest, ConfiguresSmallResolutionRatioFromScalabilityMode) {
video_codec.width = 1500; video_codec.width = 1500;
video_codec.height = 900; 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].width, 1000);
EXPECT_EQ(video_codec.spatialLayers[0].height, 600); EXPECT_EQ(video_codec.spatialLayers[0].height, 600);
@ -78,7 +104,8 @@ TEST(Av1SvcConfigTest, CopiesFramrate) {
video_codec.SetScalabilityMode(ScalabilityMode::kL2T1); video_codec.SetScalabilityMode(ScalabilityMode::kL2T1);
video_codec.maxFramerate = 27; 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[0].maxFramerate, 27);
EXPECT_EQ(video_codec.spatialLayers[1].maxFramerate, 27); EXPECT_EQ(video_codec.spatialLayers[1].maxFramerate, 27);
@ -89,7 +116,8 @@ TEST(Av1SvcConfigTest, SetsNumberOfTemporalLayers) {
video_codec.codecType = kVideoCodecAV1; video_codec.codecType = kVideoCodecAV1;
video_codec.SetScalabilityMode(ScalabilityMode::kL1T3); 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); EXPECT_EQ(video_codec.spatialLayers[0].numberOfTemporalLayers, 3);
} }
@ -101,7 +129,8 @@ TEST(Av1SvcConfigTest, CopiesMinMaxBitrateForSingleSpatialLayer) {
video_codec.minBitrate = 100; video_codec.minBitrate = 100;
video_codec.maxBitrate = 500; 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].minBitrate, 100u);
EXPECT_EQ(video_codec.spatialLayers[0].maxBitrate, 500u); EXPECT_EQ(video_codec.spatialLayers[0].maxBitrate, 500u);
@ -116,7 +145,8 @@ TEST(Av1SvcConfigTest, SetsBitratesForMultipleSpatialLayers) {
video_codec.codecType = kVideoCodecAV1; video_codec.codecType = kVideoCodecAV1;
video_codec.SetScalabilityMode(ScalabilityMode::kL3T3); 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_GT(video_codec.spatialLayers[0].minBitrate, 0u);
EXPECT_LE(video_codec.spatialLayers[0].minBitrate, EXPECT_LE(video_codec.spatialLayers[0].minBitrate,

View File

@ -263,7 +263,11 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
break; break;
} }
case kVideoCodecAV1: 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) { for (size_t i = 0; i < config.spatial_layers.size(); ++i) {
video_codec.spatialLayers[i].active = config.spatial_layers[i].active; video_codec.spatialLayers[i].active = config.spatial_layers[i].active;
} }