1 /*
2 * Copyright (c) 2015 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/congestion_controller/rtp/transport_feedback_adapter.h"
12
13 #include <limits>
14 #include <memory>
15 #include <vector>
16
17 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
18 #include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
19 #include "rtc_base/checks.h"
20 #include "rtc_base/numerics/safe_conversions.h"
21 #include "system_wrappers/include/clock.h"
22 #include "test/field_trial.h"
23 #include "test/gmock.h"
24 #include "test/gtest.h"
25
26 using ::testing::_;
27 using ::testing::Invoke;
28
29 namespace webrtc {
30
31 namespace {
32 constexpr uint32_t kSsrc = 8492;
33 const PacedPacketInfo kPacingInfo0(0, 5, 2000);
34 const PacedPacketInfo kPacingInfo1(1, 8, 4000);
35 const PacedPacketInfo kPacingInfo2(2, 14, 7000);
36 const PacedPacketInfo kPacingInfo3(3, 20, 10000);
37 const PacedPacketInfo kPacingInfo4(4, 22, 10000);
38
ComparePacketFeedbackVectors(const std::vector<PacketResult> & truth,const std::vector<PacketResult> & input)39 void ComparePacketFeedbackVectors(const std::vector<PacketResult>& truth,
40 const std::vector<PacketResult>& input) {
41 ASSERT_EQ(truth.size(), input.size());
42 size_t len = truth.size();
43 // truth contains the input data for the test, and input is what will be
44 // sent to the bandwidth estimator. truth.arrival_tims_ms is used to
45 // populate the transport feedback messages. As these times may be changed
46 // (because of resolution limits in the packets, and because of the time
47 // base adjustment performed by the TransportFeedbackAdapter at the first
48 // packet, the truth[x].arrival_time and input[x].arrival_time may not be
49 // equal. However, the difference must be the same for all x.
50 TimeDelta arrival_time_delta = truth[0].receive_time - input[0].receive_time;
51 for (size_t i = 0; i < len; ++i) {
52 RTC_CHECK(truth[i].IsReceived());
53 if (input[i].IsReceived()) {
54 EXPECT_EQ(truth[i].receive_time - input[i].receive_time,
55 arrival_time_delta);
56 }
57 EXPECT_EQ(truth[i].sent_packet.send_time, input[i].sent_packet.send_time);
58 EXPECT_EQ(truth[i].sent_packet.sequence_number,
59 input[i].sent_packet.sequence_number);
60 EXPECT_EQ(truth[i].sent_packet.size, input[i].sent_packet.size);
61 EXPECT_EQ(truth[i].sent_packet.pacing_info,
62 input[i].sent_packet.pacing_info);
63 }
64 }
65
CreatePacket(int64_t receive_time_ms,int64_t send_time_ms,int64_t sequence_number,size_t payload_size,const PacedPacketInfo & pacing_info)66 PacketResult CreatePacket(int64_t receive_time_ms,
67 int64_t send_time_ms,
68 int64_t sequence_number,
69 size_t payload_size,
70 const PacedPacketInfo& pacing_info) {
71 PacketResult res;
72 res.receive_time = Timestamp::Millis(receive_time_ms);
73 res.sent_packet.send_time = Timestamp::Millis(send_time_ms);
74 res.sent_packet.sequence_number = sequence_number;
75 res.sent_packet.size = DataSize::Bytes(payload_size);
76 res.sent_packet.pacing_info = pacing_info;
77 return res;
78 }
79
80 class MockStreamFeedbackObserver : public webrtc::StreamFeedbackObserver {
81 public:
82 MOCK_METHOD(void,
83 OnPacketFeedbackVector,
84 (std::vector<StreamPacketInfo> packet_feedback_vector),
85 (override));
86 };
87
88 } // namespace
89
90 class TransportFeedbackAdapterTest : public ::testing::Test {
91 public:
TransportFeedbackAdapterTest()92 TransportFeedbackAdapterTest() : clock_(0) {}
93
~TransportFeedbackAdapterTest()94 virtual ~TransportFeedbackAdapterTest() {}
95
SetUp()96 virtual void SetUp() { adapter_.reset(new TransportFeedbackAdapter()); }
97
TearDown()98 virtual void TearDown() { adapter_.reset(); }
99
100 protected:
OnReceivedEstimatedBitrate(uint32_t bitrate)101 void OnReceivedEstimatedBitrate(uint32_t bitrate) {}
102
OnReceivedRtcpReceiverReport(const ReportBlockList & report_blocks,int64_t rtt,int64_t now_ms)103 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
104 int64_t rtt,
105 int64_t now_ms) {}
106
OnSentPacket(const PacketResult & packet_feedback)107 void OnSentPacket(const PacketResult& packet_feedback) {
108 RtpPacketSendInfo packet_info;
109 packet_info.media_ssrc = kSsrc;
110 packet_info.transport_sequence_number =
111 packet_feedback.sent_packet.sequence_number;
112 packet_info.rtp_sequence_number = 0;
113 packet_info.length = packet_feedback.sent_packet.size.bytes();
114 packet_info.pacing_info = packet_feedback.sent_packet.pacing_info;
115 packet_info.packet_type = RtpPacketMediaType::kVideo;
116 adapter_->AddPacket(RtpPacketSendInfo(packet_info), 0u,
117 clock_.CurrentTime());
118 adapter_->ProcessSentPacket(rtc::SentPacket(
119 packet_feedback.sent_packet.sequence_number,
120 packet_feedback.sent_packet.send_time.ms(), rtc::PacketInfo()));
121 }
122
123 SimulatedClock clock_;
124 std::unique_ptr<TransportFeedbackAdapter> adapter_;
125 };
126
TEST_F(TransportFeedbackAdapterTest,AdaptsFeedbackAndPopulatesSendTimes)127 TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) {
128 std::vector<PacketResult> packets;
129 packets.push_back(CreatePacket(100, 200, 0, 1500, kPacingInfo0));
130 packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo0));
131 packets.push_back(CreatePacket(120, 220, 2, 1500, kPacingInfo0));
132 packets.push_back(CreatePacket(130, 230, 3, 1500, kPacingInfo1));
133 packets.push_back(CreatePacket(140, 240, 4, 1500, kPacingInfo1));
134
135 for (const auto& packet : packets)
136 OnSentPacket(packet);
137
138 rtcp::TransportFeedback feedback;
139 feedback.SetBase(packets[0].sent_packet.sequence_number,
140 packets[0].receive_time);
141
142 for (const auto& packet : packets) {
143 EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
144 packet.receive_time));
145 }
146
147 feedback.Build();
148
149 auto result =
150 adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
151 ComparePacketFeedbackVectors(packets, result->packet_feedbacks);
152 }
153
TEST_F(TransportFeedbackAdapterTest,FeedbackVectorReportsUnreceived)154 TEST_F(TransportFeedbackAdapterTest, FeedbackVectorReportsUnreceived) {
155 std::vector<PacketResult> sent_packets = {
156 CreatePacket(100, 220, 0, 1500, kPacingInfo0),
157 CreatePacket(110, 210, 1, 1500, kPacingInfo0),
158 CreatePacket(120, 220, 2, 1500, kPacingInfo0),
159 CreatePacket(130, 230, 3, 1500, kPacingInfo0),
160 CreatePacket(140, 240, 4, 1500, kPacingInfo0),
161 CreatePacket(150, 250, 5, 1500, kPacingInfo0),
162 CreatePacket(160, 260, 6, 1500, kPacingInfo0)};
163
164 for (const auto& packet : sent_packets)
165 OnSentPacket(packet);
166
167 // Note: Important to include the last packet, as only unreceived packets in
168 // between received packets can be inferred.
169 std::vector<PacketResult> received_packets = {
170 sent_packets[0], sent_packets[2], sent_packets[6]};
171
172 rtcp::TransportFeedback feedback;
173 feedback.SetBase(received_packets[0].sent_packet.sequence_number,
174 received_packets[0].receive_time);
175
176 for (const auto& packet : received_packets) {
177 EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
178 packet.receive_time));
179 }
180
181 feedback.Build();
182
183 auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
184 ComparePacketFeedbackVectors(sent_packets, res->packet_feedbacks);
185 }
186
TEST_F(TransportFeedbackAdapterTest,HandlesDroppedPackets)187 TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) {
188 std::vector<PacketResult> packets;
189 packets.push_back(CreatePacket(100, 200, 0, 1500, kPacingInfo0));
190 packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo1));
191 packets.push_back(CreatePacket(120, 220, 2, 1500, kPacingInfo2));
192 packets.push_back(CreatePacket(130, 230, 3, 1500, kPacingInfo3));
193 packets.push_back(CreatePacket(140, 240, 4, 1500, kPacingInfo4));
194
195 const uint16_t kSendSideDropBefore = 1;
196 const uint16_t kReceiveSideDropAfter = 3;
197
198 for (const auto& packet : packets) {
199 if (packet.sent_packet.sequence_number >= kSendSideDropBefore)
200 OnSentPacket(packet);
201 }
202
203 rtcp::TransportFeedback feedback;
204 feedback.SetBase(packets[0].sent_packet.sequence_number,
205 packets[0].receive_time);
206
207 for (const auto& packet : packets) {
208 if (packet.sent_packet.sequence_number <= kReceiveSideDropAfter) {
209 EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
210 packet.receive_time));
211 }
212 }
213
214 feedback.Build();
215
216 std::vector<PacketResult> expected_packets(
217 packets.begin() + kSendSideDropBefore,
218 packets.begin() + kReceiveSideDropAfter + 1);
219 // Packets that have timed out on the send-side have lost the
220 // information stored on the send-side. And they will not be reported to
221 // observers since we won't know that they come from the same networks.
222
223 auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
224 ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
225 }
226
TEST_F(TransportFeedbackAdapterTest,SendTimeWrapsBothWays)227 TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) {
228 TimeDelta kHighArrivalTime =
229 rtcp::TransportFeedback::kDeltaTick * (1 << 8) * ((1 << 23) - 1);
230 std::vector<PacketResult> packets;
231 packets.push_back(CreatePacket(kHighArrivalTime.ms() + 64, 210, 0, 1500,
232 PacedPacketInfo()));
233 packets.push_back(CreatePacket(kHighArrivalTime.ms() - 64, 210, 1, 1500,
234 PacedPacketInfo()));
235 packets.push_back(
236 CreatePacket(kHighArrivalTime.ms(), 220, 2, 1500, PacedPacketInfo()));
237
238 for (const auto& packet : packets)
239 OnSentPacket(packet);
240
241 for (size_t i = 0; i < packets.size(); ++i) {
242 std::unique_ptr<rtcp::TransportFeedback> feedback(
243 new rtcp::TransportFeedback());
244 feedback->SetBase(packets[i].sent_packet.sequence_number,
245 packets[i].receive_time);
246
247 EXPECT_TRUE(feedback->AddReceivedPacket(
248 packets[i].sent_packet.sequence_number, packets[i].receive_time));
249
250 rtc::Buffer raw_packet = feedback->Build();
251 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet.data(),
252 raw_packet.size());
253
254 std::vector<PacketResult> expected_packets;
255 expected_packets.push_back(packets[i]);
256
257 auto res = adapter_->ProcessTransportFeedback(*feedback.get(),
258 clock_.CurrentTime());
259 ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
260 }
261 }
262
TEST_F(TransportFeedbackAdapterTest,HandlesArrivalReordering)263 TEST_F(TransportFeedbackAdapterTest, HandlesArrivalReordering) {
264 std::vector<PacketResult> packets;
265 packets.push_back(CreatePacket(120, 200, 0, 1500, kPacingInfo0));
266 packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo0));
267 packets.push_back(CreatePacket(100, 220, 2, 1500, kPacingInfo0));
268
269 for (const auto& packet : packets)
270 OnSentPacket(packet);
271
272 rtcp::TransportFeedback feedback;
273 feedback.SetBase(packets[0].sent_packet.sequence_number,
274 packets[0].receive_time);
275
276 for (const auto& packet : packets) {
277 EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
278 packet.receive_time));
279 }
280
281 feedback.Build();
282
283 // Adapter keeps the packets ordered by sequence number (which is itself
284 // assigned by the order of transmission). Reordering by some other criteria,
285 // eg. arrival time, is up to the observers.
286 auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
287 ComparePacketFeedbackVectors(packets, res->packet_feedbacks);
288 }
289
TEST_F(TransportFeedbackAdapterTest,TimestampDeltas)290 TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) {
291 std::vector<PacketResult> sent_packets;
292 // TODO(srte): Consider using us resolution in the constants.
293 const TimeDelta kSmallDelta = (rtcp::TransportFeedback::kDeltaTick * 0xFF)
294 .RoundDownTo(TimeDelta::Millis(1));
295 const TimeDelta kLargePositiveDelta = (rtcp::TransportFeedback::kDeltaTick *
296 std::numeric_limits<int16_t>::max())
297 .RoundDownTo(TimeDelta::Millis(1));
298 const TimeDelta kLargeNegativeDelta = (rtcp::TransportFeedback::kDeltaTick *
299 std::numeric_limits<int16_t>::min())
300 .RoundDownTo(TimeDelta::Millis(1));
301
302 PacketResult packet_feedback;
303 packet_feedback.sent_packet.sequence_number = 1;
304 packet_feedback.sent_packet.send_time = Timestamp::Millis(100);
305 packet_feedback.receive_time = Timestamp::Millis(200);
306 packet_feedback.sent_packet.size = DataSize::Bytes(1500);
307 sent_packets.push_back(packet_feedback);
308
309 // TODO(srte): This rounding maintains previous behavior, but should ot be
310 // required.
311 packet_feedback.sent_packet.send_time += kSmallDelta;
312 packet_feedback.receive_time += kSmallDelta;
313 ++packet_feedback.sent_packet.sequence_number;
314 sent_packets.push_back(packet_feedback);
315
316 packet_feedback.sent_packet.send_time += kLargePositiveDelta;
317 packet_feedback.receive_time += kLargePositiveDelta;
318 ++packet_feedback.sent_packet.sequence_number;
319 sent_packets.push_back(packet_feedback);
320
321 packet_feedback.sent_packet.send_time += kLargeNegativeDelta;
322 packet_feedback.receive_time += kLargeNegativeDelta;
323 ++packet_feedback.sent_packet.sequence_number;
324 sent_packets.push_back(packet_feedback);
325
326 // Too large, delta - will need two feedback messages.
327 packet_feedback.sent_packet.send_time +=
328 kLargePositiveDelta + TimeDelta::Millis(1);
329 packet_feedback.receive_time += kLargePositiveDelta + TimeDelta::Millis(1);
330 ++packet_feedback.sent_packet.sequence_number;
331
332 // Packets will be added to send history.
333 for (const auto& packet : sent_packets)
334 OnSentPacket(packet);
335 OnSentPacket(packet_feedback);
336
337 // Create expected feedback and send into adapter.
338 std::unique_ptr<rtcp::TransportFeedback> feedback(
339 new rtcp::TransportFeedback());
340 feedback->SetBase(sent_packets[0].sent_packet.sequence_number,
341 sent_packets[0].receive_time);
342
343 for (const auto& packet : sent_packets) {
344 EXPECT_TRUE(feedback->AddReceivedPacket(packet.sent_packet.sequence_number,
345 packet.receive_time));
346 }
347 EXPECT_FALSE(
348 feedback->AddReceivedPacket(packet_feedback.sent_packet.sequence_number,
349 packet_feedback.receive_time));
350
351 rtc::Buffer raw_packet = feedback->Build();
352 feedback =
353 rtcp::TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
354
355 std::vector<PacketResult> received_feedback;
356
357 EXPECT_TRUE(feedback.get() != nullptr);
358 auto res =
359 adapter_->ProcessTransportFeedback(*feedback.get(), clock_.CurrentTime());
360 ComparePacketFeedbackVectors(sent_packets, res->packet_feedbacks);
361
362 // Create a new feedback message and add the trailing item.
363 feedback.reset(new rtcp::TransportFeedback());
364 feedback->SetBase(packet_feedback.sent_packet.sequence_number,
365 packet_feedback.receive_time);
366 EXPECT_TRUE(
367 feedback->AddReceivedPacket(packet_feedback.sent_packet.sequence_number,
368 packet_feedback.receive_time));
369 raw_packet = feedback->Build();
370 feedback =
371 rtcp::TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
372
373 EXPECT_TRUE(feedback.get() != nullptr);
374 {
375 auto res = adapter_->ProcessTransportFeedback(*feedback.get(),
376 clock_.CurrentTime());
377 std::vector<PacketResult> expected_packets;
378 expected_packets.push_back(packet_feedback);
379 ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
380 }
381 }
382
TEST_F(TransportFeedbackAdapterTest,IgnoreDuplicatePacketSentCalls)383 TEST_F(TransportFeedbackAdapterTest, IgnoreDuplicatePacketSentCalls) {
384 auto packet = CreatePacket(100, 200, 0, 1500, kPacingInfo0);
385
386 // Add a packet and then mark it as sent.
387 RtpPacketSendInfo packet_info;
388 packet_info.media_ssrc = kSsrc;
389 packet_info.transport_sequence_number = packet.sent_packet.sequence_number;
390 packet_info.length = packet.sent_packet.size.bytes();
391 packet_info.pacing_info = packet.sent_packet.pacing_info;
392 packet_info.packet_type = RtpPacketMediaType::kVideo;
393 adapter_->AddPacket(packet_info, 0u, clock_.CurrentTime());
394 absl::optional<SentPacket> sent_packet = adapter_->ProcessSentPacket(
395 rtc::SentPacket(packet.sent_packet.sequence_number,
396 packet.sent_packet.send_time.ms(), rtc::PacketInfo()));
397 EXPECT_TRUE(sent_packet.has_value());
398
399 // Call ProcessSentPacket() again with the same sequence number. This packet
400 // has already been marked as sent and the call should be ignored.
401 absl::optional<SentPacket> duplicate_packet = adapter_->ProcessSentPacket(
402 rtc::SentPacket(packet.sent_packet.sequence_number,
403 packet.sent_packet.send_time.ms(), rtc::PacketInfo()));
404 EXPECT_FALSE(duplicate_packet.has_value());
405 }
406
407 } // namespace webrtc
408