Make it possible to set spatial layer bitrates explicitly
Bug: webrtc:14852 Change-Id: Ie41d4223d0d5aef5a79f7e6067f0855f022ed428 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/335361 Auto-Submit: Sergey Silkin <ssilkin@webrtc.org> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41698}
This commit is contained in:
parent
974044efca
commit
6432970fe9
@ -1111,8 +1111,6 @@ class Encoder : public EncodedImageCallback {
|
||||
|
||||
int result = encoder_->InitEncode(&vc, ves);
|
||||
RTC_CHECK(result == WEBRTC_VIDEO_CODEC_OK);
|
||||
|
||||
SetRates(es);
|
||||
}
|
||||
|
||||
void SetRates(const EncodingSettings& es) {
|
||||
@ -1261,6 +1259,29 @@ void ConfigureSimulcast(VideoCodec* vc) {
|
||||
}
|
||||
}
|
||||
|
||||
void SetDefaultCodecSpecificSettings(VideoCodec* vc, int num_temporal_layers) {
|
||||
switch (vc->codecType) {
|
||||
case kVideoCodecVP8:
|
||||
*(vc->VP8()) = VideoEncoder::GetDefaultVp8Settings();
|
||||
vc->VP8()->SetNumberOfTemporalLayers(num_temporal_layers);
|
||||
break;
|
||||
case kVideoCodecVP9: {
|
||||
*(vc->VP9()) = VideoEncoder::GetDefaultVp9Settings();
|
||||
vc->VP9()->SetNumberOfTemporalLayers(num_temporal_layers);
|
||||
} break;
|
||||
case kVideoCodecH264: {
|
||||
*(vc->H264()) = VideoEncoder::GetDefaultH264Settings();
|
||||
vc->H264()->SetNumberOfTemporalLayers(num_temporal_layers);
|
||||
} break;
|
||||
case kVideoCodecAV1:
|
||||
case kVideoCodecH265:
|
||||
break;
|
||||
case kVideoCodecGeneric:
|
||||
case kVideoCodecMultiplex:
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::vector<DataRate>, ScalabilityMode>
|
||||
SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
|
||||
ScalabilityMode scalability_mode,
|
||||
@ -1272,11 +1293,11 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
|
||||
int num_temporal_layers =
|
||||
ScalabilityModeToNumTemporalLayers(scalability_mode);
|
||||
|
||||
if (bitrates_kbps.size() > 1 ||
|
||||
(num_spatial_layers == 1 && num_temporal_layers == 1)) {
|
||||
RTC_CHECK(bitrates_kbps.size() ==
|
||||
static_cast<size_t>(num_spatial_layers * num_temporal_layers))
|
||||
<< "bitrates must be provided for all layers";
|
||||
int num_bitrates = static_cast<int>(bitrates_kbps.size());
|
||||
RTC_CHECK(num_bitrates == 1 || num_bitrates == num_spatial_layers ||
|
||||
num_bitrates == num_spatial_layers * num_temporal_layers);
|
||||
|
||||
if (num_bitrates == num_spatial_layers * num_temporal_layers) {
|
||||
std::vector<DataRate> bitrates;
|
||||
for (const auto& bitrate_kbps : bitrates_kbps) {
|
||||
bitrates.push_back(DataRate::KilobitsPerSec(bitrate_kbps));
|
||||
@ -1284,59 +1305,93 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
|
||||
return std::make_tuple(bitrates, scalability_mode);
|
||||
}
|
||||
|
||||
int total_bitrate_kbps =
|
||||
std::accumulate(bitrates_kbps.begin(), bitrates_kbps.end(), 0);
|
||||
|
||||
VideoCodec vc;
|
||||
vc.codecType = PayloadStringToCodecType(codec_type);
|
||||
vc.width = width;
|
||||
vc.height = height;
|
||||
vc.startBitrate = bitrates_kbps.front();
|
||||
vc.maxBitrate = bitrates_kbps.front();
|
||||
vc.startBitrate = total_bitrate_kbps;
|
||||
vc.maxBitrate = total_bitrate_kbps;
|
||||
vc.minBitrate = 0;
|
||||
vc.maxFramerate = static_cast<uint32_t>(framerate_fps);
|
||||
vc.numberOfSimulcastStreams = 0;
|
||||
vc.mode = webrtc::VideoCodecMode::kRealtimeVideo;
|
||||
vc.SetScalabilityMode(scalability_mode);
|
||||
SetDefaultCodecSpecificSettings(&vc, num_temporal_layers);
|
||||
|
||||
switch (vc.codecType) {
|
||||
case kVideoCodecVP8:
|
||||
// TODO(webrtc:14852): Configure simulcast.
|
||||
*(vc.VP8()) = VideoEncoder::GetDefaultVp8Settings();
|
||||
vc.VP8()->SetNumberOfTemporalLayers(num_temporal_layers);
|
||||
ConfigureSimulcast(&vc);
|
||||
break;
|
||||
case kVideoCodecVP9: {
|
||||
*(vc.VP9()) = VideoEncoder::GetDefaultVp9Settings();
|
||||
vc.VP9()->SetNumberOfTemporalLayers(num_temporal_layers);
|
||||
const std::vector<SpatialLayer> spatialLayers = GetVp9SvcConfig(vc);
|
||||
for (size_t i = 0; i < spatialLayers.size(); ++i) {
|
||||
vc.spatialLayers[i] = spatialLayers[i];
|
||||
vc.spatialLayers[i].active = true;
|
||||
}
|
||||
} break;
|
||||
case kVideoCodecAV1: {
|
||||
bool result =
|
||||
SetAv1SvcConfig(vc, num_spatial_layers, num_temporal_layers);
|
||||
RTC_CHECK(result) << "SetAv1SvcConfig failed";
|
||||
} break;
|
||||
case kVideoCodecH264: {
|
||||
*(vc.H264()) = VideoEncoder::GetDefaultH264Settings();
|
||||
vc.H264()->SetNumberOfTemporalLayers(num_temporal_layers);
|
||||
ConfigureSimulcast(&vc);
|
||||
} break;
|
||||
case kVideoCodecH265:
|
||||
break;
|
||||
case kVideoCodecGeneric:
|
||||
case kVideoCodecMultiplex:
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
if (num_bitrates == num_spatial_layers) {
|
||||
switch (vc.codecType) {
|
||||
case kVideoCodecVP8:
|
||||
case kVideoCodecH264:
|
||||
case kVideoCodecH265:
|
||||
vc.numberOfSimulcastStreams = num_spatial_layers;
|
||||
for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
|
||||
SimulcastStream* ss = &vc.simulcastStream[sidx];
|
||||
ss->width = width >> (num_spatial_layers - sidx - 1);
|
||||
ss->height = height >> (num_spatial_layers - sidx - 1);
|
||||
ss->maxFramerate = vc.maxFramerate;
|
||||
ss->numberOfTemporalLayers = num_temporal_layers;
|
||||
ss->maxBitrate = bitrates_kbps[sidx];
|
||||
ss->targetBitrate = bitrates_kbps[sidx];
|
||||
ss->minBitrate = 0;
|
||||
ss->qpMax = 0;
|
||||
ss->active = true;
|
||||
}
|
||||
break;
|
||||
case kVideoCodecVP9:
|
||||
case kVideoCodecAV1:
|
||||
for (int sidx = num_spatial_layers - 1; sidx >= 0; --sidx) {
|
||||
SpatialLayer* ss = &vc.spatialLayers[sidx];
|
||||
ss->width = width >> (num_spatial_layers - sidx - 1);
|
||||
ss->height = height >> (num_spatial_layers - sidx - 1);
|
||||
ss->maxFramerate = vc.maxFramerate;
|
||||
ss->numberOfTemporalLayers = num_temporal_layers;
|
||||
ss->maxBitrate = bitrates_kbps[sidx];
|
||||
ss->targetBitrate = bitrates_kbps[sidx];
|
||||
ss->minBitrate = 0;
|
||||
ss->qpMax = 0;
|
||||
ss->active = true;
|
||||
}
|
||||
break;
|
||||
case kVideoCodecGeneric:
|
||||
case kVideoCodecMultiplex:
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
} else {
|
||||
switch (vc.codecType) {
|
||||
case kVideoCodecVP8:
|
||||
case kVideoCodecH264:
|
||||
case kVideoCodecH265:
|
||||
ConfigureSimulcast(&vc);
|
||||
break;
|
||||
case kVideoCodecVP9: {
|
||||
const std::vector<SpatialLayer> spatialLayers = GetVp9SvcConfig(vc);
|
||||
for (size_t i = 0; i < spatialLayers.size(); ++i) {
|
||||
vc.spatialLayers[i] = spatialLayers[i];
|
||||
vc.spatialLayers[i].active = true;
|
||||
}
|
||||
} break;
|
||||
case kVideoCodecAV1: {
|
||||
bool result =
|
||||
SetAv1SvcConfig(vc, num_spatial_layers, num_temporal_layers);
|
||||
RTC_CHECK(result) << "SetAv1SvcConfig failed";
|
||||
} break;
|
||||
case kVideoCodecGeneric:
|
||||
case kVideoCodecMultiplex:
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
|
||||
if (*vc.GetScalabilityMode() != scalability_mode) {
|
||||
RTC_LOG(LS_WARNING) << "Scalability mode changed from "
|
||||
<< ScalabilityModeToString(scalability_mode) << " to "
|
||||
<< ScalabilityModeToString(*vc.GetScalabilityMode());
|
||||
num_spatial_layers =
|
||||
ScalabilityModeToNumSpatialLayers(*vc.GetScalabilityMode());
|
||||
num_temporal_layers =
|
||||
ScalabilityModeToNumTemporalLayers(*vc.GetScalabilityMode());
|
||||
if (*vc.GetScalabilityMode() != scalability_mode) {
|
||||
RTC_LOG(LS_WARNING) << "Scalability mode changed from "
|
||||
<< ScalabilityModeToString(scalability_mode) << " to "
|
||||
<< ScalabilityModeToString(*vc.GetScalabilityMode());
|
||||
num_spatial_layers =
|
||||
ScalabilityModeToNumSpatialLayers(*vc.GetScalabilityMode());
|
||||
num_temporal_layers =
|
||||
ScalabilityModeToNumTemporalLayers(*vc.GetScalabilityMode());
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoBitrateAllocator> bitrate_allocator =
|
||||
@ -1344,7 +1399,7 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
|
||||
vc);
|
||||
VideoBitrateAllocation bitrate_allocation =
|
||||
bitrate_allocator->Allocate(VideoBitrateAllocationParameters(
|
||||
1000 * bitrates_kbps.front(), framerate_fps));
|
||||
1000 * total_bitrate_kbps, framerate_fps));
|
||||
|
||||
std::vector<DataRate> bitrates;
|
||||
for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
|
||||
|
||||
@ -675,5 +675,137 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
std::make_tuple(PacingSettings{.mode = PacingMode::kConstantRate,
|
||||
.constant_rate = Frequency::Hertz(20)},
|
||||
/*expected_delta_ms=*/50)));
|
||||
|
||||
struct EncodingSettingsTestParameters {
|
||||
std::string codec_type;
|
||||
std::string scalability_mode;
|
||||
std::vector<int> bitrate_kbps;
|
||||
std::vector<int> expected_bitrate_kbps;
|
||||
};
|
||||
|
||||
class VideoCodecTesterTestEncodingSettings
|
||||
: public ::testing::TestWithParam<EncodingSettingsTestParameters> {};
|
||||
|
||||
TEST_P(VideoCodecTesterTestEncodingSettings, CreateEncodingSettings) {
|
||||
EncodingSettingsTestParameters test_params = GetParam();
|
||||
std::map<uint32_t, EncodingSettings> encoding_settings =
|
||||
VideoCodecTester::CreateEncodingSettings(
|
||||
test_params.codec_type, test_params.scalability_mode, /*width=*/1280,
|
||||
/*height=*/720, test_params.bitrate_kbps, /*framerate_fps=*/30,
|
||||
/*num_frames=*/1);
|
||||
ASSERT_THAT(encoding_settings, SizeIs(1));
|
||||
const std::map<LayerId, LayerSettings>& layers_settings =
|
||||
encoding_settings.begin()->second.layers_settings;
|
||||
std::vector<int> configured_bitrate_kbps;
|
||||
std::transform(layers_settings.begin(), layers_settings.end(),
|
||||
std::back_inserter(configured_bitrate_kbps),
|
||||
[](const auto& layer_settings) {
|
||||
return layer_settings.second.bitrate.kbps();
|
||||
});
|
||||
EXPECT_EQ(configured_bitrate_kbps, test_params.expected_bitrate_kbps);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Vp8,
|
||||
VideoCodecTesterTestEncodingSettings,
|
||||
Values(EncodingSettingsTestParameters{.codec_type = "VP8",
|
||||
.scalability_mode = "L1T1",
|
||||
.bitrate_kbps = {1},
|
||||
.expected_bitrate_kbps = {1}},
|
||||
EncodingSettingsTestParameters{.codec_type = "VP8",
|
||||
.scalability_mode = "L1T1",
|
||||
.bitrate_kbps = {10000},
|
||||
.expected_bitrate_kbps = {10000}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP8",
|
||||
.scalability_mode = "L1T3",
|
||||
.bitrate_kbps = {1000},
|
||||
.expected_bitrate_kbps = {400, 200, 400}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP8",
|
||||
.scalability_mode = "S3T3",
|
||||
.bitrate_kbps = {100},
|
||||
.expected_bitrate_kbps = {40, 20, 40, 0, 0, 0, 0, 0, 0}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP8",
|
||||
.scalability_mode = "S3T3",
|
||||
.bitrate_kbps = {10000},
|
||||
.expected_bitrate_kbps = {60, 30, 60, 200, 100, 200, 1000, 500,
|
||||
1000}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP8",
|
||||
.scalability_mode = "S3T3",
|
||||
.bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
|
||||
.expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
|
||||
900}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Vp9,
|
||||
VideoCodecTesterTestEncodingSettings,
|
||||
Values(EncodingSettingsTestParameters{.codec_type = "VP9",
|
||||
.scalability_mode = "L1T1",
|
||||
.bitrate_kbps = {1},
|
||||
.expected_bitrate_kbps = {1}},
|
||||
EncodingSettingsTestParameters{.codec_type = "VP9",
|
||||
.scalability_mode = "L1T1",
|
||||
.bitrate_kbps = {10000},
|
||||
.expected_bitrate_kbps = {10000}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP9",
|
||||
.scalability_mode = "L1T3",
|
||||
.bitrate_kbps = {1000},
|
||||
.expected_bitrate_kbps = {540, 163, 297}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP9",
|
||||
.scalability_mode = "L3T3",
|
||||
.bitrate_kbps = {100},
|
||||
.expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP9",
|
||||
.scalability_mode = "L3T3",
|
||||
.bitrate_kbps = {10000},
|
||||
.expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249,
|
||||
452}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "VP9",
|
||||
.scalability_mode = "L3T3",
|
||||
.bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
|
||||
.expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
|
||||
900}}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Av1,
|
||||
VideoCodecTesterTestEncodingSettings,
|
||||
Values(EncodingSettingsTestParameters{.codec_type = "AV1",
|
||||
.scalability_mode = "L1T1",
|
||||
.bitrate_kbps = {1},
|
||||
.expected_bitrate_kbps = {1}},
|
||||
EncodingSettingsTestParameters{.codec_type = "AV1",
|
||||
.scalability_mode = "L1T1",
|
||||
.bitrate_kbps = {10000},
|
||||
.expected_bitrate_kbps = {10000}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "AV1",
|
||||
.scalability_mode = "L1T3",
|
||||
.bitrate_kbps = {1000},
|
||||
.expected_bitrate_kbps = {540, 163, 297}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "AV1",
|
||||
.scalability_mode = "L3T3",
|
||||
.bitrate_kbps = {100},
|
||||
.expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "AV1",
|
||||
.scalability_mode = "L3T3",
|
||||
.bitrate_kbps = {10000},
|
||||
.expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249,
|
||||
452}},
|
||||
EncodingSettingsTestParameters{
|
||||
.codec_type = "AV1",
|
||||
.scalability_mode = "L3T3",
|
||||
.bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900},
|
||||
.expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800,
|
||||
900}}));
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user