blob: a675d784bc44d8d9b3a14cd2f9342ff6e2a7a7ea [file] [log] [blame]
Sebastian Janssonc5017132018-02-02 15:24:161/*
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
Mirko Bonadei317a1f02019-09-17 15:06:1811#include <memory>
12
Danil Chapovalov44db4362019-09-30 02:16:2813#include "api/task_queue/task_queue_base.h"
Artem Titovdd2eebe2018-08-20 11:27:4514#include "call/call.h"
15#include "call/fake_network_pipe.h"
16#include "call/simulated_network.h"
Danil Chapovalov7c067772019-10-07 10:56:2417#include "modules/include/module_common_types_public.h"
Jonas Olssona4d87372019-07-05 17:08:3318#include "modules/rtp_rtcp/source/byte_io.h"
Danil Chapovalovc3475852019-12-05 12:51:3219#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
20#include "modules/rtp_rtcp/source/rtp_packet.h"
Markus Handell9bbff072020-07-07 12:23:1821#include "rtc_base/synchronization/mutex.h"
Sebastian Janssonc5017132018-02-02 15:24:1622#include "test/call_test.h"
23#include "test/field_trial.h"
24#include "test/gtest.h"
Sebastian Janssonc5017132018-02-02 15:24:1625#include "test/rtcp_packet_parser.h"
26#include "video/end_to_end_tests/multi_stream_tester.h"
27
28namespace webrtc {
Elad Alond8d32482019-02-18 22:45:5729namespace {
30enum : int { // The first valid value is 1.
31 kTransportSequenceNumberExtensionId = 1,
32};
33} // namespace
Sebastian Janssonc5017132018-02-02 15:24:1634
Danil Chapovalov1242d9c2019-11-08 15:17:4135TEST(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};
Sebastian Janssonc5017132018-02-02 15:24:1641
Sebastian Janssonc5017132018-02-02 15:24:1642 class RtpExtensionHeaderObserver : public test::DirectTransport {
43 public:
44 RtpExtensionHeaderObserver(
Danil Chapovalov44db4362019-09-30 02:16:2845 TaskQueueBase* task_queue,
Sebastian Janssonc5017132018-02-02 15:24:1646 Call* sender_call,
Sebastian Janssonc5017132018-02-02 15:24:1647 const std::map<uint32_t, uint32_t>& ssrc_map,
48 const std::map<uint8_t, MediaType>& payload_type_map)
Artem Titovdd2eebe2018-08-20 11:27:4549 : DirectTransport(task_queue,
Mirko Bonadei317a1f02019-09-17 15:06:1850 std::make_unique<FakeNetworkPipe>(
Artem Titovdd2eebe2018-08-20 11:27:4551 Clock::GetRealTimeClock(),
Mirko Bonadei317a1f02019-09-17 15:06:1852 std::make_unique<SimulatedNetwork>(
Artem Titov75e36472018-10-08 10:28:5653 BuiltInNetworkBehaviorConfig())),
Artem Titovdd2eebe2018-08-20 11:27:4554 sender_call,
55 payload_type_map),
Sebastian Janssonc5017132018-02-02 15:24:1656 rtx_to_media_ssrcs_(ssrc_map),
Sebastian Janssonc5017132018-02-02 15:24:1657 rtx_padding_observed_(false),
58 retransmit_observed_(false),
59 started_(false) {
Danil Chapovalovc3475852019-12-05 12:51:3260 extensions_.Register<TransportSequenceNumber>(
61 kTransportSequenceNumberExtensionId);
Sebastian Janssonc5017132018-02-02 15:24:1662 }
63 virtual ~RtpExtensionHeaderObserver() {}
64
65 bool SendRtp(const uint8_t* data,
66 size_t length,
67 const PacketOptions& options) override {
68 {
Markus Handell9bbff072020-07-07 12:23:1869 MutexLock lock(&lock_);
Sebastian Janssonc5017132018-02-02 15:24:1670
71 if (IsDone())
72 return false;
73
74 if (started_) {
Danil Chapovalovc3475852019-12-05 12:51:3275 RtpPacket rtp_packet(&extensions_);
76 EXPECT_TRUE(rtp_packet.Parse(data, length));
Sebastian Janssonc5017132018-02-02 15:24:1677 bool drop_packet = false;
78
Danil Chapovalovc3475852019-12-05 12:51:3279 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);
Sebastian Janssonc5017132018-02-02 15:24:1683 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.
Danil Chapovalov0f6bf752019-12-13 17:05:0990 // Only drop media, do not drop padding packets.
Danil Chapovalovc3475852019-12-05 12:51:3291 if (rtp_packet.PayloadType() != kSendRtxPayloadType &&
Danil Chapovalov0f6bf752019-12-13 17:05:0992 rtp_packet.payload_size() > 0 &&
Danil Chapovalovc3475852019-12-05 12:51:3293 transport_sequence_number % 17 == 0) {
94 dropped_seq_[rtp_packet.Ssrc()].insert(rtp_packet.SequenceNumber());
Sebastian Janssonc5017132018-02-02 15:24:1695 drop_packet = true;
96 }
97
Danil Chapovalov0f6bf752019-12-13 17:05:0998 if (rtp_packet.payload_size() == 0) {
99 // Ignore padding packets.
100 } else if (rtp_packet.PayloadType() == kSendRtxPayloadType) {
Sebastian Janssonc5017132018-02-02 15:24:16101 uint16_t original_sequence_number =
Danil Chapovalovc3475852019-12-05 12:51:32102 ByteReader<uint16_t>::ReadBigEndian(
103 rtp_packet.payload().data());
Sebastian Janssonc5017132018-02-02 15:24:16104 uint32_t original_ssrc =
Danil Chapovalovc3475852019-12-05 12:51:32105 rtx_to_media_ssrcs_.find(rtp_packet.Ssrc())->second;
Sebastian Janssonc5017132018-02-02 15:24:16106 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 {
Danil Chapovalovc3475852019-12-05 12:51:32115 streams_observed_.insert(rtp_packet.Ssrc());
Sebastian Janssonc5017132018-02-02 15:24:16116 }
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.
Markus Handell9bbff072020-07-07 12:23:18145 MutexLock lock(&lock_);
Sebastian Janssonc5017132018-02-02 15:24:16146 started_ = true;
147 }
148 return done_.Wait(kDefaultTimeoutMs);
149 }
150
Danil Chapovalov1242d9c2019-11-08 15:17:41151 private:
Markus Handell9bbff072020-07-07 12:23:18152 Mutex lock_;
Sebastian Janssonc5017132018-02-02 15:24:16153 rtc::Event done_;
Danil Chapovalovc3475852019-12-05 12:51:32154 RtpHeaderExtensionMap extensions_;
Sebastian Janssonc5017132018-02-02 15:24:16155 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_;
Sebastian Janssonc5017132018-02-02 15:24:16159 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
Sebastian Janssonc5017132018-02-02 15:24:16160 bool rtx_padding_observed_;
161 bool retransmit_observed_;
162 bool started_;
163 };
164
165 class TransportSequenceNumberTester : public MultiStreamTester {
166 public:
Danil Chapovalov0f6bf752019-12-13 17:05:09167 TransportSequenceNumberTester() : observer_(nullptr) {}
Danil Chapovalov1242d9c2019-11-08 15:17:41168 ~TransportSequenceNumberTester() override = default;
Sebastian Janssonc5017132018-02-02 15:24:16169
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();
Elad Alond8d32482019-02-18 22:45:57182 send_config->rtp.extensions.push_back(
183 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
184 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16185
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];
Sebastian Janssonc5017132018-02-02 15:24:16200 }
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();
Elad Alond8d32482019-02-18 22:45:57207 receive_config->rtp.extensions.push_back(
208 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
209 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16210 receive_config->renderer = &fake_renderer_;
211 }
212
Danil Chapovalov44db4362019-09-30 02:16:28213 std::unique_ptr<test::DirectTransport> CreateSendTransport(
214 TaskQueueBase* task_queue,
Sebastian Janssonc5017132018-02-02 15:24:16215 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;
Danil Chapovalov44db4362019-09-30 02:16:28221 auto observer = std::make_unique<RtpExtensionHeaderObserver>(
Danil Chapovalov0f6bf752019-12-13 17:05:09222 task_queue, sender_call, rtx_to_media_ssrcs_, payload_type_map);
Danil Chapovalov44db4362019-09-30 02:16:28223 observer_ = observer.get();
224 return observer;
Sebastian Janssonc5017132018-02-02 15:24:16225 }
226
227 private:
228 test::FakeVideoRenderer fake_renderer_;
Sebastian Janssonc5017132018-02-02 15:24:16229 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
230 RtpExtensionHeaderObserver* observer_;
Danil Chapovalov1242d9c2019-11-08 15:17:41231 } tester;
Sebastian Janssonc5017132018-02-02 15:24:16232
233 tester.RunTest();
234}
235
Danil Chapovalov1242d9c2019-11-08 15:17:41236class TransportFeedbackEndToEndTest : public test::CallTest {
237 public:
238 TransportFeedbackEndToEndTest() {
239 RegisterRtpExtension(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
240 kTransportSequenceNumberExtensionId));
241 }
242};
243
Sebastian Janssonc5017132018-02-02 15:24:16244class TransportFeedbackTester : public test::EndToEndTest {
245 public:
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:
261 Action OnSendRtcp(const uint8_t* data, size_t length) override {
262 EXPECT_FALSE(HasTransportFeedback(data, length));
263 return SEND_PACKET;
264 }
265
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
272 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
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
286 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
287 receiver_call_ = receiver_call;
288 }
289
290 size_t GetNumVideoStreams() const override { return num_video_streams_; }
291 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
292
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
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(
Elad Alond8d32482019-02-18 22:45:57305 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
306 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16307 (*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:
Sebastian Janssonc5017132018-02-02 15:24:16313 const bool feedback_enabled_;
314 const size_t num_video_streams_;
315 const size_t num_audio_streams_;
316 Call* receiver_call_;
317};
318
Sebastian Jansson63470292019-02-01 09:13:43319TEST_F(TransportFeedbackEndToEndTest, VideoReceivesTransportFeedback) {
Sebastian Janssonc5017132018-02-02 15:24:16320 TransportFeedbackTester test(true, 1, 0);
321 RunBaseTest(&test);
322}
323
Sebastian Jansson63470292019-02-01 09:13:43324TEST_F(TransportFeedbackEndToEndTest, VideoTransportFeedbackNotConfigured) {
Sebastian Janssonc5017132018-02-02 15:24:16325 TransportFeedbackTester test(false, 1, 0);
326 RunBaseTest(&test);
327}
328
Sebastian Jansson63470292019-02-01 09:13:43329TEST_F(TransportFeedbackEndToEndTest, AudioReceivesTransportFeedback) {
Sebastian Janssonc5017132018-02-02 15:24:16330 TransportFeedbackTester test(true, 0, 1);
331 RunBaseTest(&test);
332}
333
Sebastian Jansson63470292019-02-01 09:13:43334TEST_F(TransportFeedbackEndToEndTest, AudioTransportFeedbackNotConfigured) {
Sebastian Janssonc5017132018-02-02 15:24:16335 TransportFeedbackTester test(false, 0, 1);
336 RunBaseTest(&test);
337}
338
Sebastian Jansson63470292019-02-01 09:13:43339TEST_F(TransportFeedbackEndToEndTest, AudioVideoReceivesTransportFeedback) {
Sebastian Janssonc5017132018-02-02 15:24:16340 TransportFeedbackTester test(true, 1, 1);
341 RunBaseTest(&test);
342}
343
Sebastian Jansson63470292019-02-01 09:13:43344TEST_F(TransportFeedbackEndToEndTest,
Sebastian Janssonb0acec32018-02-07 11:04:47345 StopsAndResumesMediaWhenCongestionWindowFull) {
Sebastian Janssonc5017132018-02-02 15:24:16346 test::ScopedFieldTrials override_field_trials(
Evan Shrubsoleae68ea02019-04-09 07:59:00347 "WebRTC-CongestionWindow/QueueSize:250/");
Sebastian Janssonc5017132018-02-02 15:24:16348
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::kDefaultTimeoutMs),
354 num_video_streams_(num_video_streams),
355 num_audio_streams_(num_audio_streams),
356 media_sent_(0),
Sebastian Janssonb0acec32018-02-07 11:04:47357 media_sent_before_(0),
Sebastian Janssonc5017132018-02-02 15:24:16358 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 {
Danil Chapovalovc3475852019-12-05 12:51:32366 RtpPacket rtp_packet;
367 EXPECT_TRUE(rtp_packet.Parse(packet, length));
368 const bool only_padding = rtp_packet.payload_size() == 0;
Markus Handell9bbff072020-07-07 12:23:18369 MutexLock lock(&mutex_);
Sebastian Janssonb0acec32018-02-07 11:04:47370 // Padding is expected in congested state to probe for connectivity when
371 // packets has been dropped.
Sebastian Janssonc5017132018-02-02 15:24:16372 if (only_padding) {
Sebastian Janssonb0acec32018-02-07 11:04:47373 media_sent_before_ = media_sent_;
Sebastian Janssonc5017132018-02-02 15:24:16374 ++padding_sent_;
375 } else {
376 ++media_sent_;
Sebastian Janssonb0acec32018-02-07 11:04:47377 if (padding_sent_ == 0) {
378 ++media_sent_before_;
379 EXPECT_LT(media_sent_, 40)
380 << "Media sent without feedback when congestion window is full.";
Sebastian Jansson416332b2018-02-21 12:35:01381 } else if (media_sent_ > media_sent_before_) {
382 observation_complete_.Set();
Sebastian Janssonb0acec32018-02-07 11:04:47383 }
Sebastian Janssonc5017132018-02-02 15:24:16384 }
Sebastian Janssonc5017132018-02-02 15:24:16385 return SEND_PACKET;
386 }
387
388 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
Markus Handell9bbff072020-07-07 12:23:18389 MutexLock lock(&mutex_);
Sebastian Janssonb0acec32018-02-07 11:04:47390 // 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
Sebastian Jansson416332b2018-02-21 12:35:01396 // padding packets and when 2 padding packets have been received, feedback
Sebastian Janssonb0acec32018-02-07 11:04:47397 // 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) &&
Sebastian Jansson416332b2018-02-21 12:35:01400 padding_sent_ < 2) {
Sebastian Janssonc5017132018-02-02 15:24:16401 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 }
Niels Möllerde8e6e62018-11-13 14:10:33411 void ModifySenderBitrateConfig(
412 BitrateConstraints* bitrate_config) override {
413 bitrate_config->max_bitrate_bps = 300000;
Sebastian Janssonc5017132018-02-02 15:24:16414 }
415
416 void PerformTest() override {
Sebastian Jansson416332b2018-02-21 12:35:01417 const int64_t kFailureTimeoutMs = 10000;
418 EXPECT_TRUE(observation_complete_.Wait(kFailureTimeoutMs))
419 << "Stream not continued after congestion window full.";
Sebastian Janssonc5017132018-02-02 15:24:16420 }
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_;
Markus Handell9bbff072020-07-07 12:23:18428 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_);
Sebastian Janssonc5017132018-02-02 15:24:16432 } test(1, 0);
433 RunBaseTest(&test);
434}
435
Sebastian Jansson63470292019-02-01 09:13:43436TEST_F(TransportFeedbackEndToEndTest, TransportSeqNumOnAudioAndVideo) {
Sebastian Janssonc5017132018-02-02 15:24:16437 static constexpr size_t kMinPacketsToWaitFor = 50;
438 class TransportSequenceNumberTest : public test::EndToEndTest {
439 public:
440 TransportSequenceNumberTest()
441 : EndToEndTest(kDefaultTimeoutMs),
442 video_observed_(false),
443 audio_observed_(false) {
Danil Chapovalovc3475852019-12-05 12:51:32444 extensions_.Register<TransportSequenceNumber>(
445 kTransportSequenceNumberExtensionId);
Sebastian Janssonc5017132018-02-02 15:24:16446 }
447
448 size_t GetNumVideoStreams() const override { return 1; }
449 size_t GetNumAudioStreams() const override { return 1; }
450
451 void ModifyAudioConfigs(
452 AudioSendStream::Config* send_config,
453 std::vector<AudioReceiveStream::Config>* receive_configs) override {
454 send_config->rtp.extensions.clear();
Elad Alond8d32482019-02-18 22:45:57455 send_config->rtp.extensions.push_back(
456 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
457 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16458 (*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 {
Danil Chapovalovc3475852019-12-05 12:51:32463 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));
Sebastian Janssonc5017132018-02-02 15:24:16468 // Unwrap packet id and verify uniqueness.
Danil Chapovalovc3475852019-12-05 12:51:32469 int64_t packet_id = unwrapper_.Unwrap(transport_sequence_number);
Sebastian Janssonc5017132018-02-02 15:24:16470 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
471
Danil Chapovalovc3475852019-12-05 12:51:32472 if (rtp_packet.Ssrc() == kVideoSendSsrcs[0])
Sebastian Janssonc5017132018-02-02 15:24:16473 video_observed_ = true;
Danil Chapovalovc3475852019-12-05 12:51:32474 if (rtp_packet.Ssrc() == kAudioSendSsrc)
Sebastian Janssonc5017132018-02-02 15:24:16475 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_;
Danil Chapovalovc3475852019-12-05 12:51:32502 RtpHeaderExtensionMap extensions_;
Sebastian Janssonc5017132018-02-02 15:24:16503 } 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