OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" | 11 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" |
12 | 12 |
13 #include <limits> | 13 #include <limits> |
14 #include <memory> | 14 #include <memory> |
15 #include <vector> | |
16 | 15 |
17 #include "webrtc/test/gtest.h" | 16 #include "webrtc/test/gtest.h" |
18 | 17 |
19 namespace webrtc { | 18 namespace webrtc { |
20 namespace { | 19 namespace { |
21 constexpr uint32_t kMinBitrate = 50; | 20 constexpr uint32_t kMinBitrate = 50; |
22 constexpr uint32_t kTargetBitrate = 100; | 21 constexpr uint32_t kTargetBitrate = 100; |
23 constexpr uint32_t kMaxBitrate = 1000; | 22 constexpr uint32_t kMaxBitrate = 1000; |
24 } // namespace | 23 } // namespace |
25 | 24 |
26 class SimulcastRateAllocatorTest : public ::testing::Test { | 25 class SimulcastRateAllocatorTest : public ::testing::Test { |
27 public: | 26 public: |
28 SimulcastRateAllocatorTest() { | 27 SimulcastRateAllocatorTest() { |
29 memset(&codec_, 0, sizeof(VideoCodec)); | 28 memset(&codec_, 0, sizeof(VideoCodec)); |
30 codec_.minBitrate = kMinBitrate; | 29 codec_.minBitrate = kMinBitrate; |
31 codec_.targetBitrate = kTargetBitrate; | 30 codec_.targetBitrate = kTargetBitrate; |
32 codec_.maxBitrate = kMaxBitrate; | 31 codec_.maxBitrate = kMaxBitrate; |
33 CreateAllocator(); | 32 CreateAllocator(); |
34 } | 33 } |
35 virtual ~SimulcastRateAllocatorTest() {} | 34 virtual ~SimulcastRateAllocatorTest() {} |
36 | 35 |
37 template <size_t S> | 36 template <size_t S> |
38 void ExpectEqual(uint32_t (&expected)[S], | 37 void ExpectEqual(uint32_t (&expected)[S], |
39 const std::vector<uint32_t>& actual) { | 38 const std::vector<uint32_t>& actual) { |
40 EXPECT_EQ(S, actual.size()); | 39 EXPECT_EQ(S, actual.size()); |
41 for (size_t i = 0; i < S; ++i) | 40 for (size_t i = 0; i < S; ++i) |
42 EXPECT_EQ(expected[i], actual[i]) << "Mismatch at index " << i; | 41 EXPECT_EQ(expected[i], actual[i]) << "Mismatch at index " << i; |
43 } | 42 } |
44 | 43 |
45 template <size_t S> | |
46 void ExpectEqual(uint32_t (&expected)[S], const BitrateAllocation& actual) { | |
47 // EXPECT_EQ(S, actual.size()); | |
48 uint32_t sum = 0; | |
49 for (size_t i = 0; i < S; ++i) { | |
50 uint32_t layer_bitrate = actual.GetSpatialLayerSum(i); | |
51 EXPECT_EQ(expected[i] * 1000, layer_bitrate) << "Mismatch at index " << i; | |
52 sum += layer_bitrate; | |
53 } | |
54 EXPECT_EQ(sum, actual.get_sum_bps()); | |
55 } | |
56 | |
57 void CreateAllocator() { | 44 void CreateAllocator() { |
58 allocator_.reset(new SimulcastRateAllocator(codec_, nullptr)); | 45 allocator_.reset(new SimulcastRateAllocator(codec_)); |
59 } | |
60 | |
61 BitrateAllocation GetAllocation(uint32_t target_bitrate) { | |
62 return allocator_->GetAllocation(target_bitrate * 1000, kDefaultFrameRate); | |
63 } | 46 } |
64 | 47 |
65 protected: | 48 protected: |
66 static const int kDefaultFrameRate = 30; | |
67 VideoCodec codec_; | 49 VideoCodec codec_; |
68 std::unique_ptr<SimulcastRateAllocator> allocator_; | 50 std::unique_ptr<SimulcastRateAllocator> allocator_; |
69 }; | 51 }; |
70 | 52 |
71 TEST_F(SimulcastRateAllocatorTest, NoSimulcastBelowMin) { | 53 TEST_F(SimulcastRateAllocatorTest, NoSimulcastBelowMin) { |
72 uint32_t expected[] = {codec_.minBitrate}; | 54 uint32_t expected[] = {codec_.minBitrate}; |
73 ExpectEqual(expected, GetAllocation(codec_.minBitrate - 1)); | 55 ExpectEqual(expected, allocator_->GetAllocation(codec_.minBitrate - 1)); |
74 ExpectEqual(expected, GetAllocation(1)); | 56 ExpectEqual(expected, allocator_->GetAllocation(1)); |
75 ExpectEqual(expected, GetAllocation(0)); | 57 ExpectEqual(expected, allocator_->GetAllocation(0)); |
76 } | 58 } |
77 | 59 |
78 TEST_F(SimulcastRateAllocatorTest, NoSimulcastAboveMax) { | 60 TEST_F(SimulcastRateAllocatorTest, NoSimulcastAboveMax) { |
79 uint32_t expected[] = {codec_.maxBitrate}; | 61 uint32_t expected[] = {codec_.maxBitrate}; |
80 ExpectEqual(expected, GetAllocation(codec_.maxBitrate + 1)); | 62 ExpectEqual(expected, allocator_->GetAllocation(codec_.maxBitrate + 1)); |
81 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max())); | 63 ExpectEqual(expected, |
| 64 allocator_->GetAllocation(std::numeric_limits<uint32_t>::max())); |
82 } | 65 } |
83 | 66 |
84 TEST_F(SimulcastRateAllocatorTest, NoSimulcastNoMax) { | 67 TEST_F(SimulcastRateAllocatorTest, NoSimulcastNoMax) { |
85 const uint32_t kMax = BitrateAllocation::kMaxBitrateBps / 1000; | 68 constexpr uint32_t kMax = std::numeric_limits<uint32_t>::max(); |
86 codec_.maxBitrate = 0; | 69 codec_.maxBitrate = 0; |
87 CreateAllocator(); | 70 CreateAllocator(); |
88 | 71 |
89 uint32_t expected[] = {kMax}; | 72 uint32_t expected[] = {kMax}; |
90 ExpectEqual(expected, GetAllocation(kMax)); | 73 ExpectEqual(expected, allocator_->GetAllocation(kMax)); |
91 } | 74 } |
92 | 75 |
93 TEST_F(SimulcastRateAllocatorTest, NoSimulcastWithinLimits) { | 76 TEST_F(SimulcastRateAllocatorTest, NoSimulcastWithinLimits) { |
94 for (uint32_t bitrate = codec_.minBitrate; bitrate <= codec_.maxBitrate; | 77 for (uint32_t bitrate = codec_.minBitrate; bitrate <= codec_.maxBitrate; |
95 ++bitrate) { | 78 ++bitrate) { |
96 uint32_t expected[] = {bitrate}; | 79 uint32_t expected[] = {bitrate}; |
97 ExpectEqual(expected, GetAllocation(bitrate)); | 80 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
98 } | 81 } |
99 } | 82 } |
100 | 83 |
101 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastBelowMin) { | 84 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastBelowMin) { |
102 // With simulcast, use the min bitrate from the ss spec instead of the global. | 85 // With simulcast, use the min bitrate from the ss spec instead of the global. |
103 codec_.numberOfSimulcastStreams = 1; | 86 codec_.numberOfSimulcastStreams = 1; |
104 const uint32_t kMin = codec_.minBitrate - 10; | 87 const uint32_t kMin = codec_.minBitrate - 10; |
105 codec_.simulcastStream[0].minBitrate = kMin; | 88 codec_.simulcastStream[0].minBitrate = kMin; |
106 codec_.simulcastStream[0].targetBitrate = kTargetBitrate; | 89 codec_.simulcastStream[0].targetBitrate = kTargetBitrate; |
107 CreateAllocator(); | 90 CreateAllocator(); |
108 | 91 |
109 uint32_t expected[] = {kMin}; | 92 uint32_t expected[] = {kMin}; |
110 ExpectEqual(expected, GetAllocation(kMin - 1)); | 93 ExpectEqual(expected, allocator_->GetAllocation(kMin - 1)); |
111 ExpectEqual(expected, GetAllocation(1)); | 94 ExpectEqual(expected, allocator_->GetAllocation(1)); |
112 ExpectEqual(expected, GetAllocation(0)); | 95 ExpectEqual(expected, allocator_->GetAllocation(0)); |
113 } | 96 } |
114 | 97 |
115 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastAboveMax) { | 98 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastAboveMax) { |
116 codec_.numberOfSimulcastStreams = 1; | 99 codec_.numberOfSimulcastStreams = 1; |
117 codec_.simulcastStream[0].minBitrate = kMinBitrate; | 100 codec_.simulcastStream[0].minBitrate = kMinBitrate; |
118 const uint32_t kMax = codec_.simulcastStream[0].maxBitrate + 1000; | 101 const uint32_t kMax = codec_.simulcastStream[0].maxBitrate + 1000; |
119 codec_.simulcastStream[0].maxBitrate = kMax; | 102 codec_.simulcastStream[0].maxBitrate = kMax; |
120 CreateAllocator(); | 103 CreateAllocator(); |
121 | 104 |
122 uint32_t expected[] = {kMax}; | 105 uint32_t expected[] = {kMax}; |
123 ExpectEqual(expected, GetAllocation(kMax)); | 106 ExpectEqual(expected, allocator_->GetAllocation(kMax + 1)); |
124 ExpectEqual(expected, GetAllocation(kMax + 1)); | 107 ExpectEqual(expected, |
125 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max())); | 108 allocator_->GetAllocation(std::numeric_limits<uint32_t>::max())); |
126 } | 109 } |
127 | 110 |
128 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastWithinLimits) { | 111 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastWithinLimits) { |
129 codec_.numberOfSimulcastStreams = 1; | 112 codec_.numberOfSimulcastStreams = 1; |
130 codec_.simulcastStream[0].minBitrate = kMinBitrate; | 113 codec_.simulcastStream[0].minBitrate = kMinBitrate; |
131 codec_.simulcastStream[0].targetBitrate = kTargetBitrate; | 114 codec_.simulcastStream[0].targetBitrate = kTargetBitrate; |
132 codec_.simulcastStream[0].maxBitrate = kMaxBitrate; | 115 codec_.simulcastStream[0].maxBitrate = kMaxBitrate; |
133 CreateAllocator(); | 116 CreateAllocator(); |
134 | 117 |
135 for (uint32_t bitrate = kMinBitrate; bitrate <= kMaxBitrate; ++bitrate) { | 118 for (uint32_t bitrate = kMinBitrate; bitrate <= kMaxBitrate; ++bitrate) { |
136 uint32_t expected[] = {bitrate}; | 119 uint32_t expected[] = {bitrate}; |
137 ExpectEqual(expected, GetAllocation(bitrate)); | 120 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
138 } | 121 } |
139 } | 122 } |
140 | 123 |
141 TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { | 124 TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
142 codec_.numberOfSimulcastStreams = 3; | 125 codec_.numberOfSimulcastStreams = 3; |
143 codec_.maxBitrate = 0; | 126 codec_.maxBitrate = 0; |
144 codec_.simulcastStream[0].minBitrate = 10; | 127 codec_.simulcastStream[0].minBitrate = 10; |
145 codec_.simulcastStream[0].targetBitrate = 100; | 128 codec_.simulcastStream[0].targetBitrate = 100; |
146 codec_.simulcastStream[0].maxBitrate = 500; | 129 codec_.simulcastStream[0].maxBitrate = 500; |
147 codec_.simulcastStream[1].minBitrate = 50; | 130 codec_.simulcastStream[1].minBitrate = 50; |
148 codec_.simulcastStream[1].targetBitrate = 500; | 131 codec_.simulcastStream[1].targetBitrate = 500; |
149 codec_.simulcastStream[1].maxBitrate = 1000; | 132 codec_.simulcastStream[1].maxBitrate = 1000; |
150 codec_.simulcastStream[2].minBitrate = 2000; | 133 codec_.simulcastStream[2].minBitrate = 2000; |
151 codec_.simulcastStream[2].targetBitrate = 3000; | 134 codec_.simulcastStream[2].targetBitrate = 3000; |
152 codec_.simulcastStream[2].maxBitrate = 4000; | 135 codec_.simulcastStream[2].maxBitrate = 4000; |
153 CreateAllocator(); | 136 CreateAllocator(); |
154 | 137 |
155 { | 138 { |
156 // Single stream, min bitrate. | 139 // Single stream, min bitrate. |
157 const uint32_t bitrate = codec_.simulcastStream[0].minBitrate; | 140 const uint32_t bitrate = codec_.simulcastStream[0].minBitrate; |
158 uint32_t expected[] = {bitrate, 0, 0}; | 141 uint32_t expected[] = {bitrate, 0, 0}; |
159 ExpectEqual(expected, GetAllocation(bitrate)); | 142 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
160 } | 143 } |
161 | 144 |
162 { | 145 { |
163 // Single stream at target bitrate. | 146 // Single stream at target bitrate. |
164 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate; | 147 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate; |
165 uint32_t expected[] = {bitrate, 0, 0}; | 148 uint32_t expected[] = {bitrate, 0, 0}; |
166 ExpectEqual(expected, GetAllocation(bitrate)); | 149 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
167 } | 150 } |
168 | 151 |
169 { | 152 { |
170 // Bitrate above target for first stream, but below min for the next one. | 153 // Bitrate above target for first stream, but below min for the next one. |
171 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + | 154 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
172 codec_.simulcastStream[1].minBitrate - 1; | 155 codec_.simulcastStream[1].minBitrate - 1; |
173 uint32_t expected[] = {bitrate, 0, 0}; | 156 uint32_t expected[] = {bitrate, 0, 0}; |
174 ExpectEqual(expected, GetAllocation(bitrate)); | 157 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
175 } | 158 } |
176 | 159 |
177 { | 160 { |
178 // Just enough for two streams. | 161 // Just enough for two streams. |
179 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + | 162 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
180 codec_.simulcastStream[1].minBitrate; | 163 codec_.simulcastStream[1].minBitrate; |
181 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, | 164 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
182 codec_.simulcastStream[1].minBitrate, 0}; | 165 codec_.simulcastStream[1].minBitrate, 0}; |
183 ExpectEqual(expected, GetAllocation(bitrate)); | 166 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
184 } | 167 } |
185 | 168 |
186 { | 169 { |
187 // Second stream maxed out, but not enough for third. | 170 // Second stream maxed out, but not enough for third. |
188 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + | 171 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
189 codec_.simulcastStream[1].maxBitrate; | 172 codec_.simulcastStream[1].maxBitrate; |
190 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, | 173 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
191 codec_.simulcastStream[1].maxBitrate, 0}; | 174 codec_.simulcastStream[1].maxBitrate, 0}; |
192 ExpectEqual(expected, GetAllocation(bitrate)); | 175 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
193 } | 176 } |
194 | 177 |
195 { | 178 { |
196 // First two streams maxed out, but not enough for third. Nowhere to put | 179 // First two streams maxed out, but not enough for third. Nowhere to put |
197 // remaining bits. | 180 // remaining bits. |
198 const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate + | 181 const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate + |
199 codec_.simulcastStream[1].maxBitrate + 499; | 182 codec_.simulcastStream[1].maxBitrate + 499; |
200 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, | 183 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
201 codec_.simulcastStream[1].maxBitrate, 0}; | 184 codec_.simulcastStream[1].maxBitrate, 0}; |
202 ExpectEqual(expected, GetAllocation(bitrate)); | 185 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
203 } | 186 } |
204 | 187 |
205 { | 188 { |
206 // Just enough for all three streams. | 189 // Just enough for all three streams. |
207 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + | 190 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
208 codec_.simulcastStream[1].targetBitrate + | 191 codec_.simulcastStream[1].targetBitrate + |
209 codec_.simulcastStream[2].minBitrate; | 192 codec_.simulcastStream[2].minBitrate; |
210 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, | 193 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
211 codec_.simulcastStream[1].targetBitrate, | 194 codec_.simulcastStream[1].targetBitrate, |
212 codec_.simulcastStream[2].minBitrate}; | 195 codec_.simulcastStream[2].minBitrate}; |
213 ExpectEqual(expected, GetAllocation(bitrate)); | 196 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
214 } | 197 } |
215 | 198 |
216 { | 199 { |
217 // Third maxed out. | 200 // Third maxed out. |
218 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + | 201 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
219 codec_.simulcastStream[1].targetBitrate + | 202 codec_.simulcastStream[1].targetBitrate + |
220 codec_.simulcastStream[2].maxBitrate; | 203 codec_.simulcastStream[2].maxBitrate; |
221 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, | 204 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
222 codec_.simulcastStream[1].targetBitrate, | 205 codec_.simulcastStream[1].targetBitrate, |
223 codec_.simulcastStream[2].maxBitrate}; | 206 codec_.simulcastStream[2].maxBitrate}; |
224 ExpectEqual(expected, GetAllocation(bitrate)); | 207 ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
225 } | 208 } |
226 } | 209 } |
227 | 210 |
228 TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrateBps) { | 211 TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrate) { |
229 EXPECT_EQ(codec_.maxBitrate * 1000, | 212 EXPECT_EQ(codec_.maxBitrate, allocator_->GetPreferedBitrate()); |
230 allocator_->GetPreferredBitrateBps(codec_.maxFramerate)); | |
231 } | 213 } |
232 | 214 |
233 TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrateSimulcast) { | 215 TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrateSimulcast) { |
234 codec_.numberOfSimulcastStreams = 3; | 216 codec_.numberOfSimulcastStreams = 3; |
235 codec_.maxBitrate = 999999; | 217 codec_.maxBitrate = 999999; |
236 codec_.simulcastStream[0].minBitrate = 10; | 218 codec_.simulcastStream[0].minBitrate = 10; |
237 codec_.simulcastStream[0].targetBitrate = 100; | 219 codec_.simulcastStream[0].targetBitrate = 100; |
238 | 220 |
239 codec_.simulcastStream[0].maxBitrate = 500; | 221 codec_.simulcastStream[0].maxBitrate = 500; |
240 codec_.simulcastStream[1].minBitrate = 50; | 222 codec_.simulcastStream[1].minBitrate = 50; |
241 codec_.simulcastStream[1].targetBitrate = 500; | 223 codec_.simulcastStream[1].targetBitrate = 500; |
242 codec_.simulcastStream[1].maxBitrate = 1000; | 224 codec_.simulcastStream[1].maxBitrate = 1000; |
243 | 225 |
244 codec_.simulcastStream[2].minBitrate = 2000; | 226 codec_.simulcastStream[2].minBitrate = 2000; |
245 codec_.simulcastStream[2].targetBitrate = 3000; | 227 codec_.simulcastStream[2].targetBitrate = 3000; |
246 codec_.simulcastStream[2].maxBitrate = 4000; | 228 codec_.simulcastStream[2].maxBitrate = 4000; |
247 CreateAllocator(); | 229 CreateAllocator(); |
248 | 230 |
249 uint32_t preferred_bitrate_kbps; | 231 uint32_t preferred_bitrate; |
250 preferred_bitrate_kbps = codec_.simulcastStream[0].targetBitrate; | 232 preferred_bitrate = codec_.simulcastStream[0].targetBitrate; |
251 preferred_bitrate_kbps += codec_.simulcastStream[1].targetBitrate; | 233 preferred_bitrate += codec_.simulcastStream[1].targetBitrate; |
252 preferred_bitrate_kbps += codec_.simulcastStream[2].maxBitrate; | 234 preferred_bitrate += codec_.simulcastStream[2].maxBitrate; |
253 | 235 |
254 EXPECT_EQ(preferred_bitrate_kbps * 1000, | 236 EXPECT_EQ(preferred_bitrate, allocator_->GetPreferedBitrate()); |
255 allocator_->GetPreferredBitrateBps(codec_.maxFramerate)); | |
256 } | 237 } |
257 | 238 |
258 } // namespace webrtc | 239 } // namespace webrtc |
OLD | NEW |