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 namespace webrtc_cc {
31 
32 namespace {
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].receive_time.IsFinite());
53     if (input[i].receive_time.IsFinite()) {
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 }  // namespace
81 
82 namespace test {
83 
84 class MockStreamFeedbackObserver : public webrtc::StreamFeedbackObserver {
85  public:
86   MOCK_METHOD(void,
87               OnPacketFeedbackVector,
88               (std::vector<StreamPacketInfo> packet_feedback_vector),
89               (override));
90 };
91 
92 class TransportFeedbackAdapterTest : public ::testing::Test {
93  public:
TransportFeedbackAdapterTest()94   TransportFeedbackAdapterTest() : clock_(0) {}
95 
~TransportFeedbackAdapterTest()96   virtual ~TransportFeedbackAdapterTest() {}
97 
SetUp()98   virtual void SetUp() { adapter_.reset(new TransportFeedbackAdapter()); }
99 
TearDown()100   virtual void TearDown() { adapter_.reset(); }
101 
102  protected:
OnReceivedEstimatedBitrate(uint32_t bitrate)103   void OnReceivedEstimatedBitrate(uint32_t bitrate) {}
104 
OnReceivedRtcpReceiverReport(const ReportBlockList & report_blocks,int64_t rtt,int64_t now_ms)105   void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
106                                     int64_t rtt,
107                                     int64_t now_ms) {}
108 
OnSentPacket(const PacketResult & packet_feedback)109   void OnSentPacket(const PacketResult& packet_feedback) {
110     RtpPacketSendInfo packet_info;
111     packet_info.ssrc = kSsrc;
112     packet_info.transport_sequence_number =
113         packet_feedback.sent_packet.sequence_number;
114     packet_info.rtp_sequence_number = 0;
115     packet_info.length = packet_feedback.sent_packet.size.bytes();
116     packet_info.pacing_info = packet_feedback.sent_packet.pacing_info;
117     packet_info.packet_type = RtpPacketMediaType::kVideo;
118     adapter_->AddPacket(RtpPacketSendInfo(packet_info), 0u,
119                         clock_.CurrentTime());
120     adapter_->ProcessSentPacket(rtc::SentPacket(
121         packet_feedback.sent_packet.sequence_number,
122         packet_feedback.sent_packet.send_time.ms(), rtc::PacketInfo()));
123   }
124 
125   static constexpr uint32_t kSsrc = 8492;
126 
127   SimulatedClock clock_;
128   std::unique_ptr<TransportFeedbackAdapter> adapter_;
129 };
130 
TEST_F(TransportFeedbackAdapterTest,AdaptsFeedbackAndPopulatesSendTimes)131 TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) {
132   std::vector<PacketResult> packets;
133   packets.push_back(CreatePacket(100, 200, 0, 1500, kPacingInfo0));
134   packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo0));
135   packets.push_back(CreatePacket(120, 220, 2, 1500, kPacingInfo0));
136   packets.push_back(CreatePacket(130, 230, 3, 1500, kPacingInfo1));
137   packets.push_back(CreatePacket(140, 240, 4, 1500, kPacingInfo1));
138 
139   for (const auto& packet : packets)
140     OnSentPacket(packet);
141 
142   rtcp::TransportFeedback feedback;
143   feedback.SetBase(packets[0].sent_packet.sequence_number,
144                    packets[0].receive_time.us());
145 
146   for (const auto& packet : packets) {
147     EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
148                                            packet.receive_time.us()));
149   }
150 
151   feedback.Build();
152 
153   auto result =
154       adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
155   ComparePacketFeedbackVectors(packets, result->packet_feedbacks);
156 }
157 
TEST_F(TransportFeedbackAdapterTest,FeedbackVectorReportsUnreceived)158 TEST_F(TransportFeedbackAdapterTest, FeedbackVectorReportsUnreceived) {
159   std::vector<PacketResult> sent_packets = {
160       CreatePacket(100, 220, 0, 1500, kPacingInfo0),
161       CreatePacket(110, 210, 1, 1500, kPacingInfo0),
162       CreatePacket(120, 220, 2, 1500, kPacingInfo0),
163       CreatePacket(130, 230, 3, 1500, kPacingInfo0),
164       CreatePacket(140, 240, 4, 1500, kPacingInfo0),
165       CreatePacket(150, 250, 5, 1500, kPacingInfo0),
166       CreatePacket(160, 260, 6, 1500, kPacingInfo0)};
167 
168   for (const auto& packet : sent_packets)
169     OnSentPacket(packet);
170 
171   // Note: Important to include the last packet, as only unreceived packets in
172   // between received packets can be inferred.
173   std::vector<PacketResult> received_packets = {
174       sent_packets[0], sent_packets[2], sent_packets[6]};
175 
176   rtcp::TransportFeedback feedback;
177   feedback.SetBase(received_packets[0].sent_packet.sequence_number,
178                    received_packets[0].receive_time.us());
179 
180   for (const auto& packet : received_packets) {
181     EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
182                                            packet.receive_time.us()));
183   }
184 
185   feedback.Build();
186 
187   auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
188   ComparePacketFeedbackVectors(sent_packets, res->packet_feedbacks);
189 }
190 
TEST_F(TransportFeedbackAdapterTest,HandlesDroppedPackets)191 TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) {
192   std::vector<PacketResult> packets;
193   packets.push_back(CreatePacket(100, 200, 0, 1500, kPacingInfo0));
194   packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo1));
195   packets.push_back(CreatePacket(120, 220, 2, 1500, kPacingInfo2));
196   packets.push_back(CreatePacket(130, 230, 3, 1500, kPacingInfo3));
197   packets.push_back(CreatePacket(140, 240, 4, 1500, kPacingInfo4));
198 
199   const uint16_t kSendSideDropBefore = 1;
200   const uint16_t kReceiveSideDropAfter = 3;
201 
202   for (const auto& packet : packets) {
203     if (packet.sent_packet.sequence_number >= kSendSideDropBefore)
204       OnSentPacket(packet);
205   }
206 
207   rtcp::TransportFeedback feedback;
208   feedback.SetBase(packets[0].sent_packet.sequence_number,
209                    packets[0].receive_time.us());
210 
211   for (const auto& packet : packets) {
212     if (packet.sent_packet.sequence_number <= kReceiveSideDropAfter) {
213       EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
214                                              packet.receive_time.us()));
215     }
216   }
217 
218   feedback.Build();
219 
220   std::vector<PacketResult> expected_packets(
221       packets.begin() + kSendSideDropBefore,
222       packets.begin() + kReceiveSideDropAfter + 1);
223   // Packets that have timed out on the send-side have lost the
224   // information stored on the send-side. And they will not be reported to
225   // observers since we won't know that they come from the same networks.
226 
227   auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
228   ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
229 }
230 
TEST_F(TransportFeedbackAdapterTest,SendTimeWrapsBothWays)231 TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) {
232   int64_t kHighArrivalTimeMs = rtcp::TransportFeedback::kDeltaScaleFactor *
233                                static_cast<int64_t>(1 << 8) *
234                                static_cast<int64_t>((1 << 23) - 1) / 1000;
235   std::vector<PacketResult> packets;
236   packets.push_back(
237       CreatePacket(kHighArrivalTimeMs + 64, 210, 0, 1500, PacedPacketInfo()));
238   packets.push_back(
239       CreatePacket(kHighArrivalTimeMs - 64, 210, 1, 1500, PacedPacketInfo()));
240   packets.push_back(
241       CreatePacket(kHighArrivalTimeMs, 220, 2, 1500, PacedPacketInfo()));
242 
243   for (const auto& packet : packets)
244     OnSentPacket(packet);
245 
246   for (size_t i = 0; i < packets.size(); ++i) {
247     std::unique_ptr<rtcp::TransportFeedback> feedback(
248         new rtcp::TransportFeedback());
249     feedback->SetBase(packets[i].sent_packet.sequence_number,
250                       packets[i].receive_time.us());
251 
252     EXPECT_TRUE(feedback->AddReceivedPacket(
253         packets[i].sent_packet.sequence_number, packets[i].receive_time.us()));
254 
255     rtc::Buffer raw_packet = feedback->Build();
256     feedback = rtcp::TransportFeedback::ParseFrom(raw_packet.data(),
257                                                   raw_packet.size());
258 
259     std::vector<PacketResult> expected_packets;
260     expected_packets.push_back(packets[i]);
261 
262     auto res = adapter_->ProcessTransportFeedback(*feedback.get(),
263                                                   clock_.CurrentTime());
264     ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
265   }
266 }
267 
TEST_F(TransportFeedbackAdapterTest,HandlesArrivalReordering)268 TEST_F(TransportFeedbackAdapterTest, HandlesArrivalReordering) {
269   std::vector<PacketResult> packets;
270   packets.push_back(CreatePacket(120, 200, 0, 1500, kPacingInfo0));
271   packets.push_back(CreatePacket(110, 210, 1, 1500, kPacingInfo0));
272   packets.push_back(CreatePacket(100, 220, 2, 1500, kPacingInfo0));
273 
274   for (const auto& packet : packets)
275     OnSentPacket(packet);
276 
277   rtcp::TransportFeedback feedback;
278   feedback.SetBase(packets[0].sent_packet.sequence_number,
279                    packets[0].receive_time.us());
280 
281   for (const auto& packet : packets) {
282     EXPECT_TRUE(feedback.AddReceivedPacket(packet.sent_packet.sequence_number,
283                                            packet.receive_time.us()));
284   }
285 
286   feedback.Build();
287 
288   // Adapter keeps the packets ordered by sequence number (which is itself
289   // assigned by the order of transmission). Reordering by some other criteria,
290   // eg. arrival time, is up to the observers.
291   auto res = adapter_->ProcessTransportFeedback(feedback, clock_.CurrentTime());
292   ComparePacketFeedbackVectors(packets, res->packet_feedbacks);
293 }
294 
TEST_F(TransportFeedbackAdapterTest,TimestampDeltas)295 TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) {
296   std::vector<PacketResult> sent_packets;
297   // TODO(srte): Consider using us resolution in the constants.
298   const TimeDelta kSmallDelta =
299       TimeDelta::Micros(rtcp::TransportFeedback::kDeltaScaleFactor * 0xFF)
300           .RoundDownTo(TimeDelta::Millis(1));
301   const TimeDelta kLargePositiveDelta =
302       TimeDelta::Micros(rtcp::TransportFeedback::kDeltaScaleFactor *
303                         std::numeric_limits<int16_t>::max())
304           .RoundDownTo(TimeDelta::Millis(1));
305   const TimeDelta kLargeNegativeDelta =
306       TimeDelta::Micros(rtcp::TransportFeedback::kDeltaScaleFactor *
307                         std::numeric_limits<int16_t>::min())
308           .RoundDownTo(TimeDelta::Millis(1));
309 
310   PacketResult packet_feedback;
311   packet_feedback.sent_packet.sequence_number = 1;
312   packet_feedback.sent_packet.send_time = Timestamp::Millis(100);
313   packet_feedback.receive_time = Timestamp::Millis(200);
314   packet_feedback.sent_packet.size = DataSize::Bytes(1500);
315   sent_packets.push_back(packet_feedback);
316 
317   // TODO(srte): This rounding maintains previous behavior, but should ot be
318   // required.
319   packet_feedback.sent_packet.send_time += kSmallDelta;
320   packet_feedback.receive_time += kSmallDelta;
321   ++packet_feedback.sent_packet.sequence_number;
322   sent_packets.push_back(packet_feedback);
323 
324   packet_feedback.sent_packet.send_time += kLargePositiveDelta;
325   packet_feedback.receive_time += kLargePositiveDelta;
326   ++packet_feedback.sent_packet.sequence_number;
327   sent_packets.push_back(packet_feedback);
328 
329   packet_feedback.sent_packet.send_time += kLargeNegativeDelta;
330   packet_feedback.receive_time += kLargeNegativeDelta;
331   ++packet_feedback.sent_packet.sequence_number;
332   sent_packets.push_back(packet_feedback);
333 
334   // Too large, delta - will need two feedback messages.
335   packet_feedback.sent_packet.send_time +=
336       kLargePositiveDelta + TimeDelta::Millis(1);
337   packet_feedback.receive_time += kLargePositiveDelta + TimeDelta::Millis(1);
338   ++packet_feedback.sent_packet.sequence_number;
339 
340   // Packets will be added to send history.
341   for (const auto& packet : sent_packets)
342     OnSentPacket(packet);
343   OnSentPacket(packet_feedback);
344 
345   // Create expected feedback and send into adapter.
346   std::unique_ptr<rtcp::TransportFeedback> feedback(
347       new rtcp::TransportFeedback());
348   feedback->SetBase(sent_packets[0].sent_packet.sequence_number,
349                     sent_packets[0].receive_time.us());
350 
351   for (const auto& packet : sent_packets) {
352     EXPECT_TRUE(feedback->AddReceivedPacket(packet.sent_packet.sequence_number,
353                                             packet.receive_time.us()));
354   }
355   EXPECT_FALSE(
356       feedback->AddReceivedPacket(packet_feedback.sent_packet.sequence_number,
357                                   packet_feedback.receive_time.us()));
358 
359   rtc::Buffer raw_packet = feedback->Build();
360   feedback =
361       rtcp::TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
362 
363   std::vector<PacketResult> received_feedback;
364 
365   EXPECT_TRUE(feedback.get() != nullptr);
366   auto res =
367       adapter_->ProcessTransportFeedback(*feedback.get(), clock_.CurrentTime());
368   ComparePacketFeedbackVectors(sent_packets, res->packet_feedbacks);
369 
370   // Create a new feedback message and add the trailing item.
371   feedback.reset(new rtcp::TransportFeedback());
372   feedback->SetBase(packet_feedback.sent_packet.sequence_number,
373                     packet_feedback.receive_time.us());
374   EXPECT_TRUE(
375       feedback->AddReceivedPacket(packet_feedback.sent_packet.sequence_number,
376                                   packet_feedback.receive_time.us()));
377   raw_packet = feedback->Build();
378   feedback =
379       rtcp::TransportFeedback::ParseFrom(raw_packet.data(), raw_packet.size());
380 
381   EXPECT_TRUE(feedback.get() != nullptr);
382   {
383     auto res = adapter_->ProcessTransportFeedback(*feedback.get(),
384                                                   clock_.CurrentTime());
385     std::vector<PacketResult> expected_packets;
386     expected_packets.push_back(packet_feedback);
387     ComparePacketFeedbackVectors(expected_packets, res->packet_feedbacks);
388   }
389 }
390 
TEST_F(TransportFeedbackAdapterTest,IgnoreDuplicatePacketSentCalls)391 TEST_F(TransportFeedbackAdapterTest, IgnoreDuplicatePacketSentCalls) {
392   auto packet = CreatePacket(100, 200, 0, 1500, kPacingInfo0);
393 
394   // Add a packet and then mark it as sent.
395   RtpPacketSendInfo packet_info;
396   packet_info.ssrc = kSsrc;
397   packet_info.transport_sequence_number = packet.sent_packet.sequence_number;
398   packet_info.length = packet.sent_packet.size.bytes();
399   packet_info.pacing_info = packet.sent_packet.pacing_info;
400   packet_info.packet_type = RtpPacketMediaType::kVideo;
401   adapter_->AddPacket(packet_info, 0u, clock_.CurrentTime());
402   absl::optional<SentPacket> sent_packet = adapter_->ProcessSentPacket(
403       rtc::SentPacket(packet.sent_packet.sequence_number,
404                       packet.sent_packet.send_time.ms(), rtc::PacketInfo()));
405   EXPECT_TRUE(sent_packet.has_value());
406 
407   // Call ProcessSentPacket() again with the same sequence number. This packet
408   // has already been marked as sent and the call should be ignored.
409   absl::optional<SentPacket> duplicate_packet = adapter_->ProcessSentPacket(
410       rtc::SentPacket(packet.sent_packet.sequence_number,
411                       packet.sent_packet.send_time.ms(), rtc::PacketInfo()));
412   EXPECT_FALSE(duplicate_packet.has_value());
413 }
414 
415 }  // namespace test
416 }  // namespace webrtc_cc
417 }  // namespace webrtc
418