1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "video/alignment_adjuster.h"
12
13 #include <memory>
14 #include <tuple>
15 #include <vector>
16
17 #include "rtc_base/numerics/safe_conversions.h"
18 #include "test/encoder_settings.h"
19 #include "test/gtest.h"
20
21 namespace webrtc {
22 namespace test {
23 namespace {
GetEncoderInfo(int alignment,bool apply)24 VideoEncoder::EncoderInfo GetEncoderInfo(int alignment, bool apply) {
25 VideoEncoder::EncoderInfo info;
26 info.requested_resolution_alignment = alignment;
27 info.apply_alignment_to_all_simulcast_layers = apply;
28 return info;
29 }
30 } // namespace
31
32 class AlignmentAdjusterTest
33 : public ::testing::TestWithParam<::testing::tuple<
34 int,
35 std::tuple<std::vector<double>, std::vector<double>, int>>> {
36 protected:
AlignmentAdjusterTest()37 AlignmentAdjusterTest()
38 : kRequestedAlignment(std::get<0>(GetParam())),
39 kScaleFactors(std::get<0>(std::get<1>(GetParam()))),
40 kAdjustedScaleFactors(std::get<1>(std::get<1>(GetParam()))),
41 kAdjustedAlignment(std::get<2>(std::get<1>(GetParam()))) {}
42
43 const int kRequestedAlignment;
44 const std::vector<double> kScaleFactors;
45 const std::vector<double> kAdjustedScaleFactors;
46 const int kAdjustedAlignment;
47 };
48
49 INSTANTIATE_TEST_SUITE_P(
50 ScaleFactorsAndAlignment,
51 AlignmentAdjusterTest,
52 ::testing::Combine(
53 ::testing::Values(2), // kRequestedAlignment
54 ::testing::Values(
55 std::make_tuple(std::vector<double>{-1.0}, // kScaleFactors
56 std::vector<double>{-1.0}, // kAdjustedScaleFactors
57 2), // default: {1.0} // kAdjustedAlignment
58 std::make_tuple(std::vector<double>{-1.0, -1.0},
59 std::vector<double>{-1.0, -1.0},
60 4), // default: {1.0, 2.0}
61 std::make_tuple(std::vector<double>{-1.0, -1.0, -1.0},
62 std::vector<double>{-1.0, -1.0, -1.0},
63 8), // default: {1.0, 2.0, 4.0}
64 std::make_tuple(std::vector<double>{1.0, 2.0, 4.0},
65 std::vector<double>{1.0, 2.0, 4.0},
66 8),
67 std::make_tuple(std::vector<double>{9999.0, -1.0, 1.0},
68 std::vector<double>{8.0, 1.0, 1.0},
69 16), // kMaxAlignment
70 std::make_tuple(std::vector<double>{3.99, 2.01, 1.0},
71 std::vector<double>{4.0, 2.0, 1.0},
72 8),
73 std::make_tuple(std::vector<double>{2.9, 2.1},
74 std::vector<double>{6.0 / 2.0, 6.0 / 3.0},
75 12),
76 std::make_tuple(std::vector<double>{4.9, 1.7, 1.2},
77 std::vector<double>{5.0, 5.0 / 3.0, 5.0 / 4.0},
78 10),
79 std::make_tuple(std::vector<double>{1.0, 1.3},
80 std::vector<double>{4.0 / 4.0, 4.0 / 3.0},
81 8),
82 std::make_tuple(std::vector<double>{1.75, 3.5},
83 std::vector<double>{7.0 / 4.0, 7.0 / 2.0},
84 7),
85 std::make_tuple(std::vector<double>{1.5, 2.5},
86 std::vector<double>{1.5, 2.5},
87 15))));
88
89 class AlignmentAdjusterTestTwoLayers : public AlignmentAdjusterTest {
90 protected:
91 const int kMaxLayers = 2;
92 };
93
94 INSTANTIATE_TEST_SUITE_P(
95 ScaleFactorsAndAlignmentWithMaxLayers,
96 AlignmentAdjusterTestTwoLayers,
97 ::testing::Combine(
98 ::testing::Values(2), // kRequestedAlignment
99 ::testing::Values(
100 std::make_tuple(std::vector<double>{-1.0}, // kScaleFactors
101 std::vector<double>{-1.0}, // kAdjustedScaleFactors
102 2), // default: {1.0} // kAdjustedAlignment
103 std::make_tuple(std::vector<double>{-1.0, -1.0},
104 std::vector<double>{-1.0, -1.0},
105 4), // default: {1.0, 2.0}
106 std::make_tuple(std::vector<double>{-1.0, -1.0, -1.0},
107 std::vector<double>{-1.0, -1.0, -1.0},
108 4), // default: {1.0, 2.0, 4.0}
109 std::make_tuple(std::vector<double>{1.0, 2.0, 4.0},
110 std::vector<double>{1.0, 2.0, 4.0},
111 8))));
112
TEST_P(AlignmentAdjusterTest,AlignmentAppliedToAllLayers)113 TEST_P(AlignmentAdjusterTest, AlignmentAppliedToAllLayers) {
114 const bool kApplyAlignmentToAllLayers = true;
115
116 // Fill config with the scaling factor by which to reduce encoding size.
117 const int num_streams = kScaleFactors.size();
118 VideoEncoderConfig config;
119 test::FillEncoderConfiguration(kVideoCodecVP8, num_streams, &config);
120 for (int i = 0; i < num_streams; ++i) {
121 config.simulcast_layers[i].scale_resolution_down_by = kScaleFactors[i];
122 }
123
124 // Verify requested alignment from sink.
125 VideoEncoder::EncoderInfo info =
126 GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers);
127 int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(
128 info, &config, absl::nullopt);
129 EXPECT_EQ(alignment, kAdjustedAlignment);
130
131 // Verify adjusted scale factors.
132 for (int i = 0; i < num_streams; ++i) {
133 EXPECT_EQ(config.simulcast_layers[i].scale_resolution_down_by,
134 kAdjustedScaleFactors[i]);
135 }
136 }
137
TEST_P(AlignmentAdjusterTest,AlignmentNotAppliedToAllLayers)138 TEST_P(AlignmentAdjusterTest, AlignmentNotAppliedToAllLayers) {
139 const bool kApplyAlignmentToAllLayers = false;
140
141 // Fill config with the scaling factor by which to reduce encoding size.
142 const int num_streams = kScaleFactors.size();
143 VideoEncoderConfig config;
144 test::FillEncoderConfiguration(kVideoCodecVP8, num_streams, &config);
145 for (int i = 0; i < num_streams; ++i) {
146 config.simulcast_layers[i].scale_resolution_down_by = kScaleFactors[i];
147 }
148
149 // Verify requested alignment from sink, alignment is not adjusted.
150 VideoEncoder::EncoderInfo info =
151 GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers);
152 int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(
153 info, &config, absl::nullopt);
154 EXPECT_EQ(alignment, kRequestedAlignment);
155
156 // Verify that scale factors are not adjusted.
157 for (int i = 0; i < num_streams; ++i) {
158 EXPECT_EQ(config.simulcast_layers[i].scale_resolution_down_by,
159 kScaleFactors[i]);
160 }
161 }
162
TEST_P(AlignmentAdjusterTestTwoLayers,AlignmentAppliedToAllLayers)163 TEST_P(AlignmentAdjusterTestTwoLayers, AlignmentAppliedToAllLayers) {
164 const bool kApplyAlignmentToAllLayers = true;
165
166 // Fill config with the scaling factor by which to reduce encoding size.
167 const int num_streams = kScaleFactors.size();
168 VideoEncoderConfig config;
169 test::FillEncoderConfiguration(kVideoCodecVP8, num_streams, &config);
170 for (int i = 0; i < num_streams; ++i) {
171 config.simulcast_layers[i].scale_resolution_down_by = kScaleFactors[i];
172 }
173
174 // Verify requested alignment from sink, alignment is not adjusted.
175 VideoEncoder::EncoderInfo info =
176 GetEncoderInfo(kRequestedAlignment, kApplyAlignmentToAllLayers);
177 int alignment = AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(
178 info, &config, absl::optional<size_t>(kMaxLayers));
179 EXPECT_EQ(alignment, kAdjustedAlignment);
180
181 // Verify adjusted scale factors.
182 for (int i = 0; i < num_streams; ++i) {
183 EXPECT_EQ(config.simulcast_layers[i].scale_resolution_down_by,
184 kAdjustedScaleFactors[i]);
185 }
186 }
187
188 } // namespace test
189 } // namespace webrtc
190