Add support for VideoLayersAllocation for Vp9 scv/ksvc and none scalable

VideoCodecInitializer::VideoEncoderConfigToVideoCodec is modified to always set correct frame rate, width and height on spatial layer 0 so the rest of the code does not need to differentiate between scalable/none scalable codecs.


Bug: webrtc:12000
Change-Id: I5a068b98ca2038621205f55e4024f949ab51587a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/198540
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32890}
This commit is contained in:
Per Kjellander
2020-12-30 15:27:35 +01:00
committed by Commit Bot
parent 167ecc9bc5
commit f86cf4c2de
3 changed files with 523 additions and 11 deletions

View File

@ -148,6 +148,12 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
video_codec.maxBitrate = kEncoderMinBitrateKbps;
video_codec.maxFramerate = max_framerate;
video_codec.spatialLayers[0] = {0};
video_codec.spatialLayers[0].width = video_codec.width;
video_codec.spatialLayers[0].height = video_codec.height;
video_codec.spatialLayers[0].maxFramerate = max_framerate;
video_codec.spatialLayers[0].numberOfTemporalLayers =
streams[0].num_temporal_layers.value_or(1);
// Set codec specific options
if (config.encoder_specific_settings)

View File

@ -218,12 +218,12 @@ VideoLayersAllocation CreateVideoLayersAllocation(
return layers_allocation;
}
if (encoder_config.numberOfSimulcastStreams > 0) {
if (encoder_config.numberOfSimulcastStreams > 1) {
layers_allocation.resolution_and_frame_rate_is_valid = true;
for (int si = 0; si < encoder_config.numberOfSimulcastStreams; ++si) {
if (!target_bitrate.IsSpatialLayerUsed(si) ||
target_bitrate.GetSpatialLayerSum(si) == 0) {
break;
continue;
}
layers_allocation.active_spatial_layers.emplace_back();
VideoLayersAllocation::SpatialLayer& spatial_layer =
@ -258,14 +258,80 @@ VideoLayersAllocation CreateVideoLayersAllocation(
}
}
// Encoder may drop frames internally if `maxFramerate` is set.
spatial_layer.frame_rate_fps = std::min(
static_cast<uint8_t>(encoder_config.simulcastStream[si].maxFramerate),
static_cast<uint8_t>(
(current_rate.framerate_fps * frame_rate_fraction) /
VideoEncoder::EncoderInfo::kMaxFramerateFraction));
spatial_layer.frame_rate_fps = std::min<uint8_t>(
encoder_config.simulcastStream[si].maxFramerate,
(current_rate.framerate_fps * frame_rate_fraction) /
VideoEncoder::EncoderInfo::kMaxFramerateFraction);
}
} else if (encoder_config.numberOfSimulcastStreams == 1) {
// TODO(bugs.webrtc.org/12000): Implement support for AV1 with
// scalability.
const bool higher_spatial_depend_on_lower =
encoder_config.codecType == kVideoCodecVP9 &&
encoder_config.VP9().interLayerPred == InterLayerPredMode::kOn;
layers_allocation.resolution_and_frame_rate_is_valid = true;
std::vector<DataRate> aggregated_spatial_bitrate(
webrtc::kMaxTemporalStreams, DataRate::Zero());
for (int si = 0; si < webrtc::kMaxSpatialLayers; ++si) {
layers_allocation.resolution_and_frame_rate_is_valid = true;
if (!target_bitrate.IsSpatialLayerUsed(si) ||
target_bitrate.GetSpatialLayerSum(si) == 0) {
break;
}
layers_allocation.active_spatial_layers.emplace_back();
VideoLayersAllocation::SpatialLayer& spatial_layer =
layers_allocation.active_spatial_layers.back();
spatial_layer.width = encoder_config.spatialLayers[si].width;
spatial_layer.height = encoder_config.spatialLayers[si].height;
spatial_layer.rtp_stream_index = 0;
spatial_layer.spatial_id = si;
auto frame_rate_fraction =
VideoEncoder::EncoderInfo::kMaxFramerateFraction;
if (encoder_info.fps_allocation[si].size() == 1) {
// One TL is signalled to be used by the encoder. Do not distribute
// bitrate allocation across TLs (use sum at tl:0).
DataRate aggregated_temporal_bitrate =
DataRate::BitsPerSec(target_bitrate.GetSpatialLayerSum(si));
aggregated_spatial_bitrate[0] += aggregated_temporal_bitrate;
if (higher_spatial_depend_on_lower) {
spatial_layer.target_bitrate_per_temporal_layer.push_back(
aggregated_spatial_bitrate[0]);
} else {
spatial_layer.target_bitrate_per_temporal_layer.push_back(
aggregated_temporal_bitrate);
}
frame_rate_fraction = encoder_info.fps_allocation[si][0];
} else { // Temporal layers are supported.
DataRate aggregated_temporal_bitrate = DataRate::Zero();
for (size_t ti = 0;
ti < encoder_config.spatialLayers[si].numberOfTemporalLayers;
++ti) {
if (!target_bitrate.HasBitrate(si, ti)) {
break;
}
if (ti < encoder_info.fps_allocation[si].size()) {
// Use frame rate of the top used temporal layer.
frame_rate_fraction = encoder_info.fps_allocation[si][ti];
}
aggregated_temporal_bitrate +=
DataRate::BitsPerSec(target_bitrate.GetBitrate(si, ti));
if (higher_spatial_depend_on_lower) {
spatial_layer.target_bitrate_per_temporal_layer.push_back(
aggregated_temporal_bitrate + aggregated_spatial_bitrate[ti]);
aggregated_spatial_bitrate[ti] += aggregated_temporal_bitrate;
} else {
spatial_layer.target_bitrate_per_temporal_layer.push_back(
aggregated_temporal_bitrate);
}
}
}
// Encoder may drop frames internally if `maxFramerate` is set.
spatial_layer.frame_rate_fps = std::min<uint8_t>(
encoder_config.spatialLayers[si].maxFramerate,
(current_rate.framerate_fps * frame_rate_fraction) /
VideoEncoder::EncoderInfo::kMaxFramerateFraction);
}
} else {
// TODO(bugs.webrtc.org/12000): Implement support for kSVC and full SVC.
}
return layers_allocation;

View File

@ -842,8 +842,10 @@ class VideoStreamEncoderTest : public ::testing::Test {
info.is_hardware_accelerated = is_hardware_accelerated_;
for (int i = 0; i < kMaxSpatialLayers; ++i) {
if (temporal_layers_supported_[i]) {
info.fps_allocation[i].clear();
int num_layers = temporal_layers_supported_[i].value() ? 2 : 1;
info.fps_allocation[i].resize(num_layers);
for (int tid = 0; tid < num_layers; ++tid)
info.fps_allocation[i].push_back(255 / (num_layers - tid));
}
}
}
@ -4030,7 +4032,7 @@ TEST_F(VideoStreamEncoderTest, ReportsVideoBitrateAllocation) {
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForV8Simulcast) {
TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForVP8Simulcast) {
ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation);
@ -4082,6 +4084,444 @@ TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForV8Simulcast) {
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForVP8WithMidleLayerDisabled) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP8,
/* num_streams*/ 3, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
VideoEncoder::GetDefaultVp8Settings());
for (auto& layer : video_encoder_config.simulcast_layers) {
layer.num_temporal_layers = 2;
}
// Simulcast layers are used for enabling/disabling streams.
video_encoder_config.simulcast_layers[0].active = true;
video_encoder_config.simulcast_layers[1].active = false;
video_encoder_config.simulcast_layers[2].active = true;
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_LT(last_layer_allocation.active_spatial_layers[0].width, 1280);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 1280);
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForVP8WithMidleAndHighestLayerDisabled) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP8,
/* num_streams*/ 3, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
VideoEncoder::GetDefaultVp8Settings());
for (auto& layer : video_encoder_config.simulcast_layers) {
layer.num_temporal_layers = 2;
}
// Simulcast layers are used for enabling/disabling streams.
video_encoder_config.simulcast_layers[0].active = true;
video_encoder_config.simulcast_layers[1].active = false;
video_encoder_config.simulcast_layers[2].active = false;
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(1));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_LT(last_layer_allocation.active_spatial_layers[0].width, 1280);
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForV9SvcWithTemporalLayerSupport) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 2;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOn;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 640);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].height, 360);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].frame_rate_fps, 30);
EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 1280);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].height, 720);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].frame_rate_fps, 30);
// Since full SVC is used, expect the top layer to utilize the full target
// rate.
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer[1],
DataRate::BitsPerSec(kTargetBitrateBps));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForV9SvcWithoutTemporalLayerSupport) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, false);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, false);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 2;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOn;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(1));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer,
SizeIs(1));
// Since full SVC is used, expect the top layer to utilize the full target
// rate.
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer[0],
DataRate::BitsPerSec(kTargetBitrateBps));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForVP9KSvcWithTemporalLayerSupport) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 2;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOnKeyPic;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer,
SizeIs(2));
// Since KSVC is, spatial layers are independend except on key frames.
EXPECT_LT(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer[1],
DataRate::BitsPerSec(kTargetBitrateBps));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForV9SvcWithLowestLayerDisabled) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 3;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOn;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
// Simulcast layers are used for enabling/disabling streams.
video_encoder_config.simulcast_layers.resize(3);
video_encoder_config.simulcast_layers[0].active = false;
video_encoder_config.simulcast_layers[1].active = true;
video_encoder_config.simulcast_layers[2].active = true;
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 640);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].spatial_id, 0);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 1280);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].spatial_id, 1);
EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer,
SizeIs(2));
// Since full SVC is used, expect the top layer to utilize the full target
// rate.
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer[1],
DataRate::BitsPerSec(kTargetBitrateBps));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForV9SvcWithHighestLayerDisabled) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 3;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOn;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
// Simulcast layers are used for enabling/disabling streams.
video_encoder_config.simulcast_layers.resize(3);
video_encoder_config.simulcast_layers[2].active = false;
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 320);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].spatial_id, 0);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 640);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].spatial_id, 1);
EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
.target_bitrate_per_temporal_layer,
SizeIs(2));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsVideoLayersAllocationForV9SvcWithAllButHighestLayerDisabled) {
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
video_send_config_.encoder_settings.allocation_cb_type =
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation;
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrateBps;
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 3;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOn;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
// Simulcast layers are used for enabling/disabling streams.
video_encoder_config.simulcast_layers.resize(3);
video_encoder_config.simulcast_layers[0].active = false;
video_encoder_config.simulcast_layers[1].active = false;
video_encoder_config.simulcast_layers[2].active = true;
ConfigureEncoder(std::move(video_encoder_config));
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(1));
EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(2));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 1280);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].spatial_id, 0);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer[1],
DataRate::BitsPerSec(kTargetBitrateBps));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForH264) {
ResetEncoder("H264", 1, 1, 1, false,
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
kVideoLayersAllocation);
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps),
DataRate::BitsPerSec(kTargetBitrateBps), 0, 0, 0);
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
VideoLayersAllocation last_layer_allocation =
sink_.GetLastVideoLayersAllocation();
ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(1));
ASSERT_THAT(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer,
SizeIs(1));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0]
.target_bitrate_per_temporal_layer[0],
DataRate::BitsPerSec(kTargetBitrateBps));
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 1280);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].height, 720);
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].frame_rate_fps, 30);
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
ReportsUpdatedVideoLayersAllocationWhenBweChanges) {
ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,