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/rtp_rtcp/source/rtp_format.h"
12
13 #include <memory>
14 #include <numeric>
15
16 #include "absl/algorithm/container.h"
17 #include "test/gmock.h"
18 #include "test/gtest.h"
19
20 namespace webrtc {
21 namespace {
22
23 using ::testing::Each;
24 using ::testing::ElementsAre;
25 using ::testing::Gt;
26 using ::testing::IsEmpty;
27 using ::testing::Le;
28 using ::testing::Not;
29 using ::testing::SizeIs;
30
31 // Calculate difference between largest and smallest packets respecting sizes
32 // adjustement provided by limits,
33 // i.e. last packet expected to be smaller than 'average' by reduction_len.
EffectivePacketsSizeDifference(std::vector<int> sizes,const RtpPacketizer::PayloadSizeLimits & limits)34 int EffectivePacketsSizeDifference(
35 std::vector<int> sizes,
36 const RtpPacketizer::PayloadSizeLimits& limits) {
37 // Account for larger last packet header.
38 sizes.back() += limits.last_packet_reduction_len;
39
40 auto minmax = absl::c_minmax_element(sizes);
41 // MAX-MIN
42 return *minmax.second - *minmax.first;
43 }
44
Sum(const std::vector<int> & sizes)45 int Sum(const std::vector<int>& sizes) {
46 return absl::c_accumulate(sizes, 0);
47 }
48
TEST(RtpPacketizerSplitAboutEqually,AllPacketsAreEqualSumToPayloadLen)49 TEST(RtpPacketizerSplitAboutEqually, AllPacketsAreEqualSumToPayloadLen) {
50 RtpPacketizer::PayloadSizeLimits limits;
51 limits.max_payload_len = 5;
52 limits.last_packet_reduction_len = 2;
53
54 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(13, limits);
55
56 EXPECT_THAT(Sum(payload_sizes), 13);
57 }
58
TEST(RtpPacketizerSplitAboutEqually,AllPacketsAreEqualRespectsMaxPayloadSize)59 TEST(RtpPacketizerSplitAboutEqually, AllPacketsAreEqualRespectsMaxPayloadSize) {
60 RtpPacketizer::PayloadSizeLimits limits;
61 limits.max_payload_len = 5;
62 limits.last_packet_reduction_len = 2;
63
64 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(13, limits);
65
66 EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
67 }
68
TEST(RtpPacketizerSplitAboutEqually,AllPacketsAreEqualRespectsFirstPacketReduction)69 TEST(RtpPacketizerSplitAboutEqually,
70 AllPacketsAreEqualRespectsFirstPacketReduction) {
71 RtpPacketizer::PayloadSizeLimits limits;
72 limits.max_payload_len = 5;
73 limits.first_packet_reduction_len = 2;
74
75 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(13, limits);
76
77 ASSERT_THAT(payload_sizes, Not(IsEmpty()));
78 EXPECT_EQ(payload_sizes.front() + limits.first_packet_reduction_len,
79 limits.max_payload_len);
80 }
81
TEST(RtpPacketizerSplitAboutEqually,AllPacketsAreEqualRespectsLastPacketReductionLength)82 TEST(RtpPacketizerSplitAboutEqually,
83 AllPacketsAreEqualRespectsLastPacketReductionLength) {
84 RtpPacketizer::PayloadSizeLimits limits;
85 limits.max_payload_len = 5;
86 limits.last_packet_reduction_len = 2;
87
88 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(13, limits);
89
90 ASSERT_THAT(payload_sizes, Not(IsEmpty()));
91 EXPECT_LE(payload_sizes.back() + limits.last_packet_reduction_len,
92 limits.max_payload_len);
93 }
94
TEST(RtpPacketizerSplitAboutEqually,AllPacketsAreEqualInSize)95 TEST(RtpPacketizerSplitAboutEqually, AllPacketsAreEqualInSize) {
96 RtpPacketizer::PayloadSizeLimits limits;
97 limits.max_payload_len = 5;
98 limits.last_packet_reduction_len = 2;
99
100 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(13, limits);
101
102 EXPECT_EQ(EffectivePacketsSizeDifference(payload_sizes, limits), 0);
103 }
104
TEST(RtpPacketizerSplitAboutEqually,AllPacketsAreEqualGeneratesMinimumNumberOfPackets)105 TEST(RtpPacketizerSplitAboutEqually,
106 AllPacketsAreEqualGeneratesMinimumNumberOfPackets) {
107 RtpPacketizer::PayloadSizeLimits limits;
108 limits.max_payload_len = 5;
109 limits.last_packet_reduction_len = 2;
110
111 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(13, limits);
112 // Computed by hand. 3 packets would have exactly capacity 3*5-2=13
113 // (max length - for each packet minus last packet reduction).
114 EXPECT_THAT(payload_sizes, SizeIs(3));
115 }
116
TEST(RtpPacketizerSplitAboutEqually,SomePacketsAreSmallerSumToPayloadLen)117 TEST(RtpPacketizerSplitAboutEqually, SomePacketsAreSmallerSumToPayloadLen) {
118 RtpPacketizer::PayloadSizeLimits limits;
119 limits.max_payload_len = 7;
120 limits.last_packet_reduction_len = 5;
121
122 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(28, limits);
123
124 EXPECT_THAT(Sum(payload_sizes), 28);
125 }
126
TEST(RtpPacketizerSplitAboutEqually,SomePacketsAreSmallerRespectsMaxPayloadSize)127 TEST(RtpPacketizerSplitAboutEqually,
128 SomePacketsAreSmallerRespectsMaxPayloadSize) {
129 RtpPacketizer::PayloadSizeLimits limits;
130 limits.max_payload_len = 7;
131 limits.last_packet_reduction_len = 5;
132
133 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(28, limits);
134
135 EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
136 }
137
TEST(RtpPacketizerSplitAboutEqually,SomePacketsAreSmallerRespectsFirstPacketReduction)138 TEST(RtpPacketizerSplitAboutEqually,
139 SomePacketsAreSmallerRespectsFirstPacketReduction) {
140 RtpPacketizer::PayloadSizeLimits limits;
141 limits.max_payload_len = 7;
142 limits.first_packet_reduction_len = 5;
143
144 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(28, limits);
145
146 EXPECT_LE(payload_sizes.front() + limits.first_packet_reduction_len,
147 limits.max_payload_len);
148 }
149
TEST(RtpPacketizerSplitAboutEqually,SomePacketsAreSmallerRespectsLastPacketReductionLength)150 TEST(RtpPacketizerSplitAboutEqually,
151 SomePacketsAreSmallerRespectsLastPacketReductionLength) {
152 RtpPacketizer::PayloadSizeLimits limits;
153 limits.max_payload_len = 7;
154 limits.last_packet_reduction_len = 5;
155
156 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(28, limits);
157
158 EXPECT_LE(payload_sizes.back(),
159 limits.max_payload_len - limits.last_packet_reduction_len);
160 }
161
TEST(RtpPacketizerSplitAboutEqually,SomePacketsAreSmallerPacketsAlmostEqualInSize)162 TEST(RtpPacketizerSplitAboutEqually,
163 SomePacketsAreSmallerPacketsAlmostEqualInSize) {
164 RtpPacketizer::PayloadSizeLimits limits;
165 limits.max_payload_len = 7;
166 limits.last_packet_reduction_len = 5;
167
168 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(28, limits);
169
170 EXPECT_LE(EffectivePacketsSizeDifference(payload_sizes, limits), 1);
171 }
172
TEST(RtpPacketizerSplitAboutEqually,SomePacketsAreSmallerGeneratesMinimumNumberOfPackets)173 TEST(RtpPacketizerSplitAboutEqually,
174 SomePacketsAreSmallerGeneratesMinimumNumberOfPackets) {
175 RtpPacketizer::PayloadSizeLimits limits;
176 limits.max_payload_len = 7;
177 limits.last_packet_reduction_len = 5;
178
179 std::vector<int> payload_sizes = RtpPacketizer::SplitAboutEqually(24, limits);
180 // Computed by hand. 4 packets would have capacity 4*7-5=23 (max length -
181 // for each packet minus last packet reduction).
182 // 5 packets is enough for kPayloadSize.
183 EXPECT_THAT(payload_sizes, SizeIs(5));
184 }
185
TEST(RtpPacketizerSplitAboutEqually,GivesNonZeroPayloadLengthEachPacket)186 TEST(RtpPacketizerSplitAboutEqually, GivesNonZeroPayloadLengthEachPacket) {
187 RtpPacketizer::PayloadSizeLimits limits;
188 limits.max_payload_len = 600;
189 limits.first_packet_reduction_len = 500;
190 limits.last_packet_reduction_len = 550;
191
192 // Naive implementation would split 1450 payload + 1050 reduction bytes into 5
193 // packets 500 bytes each, thus leaving first packet zero bytes and even less
194 // to last packet.
195 std::vector<int> payload_sizes =
196 RtpPacketizer::SplitAboutEqually(1450, limits);
197
198 EXPECT_EQ(Sum(payload_sizes), 1450);
199 EXPECT_THAT(payload_sizes, Each(Gt(0)));
200 }
201
TEST(RtpPacketizerSplitAboutEqually,IgnoresFirstAndLastPacketReductionWhenPayloadFitsIntoSinglePacket)202 TEST(RtpPacketizerSplitAboutEqually,
203 IgnoresFirstAndLastPacketReductionWhenPayloadFitsIntoSinglePacket) {
204 RtpPacketizer::PayloadSizeLimits limits;
205 limits.max_payload_len = 30;
206 limits.first_packet_reduction_len = 29;
207 limits.last_packet_reduction_len = 29;
208 limits.single_packet_reduction_len = 10;
209
210 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(20, limits), ElementsAre(20));
211 }
212
TEST(RtpPacketizerSplitAboutEqually,OnePacketWhenExtraSpaceIsEnoughForSinglePacketReduction)213 TEST(RtpPacketizerSplitAboutEqually,
214 OnePacketWhenExtraSpaceIsEnoughForSinglePacketReduction) {
215 RtpPacketizer::PayloadSizeLimits limits;
216 limits.max_payload_len = 30;
217 limits.single_packet_reduction_len = 10;
218
219 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(20, limits), ElementsAre(20));
220 }
221
TEST(RtpPacketizerSplitAboutEqually,TwoPacketsWhenExtraSpaceIsTooSmallForSinglePacketReduction)222 TEST(RtpPacketizerSplitAboutEqually,
223 TwoPacketsWhenExtraSpaceIsTooSmallForSinglePacketReduction) {
224 RtpPacketizer::PayloadSizeLimits limits;
225 limits.max_payload_len = 29;
226 limits.first_packet_reduction_len = 3;
227 limits.last_packet_reduction_len = 1;
228 limits.single_packet_reduction_len = 10;
229
230 // First packet needs two more extra bytes compared to last one,
231 // so should have two less payload bytes.
232 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(20, limits), ElementsAre(9, 11));
233 }
234
TEST(RtpPacketizerSplitAboutEqually,RejectsZeroMaxPayloadLen)235 TEST(RtpPacketizerSplitAboutEqually, RejectsZeroMaxPayloadLen) {
236 RtpPacketizer::PayloadSizeLimits limits;
237 limits.max_payload_len = 0;
238
239 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(20, limits), IsEmpty());
240 }
241
TEST(RtpPacketizerSplitAboutEqually,RejectsZeroFirstPacketLen)242 TEST(RtpPacketizerSplitAboutEqually, RejectsZeroFirstPacketLen) {
243 RtpPacketizer::PayloadSizeLimits limits;
244 limits.max_payload_len = 5;
245 limits.first_packet_reduction_len = 5;
246
247 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(20, limits), IsEmpty());
248 }
249
TEST(RtpPacketizerSplitAboutEqually,RejectsZeroLastPacketLen)250 TEST(RtpPacketizerSplitAboutEqually, RejectsZeroLastPacketLen) {
251 RtpPacketizer::PayloadSizeLimits limits;
252 limits.max_payload_len = 5;
253 limits.last_packet_reduction_len = 5;
254
255 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(20, limits), IsEmpty());
256 }
257
TEST(RtpPacketizerSplitAboutEqually,CantPutSinglePayloadByteInTwoPackets)258 TEST(RtpPacketizerSplitAboutEqually, CantPutSinglePayloadByteInTwoPackets) {
259 RtpPacketizer::PayloadSizeLimits limits;
260 limits.max_payload_len = 10;
261 limits.single_packet_reduction_len = 10;
262
263 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(1, limits), IsEmpty());
264 }
265
TEST(RtpPacketizerSplitAboutEqually,CanPutTwoPayloadBytesInTwoPackets)266 TEST(RtpPacketizerSplitAboutEqually, CanPutTwoPayloadBytesInTwoPackets) {
267 RtpPacketizer::PayloadSizeLimits limits;
268 limits.max_payload_len = 10;
269 limits.single_packet_reduction_len = 10;
270
271 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(2, limits), ElementsAre(1, 1));
272 }
273
TEST(RtpPacketizerSplitAboutEqually,CanPutSinglePayloadByteInOnePacket)274 TEST(RtpPacketizerSplitAboutEqually, CanPutSinglePayloadByteInOnePacket) {
275 RtpPacketizer::PayloadSizeLimits limits;
276 limits.max_payload_len = 11;
277 limits.single_packet_reduction_len = 10;
278
279 EXPECT_THAT(RtpPacketizer::SplitAboutEqually(1, limits), ElementsAre(1));
280 }
281
282 } // namespace
283 } // namespace webrtc
284