• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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