• 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 "api/task_queue/task_queue_base.h"
14 #include "api/units/time_delta.h"
15 #include "call/call.h"
16 #include "call/fake_network_pipe.h"
17 #include "call/simulated_network.h"
18 #include "modules/include/module_common_types_public.h"
19 #include "modules/rtp_rtcp/source/byte_io.h"
20 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
21 #include "modules/rtp_rtcp/source/rtp_packet.h"
22 #include "rtc_base/synchronization/mutex.h"
23 #include "test/call_test.h"
24 #include "test/field_trial.h"
25 #include "test/gtest.h"
26 #include "test/rtcp_packet_parser.h"
27 #include "video/end_to_end_tests/multi_stream_tester.h"
28 
29 namespace webrtc {
30 namespace {
31 enum : int {  // The first valid value is 1.
32   kTransportSequenceNumberExtensionId = 1,
33 };
34 }  // namespace
35 
TEST(TransportFeedbackMultiStreamTest,AssignsTransportSequenceNumbers)36 TEST(TransportFeedbackMultiStreamTest, AssignsTransportSequenceNumbers) {
37   static constexpr int kSendRtxPayloadType = 98;
38   static constexpr TimeDelta kDefaultTimeout = TimeDelta::Seconds(30);
39   static constexpr int kNackRtpHistoryMs = 1000;
40   static constexpr uint32_t kSendRtxSsrcs[MultiStreamTester::kNumStreams] = {
41       0xBADCAFD, 0xBADCAFE, 0xBADCAFF};
42 
43   class RtpExtensionHeaderObserver : public test::DirectTransport {
44    public:
45     RtpExtensionHeaderObserver(
46         TaskQueueBase* task_queue,
47         Call* sender_call,
48         const std::map<uint32_t, uint32_t>& ssrc_map,
49         const std::map<uint8_t, MediaType>& payload_type_map)
50         : DirectTransport(task_queue,
51                           std::make_unique<FakeNetworkPipe>(
52                               Clock::GetRealTimeClock(),
53                               std::make_unique<SimulatedNetwork>(
54                                   BuiltInNetworkBehaviorConfig())),
55                           sender_call,
56                           payload_type_map),
57           rtx_to_media_ssrcs_(ssrc_map),
58           rtx_padding_observed_(false),
59           retransmit_observed_(false),
60           started_(false) {
61       extensions_.Register<TransportSequenceNumber>(
62           kTransportSequenceNumberExtensionId);
63     }
64     virtual ~RtpExtensionHeaderObserver() {}
65 
66     bool SendRtp(const uint8_t* data,
67                  size_t length,
68                  const PacketOptions& options) override {
69       {
70         MutexLock lock(&lock_);
71 
72         if (IsDone())
73           return false;
74 
75         if (started_) {
76           RtpPacket rtp_packet(&extensions_);
77           EXPECT_TRUE(rtp_packet.Parse(data, length));
78           bool drop_packet = false;
79 
80           uint16_t transport_sequence_number = 0;
81           EXPECT_TRUE(rtp_packet.GetExtension<TransportSequenceNumber>(
82               &transport_sequence_number));
83           EXPECT_EQ(options.packet_id, transport_sequence_number);
84           if (!streams_observed_.empty()) {
85             // Unwrap packet id and verify uniqueness.
86             int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
87             EXPECT_TRUE(received_packed_ids_.insert(packet_id).second);
88           }
89 
90           // Drop (up to) every 17th packet, so we get retransmits.
91           // Only drop media, do not drop padding packets.
92           if (rtp_packet.PayloadType() != kSendRtxPayloadType &&
93               rtp_packet.payload_size() > 0 &&
94               transport_sequence_number % 17 == 0) {
95             dropped_seq_[rtp_packet.Ssrc()].insert(rtp_packet.SequenceNumber());
96             drop_packet = true;
97           }
98 
99           if (rtp_packet.payload_size() == 0) {
100             // Ignore padding packets.
101           } else if (rtp_packet.PayloadType() == kSendRtxPayloadType) {
102             uint16_t original_sequence_number =
103                 ByteReader<uint16_t>::ReadBigEndian(
104                     rtp_packet.payload().data());
105             uint32_t original_ssrc =
106                 rtx_to_media_ssrcs_.find(rtp_packet.Ssrc())->second;
107             std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
108             auto it = seq_no_map->find(original_sequence_number);
109             if (it != seq_no_map->end()) {
110               retransmit_observed_ = true;
111               seq_no_map->erase(it);
112             } else {
113               rtx_padding_observed_ = true;
114             }
115           } else {
116             streams_observed_.insert(rtp_packet.Ssrc());
117           }
118 
119           if (IsDone())
120             done_.Set();
121 
122           if (drop_packet)
123             return true;
124         }
125       }
126 
127       return test::DirectTransport::SendRtp(data, length, options);
128     }
129 
130     bool IsDone() {
131       bool observed_types_ok =
132           streams_observed_.size() == MultiStreamTester::kNumStreams &&
133           retransmit_observed_ && rtx_padding_observed_;
134       if (!observed_types_ok)
135         return false;
136       // We should not have any gaps in the sequence number range.
137       size_t seqno_range =
138           *received_packed_ids_.rbegin() - *received_packed_ids_.begin() + 1;
139       return seqno_range == received_packed_ids_.size();
140     }
141 
142     bool Wait() {
143       {
144         // Can't be sure until this point that rtx_to_media_ssrcs_ etc have
145         // been initialized and are OK to read.
146         MutexLock lock(&lock_);
147         started_ = true;
148       }
149       return done_.Wait(kDefaultTimeout);
150     }
151 
152    private:
153     Mutex lock_;
154     rtc::Event done_;
155     RtpHeaderExtensionMap extensions_;
156     SequenceNumberUnwrapper unwrapper_;
157     std::set<int64_t> received_packed_ids_;
158     std::set<uint32_t> streams_observed_;
159     std::map<uint32_t, std::set<uint16_t>> dropped_seq_;
160     const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
161     bool rtx_padding_observed_;
162     bool retransmit_observed_;
163     bool started_;
164   };
165 
166   class TransportSequenceNumberTester : public MultiStreamTester {
167    public:
168     TransportSequenceNumberTester() : observer_(nullptr) {}
169     ~TransportSequenceNumberTester() override = default;
170 
171    protected:
172     void Wait() override {
173       RTC_DCHECK(observer_);
174       EXPECT_TRUE(observer_->Wait());
175     }
176 
177     void UpdateSendConfig(
178         size_t stream_index,
179         VideoSendStream::Config* send_config,
180         VideoEncoderConfig* encoder_config,
181         test::FrameGeneratorCapturer** frame_generator) override {
182       send_config->rtp.extensions.clear();
183       send_config->rtp.extensions.push_back(
184           RtpExtension(RtpExtension::kTransportSequenceNumberUri,
185                        kTransportSequenceNumberExtensionId));
186 
187       // Force some padding to be sent. Note that since we do send media
188       // packets we can not guarantee that a padding only packet is sent.
189       // Instead, padding will most likely be send as an RTX packet.
190       const int kPaddingBitrateBps = 50000;
191       encoder_config->max_bitrate_bps = 200000;
192       encoder_config->min_transmit_bitrate_bps =
193           encoder_config->max_bitrate_bps + kPaddingBitrateBps;
194 
195       // Configure RTX for redundant payload padding.
196       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
197       send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[stream_index]);
198       send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
199       rtx_to_media_ssrcs_[kSendRtxSsrcs[stream_index]] =
200           send_config->rtp.ssrcs[0];
201     }
202 
203     void UpdateReceiveConfig(
204         size_t stream_index,
205         VideoReceiveStreamInterface::Config* receive_config) override {
206       receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
207       receive_config->rtp.extensions.clear();
208       receive_config->rtp.extensions.push_back(
209           RtpExtension(RtpExtension::kTransportSequenceNumberUri,
210                        kTransportSequenceNumberExtensionId));
211       receive_config->renderer = &fake_renderer_;
212     }
213 
214     std::unique_ptr<test::DirectTransport> CreateSendTransport(
215         TaskQueueBase* task_queue,
216         Call* sender_call) override {
217       std::map<uint8_t, MediaType> payload_type_map =
218           MultiStreamTester::payload_type_map_;
219       RTC_DCHECK(payload_type_map.find(kSendRtxPayloadType) ==
220                  payload_type_map.end());
221       payload_type_map[kSendRtxPayloadType] = MediaType::VIDEO;
222       auto observer = std::make_unique<RtpExtensionHeaderObserver>(
223           task_queue, sender_call, rtx_to_media_ssrcs_, payload_type_map);
224       observer_ = observer.get();
225       return observer;
226     }
227 
228    private:
229     test::FakeVideoRenderer fake_renderer_;
230     std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
231     RtpExtensionHeaderObserver* observer_;
232   } tester;
233 
234   tester.RunTest();
235 }
236 
237 class TransportFeedbackEndToEndTest : public test::CallTest {
238  public:
TransportFeedbackEndToEndTest()239   TransportFeedbackEndToEndTest() {
240     RegisterRtpExtension(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
241                                       kTransportSequenceNumberExtensionId));
242   }
243 };
244 
245 class TransportFeedbackTester : public test::EndToEndTest {
246  public:
TransportFeedbackTester(bool feedback_enabled,size_t num_video_streams,size_t num_audio_streams)247   TransportFeedbackTester(bool feedback_enabled,
248                           size_t num_video_streams,
249                           size_t num_audio_streams)
250       : EndToEndTest(::webrtc::TransportFeedbackEndToEndTest::kDefaultTimeout),
251         feedback_enabled_(feedback_enabled),
252         num_video_streams_(num_video_streams),
253         num_audio_streams_(num_audio_streams),
254         receiver_call_(nullptr) {
255     // Only one stream of each supported for now.
256     EXPECT_LE(num_video_streams, 1u);
257     EXPECT_LE(num_audio_streams, 1u);
258   }
259 
260  protected:
OnSendRtcp(const uint8_t * data,size_t length)261   Action OnSendRtcp(const uint8_t* data, size_t length) override {
262     EXPECT_FALSE(HasTransportFeedback(data, length));
263     return SEND_PACKET;
264   }
265 
OnReceiveRtcp(const uint8_t * data,size_t length)266   Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
267     if (HasTransportFeedback(data, length))
268       observation_complete_.Set();
269     return SEND_PACKET;
270   }
271 
HasTransportFeedback(const uint8_t * data,size_t length) const272   bool HasTransportFeedback(const uint8_t* data, size_t length) const {
273     test::RtcpPacketParser parser;
274     EXPECT_TRUE(parser.Parse(data, length));
275     return parser.transport_feedback()->num_packets() > 0;
276   }
277 
PerformTest()278   void PerformTest() override {
279     constexpr TimeDelta kDisabledFeedbackTimeout = TimeDelta::Seconds(5);
280     EXPECT_EQ(feedback_enabled_,
281               observation_complete_.Wait(feedback_enabled_
282                                              ? test::CallTest::kDefaultTimeout
283                                              : kDisabledFeedbackTimeout));
284   }
285 
OnCallsCreated(Call * sender_call,Call * receiver_call)286   void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
287     receiver_call_ = receiver_call;
288   }
289 
GetNumVideoStreams() const290   size_t GetNumVideoStreams() const override { return num_video_streams_; }
GetNumAudioStreams() const291   size_t GetNumAudioStreams() const override { return num_audio_streams_; }
292 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)293   void ModifyVideoConfigs(
294       VideoSendStream::Config* send_config,
295       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
296       VideoEncoderConfig* encoder_config) override {
297     (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
298   }
299 
ModifyAudioConfigs(AudioSendStream::Config * send_config,std::vector<AudioReceiveStreamInterface::Config> * receive_configs)300   void ModifyAudioConfigs(AudioSendStream::Config* send_config,
301                           std::vector<AudioReceiveStreamInterface::Config>*
302                               receive_configs) override {
303     send_config->rtp.extensions.clear();
304     send_config->rtp.extensions.push_back(
305         RtpExtension(RtpExtension::kTransportSequenceNumberUri,
306                      kTransportSequenceNumberExtensionId));
307     (*receive_configs)[0].rtp.extensions.clear();
308     (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
309     (*receive_configs)[0].rtp.transport_cc = feedback_enabled_;
310   }
311 
312  private:
313   const bool feedback_enabled_;
314   const size_t num_video_streams_;
315   const size_t num_audio_streams_;
316   Call* receiver_call_;
317 };
318 
TEST_F(TransportFeedbackEndToEndTest,VideoReceivesTransportFeedback)319 TEST_F(TransportFeedbackEndToEndTest, VideoReceivesTransportFeedback) {
320   TransportFeedbackTester test(true, 1, 0);
321   RunBaseTest(&test);
322 }
323 
TEST_F(TransportFeedbackEndToEndTest,VideoTransportFeedbackNotConfigured)324 TEST_F(TransportFeedbackEndToEndTest, VideoTransportFeedbackNotConfigured) {
325   TransportFeedbackTester test(false, 1, 0);
326   RunBaseTest(&test);
327 }
328 
TEST_F(TransportFeedbackEndToEndTest,AudioReceivesTransportFeedback)329 TEST_F(TransportFeedbackEndToEndTest, AudioReceivesTransportFeedback) {
330   TransportFeedbackTester test(true, 0, 1);
331   RunBaseTest(&test);
332 }
333 
TEST_F(TransportFeedbackEndToEndTest,AudioTransportFeedbackNotConfigured)334 TEST_F(TransportFeedbackEndToEndTest, AudioTransportFeedbackNotConfigured) {
335   TransportFeedbackTester test(false, 0, 1);
336   RunBaseTest(&test);
337 }
338 
TEST_F(TransportFeedbackEndToEndTest,AudioVideoReceivesTransportFeedback)339 TEST_F(TransportFeedbackEndToEndTest, AudioVideoReceivesTransportFeedback) {
340   TransportFeedbackTester test(true, 1, 1);
341   RunBaseTest(&test);
342 }
343 
TEST_F(TransportFeedbackEndToEndTest,StopsAndResumesMediaWhenCongestionWindowFull)344 TEST_F(TransportFeedbackEndToEndTest,
345        StopsAndResumesMediaWhenCongestionWindowFull) {
346   test::ScopedFieldTrials override_field_trials(
347       "WebRTC-CongestionWindow/QueueSize:250/");
348 
349   class TransportFeedbackTester : public test::EndToEndTest {
350    public:
351     TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
352         : EndToEndTest(
353               ::webrtc::TransportFeedbackEndToEndTest::kDefaultTimeout),
354           num_video_streams_(num_video_streams),
355           num_audio_streams_(num_audio_streams),
356           media_sent_(0),
357           media_sent_before_(0),
358           padding_sent_(0) {
359       // Only one stream of each supported for now.
360       EXPECT_LE(num_video_streams, 1u);
361       EXPECT_LE(num_audio_streams, 1u);
362     }
363 
364    protected:
365     Action OnSendRtp(const uint8_t* packet, size_t length) override {
366       RtpPacket rtp_packet;
367       EXPECT_TRUE(rtp_packet.Parse(packet, length));
368       const bool only_padding = rtp_packet.payload_size() == 0;
369       MutexLock lock(&mutex_);
370       // Padding is expected in congested state to probe for connectivity when
371       // packets has been dropped.
372       if (only_padding) {
373         media_sent_before_ = media_sent_;
374         ++padding_sent_;
375       } else {
376         ++media_sent_;
377         if (padding_sent_ == 0) {
378           ++media_sent_before_;
379           EXPECT_LT(media_sent_, 40)
380               << "Media sent without feedback when congestion window is full.";
381         } else if (media_sent_ > media_sent_before_) {
382           observation_complete_.Set();
383         }
384       }
385       return SEND_PACKET;
386     }
387 
388     Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
389       MutexLock lock(&mutex_);
390       // To fill up the congestion window we drop feedback on packets after 20
391       // packets have been sent. This means that any packets that has not yet
392       // received feedback after that will be considered as oustanding data and
393       // therefore filling up the congestion window. In the congested state, the
394       // pacer should send padding packets to trigger feedback in case all
395       // feedback of previous traffic was lost. This test listens for the
396       // padding packets and when 2 padding packets have been received, feedback
397       // will be let trough again. This should cause the pacer to continue
398       // sending meadia yet again.
399       if (media_sent_ > 20 && HasTransportFeedback(data, length) &&
400           padding_sent_ < 2) {
401         return DROP_PACKET;
402       }
403       return SEND_PACKET;
404     }
405 
406     bool HasTransportFeedback(const uint8_t* data, size_t length) const {
407       test::RtcpPacketParser parser;
408       EXPECT_TRUE(parser.Parse(data, length));
409       return parser.transport_feedback()->num_packets() > 0;
410     }
411     void ModifySenderBitrateConfig(
412         BitrateConstraints* bitrate_config) override {
413       bitrate_config->max_bitrate_bps = 300000;
414     }
415 
416     void PerformTest() override {
417       constexpr TimeDelta kFailureTimeout = TimeDelta::Seconds(10);
418       EXPECT_TRUE(observation_complete_.Wait(kFailureTimeout))
419           << "Stream not continued after congestion window full.";
420     }
421 
422     size_t GetNumVideoStreams() const override { return num_video_streams_; }
423     size_t GetNumAudioStreams() const override { return num_audio_streams_; }
424 
425    private:
426     const size_t num_video_streams_;
427     const size_t num_audio_streams_;
428     Mutex mutex_;
429     int media_sent_ RTC_GUARDED_BY(mutex_);
430     int media_sent_before_ RTC_GUARDED_BY(mutex_);
431     int padding_sent_ RTC_GUARDED_BY(mutex_);
432   } test(1, 0);
433   RunBaseTest(&test);
434 }
435 
TEST_F(TransportFeedbackEndToEndTest,TransportSeqNumOnAudioAndVideo)436 TEST_F(TransportFeedbackEndToEndTest, TransportSeqNumOnAudioAndVideo) {
437   static constexpr size_t kMinPacketsToWaitFor = 50;
438   class TransportSequenceNumberTest : public test::EndToEndTest {
439    public:
440     TransportSequenceNumberTest()
441         : EndToEndTest(kDefaultTimeout),
442           video_observed_(false),
443           audio_observed_(false) {
444       extensions_.Register<TransportSequenceNumber>(
445           kTransportSequenceNumberExtensionId);
446     }
447 
448     size_t GetNumVideoStreams() const override { return 1; }
449     size_t GetNumAudioStreams() const override { return 1; }
450 
451     void ModifyAudioConfigs(AudioSendStream::Config* send_config,
452                             std::vector<AudioReceiveStreamInterface::Config>*
453                                 receive_configs) override {
454       send_config->rtp.extensions.clear();
455       send_config->rtp.extensions.push_back(
456           RtpExtension(RtpExtension::kTransportSequenceNumberUri,
457                        kTransportSequenceNumberExtensionId));
458       (*receive_configs)[0].rtp.extensions.clear();
459       (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
460     }
461 
462     Action OnSendRtp(const uint8_t* packet, size_t length) override {
463       RtpPacket rtp_packet(&extensions_);
464       EXPECT_TRUE(rtp_packet.Parse(packet, length));
465       uint16_t transport_sequence_number = 0;
466       EXPECT_TRUE(rtp_packet.GetExtension<TransportSequenceNumber>(
467           &transport_sequence_number));
468       // Unwrap packet id and verify uniqueness.
469       int64_t packet_id = unwrapper_.Unwrap(transport_sequence_number);
470       EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
471 
472       if (rtp_packet.Ssrc() == kVideoSendSsrcs[0])
473         video_observed_ = true;
474       if (rtp_packet.Ssrc() == kAudioSendSsrc)
475         audio_observed_ = true;
476       if (audio_observed_ && video_observed_ &&
477           received_packet_ids_.size() >= kMinPacketsToWaitFor) {
478         size_t packet_id_range =
479             *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
480         EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
481         observation_complete_.Set();
482       }
483       return SEND_PACKET;
484     }
485 
486     void PerformTest() override {
487       EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
488                              "packets with transport sequence number.";
489     }
490 
491     void ExpectSuccessful() {
492       EXPECT_TRUE(video_observed_);
493       EXPECT_TRUE(audio_observed_);
494       EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
495     }
496 
497    private:
498     bool video_observed_;
499     bool audio_observed_;
500     SequenceNumberUnwrapper unwrapper_;
501     std::set<int64_t> received_packet_ids_;
502     RtpHeaderExtensionMap extensions_;
503   } test;
504 
505   RunBaseTest(&test);
506   // Double check conditions for successful test to produce better error
507   // message when the test fail.
508   test.ExpectSuccessful();
509 }
510 }  // namespace webrtc
511