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