|  | /* | 
|  | *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "video/alignment_adjuster.h" | 
|  |  | 
|  | #include <cstddef> | 
|  | #include <optional> | 
|  | #include <tuple> | 
|  | #include <vector> | 
|  |  | 
|  | #include "api/video/video_codec_type.h" | 
|  | #include "api/video_codecs/video_encoder.h" | 
|  | #include "test/encoder_settings.h" | 
|  | #include "test/gtest.h" | 
|  | #include "video/config/video_encoder_config.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace test { | 
|  | namespace { | 
|  | VideoEncoder::EncoderInfo GetEncoderInfo(int alignment, bool apply) { | 
|  | VideoEncoder::EncoderInfo info; | 
|  | info.requested_resolution_alignment = alignment; | 
|  | info.apply_alignment_to_all_simulcast_layers = apply; | 
|  | return info; | 
|  | } | 
|  | }  // namespace | 
|  |  | 
|  | class AlignmentAdjusterTest | 
|  | : public ::testing::TestWithParam<::testing::tuple< | 
|  | int, | 
|  | std::tuple<std::vector<double>, std::vector<double>, int>>> { | 
|  | protected: | 
|  | AlignmentAdjusterTest() | 
|  | : kRequestedAlignment(std::get<0>(GetParam())), | 
|  | kScaleFactors(std::get<0>(std::get<1>(GetParam()))), | 
|  | kAdjustedScaleFactors(std::get<1>(std::get<1>(GetParam()))), | 
|  | kAdjustedAlignment(std::get<2>(std::get<1>(GetParam()))) {} | 
|  |  | 
|  | const int kRequestedAlignment; | 
|  | const std::vector<double> kScaleFactors; | 
|  | const std::vector<double> kAdjustedScaleFactors; | 
|  | const int kAdjustedAlignment; | 
|  | }; | 
|  |  | 
|  | INSTANTIATE_TEST_SUITE_P( | 
|  | ScaleFactorsAndAlignment, | 
|  | AlignmentAdjusterTest, | 
|  | ::testing::Combine( | 
|  | ::testing::Values(2),  // kRequestedAlignment | 
|  | ::testing::Values( | 
|  | std::make_tuple(std::vector<double>{-1.0},  // kScaleFactors | 
|  | std::vector<double>{-1.0},  // kAdjustedScaleFactors | 
|  | 2),  // default: {1.0}      // kAdjustedAlignment | 
|  | std::make_tuple(std::vector<double>{-1.0, -1.0}, | 
|  | std::vector<double>{-1.0, -1.0}, | 
|  | 4),  // default: {1.0, 2.0} | 
|  | std::make_tuple(std::vector<double>{-1.0, -1.0, -1.0}, | 
|  | std::vector<double>{-1.0, -1.0, -1.0}, | 
|  | 8),  // default: {1.0, 2.0, 4.0} | 
|  | std::make_tuple(std::vector<double>{1.0, 2.0, 4.0}, | 
|  | std::vector<double>{1.0, 2.0, 4.0}, | 
|  | 8), | 
|  | std::make_tuple(std::vector<double>{9999.0, -1.0, 1.0}, | 
|  | std::vector<double>{8.0, 1.0, 1.0}, | 
|  | 16),  // kMaxAlignment | 
|  | std::make_tuple(std::vector<double>{3.99, 2.01, 1.0}, | 
|  | std::vector<double>{4.0, 2.0, 1.0}, | 
|  | 8), | 
|  | std::make_tuple(std::vector<double>{2.9, 2.1}, | 
|  | std::vector<double>{6.0 / 2.0, 6.0 / 3.0}, | 
|  | 12), | 
|  | std::make_tuple(std::vector<double>{4.9, 1.7, 1.2}, | 
|  | std::vector<double>{5.0, 5.0 / 3.0, 5.0 / 4.0}, | 
|  | 10), | 
|  | std::make_tuple(std::vector<double>{1.0, 1.3}, | 
|  | std::vector<double>{4.0 / 4.0, 4.0 / 3.0}, | 
|  | 8), | 
|  | std::make_tuple(std::vector<double>{1.75, 3.5}, | 
|  | std::vector<double>{7.0 / 4.0, 7.0 / 2.0}, | 
|  | 7), | 
|  | std::make_tuple(std::vector<double>{1.5, 2.5}, | 
|  | std::vector<double>{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<double>{-1.0},  // kScaleFactors | 
|  | std::vector<double>{-1.0},  // kAdjustedScaleFactors | 
|  | 2),  // default: {1.0}      // kAdjustedAlignment | 
|  | std::make_tuple(std::vector<double>{-1.0, -1.0}, | 
|  | std::vector<double>{-1.0, -1.0}, | 
|  | 4),  // default: {1.0, 2.0} | 
|  | std::make_tuple(std::vector<double>{-1.0, -1.0, -1.0}, | 
|  | std::vector<double>{-1.0, -1.0, -1.0}, | 
|  | 4),  // default: {1.0, 2.0, 4.0} | 
|  | std::make_tuple(std::vector<double>{1.0, 2.0, 4.0}, | 
|  | std::vector<double>{1.0, 2.0, 4.0}, | 
|  | 8)))); | 
|  |  | 
|  | TEST_P(AlignmentAdjusterTest, 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. | 
|  | VideoEncoder::EncoderInfo info = | 
|  | GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers); | 
|  | int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors( | 
|  | info, &config, std::nullopt); | 
|  | 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]); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST_P(AlignmentAdjusterTest, AlignmentNotAppliedToAllLayers) { | 
|  | const bool kApplyAlignmentToAllLayers = false; | 
|  |  | 
|  | // 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, std::nullopt); | 
|  | EXPECT_EQ(alignment, kRequestedAlignment); | 
|  |  | 
|  | // Verify that scale factors are not adjusted. | 
|  | for (int i = 0; i < num_streams; ++i) { | 
|  | EXPECT_EQ(config.simulcast_layers[i].scale_resolution_down_by, | 
|  | kScaleFactors[i]); | 
|  | } | 
|  | } | 
|  |  | 
|  | 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, std::optional<size_t>(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 |