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