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:

committed by
Commit Bot

parent
167ecc9bc5
commit
f86cf4c2de
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user