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