1 /*
2 * Copyright (c) 2018 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 "modules/video_coding/codecs/vp9/svc_config.h"
12
13 #include <cstddef>
14 #include <vector>
15
16 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
17 #include "test/gmock.h"
18 #include "test/gtest.h"
19
20 using ::testing::ElementsAre;
21 using ::testing::Field;
22
23 namespace webrtc {
TEST(SvcConfig,NumSpatialLayers)24 TEST(SvcConfig, NumSpatialLayers) {
25 const size_t max_num_spatial_layers = 6;
26 const size_t first_active_layer = 0;
27 const size_t num_spatial_layers = 2;
28
29 std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
30 kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1),
31 kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1), 30,
32 first_active_layer, max_num_spatial_layers, 1, false);
33
34 EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
35 }
36
TEST(SvcConfig,NumSpatialLayersPortrait)37 TEST(SvcConfig, NumSpatialLayersPortrait) {
38 const size_t max_num_spatial_layers = 6;
39 const size_t first_active_layer = 0;
40 const size_t num_spatial_layers = 2;
41
42 std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
43 kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1),
44 kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1), 30,
45 first_active_layer, max_num_spatial_layers, 1, false);
46
47 EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
48 }
49
TEST(SvcConfig,NumSpatialLayersWithScalabilityMode)50 TEST(SvcConfig, NumSpatialLayersWithScalabilityMode) {
51 VideoCodec codec;
52 codec.codecType = kVideoCodecVP9;
53 codec.width = 960;
54 codec.height = 540;
55 codec.SetScalabilityMode(ScalabilityMode::kL3T3_KEY);
56
57 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
58 EXPECT_THAT(spatial_layers, ElementsAre(Field(&SpatialLayer::height, 135),
59 Field(&SpatialLayer::height, 270),
60 Field(&SpatialLayer::height, 540)));
61 EXPECT_THAT(spatial_layers,
62 ElementsAre(Field(&SpatialLayer::numberOfTemporalLayers, 3),
63 Field(&SpatialLayer::numberOfTemporalLayers, 3),
64 Field(&SpatialLayer::numberOfTemporalLayers, 3)));
65 EXPECT_EQ(codec.GetScalabilityMode(), ScalabilityMode::kL3T3_KEY);
66 }
67
TEST(SvcConfig,NumSpatialLayersLimitedWithScalabilityMode)68 TEST(SvcConfig, NumSpatialLayersLimitedWithScalabilityMode) {
69 VideoCodec codec;
70 codec.codecType = kVideoCodecVP9;
71 codec.width = 480;
72 codec.height = 270;
73 codec.SetScalabilityMode(ScalabilityMode::kL3T3_KEY);
74
75 // Scalability mode updated.
76 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
77 EXPECT_THAT(spatial_layers, ElementsAre(Field(&SpatialLayer::height, 135),
78 Field(&SpatialLayer::height, 270)));
79 EXPECT_THAT(spatial_layers,
80 ElementsAre(Field(&SpatialLayer::numberOfTemporalLayers, 3),
81 Field(&SpatialLayer::numberOfTemporalLayers, 3)));
82 EXPECT_EQ(codec.GetScalabilityMode(), ScalabilityMode::kL2T3_KEY);
83 }
84
TEST(SvcConfig,NumSpatialLayersLimitedWithScalabilityModePortrait)85 TEST(SvcConfig, NumSpatialLayersLimitedWithScalabilityModePortrait) {
86 VideoCodec codec;
87 codec.codecType = kVideoCodecVP9;
88 codec.width = 270;
89 codec.height = 480;
90 codec.SetScalabilityMode(ScalabilityMode::kL3T1);
91
92 // Scalability mode updated.
93 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
94 EXPECT_THAT(spatial_layers, ElementsAre(Field(&SpatialLayer::width, 135),
95 Field(&SpatialLayer::width, 270)));
96 EXPECT_THAT(spatial_layers,
97 ElementsAre(Field(&SpatialLayer::numberOfTemporalLayers, 1),
98 Field(&SpatialLayer::numberOfTemporalLayers, 1)));
99 EXPECT_EQ(codec.GetScalabilityMode(), ScalabilityMode::kL2T1);
100 }
101
TEST(SvcConfig,NumSpatialLayersWithScalabilityModeResolutionRatio1_5)102 TEST(SvcConfig, NumSpatialLayersWithScalabilityModeResolutionRatio1_5) {
103 VideoCodec codec;
104 codec.codecType = kVideoCodecVP9;
105 codec.width = 270;
106 codec.height = 480;
107 codec.SetScalabilityMode(ScalabilityMode::kL2T1h); // 1.5:1
108
109 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
110 EXPECT_THAT(spatial_layers, ElementsAre(Field(&SpatialLayer::width, 180),
111 Field(&SpatialLayer::width, 270)));
112 EXPECT_THAT(spatial_layers,
113 ElementsAre(Field(&SpatialLayer::numberOfTemporalLayers, 1),
114 Field(&SpatialLayer::numberOfTemporalLayers, 1)));
115 EXPECT_EQ(codec.GetScalabilityMode(), ScalabilityMode::kL2T1h);
116 }
117
TEST(SvcConfig,NumSpatialLayersLimitedWithScalabilityModeResolutionRatio1_5)118 TEST(SvcConfig, NumSpatialLayersLimitedWithScalabilityModeResolutionRatio1_5) {
119 VideoCodec codec;
120 codec.codecType = kVideoCodecVP9;
121 codec.width = 320;
122 codec.height = 180;
123 codec.SetScalabilityMode(ScalabilityMode::kL3T1h); // 1.5:1
124
125 // Scalability mode updated.
126 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
127 EXPECT_THAT(spatial_layers, ElementsAre(Field(&SpatialLayer::width, 320)));
128 EXPECT_THAT(spatial_layers,
129 ElementsAre(Field(&SpatialLayer::numberOfTemporalLayers, 1)));
130 EXPECT_EQ(codec.GetScalabilityMode(), ScalabilityMode::kL1T1);
131 }
132
TEST(SvcConfig,AlwaysSendsAtLeastOneLayer)133 TEST(SvcConfig, AlwaysSendsAtLeastOneLayer) {
134 const size_t max_num_spatial_layers = 6;
135 const size_t first_active_layer = 5;
136
137 std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
138 kMinVp9SpatialLayerLongSideLength, kMinVp9SpatialLayerShortSideLength, 30,
139 first_active_layer, max_num_spatial_layers, 1, false);
140 EXPECT_EQ(spatial_layers.size(), 1u);
141 EXPECT_EQ(spatial_layers.back().width, kMinVp9SpatialLayerLongSideLength);
142 }
143
TEST(SvcConfig,AlwaysSendsAtLeastOneLayerPortrait)144 TEST(SvcConfig, AlwaysSendsAtLeastOneLayerPortrait) {
145 const size_t max_num_spatial_layers = 6;
146 const size_t first_active_layer = 5;
147
148 std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
149 kMinVp9SpatialLayerShortSideLength, kMinVp9SpatialLayerLongSideLength, 30,
150 first_active_layer, max_num_spatial_layers, 1, false);
151 EXPECT_EQ(spatial_layers.size(), 1u);
152 EXPECT_EQ(spatial_layers.back().width, kMinVp9SpatialLayerShortSideLength);
153 }
154
TEST(SvcConfig,EnforcesMinimalRequiredParity)155 TEST(SvcConfig, EnforcesMinimalRequiredParity) {
156 const size_t max_num_spatial_layers = 3;
157 const size_t kOddSize = 1023;
158
159 std::vector<SpatialLayer> spatial_layers =
160 GetSvcConfig(kOddSize, kOddSize, 30,
161 /*first_active_layer=*/1, max_num_spatial_layers, 1, false);
162 // Since there are 2 layers total (1, 2), divisiblity by 2 is required.
163 EXPECT_EQ(spatial_layers.back().width, kOddSize - 1);
164 EXPECT_EQ(spatial_layers.back().width, kOddSize - 1);
165
166 spatial_layers =
167 GetSvcConfig(kOddSize, kOddSize, 30,
168 /*first_active_layer=*/0, max_num_spatial_layers, 1, false);
169 // Since there are 3 layers total (0, 1, 2), divisiblity by 4 is required.
170 EXPECT_EQ(spatial_layers.back().width, kOddSize - 3);
171 EXPECT_EQ(spatial_layers.back().width, kOddSize - 3);
172
173 spatial_layers =
174 GetSvcConfig(kOddSize, kOddSize, 30,
175 /*first_active_layer=*/2, max_num_spatial_layers, 1, false);
176 // Since there is only 1 layer active (2), divisiblity by 1 is required.
177 EXPECT_EQ(spatial_layers.back().width, kOddSize);
178 EXPECT_EQ(spatial_layers.back().width, kOddSize);
179 }
180
TEST(SvcConfig,EnforcesMinimalRequiredParityWithScalabilityMode)181 TEST(SvcConfig, EnforcesMinimalRequiredParityWithScalabilityMode) {
182 VideoCodec codec;
183 codec.codecType = kVideoCodecVP9;
184 codec.width = 1023;
185 codec.height = 1023;
186 codec.SetScalabilityMode(ScalabilityMode::kL3T1);
187
188 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
189 EXPECT_THAT(spatial_layers, // Divisiblity by 4 required.
190 ElementsAre(Field(&SpatialLayer::width, 255),
191 Field(&SpatialLayer::width, 510),
192 Field(&SpatialLayer::width, 1020)));
193
194 codec.SetScalabilityMode(ScalabilityMode::kL2T1);
195 spatial_layers = GetVp9SvcConfig(codec);
196 EXPECT_THAT(spatial_layers, // Divisiblity by 2 required.
197 ElementsAre(Field(&SpatialLayer::width, 511),
198 Field(&SpatialLayer::width, 1022)));
199
200 codec.SetScalabilityMode(ScalabilityMode::kL1T1);
201 spatial_layers = GetVp9SvcConfig(codec);
202 EXPECT_THAT(spatial_layers, // Divisiblity by 1 required.
203 ElementsAre(Field(&SpatialLayer::width, 1023)));
204 }
205
TEST(SvcConfig,EnforcesMinimalRequiredParityWithScalabilityModeResRatio1_5)206 TEST(SvcConfig, EnforcesMinimalRequiredParityWithScalabilityModeResRatio1_5) {
207 VideoCodec codec;
208 codec.codecType = kVideoCodecVP9;
209 codec.width = 1280;
210 codec.height = 1280;
211 codec.SetScalabilityMode(ScalabilityMode::kL2T1h); // 1.5:1
212
213 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
214 EXPECT_THAT(spatial_layers, // Divisiblity by 3 required.
215 ElementsAre(Field(&SpatialLayer::width, 852),
216 Field(&SpatialLayer::width, 1278)));
217 }
218
TEST(SvcConfig,SkipsInactiveLayers)219 TEST(SvcConfig, SkipsInactiveLayers) {
220 const size_t num_spatial_layers = 4;
221 const size_t first_active_layer = 2;
222
223 std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
224 kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1),
225 kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1), 30,
226 first_active_layer, num_spatial_layers, 1, false);
227 EXPECT_EQ(spatial_layers.size(), 2u);
228 EXPECT_EQ(spatial_layers.back().width,
229 kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1));
230 }
231
TEST(SvcConfig,BitrateThresholds)232 TEST(SvcConfig, BitrateThresholds) {
233 const size_t first_active_layer = 0;
234 const size_t num_spatial_layers = 3;
235 std::vector<SpatialLayer> spatial_layers = GetSvcConfig(
236 kMinVp9SpatialLayerLongSideLength << (num_spatial_layers - 1),
237 kMinVp9SpatialLayerShortSideLength << (num_spatial_layers - 1), 30,
238 first_active_layer, num_spatial_layers, 1, false);
239
240 EXPECT_EQ(spatial_layers.size(), num_spatial_layers);
241
242 for (const SpatialLayer& layer : spatial_layers) {
243 EXPECT_LE(layer.minBitrate, layer.maxBitrate);
244 EXPECT_LE(layer.minBitrate, layer.targetBitrate);
245 EXPECT_LE(layer.targetBitrate, layer.maxBitrate);
246 }
247 }
248
TEST(SvcConfig,BitrateThresholdsWithScalabilityMode)249 TEST(SvcConfig, BitrateThresholdsWithScalabilityMode) {
250 VideoCodec codec;
251 codec.codecType = kVideoCodecVP9;
252 codec.width = 960;
253 codec.height = 540;
254 codec.SetScalabilityMode(ScalabilityMode::kS3T3);
255
256 std::vector<SpatialLayer> spatial_layers = GetVp9SvcConfig(codec);
257 EXPECT_THAT(spatial_layers, ElementsAre(Field(&SpatialLayer::height, 135),
258 Field(&SpatialLayer::height, 270),
259 Field(&SpatialLayer::height, 540)));
260
261 for (const SpatialLayer& layer : spatial_layers) {
262 EXPECT_LE(layer.minBitrate, layer.maxBitrate);
263 EXPECT_LE(layer.minBitrate, layer.targetBitrate);
264 EXPECT_LE(layer.targetBitrate, layer.maxBitrate);
265 }
266 }
267
TEST(SvcConfig,ScreenSharing)268 TEST(SvcConfig, ScreenSharing) {
269 std::vector<SpatialLayer> spatial_layers =
270 GetSvcConfig(1920, 1080, 30, 1, 3, 3, true);
271
272 EXPECT_EQ(spatial_layers.size(), 3UL);
273
274 for (size_t i = 0; i < 3; ++i) {
275 const SpatialLayer& layer = spatial_layers[i];
276 EXPECT_EQ(layer.width, 1920);
277 EXPECT_EQ(layer.height, 1080);
278 EXPECT_EQ(layer.maxFramerate, (i < 1) ? 5 : (i < 2 ? 10 : 30));
279 EXPECT_EQ(layer.numberOfTemporalLayers, 1);
280 EXPECT_LE(layer.minBitrate, layer.maxBitrate);
281 EXPECT_LE(layer.minBitrate, layer.targetBitrate);
282 EXPECT_LE(layer.targetBitrate, layer.maxBitrate);
283 }
284 }
285 } // namespace webrtc
286