diff --git a/video/alignment_adjuster.cc b/video/alignment_adjuster.cc index b08f2f184a..6b1db9238b 100644 --- a/video/alignment_adjuster.cc +++ b/video/alignment_adjuster.cc @@ -66,7 +66,8 @@ double RoundToMultiple(int alignment, int AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( const VideoEncoder::EncoderInfo& encoder_info, - VideoEncoderConfig* config) { + VideoEncoderConfig* config, + absl::optional max_layers) { const int requested_alignment = encoder_info.requested_resolution_alignment; if (!encoder_info.apply_alignment_to_all_simulcast_layers) { return requested_alignment; @@ -85,7 +86,11 @@ int AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( if (!has_scale_resolution_down_by) { // Default resolution downscaling used (scale factors: 1, 2, 4, ...). - return requested_alignment * (1 << (config->simulcast_layers.size() - 1)); + size_t size = config->simulcast_layers.size(); + if (max_layers && *max_layers > 0 && *max_layers < size) { + size = *max_layers; + } + return requested_alignment * (1 << (size - 1)); } // Get alignment for downscaled layers. diff --git a/video/alignment_adjuster.h b/video/alignment_adjuster.h index 53d7927887..4b72623a19 100644 --- a/video/alignment_adjuster.h +++ b/video/alignment_adjuster.h @@ -28,9 +28,13 @@ class AlignmentAdjuster { // |scale_resolution_down_by| may be adjusted to a common multiple to limit // the alignment value to avoid largely cropped frames and possibly with an // aspect ratio far from the original. + + // Note: |max_layers| currently only taken into account when using default + // scale factors. static int GetAlignmentAndMaybeAdjustScaleFactors( const VideoEncoder::EncoderInfo& info, - VideoEncoderConfig* config); + VideoEncoderConfig* config, + absl::optional max_layers); }; } // namespace webrtc diff --git a/video/alignment_adjuster_unittest.cc b/video/alignment_adjuster_unittest.cc index 07c7de5f16..28e4bc0550 100644 --- a/video/alignment_adjuster_unittest.cc +++ b/video/alignment_adjuster_unittest.cc @@ -86,6 +86,30 @@ INSTANTIATE_TEST_SUITE_P( std::vector{1.5, 2.5}, 15)))); +class AlignmentAdjusterTestTwoLayers : public AlignmentAdjusterTest { + protected: + const int kMaxLayers = 2; +}; + +INSTANTIATE_TEST_SUITE_P( + ScaleFactorsAndAlignmentWithMaxLayers, + AlignmentAdjusterTestTwoLayers, + ::testing::Combine( + ::testing::Values(2), // kRequestedAlignment + ::testing::Values( + std::make_tuple(std::vector{-1.0}, // kScaleFactors + std::vector{-1.0}, // kAdjustedScaleFactors + 2), // default: {1.0} // kAdjustedAlignment + std::make_tuple(std::vector{-1.0, -1.0}, + std::vector{-1.0, -1.0}, + 4), // default: {1.0, 2.0} + std::make_tuple(std::vector{-1.0, -1.0, -1.0}, + std::vector{-1.0, -1.0, -1.0}, + 4), // default: {1.0, 2.0, 4.0} + std::make_tuple(std::vector{1.0, 2.0, 4.0}, + std::vector{1.0, 2.0, 4.0}, + 8)))); + TEST_P(AlignmentAdjusterTest, AlignmentAppliedToAllLayers) { const bool kApplyAlignmentToAllLayers = true; @@ -100,8 +124,8 @@ TEST_P(AlignmentAdjusterTest, AlignmentAppliedToAllLayers) { // Verify requested alignment from sink. VideoEncoder::EncoderInfo info = GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers); - int alignment = - AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(info, &config); + int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( + info, &config, absl::nullopt); EXPECT_EQ(alignment, kAdjustedAlignment); // Verify adjusted scale factors. @@ -125,8 +149,8 @@ TEST_P(AlignmentAdjusterTest, AlignmentNotAppliedToAllLayers) { // Verify requested alignment from sink, alignment is not adjusted. VideoEncoder::EncoderInfo info = GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers); - int alignment = - AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(info, &config); + int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( + info, &config, absl::nullopt); EXPECT_EQ(alignment, kRequestedAlignment); // Verify that scale factors are not adjusted. @@ -136,5 +160,30 @@ TEST_P(AlignmentAdjusterTest, AlignmentNotAppliedToAllLayers) { } } +TEST_P(AlignmentAdjusterTestTwoLayers, AlignmentAppliedToAllLayers) { + const bool kApplyAlignmentToAllLayers = true; + + // Fill config with the scaling factor by which to reduce encoding size. + const int num_streams = kScaleFactors.size(); + VideoEncoderConfig config; + test::FillEncoderConfiguration(kVideoCodecVP8, num_streams, &config); + for (int i = 0; i < num_streams; ++i) { + config.simulcast_layers[i].scale_resolution_down_by = kScaleFactors[i]; + } + + // Verify requested alignment from sink, alignment is not adjusted. + VideoEncoder::EncoderInfo info = + GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers); + int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( + info, &config, absl::optional(kMaxLayers)); + EXPECT_EQ(alignment, kAdjustedAlignment); + + // Verify adjusted scale factors. + for (int i = 0; i < num_streams; ++i) { + EXPECT_EQ(config.simulcast_layers[i].scale_resolution_down_by, + kAdjustedScaleFactors[i]); + } +} + } // namespace test } // namespace webrtc diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 1cfb280208..3d87379749 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -726,13 +726,17 @@ void VideoStreamEncoder::ReconfigureEncoder() { // Possibly adjusts scale_resolution_down_by in |encoder_config_| to limit the // alignment value. - int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( - encoder_->GetEncoderInfo(), &encoder_config_); + AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( + encoder_->GetEncoderInfo(), &encoder_config_, absl::nullopt); std::vector streams = encoder_config_.video_stream_factory->CreateEncoderStreams( last_frame_info_->width, last_frame_info_->height, encoder_config_); + // Get alignment when actual number of layers are known. + int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( + encoder_->GetEncoderInfo(), &encoder_config_, streams.size()); + // Check that the higher layers do not try to set number of temporal layers // to less than 1. // TODO(brandtr): Get rid of the wrapping optional as it serves no purpose