blob: dbe3f0c82302ddc8ec630594b611591a78a9ca93 [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"
Markus Handellf4f22872022-08-16 11:02:4514#include "api/units/time_delta.h"
Artem Titovdd2eebe2018-08-20 11:27:4515#include "call/call.h"
16#include "call/fake_network_pipe.h"
17#include "call/simulated_network.h"
Danil Chapovalov7c067772019-10-07 10:56:2418#include "modules/include/module_common_types_public.h"
Jonas Olssona4d87372019-07-05 17:08:3319#include "modules/rtp_rtcp/source/byte_io.h"
Danil Chapovalovc3475852019-12-05 12:51:3220#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
21#include "modules/rtp_rtcp/source/rtp_packet.h"
Markus Handell9bbff072020-07-07 12:23:1822#include "rtc_base/synchronization/mutex.h"
Sebastian Janssonc5017132018-02-02 15:24:1623#include "test/call_test.h"
24#include "test/field_trial.h"
25#include "test/gtest.h"
Sebastian Janssonc5017132018-02-02 15:24:1626#include "test/rtcp_packet_parser.h"
27#include "video/end_to_end_tests/multi_stream_tester.h"
28
29namespace webrtc {
Elad Alond8d32482019-02-18 22:45:5730namespace {
31enum : int { // The first valid value is 1.
32 kTransportSequenceNumberExtensionId = 1,
33};
34} // namespace
Sebastian Janssonc5017132018-02-02 15:24:1635
Danil Chapovalov1242d9c2019-11-08 15:17:4136TEST(TransportFeedbackMultiStreamTest, AssignsTransportSequenceNumbers) {
37 static constexpr int kSendRtxPayloadType = 98;
Markus Handell2cfc1af2022-08-19 08:16:4838 static constexpr TimeDelta kDefaultTimeout = TimeDelta::Seconds(30);
Danil Chapovalov1242d9c2019-11-08 15:17:4139 static constexpr int kNackRtpHistoryMs = 1000;
40 static constexpr uint32_t kSendRtxSsrcs[MultiStreamTester::kNumStreams] = {
41 0xBADCAFD, 0xBADCAFE, 0xBADCAFF};
Sebastian Janssonc5017132018-02-02 15:24:1642
Sebastian Janssonc5017132018-02-02 15:24:1643 class RtpExtensionHeaderObserver : public test::DirectTransport {
44 public:
45 RtpExtensionHeaderObserver(
Danil Chapovalov44db4362019-09-30 02:16:2846 TaskQueueBase* task_queue,
Sebastian Janssonc5017132018-02-02 15:24:1647 Call* sender_call,
Sebastian Janssonc5017132018-02-02 15:24:1648 const std::map<uint32_t, uint32_t>& ssrc_map,
49 const std::map<uint8_t, MediaType>& payload_type_map)
Artem Titovdd2eebe2018-08-20 11:27:4550 : DirectTransport(task_queue,
Mirko Bonadei317a1f02019-09-17 15:06:1851 std::make_unique<FakeNetworkPipe>(
Artem Titovdd2eebe2018-08-20 11:27:4552 Clock::GetRealTimeClock(),
Mirko Bonadei317a1f02019-09-17 15:06:1853 std::make_unique<SimulatedNetwork>(
Artem Titov75e36472018-10-08 10:28:5654 BuiltInNetworkBehaviorConfig())),
Artem Titovdd2eebe2018-08-20 11:27:4555 sender_call,
56 payload_type_map),
Sebastian Janssonc5017132018-02-02 15:24:1657 rtx_to_media_ssrcs_(ssrc_map),
Sebastian Janssonc5017132018-02-02 15:24:1658 rtx_padding_observed_(false),
59 retransmit_observed_(false),
60 started_(false) {
Danil Chapovalovc3475852019-12-05 12:51:3261 extensions_.Register<TransportSequenceNumber>(
62 kTransportSequenceNumberExtensionId);
Sebastian Janssonc5017132018-02-02 15:24:1663 }
64 virtual ~RtpExtensionHeaderObserver() {}
65
66 bool SendRtp(const uint8_t* data,
67 size_t length,
68 const PacketOptions& options) override {
69 {
Markus Handell9bbff072020-07-07 12:23:1870 MutexLock lock(&lock_);
Sebastian Janssonc5017132018-02-02 15:24:1671
72 if (IsDone())
73 return false;
74
75 if (started_) {
Danil Chapovalovc3475852019-12-05 12:51:3276 RtpPacket rtp_packet(&extensions_);
77 EXPECT_TRUE(rtp_packet.Parse(data, length));
Sebastian Janssonc5017132018-02-02 15:24:1678 bool drop_packet = false;
79
Danil Chapovalovc3475852019-12-05 12:51:3280 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);
Sebastian Janssonc5017132018-02-02 15:24:1684 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.
Danil Chapovalov0f6bf752019-12-13 17:05:0991 // Only drop media, do not drop padding packets.
Danil Chapovalovc3475852019-12-05 12:51:3292 if (rtp_packet.PayloadType() != kSendRtxPayloadType &&
Danil Chapovalov0f6bf752019-12-13 17:05:0993 rtp_packet.payload_size() > 0 &&
Danil Chapovalovc3475852019-12-05 12:51:3294 transport_sequence_number % 17 == 0) {
95 dropped_seq_[rtp_packet.Ssrc()].insert(rtp_packet.SequenceNumber());
Sebastian Janssonc5017132018-02-02 15:24:1696 drop_packet = true;
97 }
98
Danil Chapovalov0f6bf752019-12-13 17:05:0999 if (rtp_packet.payload_size() == 0) {
100 // Ignore padding packets.
101 } else if (rtp_packet.PayloadType() == kSendRtxPayloadType) {
Sebastian Janssonc5017132018-02-02 15:24:16102 uint16_t original_sequence_number =
Danil Chapovalovc3475852019-12-05 12:51:32103 ByteReader<uint16_t>::ReadBigEndian(
104 rtp_packet.payload().data());
Sebastian Janssonc5017132018-02-02 15:24:16105 uint32_t original_ssrc =
Danil Chapovalovc3475852019-12-05 12:51:32106 rtx_to_media_ssrcs_.find(rtp_packet.Ssrc())->second;
Sebastian Janssonc5017132018-02-02 15:24:16107 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 {
Danil Chapovalovc3475852019-12-05 12:51:32116 streams_observed_.insert(rtp_packet.Ssrc());
Sebastian Janssonc5017132018-02-02 15:24:16117 }
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.
Markus Handell9bbff072020-07-07 12:23:18146 MutexLock lock(&lock_);
Sebastian Janssonc5017132018-02-02 15:24:16147 started_ = true;
148 }
Markus Handell2cfc1af2022-08-19 08:16:48149 return done_.Wait(kDefaultTimeout);
Sebastian Janssonc5017132018-02-02 15:24:16150 }
151
Danil Chapovalov1242d9c2019-11-08 15:17:41152 private:
Markus Handell9bbff072020-07-07 12:23:18153 Mutex lock_;
Sebastian Janssonc5017132018-02-02 15:24:16154 rtc::Event done_;
Danil Chapovalovc3475852019-12-05 12:51:32155 RtpHeaderExtensionMap extensions_;
Sebastian Janssonc5017132018-02-02 15:24:16156 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_;
Sebastian Janssonc5017132018-02-02 15:24:16160 const std::map<uint32_t, uint32_t>& rtx_to_media_ssrcs_;
Sebastian Janssonc5017132018-02-02 15:24:16161 bool rtx_padding_observed_;
162 bool retransmit_observed_;
163 bool started_;
164 };
165
166 class TransportSequenceNumberTester : public MultiStreamTester {
167 public:
Danil Chapovalov0f6bf752019-12-13 17:05:09168 TransportSequenceNumberTester() : observer_(nullptr) {}
Danil Chapovalov1242d9c2019-11-08 15:17:41169 ~TransportSequenceNumberTester() override = default;
Sebastian Janssonc5017132018-02-02 15:24:16170
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();
Elad Alond8d32482019-02-18 22:45:57183 send_config->rtp.extensions.push_back(
184 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
185 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16186
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];
Sebastian Janssonc5017132018-02-02 15:24:16201 }
202
203 void UpdateReceiveConfig(
204 size_t stream_index,
Tommif6f45432022-05-20 13:21:20205 VideoReceiveStreamInterface::Config* receive_config) override {
Sebastian Janssonc5017132018-02-02 15:24:16206 receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
207 receive_config->rtp.extensions.clear();
Elad Alond8d32482019-02-18 22:45:57208 receive_config->rtp.extensions.push_back(
209 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
210 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16211 receive_config->renderer = &fake_renderer_;
212 }
213
Danil Chapovalov44db4362019-09-30 02:16:28214 std::unique_ptr<test::DirectTransport> CreateSendTransport(
215 TaskQueueBase* task_queue,
Sebastian Janssonc5017132018-02-02 15:24:16216 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;
Danil Chapovalov44db4362019-09-30 02:16:28222 auto observer = std::make_unique<RtpExtensionHeaderObserver>(
Danil Chapovalov0f6bf752019-12-13 17:05:09223 task_queue, sender_call, rtx_to_media_ssrcs_, payload_type_map);
Danil Chapovalov44db4362019-09-30 02:16:28224 observer_ = observer.get();
225 return observer;
Sebastian Janssonc5017132018-02-02 15:24:16226 }
227
228 private:
229 test::FakeVideoRenderer fake_renderer_;
Sebastian Janssonc5017132018-02-02 15:24:16230 std::map<uint32_t, uint32_t> rtx_to_media_ssrcs_;
231 RtpExtensionHeaderObserver* observer_;
Danil Chapovalov1242d9c2019-11-08 15:17:41232 } tester;
Sebastian Janssonc5017132018-02-02 15:24:16233
234 tester.RunTest();
235}
236
Danil Chapovalov1242d9c2019-11-08 15:17:41237class TransportFeedbackEndToEndTest : public test::CallTest {
238 public:
239 TransportFeedbackEndToEndTest() {
240 RegisterRtpExtension(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
241 kTransportSequenceNumberExtensionId));
242 }
243};
244
Sebastian Janssonc5017132018-02-02 15:24:16245class TransportFeedbackTester : public test::EndToEndTest {
246 public:
Per K92532402023-01-02 15:57:18247 TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
Markus Handellf4f22872022-08-16 11:02:45248 : EndToEndTest(::webrtc::TransportFeedbackEndToEndTest::kDefaultTimeout),
Sebastian Janssonc5017132018-02-02 15:24:16249 num_video_streams_(num_video_streams),
250 num_audio_streams_(num_audio_streams),
251 receiver_call_(nullptr) {
252 // Only one stream of each supported for now.
253 EXPECT_LE(num_video_streams, 1u);
254 EXPECT_LE(num_audio_streams, 1u);
255 }
256
257 protected:
258 Action OnSendRtcp(const uint8_t* data, size_t length) override {
259 EXPECT_FALSE(HasTransportFeedback(data, length));
260 return SEND_PACKET;
261 }
262
263 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
264 if (HasTransportFeedback(data, length))
265 observation_complete_.Set();
266 return SEND_PACKET;
267 }
268
269 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
270 test::RtcpPacketParser parser;
271 EXPECT_TRUE(parser.Parse(data, length));
272 return parser.transport_feedback()->num_packets() > 0;
273 }
274
275 void PerformTest() override {
Per K92532402023-01-02 15:57:18276 EXPECT_TRUE(observation_complete_.Wait(test::CallTest::kDefaultTimeout));
Sebastian Janssonc5017132018-02-02 15:24:16277 }
278
279 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
280 receiver_call_ = receiver_call;
281 }
282
283 size_t GetNumVideoStreams() const override { return num_video_streams_; }
284 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
285
Tommi3176ef72022-05-22 18:47:28286 void ModifyAudioConfigs(AudioSendStream::Config* send_config,
287 std::vector<AudioReceiveStreamInterface::Config>*
288 receive_configs) override {
Sebastian Janssonc5017132018-02-02 15:24:16289 send_config->rtp.extensions.clear();
290 send_config->rtp.extensions.push_back(
Elad Alond8d32482019-02-18 22:45:57291 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
292 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16293 (*receive_configs)[0].rtp.extensions.clear();
294 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
Sebastian Janssonc5017132018-02-02 15:24:16295 }
296
297 private:
Sebastian Janssonc5017132018-02-02 15:24:16298 const size_t num_video_streams_;
299 const size_t num_audio_streams_;
300 Call* receiver_call_;
301};
302
Sebastian Jansson63470292019-02-01 09:13:43303TEST_F(TransportFeedbackEndToEndTest, VideoReceivesTransportFeedback) {
Per K92532402023-01-02 15:57:18304 TransportFeedbackTester test(1, 0);
Sebastian Janssonc5017132018-02-02 15:24:16305 RunBaseTest(&test);
306}
Sebastian Jansson63470292019-02-01 09:13:43307TEST_F(TransportFeedbackEndToEndTest, AudioReceivesTransportFeedback) {
Per K92532402023-01-02 15:57:18308 TransportFeedbackTester test(0, 1);
Sebastian Janssonc5017132018-02-02 15:24:16309 RunBaseTest(&test);
310}
311
Sebastian Jansson63470292019-02-01 09:13:43312TEST_F(TransportFeedbackEndToEndTest, AudioVideoReceivesTransportFeedback) {
Per K92532402023-01-02 15:57:18313 TransportFeedbackTester test(1, 1);
Sebastian Janssonc5017132018-02-02 15:24:16314 RunBaseTest(&test);
315}
316
Sebastian Jansson63470292019-02-01 09:13:43317TEST_F(TransportFeedbackEndToEndTest,
Sebastian Janssonb0acec32018-02-07 11:04:47318 StopsAndResumesMediaWhenCongestionWindowFull) {
Sebastian Janssonc5017132018-02-02 15:24:16319 test::ScopedFieldTrials override_field_trials(
Evan Shrubsoleae68ea02019-04-09 07:59:00320 "WebRTC-CongestionWindow/QueueSize:250/");
Sebastian Janssonc5017132018-02-02 15:24:16321
322 class TransportFeedbackTester : public test::EndToEndTest {
323 public:
324 TransportFeedbackTester(size_t num_video_streams, size_t num_audio_streams)
325 : EndToEndTest(
Markus Handellf4f22872022-08-16 11:02:45326 ::webrtc::TransportFeedbackEndToEndTest::kDefaultTimeout),
Sebastian Janssonc5017132018-02-02 15:24:16327 num_video_streams_(num_video_streams),
328 num_audio_streams_(num_audio_streams),
329 media_sent_(0),
Sebastian Janssonb0acec32018-02-07 11:04:47330 media_sent_before_(0),
Sebastian Janssonc5017132018-02-02 15:24:16331 padding_sent_(0) {
332 // Only one stream of each supported for now.
333 EXPECT_LE(num_video_streams, 1u);
334 EXPECT_LE(num_audio_streams, 1u);
335 }
336
337 protected:
338 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Danil Chapovalovc3475852019-12-05 12:51:32339 RtpPacket rtp_packet;
340 EXPECT_TRUE(rtp_packet.Parse(packet, length));
341 const bool only_padding = rtp_packet.payload_size() == 0;
Markus Handell9bbff072020-07-07 12:23:18342 MutexLock lock(&mutex_);
Sebastian Janssonb0acec32018-02-07 11:04:47343 // Padding is expected in congested state to probe for connectivity when
344 // packets has been dropped.
Sebastian Janssonc5017132018-02-02 15:24:16345 if (only_padding) {
Sebastian Janssonb0acec32018-02-07 11:04:47346 media_sent_before_ = media_sent_;
Sebastian Janssonc5017132018-02-02 15:24:16347 ++padding_sent_;
348 } else {
349 ++media_sent_;
Sebastian Janssonb0acec32018-02-07 11:04:47350 if (padding_sent_ == 0) {
351 ++media_sent_before_;
352 EXPECT_LT(media_sent_, 40)
353 << "Media sent without feedback when congestion window is full.";
Sebastian Jansson416332b2018-02-21 12:35:01354 } else if (media_sent_ > media_sent_before_) {
355 observation_complete_.Set();
Sebastian Janssonb0acec32018-02-07 11:04:47356 }
Sebastian Janssonc5017132018-02-02 15:24:16357 }
Sebastian Janssonc5017132018-02-02 15:24:16358 return SEND_PACKET;
359 }
360
361 Action OnReceiveRtcp(const uint8_t* data, size_t length) override {
Markus Handell9bbff072020-07-07 12:23:18362 MutexLock lock(&mutex_);
Sebastian Janssonb0acec32018-02-07 11:04:47363 // To fill up the congestion window we drop feedback on packets after 20
364 // packets have been sent. This means that any packets that has not yet
365 // received feedback after that will be considered as oustanding data and
366 // therefore filling up the congestion window. In the congested state, the
367 // pacer should send padding packets to trigger feedback in case all
368 // feedback of previous traffic was lost. This test listens for the
Sebastian Jansson416332b2018-02-21 12:35:01369 // padding packets and when 2 padding packets have been received, feedback
Sebastian Janssonb0acec32018-02-07 11:04:47370 // will be let trough again. This should cause the pacer to continue
371 // sending meadia yet again.
372 if (media_sent_ > 20 && HasTransportFeedback(data, length) &&
Sebastian Jansson416332b2018-02-21 12:35:01373 padding_sent_ < 2) {
Sebastian Janssonc5017132018-02-02 15:24:16374 return DROP_PACKET;
375 }
376 return SEND_PACKET;
377 }
378
379 bool HasTransportFeedback(const uint8_t* data, size_t length) const {
380 test::RtcpPacketParser parser;
381 EXPECT_TRUE(parser.Parse(data, length));
382 return parser.transport_feedback()->num_packets() > 0;
383 }
Niels Möllerde8e6e62018-11-13 14:10:33384 void ModifySenderBitrateConfig(
385 BitrateConstraints* bitrate_config) override {
386 bitrate_config->max_bitrate_bps = 300000;
Sebastian Janssonc5017132018-02-02 15:24:16387 }
388
389 void PerformTest() override {
Markus Handell2cfc1af2022-08-19 08:16:48390 constexpr TimeDelta kFailureTimeout = TimeDelta::Seconds(10);
391 EXPECT_TRUE(observation_complete_.Wait(kFailureTimeout))
Sebastian Jansson416332b2018-02-21 12:35:01392 << "Stream not continued after congestion window full.";
Sebastian Janssonc5017132018-02-02 15:24:16393 }
394
395 size_t GetNumVideoStreams() const override { return num_video_streams_; }
396 size_t GetNumAudioStreams() const override { return num_audio_streams_; }
397
398 private:
399 const size_t num_video_streams_;
400 const size_t num_audio_streams_;
Markus Handell9bbff072020-07-07 12:23:18401 Mutex mutex_;
402 int media_sent_ RTC_GUARDED_BY(mutex_);
403 int media_sent_before_ RTC_GUARDED_BY(mutex_);
404 int padding_sent_ RTC_GUARDED_BY(mutex_);
Sebastian Janssonc5017132018-02-02 15:24:16405 } test(1, 0);
406 RunBaseTest(&test);
407}
408
Sebastian Jansson63470292019-02-01 09:13:43409TEST_F(TransportFeedbackEndToEndTest, TransportSeqNumOnAudioAndVideo) {
Sebastian Janssonc5017132018-02-02 15:24:16410 static constexpr size_t kMinPacketsToWaitFor = 50;
411 class TransportSequenceNumberTest : public test::EndToEndTest {
412 public:
413 TransportSequenceNumberTest()
Markus Handellf4f22872022-08-16 11:02:45414 : EndToEndTest(kDefaultTimeout),
Sebastian Janssonc5017132018-02-02 15:24:16415 video_observed_(false),
416 audio_observed_(false) {
Danil Chapovalovc3475852019-12-05 12:51:32417 extensions_.Register<TransportSequenceNumber>(
418 kTransportSequenceNumberExtensionId);
Sebastian Janssonc5017132018-02-02 15:24:16419 }
420
421 size_t GetNumVideoStreams() const override { return 1; }
422 size_t GetNumAudioStreams() const override { return 1; }
423
Tommi3176ef72022-05-22 18:47:28424 void ModifyAudioConfigs(AudioSendStream::Config* send_config,
425 std::vector<AudioReceiveStreamInterface::Config>*
426 receive_configs) override {
Sebastian Janssonc5017132018-02-02 15:24:16427 send_config->rtp.extensions.clear();
Elad Alond8d32482019-02-18 22:45:57428 send_config->rtp.extensions.push_back(
429 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
430 kTransportSequenceNumberExtensionId));
Sebastian Janssonc5017132018-02-02 15:24:16431 (*receive_configs)[0].rtp.extensions.clear();
432 (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
433 }
434
435 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Danil Chapovalovc3475852019-12-05 12:51:32436 RtpPacket rtp_packet(&extensions_);
437 EXPECT_TRUE(rtp_packet.Parse(packet, length));
438 uint16_t transport_sequence_number = 0;
439 EXPECT_TRUE(rtp_packet.GetExtension<TransportSequenceNumber>(
440 &transport_sequence_number));
Sebastian Janssonc5017132018-02-02 15:24:16441 // Unwrap packet id and verify uniqueness.
Danil Chapovalovc3475852019-12-05 12:51:32442 int64_t packet_id = unwrapper_.Unwrap(transport_sequence_number);
Sebastian Janssonc5017132018-02-02 15:24:16443 EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
444
Danil Chapovalovc3475852019-12-05 12:51:32445 if (rtp_packet.Ssrc() == kVideoSendSsrcs[0])
Sebastian Janssonc5017132018-02-02 15:24:16446 video_observed_ = true;
Danil Chapovalovc3475852019-12-05 12:51:32447 if (rtp_packet.Ssrc() == kAudioSendSsrc)
Sebastian Janssonc5017132018-02-02 15:24:16448 audio_observed_ = true;
449 if (audio_observed_ && video_observed_ &&
450 received_packet_ids_.size() >= kMinPacketsToWaitFor) {
451 size_t packet_id_range =
452 *received_packet_ids_.rbegin() - *received_packet_ids_.begin() + 1;
453 EXPECT_EQ(received_packet_ids_.size(), packet_id_range);
454 observation_complete_.Set();
455 }
456 return SEND_PACKET;
457 }
458
459 void PerformTest() override {
460 EXPECT_TRUE(Wait()) << "Timed out while waiting for audio and video "
461 "packets with transport sequence number.";
462 }
463
464 void ExpectSuccessful() {
465 EXPECT_TRUE(video_observed_);
466 EXPECT_TRUE(audio_observed_);
467 EXPECT_GE(received_packet_ids_.size(), kMinPacketsToWaitFor);
468 }
469
470 private:
471 bool video_observed_;
472 bool audio_observed_;
473 SequenceNumberUnwrapper unwrapper_;
474 std::set<int64_t> received_packet_ids_;
Danil Chapovalovc3475852019-12-05 12:51:32475 RtpHeaderExtensionMap extensions_;
Sebastian Janssonc5017132018-02-02 15:24:16476 } test;
477
478 RunBaseTest(&test);
479 // Double check conditions for successful test to produce better error
480 // message when the test fail.
481 test.ExpectSuccessful();
482}
483} // namespace webrtc