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