blob: 73a5585e747191b2e385867abf27257475728ef1 [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
Artem Titov46c4e602018-08-17 12:26:5411#include "api/test/simulated_network.h"
Artem Titov4e199e92018-08-20 11:30:3912#include "call/fake_network_pipe.h"
13#include "call/simulated_network.h"
Sebastian Janssonc5017132018-02-02 15:24:1614#include "modules/video_coding/codecs/vp8/include/vp8.h"
15#include "system_wrappers/include/sleep.h"
16#include "test/call_test.h"
17#include "test/field_trial.h"
Niels Möller4db138e2018-04-19 07:04:1318#include "test/function_video_encoder_factory.h"
Sebastian Janssonc5017132018-02-02 15:24:1619#include "test/gtest.h"
20#include "test/rtcp_packet_parser.h"
21
22namespace webrtc {
Ilya Nikolaevskiycb960622018-09-04 09:07:3123class RetransmissionEndToEndTest : public test::CallTest {
Sebastian Janssonc5017132018-02-02 15:24:1624 public:
Ilya Nikolaevskiycb960622018-09-04 09:07:3125 RetransmissionEndToEndTest() = default;
Sebastian Janssonc5017132018-02-02 15:24:1626
Sebastian Janssonc5017132018-02-02 15:24:1627 protected:
28 void DecodesRetransmittedFrame(bool enable_rtx, bool enable_red);
29 void ReceivesPliAndRecovers(int rtp_history_ms);
Sebastian Janssonc5017132018-02-02 15:24:1630};
31
Ilya Nikolaevskiycb960622018-09-04 09:07:3132TEST_F(RetransmissionEndToEndTest, ReceivesAndRetransmitsNack) {
Sebastian Janssonc5017132018-02-02 15:24:1633 static const int kNumberOfNacksToObserve = 2;
34 static const int kLossBurstSize = 2;
35 static const int kPacketsBetweenLossBursts = 9;
36 class NackObserver : public test::EndToEndTest {
37 public:
38 NackObserver()
39 : EndToEndTest(kLongTimeoutMs),
40 sent_rtp_packets_(0),
41 packets_left_to_drop_(0),
42 nacks_left_(kNumberOfNacksToObserve) {}
43
44 private:
45 Action OnSendRtp(const uint8_t* packet, size_t length) override {
46 rtc::CritScope lock(&crit_);
47 RTPHeader header;
48 EXPECT_TRUE(parser_->Parse(packet, length, &header));
49
50 // Never drop retransmitted packets.
51 if (dropped_packets_.find(header.sequenceNumber) !=
52 dropped_packets_.end()) {
53 retransmitted_packets_.insert(header.sequenceNumber);
54 return SEND_PACKET;
55 }
56
57 if (nacks_left_ <= 0 &&
58 retransmitted_packets_.size() == dropped_packets_.size()) {
59 observation_complete_.Set();
60 }
61
62 ++sent_rtp_packets_;
63
64 // Enough NACKs received, stop dropping packets.
65 if (nacks_left_ <= 0)
66 return SEND_PACKET;
67
68 // Check if it's time for a new loss burst.
69 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
70 packets_left_to_drop_ = kLossBurstSize;
71
72 // Never drop padding packets as those won't be retransmitted.
73 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
74 --packets_left_to_drop_;
75 dropped_packets_.insert(header.sequenceNumber);
76 return DROP_PACKET;
77 }
78
79 return SEND_PACKET;
80 }
81
82 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
83 rtc::CritScope lock(&crit_);
84 test::RtcpPacketParser parser;
85 EXPECT_TRUE(parser.Parse(packet, length));
86 nacks_left_ -= parser.nack()->num_packets();
87 return SEND_PACKET;
88 }
89
90 void ModifyVideoConfigs(
91 VideoSendStream::Config* send_config,
92 std::vector<VideoReceiveStream::Config>* receive_configs,
93 VideoEncoderConfig* encoder_config) override {
94 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
95 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
96 }
97
98 void PerformTest() override {
99 EXPECT_TRUE(Wait())
100 << "Timed out waiting for packets to be NACKed, retransmitted and "
101 "rendered.";
102 }
103
104 rtc::CriticalSection crit_;
105 std::set<uint16_t> dropped_packets_;
106 std::set<uint16_t> retransmitted_packets_;
107 uint64_t sent_rtp_packets_;
108 int packets_left_to_drop_;
109 int nacks_left_ RTC_GUARDED_BY(&crit_);
110 } test;
111
112 RunBaseTest(&test);
113}
114
Ilya Nikolaevskiycb960622018-09-04 09:07:31115TEST_F(RetransmissionEndToEndTest, ReceivesNackAndRetransmitsAudio) {
Sebastian Janssonc5017132018-02-02 15:24:16116 class NackObserver : public test::EndToEndTest {
117 public:
118 NackObserver()
119 : EndToEndTest(kLongTimeoutMs),
120 local_ssrc_(0),
121 remote_ssrc_(0),
122 receive_transport_(nullptr) {}
123
124 private:
125 size_t GetNumVideoStreams() const override { return 0; }
126 size_t GetNumAudioStreams() const override { return 1; }
127
128 test::PacketTransport* CreateReceiveTransport(
129 test::SingleThreadedTaskQueueForTesting* task_queue) override {
130 test::PacketTransport* receive_transport = new test::PacketTransport(
131 task_queue, nullptr, this, test::PacketTransport::kReceiver,
Artem Titov4e199e92018-08-20 11:30:39132 payload_type_map_,
133 absl::make_unique<FakeNetworkPipe>(
134 Clock::GetRealTimeClock(),
135 absl::make_unique<SimulatedNetwork>(
136 DefaultNetworkSimulationConfig())));
Sebastian Janssonc5017132018-02-02 15:24:16137 receive_transport_ = receive_transport;
138 return receive_transport;
139 }
140
141 Action OnSendRtp(const uint8_t* packet, size_t length) override {
142 RTPHeader header;
143 EXPECT_TRUE(parser_->Parse(packet, length, &header));
144
145 if (!sequence_number_to_retransmit_) {
146 sequence_number_to_retransmit_ = header.sequenceNumber;
147
148 // Don't ask for retransmission straight away, may be deduped in pacer.
149 } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
150 observation_complete_.Set();
151 } else {
152 // Send a NACK as often as necessary until retransmission is received.
153 rtcp::Nack nack;
154 nack.SetSenderSsrc(local_ssrc_);
155 nack.SetMediaSsrc(remote_ssrc_);
156 uint16_t nack_list[] = {*sequence_number_to_retransmit_};
157 nack.SetPacketIds(nack_list, 1);
158 rtc::Buffer buffer = nack.Build();
159
160 EXPECT_TRUE(receive_transport_->SendRtcp(buffer.data(), buffer.size()));
161 }
162
163 return SEND_PACKET;
164 }
165
166 void ModifyAudioConfigs(
167 AudioSendStream::Config* send_config,
168 std::vector<AudioReceiveStream::Config>* receive_configs) override {
169 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
170 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
171 local_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
172 remote_ssrc_ = (*receive_configs)[0].rtp.remote_ssrc;
173 }
174
175 void PerformTest() override {
176 EXPECT_TRUE(Wait())
177 << "Timed out waiting for packets to be NACKed, retransmitted and "
178 "rendered.";
179 }
180
181 uint32_t local_ssrc_;
182 uint32_t remote_ssrc_;
183 Transport* receive_transport_;
Danil Chapovalovb9b146c2018-06-15 10:28:07184 absl::optional<uint16_t> sequence_number_to_retransmit_;
Sebastian Janssonc5017132018-02-02 15:24:16185 } test;
186
187 RunBaseTest(&test);
188}
189
Ilya Nikolaevskiycb960622018-09-04 09:07:31190TEST_F(RetransmissionEndToEndTest,
Sebastian Janssonc5017132018-02-02 15:24:16191 StopSendingKeyframeRequestsForInactiveStream) {
192 class KeyframeRequestObserver : public test::EndToEndTest {
193 public:
194 explicit KeyframeRequestObserver(
195 test::SingleThreadedTaskQueueForTesting* task_queue)
196 : clock_(Clock::GetRealTimeClock()), task_queue_(task_queue) {}
197
198 void OnVideoStreamsCreated(
199 VideoSendStream* send_stream,
200 const std::vector<VideoReceiveStream*>& receive_streams) override {
201 RTC_DCHECK_EQ(1, receive_streams.size());
202 send_stream_ = send_stream;
203 receive_stream_ = receive_streams[0];
204 }
205
206 void PerformTest() override {
207 bool frame_decoded = false;
208 int64_t start_time = clock_->TimeInMilliseconds();
209 while (clock_->TimeInMilliseconds() - start_time <= 5000) {
210 if (receive_stream_->GetStats().frames_decoded > 0) {
211 frame_decoded = true;
212 break;
213 }
214 SleepMs(100);
215 }
216 ASSERT_TRUE(frame_decoded);
217 task_queue_->SendTask([this]() { send_stream_->Stop(); });
218 SleepMs(10000);
219 ASSERT_EQ(
220 1U, receive_stream_->GetStats().rtcp_packet_type_counts.pli_packets);
221 }
222
223 private:
224 Clock* clock_;
225 VideoSendStream* send_stream_;
226 VideoReceiveStream* receive_stream_;
227 test::SingleThreadedTaskQueueForTesting* const task_queue_;
228 } test(&task_queue_);
229
230 RunBaseTest(&test);
231}
232
233void RetransmissionEndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
234 static const int kPacketsToDrop = 1;
235
236 class PliObserver : public test::EndToEndTest,
237 public rtc::VideoSinkInterface<VideoFrame> {
238 public:
239 explicit PliObserver(int rtp_history_ms)
240 : EndToEndTest(kLongTimeoutMs),
241 rtp_history_ms_(rtp_history_ms),
242 nack_enabled_(rtp_history_ms > 0),
243 highest_dropped_timestamp_(0),
244 frames_to_drop_(0),
245 received_pli_(false) {}
246
247 private:
248 Action OnSendRtp(const uint8_t* packet, size_t length) override {
249 rtc::CritScope lock(&crit_);
250 RTPHeader header;
251 EXPECT_TRUE(parser_->Parse(packet, length, &header));
252
253 // Drop all retransmitted packets to force a PLI.
254 if (header.timestamp <= highest_dropped_timestamp_)
255 return DROP_PACKET;
256
257 if (frames_to_drop_ > 0) {
258 highest_dropped_timestamp_ = header.timestamp;
259 --frames_to_drop_;
260 return DROP_PACKET;
261 }
262
263 return SEND_PACKET;
264 }
265
266 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
267 rtc::CritScope lock(&crit_);
268 test::RtcpPacketParser parser;
269 EXPECT_TRUE(parser.Parse(packet, length));
270 if (!nack_enabled_)
271 EXPECT_EQ(0, parser.nack()->num_packets());
272 if (parser.pli()->num_packets() > 0)
273 received_pli_ = true;
274 return SEND_PACKET;
275 }
276
277 void OnFrame(const VideoFrame& video_frame) override {
278 rtc::CritScope lock(&crit_);
279 if (received_pli_ &&
280 video_frame.timestamp() > highest_dropped_timestamp_) {
281 observation_complete_.Set();
282 }
283 if (!received_pli_)
284 frames_to_drop_ = kPacketsToDrop;
285 }
286
287 void ModifyVideoConfigs(
288 VideoSendStream::Config* send_config,
289 std::vector<VideoReceiveStream::Config>* receive_configs,
290 VideoEncoderConfig* encoder_config) override {
291 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
292 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
293 (*receive_configs)[0].renderer = this;
294 }
295
296 void PerformTest() override {
297 EXPECT_TRUE(Wait()) << "Timed out waiting for PLI to be "
298 "received and a frame to be "
299 "rendered afterwards.";
300 }
301
302 rtc::CriticalSection crit_;
303 int rtp_history_ms_;
304 bool nack_enabled_;
305 uint32_t highest_dropped_timestamp_ RTC_GUARDED_BY(&crit_);
306 int frames_to_drop_ RTC_GUARDED_BY(&crit_);
307 bool received_pli_ RTC_GUARDED_BY(&crit_);
308 } test(rtp_history_ms);
309
310 RunBaseTest(&test);
311}
312
Ilya Nikolaevskiycb960622018-09-04 09:07:31313TEST_F(RetransmissionEndToEndTest, ReceivesPliAndRecoversWithNack) {
Sebastian Janssonc5017132018-02-02 15:24:16314 ReceivesPliAndRecovers(1000);
315}
316
Ilya Nikolaevskiycb960622018-09-04 09:07:31317TEST_F(RetransmissionEndToEndTest, ReceivesPliAndRecoversWithoutNack) {
Sebastian Janssonc5017132018-02-02 15:24:16318 ReceivesPliAndRecovers(0);
319}
320// This test drops second RTP packet with a marker bit set, makes sure it's
321// retransmitted and renders. Retransmission SSRCs are also checked.
322void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx,
323 bool enable_red) {
324 static const int kDroppedFrameNumber = 10;
325 class RetransmissionObserver : public test::EndToEndTest,
326 public rtc::VideoSinkInterface<VideoFrame> {
327 public:
328 RetransmissionObserver(bool enable_rtx, bool enable_red)
329 : EndToEndTest(kDefaultTimeoutMs),
330 payload_type_(GetPayloadType(false, enable_red)),
331 retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
332 : kVideoSendSsrcs[0]),
333 retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
Niels Möller4db138e2018-04-19 07:04:13334 encoder_factory_([]() { return VP8Encoder::Create(); }),
Sebastian Janssonc5017132018-02-02 15:24:16335 marker_bits_observed_(0),
336 retransmitted_timestamp_(0) {}
337
338 private:
339 Action OnSendRtp(const uint8_t* packet, size_t length) override {
340 rtc::CritScope lock(&crit_);
341 RTPHeader header;
342 EXPECT_TRUE(parser_->Parse(packet, length, &header));
343
344 // Ignore padding-only packets over RTX.
345 if (header.payloadType != payload_type_) {
346 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
347 if (length == header.headerLength + header.paddingLength)
348 return SEND_PACKET;
349 }
350
351 if (header.timestamp == retransmitted_timestamp_) {
352 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
353 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
354 return SEND_PACKET;
355 }
356
357 // Found the final packet of the frame to inflict loss to, drop this and
358 // expect a retransmission.
359 if (header.payloadType == payload_type_ && header.markerBit &&
360 ++marker_bits_observed_ == kDroppedFrameNumber) {
361 // This should be the only dropped packet.
362 EXPECT_EQ(0u, retransmitted_timestamp_);
363 retransmitted_timestamp_ = header.timestamp;
364 if (std::find(rendered_timestamps_.begin(), rendered_timestamps_.end(),
365 retransmitted_timestamp_) != rendered_timestamps_.end()) {
366 // Frame was rendered before last packet was scheduled for sending.
367 // This is extremly rare but possible scenario because prober able to
368 // resend packet before it was send.
369 // TODO(danilchap): Remove this corner case when prober would not be
370 // able to sneak in between packet saved to history for resending and
371 // pacer notified about existance of that packet for sending.
372 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5540 for
373 // details.
374 observation_complete_.Set();
375 }
376 return DROP_PACKET;
377 }
378
379 return SEND_PACKET;
380 }
381
382 void OnFrame(const VideoFrame& frame) override {
383 EXPECT_EQ(kVideoRotation_90, frame.rotation());
384 {
385 rtc::CritScope lock(&crit_);
386 if (frame.timestamp() == retransmitted_timestamp_)
387 observation_complete_.Set();
388 rendered_timestamps_.push_back(frame.timestamp());
389 }
390 orig_renderer_->OnFrame(frame);
391 }
392
393 void ModifyVideoConfigs(
394 VideoSendStream::Config* send_config,
395 std::vector<VideoReceiveStream::Config>* receive_configs,
396 VideoEncoderConfig* encoder_config) override {
397 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
398
399 // Insert ourselves into the rendering pipeline.
400 RTC_DCHECK(!orig_renderer_);
401 orig_renderer_ = (*receive_configs)[0].renderer;
402 RTC_DCHECK(orig_renderer_);
403 (*receive_configs)[0].disable_prerenderer_smoothing = true;
404 (*receive_configs)[0].renderer = this;
405
406 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
407
408 if (payload_type_ == kRedPayloadType) {
409 send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
410 send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
411 if (retransmission_ssrc_ == kSendRtxSsrcs[0])
412 send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
413 (*receive_configs)[0].rtp.ulpfec_payload_type =
414 send_config->rtp.ulpfec.ulpfec_payload_type;
415 (*receive_configs)[0].rtp.red_payload_type =
416 send_config->rtp.ulpfec.red_payload_type;
417 }
418
419 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
420 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
421 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
422 (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
423 (*receive_configs)[0]
424 .rtp.rtx_associated_payload_types[(payload_type_ == kRedPayloadType)
425 ? kRtxRedPayloadType
426 : kSendRtxPayloadType] =
427 payload_type_;
428 }
429 // Configure encoding and decoding with VP8, since generic packetization
430 // doesn't support FEC with NACK.
431 RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
Niels Möller4db138e2018-04-19 07:04:13432 send_config->encoder_settings.encoder_factory = &encoder_factory_;
Niels Möller259a4972018-04-05 13:36:51433 send_config->rtp.payload_name = "VP8";
434 encoder_config->codec_type = kVideoCodecVP8;
Niels Möllercb7e1d22018-09-11 13:56:04435 (*receive_configs)[0].decoders[0].video_format = SdpVideoFormat("VP8");
Sebastian Janssonc5017132018-02-02 15:24:16436 }
437
438 void OnFrameGeneratorCapturerCreated(
439 test::FrameGeneratorCapturer* frame_generator_capturer) override {
440 frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
441 }
442
443 void PerformTest() override {
444 EXPECT_TRUE(Wait())
445 << "Timed out while waiting for retransmission to render.";
446 }
447
448 int GetPayloadType(bool use_rtx, bool use_fec) {
449 if (use_fec) {
450 if (use_rtx)
451 return kRtxRedPayloadType;
452 return kRedPayloadType;
453 }
454 if (use_rtx)
455 return kSendRtxPayloadType;
456 return kFakeVideoSendPayloadType;
457 }
458
459 rtc::CriticalSection crit_;
460 rtc::VideoSinkInterface<VideoFrame>* orig_renderer_ = nullptr;
461 const int payload_type_;
462 const uint32_t retransmission_ssrc_;
463 const int retransmission_payload_type_;
Niels Möller4db138e2018-04-19 07:04:13464 test::FunctionVideoEncoderFactory encoder_factory_;
Sebastian Janssonc5017132018-02-02 15:24:16465 const std::string payload_name_;
466 int marker_bits_observed_;
467 uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_);
468 std::vector<uint32_t> rendered_timestamps_ RTC_GUARDED_BY(&crit_);
469 } test(enable_rtx, enable_red);
470
471 RunBaseTest(&test);
472}
473
Ilya Nikolaevskiycb960622018-09-04 09:07:31474TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrame) {
Sebastian Janssonc5017132018-02-02 15:24:16475 DecodesRetransmittedFrame(false, false);
476}
477
Ilya Nikolaevskiycb960622018-09-04 09:07:31478TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrameOverRtx) {
Sebastian Janssonc5017132018-02-02 15:24:16479 DecodesRetransmittedFrame(true, false);
480}
481
Ilya Nikolaevskiycb960622018-09-04 09:07:31482TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrameByRed) {
Sebastian Janssonc5017132018-02-02 15:24:16483 DecodesRetransmittedFrame(false, true);
484}
485
Ilya Nikolaevskiycb960622018-09-04 09:07:31486TEST_F(RetransmissionEndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
Sebastian Janssonc5017132018-02-02 15:24:16487 DecodesRetransmittedFrame(true, true);
488}
489
490} // namespace webrtc