1 /*
2 * Copyright 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 <memory>
12
13 #include "absl/algorithm/container.h"
14 #include "api/task_queue/task_queue_base.h"
15 #include "api/test/simulated_network.h"
16 #include "api/test/video/function_video_encoder_factory.h"
17 #include "call/fake_network_pipe.h"
18 #include "call/simulated_network.h"
19 #include "modules/rtp_rtcp/source/rtp_packet.h"
20 #include "modules/video_coding/codecs/vp8/include/vp8.h"
21 #include "rtc_base/event.h"
22 #include "rtc_base/synchronization/mutex.h"
23 #include "rtc_base/task_queue_for_test.h"
24 #include "test/call_test.h"
25 #include "test/field_trial.h"
26 #include "test/gtest.h"
27 #include "test/rtcp_packet_parser.h"
28
29 namespace webrtc {
30 namespace {
31 enum : int { // The first valid value is 1.
32 kVideoRotationExtensionId = 1,
33 };
34 } // namespace
35
36 class RetransmissionEndToEndTest : public test::CallTest {
37 public:
RetransmissionEndToEndTest()38 RetransmissionEndToEndTest() {
39 RegisterRtpExtension(RtpExtension(RtpExtension::kVideoRotationUri,
40 kVideoRotationExtensionId));
41 }
42
43 protected:
44 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
45 void ReceivesPliAndRecovers(int rtp_history_ms);
46 };
47
TEST_F(RetransmissionEndToEndTest,ReceivesAndRetransmitsNack)48 TEST_F(RetransmissionEndToEndTest, ReceivesAndRetransmitsNack) {
49 static const int kNumberOfNacksToObserve = 2;
50 static const int kLossBurstSize = 2;
51 static const int kPacketsBetweenLossBursts = 9;
52 class NackObserver : public test::EndToEndTest {
53 public:
54 NackObserver()
55 : EndToEndTest(kLongTimeoutMs),
56 sent_rtp_packets_(0),
57 packets_left_to_drop_(0),
58 nacks_left_(kNumberOfNacksToObserve) {}
59
60 private:
61 Action OnSendRtp(const uint8_t* packet, size_t length) override {
62 MutexLock lock(&mutex_);
63 RtpPacket rtp_packet;
64 EXPECT_TRUE(rtp_packet.Parse(packet, length));
65
66 // Never drop retransmitted packets.
67 if (dropped_packets_.find(rtp_packet.SequenceNumber()) !=
68 dropped_packets_.end()) {
69 retransmitted_packets_.insert(rtp_packet.SequenceNumber());
70 return SEND_PACKET;
71 }
72
73 if (nacks_left_ <= 0 &&
74 retransmitted_packets_.size() == dropped_packets_.size()) {
75 observation_complete_.Set();
76 }
77
78 ++sent_rtp_packets_;
79
80 // Enough NACKs received, stop dropping packets.
81 if (nacks_left_ <= 0)
82 return SEND_PACKET;
83
84 // Check if it's time for a new loss burst.
85 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
86 packets_left_to_drop_ = kLossBurstSize;
87
88 // Never drop padding packets as those won't be retransmitted.
89 if (packets_left_to_drop_ > 0 && rtp_packet.padding_size() == 0) {
90 --packets_left_to_drop_;
91 dropped_packets_.insert(rtp_packet.SequenceNumber());
92 return DROP_PACKET;
93 }
94
95 return SEND_PACKET;
96 }
97
98 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
99 MutexLock lock(&mutex_);
100 test::RtcpPacketParser parser;
101 EXPECT_TRUE(parser.Parse(packet, length));
102 nacks_left_ -= parser.nack()->num_packets();
103 return SEND_PACKET;
104 }
105
106 void ModifyVideoConfigs(
107 VideoSendStream::Config* send_config,
108 std::vector<VideoReceiveStream::Config>* receive_configs,
109 VideoEncoderConfig* encoder_config) override {
110 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
111 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
112 }
113
114 void PerformTest() override {
115 EXPECT_TRUE(Wait())
116 << "Timed out waiting for packets to be NACKed, retransmitted and "
117 "rendered.";
118 }
119
120 Mutex mutex_;
121 std::set<uint16_t> dropped_packets_;
122 std::set<uint16_t> retransmitted_packets_;
123 uint64_t sent_rtp_packets_;
124 int packets_left_to_drop_;
125 int nacks_left_ RTC_GUARDED_BY(&mutex_);
126 } test;
127
128 RunBaseTest(&test);
129 }
130
TEST_F(RetransmissionEndToEndTest,ReceivesNackAndRetransmitsAudio)131 TEST_F(RetransmissionEndToEndTest, ReceivesNackAndRetransmitsAudio) {
132 class NackObserver : public test::EndToEndTest {
133 public:
134 NackObserver()
135 : EndToEndTest(kLongTimeoutMs),
136 local_ssrc_(0),
137 remote_ssrc_(0),
138 receive_transport_(nullptr) {}
139
140 private:
141 size_t GetNumVideoStreams() const override { return 0; }
142 size_t GetNumAudioStreams() const override { return 1; }
143
144 std::unique_ptr<test::PacketTransport> CreateReceiveTransport(
145 TaskQueueBase* task_queue) override {
146 auto receive_transport = std::make_unique<test::PacketTransport>(
147 task_queue, nullptr, this, test::PacketTransport::kReceiver,
148 payload_type_map_,
149 std::make_unique<FakeNetworkPipe>(
150 Clock::GetRealTimeClock(), std::make_unique<SimulatedNetwork>(
151 BuiltInNetworkBehaviorConfig())));
152 receive_transport_ = receive_transport.get();
153 return receive_transport;
154 }
155
156 Action OnSendRtp(const uint8_t* packet, size_t length) override {
157 RtpPacket rtp_packet;
158 EXPECT_TRUE(rtp_packet.Parse(packet, length));
159
160 if (!sequence_number_to_retransmit_) {
161 sequence_number_to_retransmit_ = rtp_packet.SequenceNumber();
162
163 // Don't ask for retransmission straight away, may be deduped in pacer.
164 } else if (rtp_packet.SequenceNumber() ==
165 *sequence_number_to_retransmit_) {
166 observation_complete_.Set();
167 } else {
168 // Send a NACK as often as necessary until retransmission is received.
169 rtcp::Nack nack;
170 nack.SetSenderSsrc(local_ssrc_);
171 nack.SetMediaSsrc(remote_ssrc_);
172 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
173 nack.SetPacketIds(nack_list, 1);
174 rtc::Buffer buffer = nack.Build();
175
176 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
177 }
178
179 return SEND_PACKET;
180 }
181
182 void ModifyAudioConfigs(
183 AudioSendStream::Config* send_config,
184 std::vector<AudioReceiveStream::Config>* receive_configs) override {
185 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
186 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
187 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
188 }
189
190 void PerformTest() override {
191 EXPECT_TRUE(Wait())
192 << "Timed out waiting for packets to be NACKed, retransmitted and "
193 "rendered.";
194 }
195
196 uint32_t local_ssrc_;
197 uint32_t remote_ssrc_;
198 Transport* receive_transport_;
199 absl::optional<uint16_t> sequence_number_to_retransmit_;
200 } test;
201
202 RunBaseTest(&test);
203 }
204
TEST_F(RetransmissionEndToEndTest,StopSendingKeyframeRequestsForInactiveStream)205 TEST_F(RetransmissionEndToEndTest,
206 StopSendingKeyframeRequestsForInactiveStream) {
207 class KeyframeRequestObserver : public test::EndToEndTest, public QueuedTask {
208 public:
209 explicit KeyframeRequestObserver(TaskQueueBase* task_queue)
210 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
211
212 void OnVideoStreamsCreated(
213 VideoSendStream* send_stream,
214 const std::vector<VideoReceiveStream*>& receive_streams) override {
215 RTC_DCHECK_EQ(1, receive_streams.size());
216 send_stream_ = send_stream;
217 receive_stream_ = receive_streams[0];
218 }
219
220 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
221 test::RtcpPacketParser parser;
222 EXPECT_TRUE(parser.Parse(packet, length));
223 if (parser.pli()->num_packets() > 0)
224 task_queue_->PostTask(std::unique_ptr<QueuedTask>(this));
225 return SEND_PACKET;
226 }
227
228 bool PollStats() {
229 if (receive_stream_->GetStats().frames_decoded > 0) {
230 frame_decoded_ = true;
231 } else if (clock_->TimeInMilliseconds() - start_time_ < 5000) {
232 task_queue_->PostDelayedTask(std::unique_ptr<QueuedTask>(this), 100);
233 return false;
234 }
235 return true;
236 }
237
238 void PerformTest() override {
239 start_time_ = clock_->TimeInMilliseconds();
240 task_queue_->PostTask(std::unique_ptr<QueuedTask>(this));
241 test_done_.Wait(rtc::Event::kForever);
242 }
243
244 bool Run() override {
245 if (!frame_decoded_) {
246 if (PollStats()) {
247 send_stream_->Stop();
248 if (!frame_decoded_) {
249 test_done_.Set();
250 } else {
251 // Now we wait for the PLI packet. Once we receive it, a task
252 // will be posted (see OnReceiveRtcp) and we'll check the stats
253 // once more before signaling that we're done.
254 }
255 }
256 } else {
257 EXPECT_EQ(
258 1U,
259 receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
260 test_done_.Set();
261 }
262 return false;
263 }
264
265 private:
266 Clock* const clock_;
267 VideoSendStream* send_stream_;
268 VideoReceiveStream* receive_stream_;
269 TaskQueueBase* const task_queue_;
270 rtc::Event test_done_;
271 bool frame_decoded_ = false;
272 int64_t start_time_ = 0;
273 } test(task_queue());
274
275 RunBaseTest(&test);
276 }
277
ReceivesPliAndRecovers(int rtp_history_ms)278 void RetransmissionEndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
279 static const int kPacketsToDrop = 1;
280
281 class PliObserver : public test::EndToEndTest,
282 public rtc::VideoSinkInterface<VideoFrame> {
283 public:
284 explicit PliObserver(int rtp_history_ms)
285 : EndToEndTest(kLongTimeoutMs),
286 rtp_history_ms_(rtp_history_ms),
287 nack_enabled_(rtp_history_ms > 0),
288 highest_dropped_timestamp_(0),
289 frames_to_drop_(0),
290 received_pli_(false) {}
291
292 private:
293 Action OnSendRtp(const uint8_t* packet, size_t length) override {
294 MutexLock lock(&mutex_);
295 RtpPacket rtp_packet;
296 EXPECT_TRUE(rtp_packet.Parse(packet, length));
297
298 // Drop all retransmitted packets to force a PLI.
299 if (rtp_packet.Timestamp() <= highest_dropped_timestamp_)
300 return DROP_PACKET;
301
302 if (frames_to_drop_ > 0) {
303 highest_dropped_timestamp_ = rtp_packet.Timestamp();
304 --frames_to_drop_;
305 return DROP_PACKET;
306 }
307
308 return SEND_PACKET;
309 }
310
311 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
312 MutexLock lock(&mutex_);
313 test::RtcpPacketParser parser;
314 EXPECT_TRUE(parser.Parse(packet, length));
315 if (!nack_enabled_)
316 EXPECT_EQ(0, parser.nack()->num_packets());
317 if (parser.pli()->num_packets() > 0)
318 received_pli_ = true;
319 return SEND_PACKET;
320 }
321
322 void OnFrame(const VideoFrame& video_frame) override {
323 MutexLock lock(&mutex_);
324 if (received_pli_ &&
325 video_frame.timestamp() > highest_dropped_timestamp_) {
326 observation_complete_.Set();
327 }
328 if (!received_pli_)
329 frames_to_drop_ = kPacketsToDrop;
330 }
331
332 void ModifyVideoConfigs(
333 VideoSendStream::Config* send_config,
334 std::vector<VideoReceiveStream::Config>* receive_configs,
335 VideoEncoderConfig* encoder_config) override {
336 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
337 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
338 (*receive_configs)[0].renderer = this;
339 }
340
341 void PerformTest() override {
342 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
343 "received and a frame to be "
344 "rendered afterwards.";
345 }
346
347 Mutex mutex_;
348 int rtp_history_ms_;
349 bool nack_enabled_;
350 uint32_t highest_dropped_timestamp_ RTC_GUARDED_BY(&mutex_);
351 int frames_to_drop_ RTC_GUARDED_BY(&mutex_);
352 bool received_pli_ RTC_GUARDED_BY(&mutex_);
353 } test(rtp_history_ms);
354
355 RunBaseTest(&test);
356 }
357
TEST_F(RetransmissionEndToEndTest,ReceivesPliAndRecoversWithNack)358 TEST_F(RetransmissionEndToEndTest, ReceivesPliAndRecoversWithNack) {
359 ReceivesPliAndRecovers(1000);
360 }
361
TEST_F(RetransmissionEndToEndTest,ReceivesPliAndRecoversWithoutNack)362 TEST_F(RetransmissionEndToEndTest, ReceivesPliAndRecoversWithoutNack) {
363 ReceivesPliAndRecovers(0);
364 }
365
366 // This test drops second RTP packet with a marker bit set, makes sure it's
367 // retransmitted and renders. Retransmission SSRCs are also checked.
DecodesRetransmittedFrame(bool enable_rtx,bool enable_red)368 void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx,
369 bool enable_red) {
370 static const int kDroppedFrameNumber = 10;
371 class RetransmissionObserver : public test::EndToEndTest,
372 public rtc::VideoSinkInterface<VideoFrame> {
373 public:
374 RetransmissionObserver(bool enable_rtx, bool enable_red)
375 : EndToEndTest(kDefaultTimeoutMs),
376 payload_type_(GetPayloadType(false, enable_red)),
377 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
378 : kVideoSendSsrcs[0]),
379 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
380 encoder_factory_([]() { return VP8Encoder::Create(); }),
381 marker_bits_observed_(0),
382 retransmitted_timestamp_(0) {}
383
384 private:
385 Action OnSendRtp(const uint8_t* packet, size_t length) override {
386 MutexLock lock(&mutex_);
387 RtpPacket rtp_packet;
388 EXPECT_TRUE(rtp_packet.Parse(packet, length));
389
390 // Ignore padding-only packets over RTX.
391 if (rtp_packet.PayloadType() != payload_type_) {
392 EXPECT_EQ(retransmission_ssrc_, rtp_packet.Ssrc());
393 if (rtp_packet.payload_size() == 0)
394 return SEND_PACKET;
395 }
396
397 if (rtp_packet.Timestamp() == retransmitted_timestamp_) {
398 EXPECT_EQ(retransmission_ssrc_, rtp_packet.Ssrc());
399 EXPECT_EQ(retransmission_payload_type_, rtp_packet.PayloadType());
400 return SEND_PACKET;
401 }
402
403 // Found the final packet of the frame to inflict loss to, drop this and
404 // expect a retransmission.
405 if (rtp_packet.PayloadType() == payload_type_ && rtp_packet.Marker() &&
406 ++marker_bits_observed_ == kDroppedFrameNumber) {
407 // This should be the only dropped packet.
408 EXPECT_EQ(0u, retransmitted_timestamp_);
409 retransmitted_timestamp_ = rtp_packet.Timestamp();
410 if (absl::c_linear_search(rendered_timestamps_,
411 retransmitted_timestamp_)) {
412 // Frame was rendered before last packet was scheduled for sending.
413 // This is extremly rare but possible scenario because prober able to
414 // resend packet before it was send.
415 // TODO(danilchap): Remove this corner case when prober would not be
416 // able to sneak in between packet saved to history for resending and
417 // pacer notified about existance of that packet for sending.
418 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
419 // details.
420 observation_complete_.Set();
421 }
422 return DROP_PACKET;
423 }
424
425 return SEND_PACKET;
426 }
427
428 void OnFrame(const VideoFrame& frame) override {
429 EXPECT_EQ(kVideoRotation_90, frame.rotation());
430 {
431 MutexLock lock(&mutex_);
432 if (frame.timestamp() == retransmitted_timestamp_)
433 observation_complete_.Set();
434 rendered_timestamps_.push_back(frame.timestamp());
435 }
436 orig_renderer_->OnFrame(frame);
437 }
438
439 void ModifyVideoConfigs(
440 VideoSendStream::Config* send_config,
441 std::vector<VideoReceiveStream::Config>* receive_configs,
442 VideoEncoderConfig* encoder_config) override {
443 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
444
445 // Insert ourselves into the rendering pipeline.
446 RTC_DCHECK(!orig_renderer_);
447 orig_renderer_ = (*receive_configs)[0].renderer;
448 RTC_DCHECK(orig_renderer_);
449 // To avoid post-decode frame dropping, disable the prerender buffer.
450 (*receive_configs)[0].enable_prerenderer_smoothing = false;
451 (*receive_configs)[0].renderer = this;
452
453 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
454
455 if (payload_type_ == kRedPayloadType) {
456 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
457 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
458 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
459 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
460 (*receive_configs)[0].rtp.ulpfec_payload_type =
461 send_config->rtp.ulpfec.ulpfec_payload_type;
462 (*receive_configs)[0].rtp.red_payload_type =
463 send_config->rtp.ulpfec.red_payload_type;
464 }
465
466 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
467 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
468 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
469 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
470 (*receive_configs)[0]
471 .rtp.rtx_associated_payload_types[(payload_type_ == kRedPayloadType)
472 ? kRtxRedPayloadType
473 : kSendRtxPayloadType] =
474 payload_type_;
475 }
476 // Configure encoding and decoding with VP8, since generic packetization
477 // doesn't support FEC with NACK.
478 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
479 send_config->encoder_settings.encoder_factory = &encoder_factory_;
480 send_config->rtp.payload_name = "VP8";
481 encoder_config->codec_type = kVideoCodecVP8;
482 (*receive_configs)[0].decoders[0].video_format = SdpVideoFormat("VP8");
483 }
484
485 void OnFrameGeneratorCapturerCreated(
486 test::FrameGeneratorCapturer* frame_generator_capturer) override {
487 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
488 }
489
490 void PerformTest() override {
491 EXPECT_TRUE(Wait())
492 << "Timed out while waiting for retransmission to render.";
493 }
494
495 int GetPayloadType(bool use_rtx, bool use_fec) {
496 if (use_fec) {
497 if (use_rtx)
498 return kRtxRedPayloadType;
499 return kRedPayloadType;
500 }
501 if (use_rtx)
502 return kSendRtxPayloadType;
503 return kFakeVideoSendPayloadType;
504 }
505
506 Mutex mutex_;
507 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
508 const int payload_type_;
509 const uint32_t retransmission_ssrc_;
510 const int retransmission_payload_type_;
511 test::FunctionVideoEncoderFactory encoder_factory_;
512 const std::string payload_name_;
513 int marker_bits_observed_;
514 uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&mutex_);
515 std::vector<uint32_t> rendered_timestamps_ RTC_GUARDED_BY(&mutex_);
516 } test(enable_rtx, enable_red);
517
518 RunBaseTest(&test);
519 }
520
TEST_F(RetransmissionEndToEndTest,DecodesRetransmittedFrame)521 TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrame) {
522 DecodesRetransmittedFrame(false, false);
523 }
524
TEST_F(RetransmissionEndToEndTest,DecodesRetransmittedFrameOverRtx)525 TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrameOverRtx) {
526 DecodesRetransmittedFrame(true, false);
527 }
528
TEST_F(RetransmissionEndToEndTest,DecodesRetransmittedFrameByRed)529 TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrameByRed) {
530 DecodesRetransmittedFrame(false, true);
531 }
532
TEST_F(RetransmissionEndToEndTest,DecodesRetransmittedFrameByRedOverRtx)533 TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
534 DecodesRetransmittedFrame(true, true);
535 }
536
537 } // namespace webrtc
538