OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 #include <algorithm> // max | 10 #include <algorithm> // max |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
301 return true; | 301 return true; |
302 } | 302 } |
303 | 303 |
304 RtcpStatistics stats_; | 304 RtcpStatistics stats_; |
305 }; | 305 }; |
306 | 306 |
307 rtc::scoped_ptr<LossyStatistician> lossy_stats_; | 307 rtc::scoped_ptr<LossyStatistician> lossy_stats_; |
308 StatisticianMap stats_map_; | 308 StatisticianMap stats_map_; |
309 }; | 309 }; |
310 | 310 |
311 class FecObserver : public test::SendTest { | 311 class FecObserver : public test::EndToEndTest { |
312 public: | 312 public: |
313 explicit FecObserver(bool header_extensions_enabled) | 313 FecObserver(bool header_extensions_enabled, |
314 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs), | 314 bool use_nack, |
315 bool expect_red, | |
316 const std::string& codec) | |
317 : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs), | |
318 payload_name_(codec), | |
319 use_nack_(use_nack), | |
320 expect_red_(expect_red), | |
315 send_count_(0), | 321 send_count_(0), |
316 received_media_(false), | 322 received_media_(false), |
317 received_fec_(false), | 323 received_fec_(false), |
318 header_extensions_enabled_(header_extensions_enabled) {} | 324 header_extensions_enabled_(header_extensions_enabled) { |
325 if (codec == "H264") { | |
326 encoder_.reset(new test::FakeH264Encoder(Clock::GetRealTimeClock())); | |
327 } else if (codec == "VP8") { | |
328 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8)); | |
329 } else if (codec == "VP9") { | |
330 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp9)); | |
331 } else { | |
332 RTC_NOTREACHED(); | |
333 } | |
334 } | |
319 | 335 |
320 private: | 336 private: |
321 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 337 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
322 RTPHeader header; | 338 RTPHeader header; |
323 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | 339 EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
324 | 340 |
325 // Send lossy receive reports to trigger FEC enabling. | 341 ++send_count_; |
326 if (send_count_++ % 2 != 0) { | |
327 // Receive statistics reporting having lost 50% of the packets. | |
328 FakeReceiveStatistics lossy_receive_stats( | |
329 VideoSendStreamTest::kVideoSendSsrcs[0], header.sequenceNumber, | |
330 send_count_ / 2, 127); | |
331 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), | |
332 &lossy_receive_stats, nullptr, nullptr, | |
333 transport_adapter_.get()); | |
334 | |
335 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize); | |
336 rtcp_sender.SetRemoteSSRC(VideoSendStreamTest::kVideoSendSsrcs[0]); | |
337 | |
338 RTCPSender::FeedbackState feedback_state; | |
339 | |
340 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr)); | |
341 } | |
342 | |
343 int encapsulated_payload_type = -1; | 342 int encapsulated_payload_type = -1; |
344 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) { | 343 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) { |
344 EXPECT_TRUE(expect_red_); | |
345 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]); | 345 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]); |
346 if (encapsulated_payload_type != | 346 if (encapsulated_payload_type != |
347 VideoSendStreamTest::kFakeVideoSendPayloadType) | 347 VideoSendStreamTest::kFakeVideoSendPayloadType) { |
348 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType, | 348 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType, |
349 encapsulated_payload_type); | 349 encapsulated_payload_type); |
350 } | |
350 } else { | 351 } else { |
351 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType, | 352 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType, |
352 header.payloadType); | 353 header.payloadType); |
354 if (static_cast<size_t>(header.headerLength + header.paddingLength) < | |
355 length) { | |
356 // Not padding-only, media received outside of RED. | |
357 EXPECT_FALSE(expect_red_); | |
358 received_media_ = true; | |
359 } | |
353 } | 360 } |
354 | 361 |
355 if (header_extensions_enabled_) { | 362 if (header_extensions_enabled_) { |
356 EXPECT_TRUE(header.extension.hasAbsoluteSendTime); | 363 EXPECT_TRUE(header.extension.hasAbsoluteSendTime); |
357 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2; | 364 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2; |
358 if (header.extension.absoluteSendTime <= kHalf24BitsSpace && | 365 if (header.extension.absoluteSendTime <= kHalf24BitsSpace && |
359 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) { | 366 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) { |
360 // 24 bits wrap. | 367 // 24 bits wrap. |
361 EXPECT_GT(prev_header_.extension.absoluteSendTime, | 368 EXPECT_GT(prev_header_.extension.absoluteSendTime, |
362 header.extension.absoluteSendTime); | 369 header.extension.absoluteSendTime); |
363 } else { | 370 } else { |
364 EXPECT_GE(header.extension.absoluteSendTime, | 371 EXPECT_GE(header.extension.absoluteSendTime, |
365 prev_header_.extension.absoluteSendTime); | 372 prev_header_.extension.absoluteSendTime); |
366 } | 373 } |
367 EXPECT_TRUE(header.extension.hasTransportSequenceNumber); | 374 EXPECT_TRUE(header.extension.hasTransportSequenceNumber); |
368 uint16_t seq_num_diff = header.extension.transportSequenceNumber - | 375 uint16_t seq_num_diff = header.extension.transportSequenceNumber - |
369 prev_header_.extension.transportSequenceNumber; | 376 prev_header_.extension.transportSequenceNumber; |
370 EXPECT_EQ(1, seq_num_diff); | 377 EXPECT_EQ(1, seq_num_diff); |
371 } | 378 } |
372 | 379 |
373 if (encapsulated_payload_type != -1) { | 380 if (encapsulated_payload_type != -1) { |
374 if (encapsulated_payload_type == | 381 if (encapsulated_payload_type == |
375 VideoSendStreamTest::kUlpfecPayloadType) { | 382 VideoSendStreamTest::kUlpfecPayloadType) { |
376 received_fec_ = true; | 383 received_fec_ = true; |
377 } else { | 384 } else { |
378 received_media_ = true; | 385 received_media_ = true; |
379 } | 386 } |
380 } | 387 } |
381 | 388 |
382 if (received_media_ && received_fec_ && send_count_ > 100) | 389 if (send_count_ > 100 && received_media_) { |
383 observation_complete_.Set(); | 390 if (received_fec_ || !expect_red_) |
391 observation_complete_.Set(); | |
392 } | |
384 | 393 |
385 prev_header_ = header; | 394 prev_header_ = header; |
386 | 395 |
387 return SEND_PACKET; | 396 return SEND_PACKET; |
388 } | 397 } |
389 | 398 |
399 test::PacketTransport* CreateSendTransport(Call* sender_call) override { | |
400 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC. | |
401 // Configure some network delay. | |
402 const int kNetworkDelayMs = 100; | |
403 FakeNetworkPipe::Config config; | |
404 config.loss_percent = 50; | |
405 config.queue_delay_ms = kNetworkDelayMs; | |
406 return new test::PacketTransport(sender_call, this, | |
407 test::PacketTransport::kSender, config); | |
408 } | |
409 | |
390 void ModifyVideoConfigs( | 410 void ModifyVideoConfigs( |
391 VideoSendStream::Config* send_config, | 411 VideoSendStream::Config* send_config, |
392 std::vector<VideoReceiveStream::Config>* receive_configs, | 412 std::vector<VideoReceiveStream::Config>* receive_configs, |
393 VideoEncoderConfig* encoder_config) override { | 413 VideoEncoderConfig* encoder_config) override { |
394 transport_adapter_.reset( | 414 transport_adapter_.reset( |
395 new internal::TransportAdapter(send_config->send_transport)); | 415 new internal::TransportAdapter(send_config->send_transport)); |
396 transport_adapter_->Enable(); | 416 transport_adapter_->Enable(); |
417 if (use_nack_) { | |
418 send_config->rtp.nack.rtp_history_ms = | |
419 (*receive_configs)[0].rtp.nack.rtp_history_ms = | |
420 VideoSendStreamTest::kNackRtpHistoryMs; | |
421 } | |
422 send_config->encoder_settings.encoder = encoder_.get(); | |
423 send_config->encoder_settings.payload_name = payload_name_; | |
397 send_config->rtp.fec.red_payload_type = | 424 send_config->rtp.fec.red_payload_type = |
398 VideoSendStreamTest::kRedPayloadType; | 425 (*receive_configs)[0].rtp.fec.red_payload_type = |
426 VideoSendStreamTest::kRedPayloadType; | |
399 send_config->rtp.fec.ulpfec_payload_type = | 427 send_config->rtp.fec.ulpfec_payload_type = |
400 VideoSendStreamTest::kUlpfecPayloadType; | 428 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = |
429 VideoSendStreamTest::kUlpfecPayloadType; | |
stefan-webrtc
2016/02/12 10:46:27
I personally prefer to configure the sender first
pbos-webrtc
2016/02/12 12:00:27
Done.
| |
401 if (header_extensions_enabled_) { | 430 if (header_extensions_enabled_) { |
402 send_config->rtp.extensions.push_back(RtpExtension( | 431 send_config->rtp.extensions.push_back(RtpExtension( |
403 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); | 432 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); |
404 send_config->rtp.extensions.push_back( | 433 send_config->rtp.extensions.push_back( |
405 RtpExtension(RtpExtension::kTransportSequenceNumber, | 434 RtpExtension(RtpExtension::kTransportSequenceNumber, |
406 test::kTransportSequenceNumberExtensionId)); | 435 test::kTransportSequenceNumberExtensionId)); |
407 } | 436 } |
408 } | 437 } |
409 | 438 |
410 void PerformTest() override { | 439 void PerformTest() override { |
411 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; | 440 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; |
412 } | 441 } |
413 | 442 |
414 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_; | 443 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_; |
444 rtc::scoped_ptr<VideoEncoder> encoder_; | |
445 const std::string payload_name_; | |
446 const bool use_nack_; | |
447 const bool expect_red_; | |
415 int send_count_; | 448 int send_count_; |
416 bool received_media_; | 449 bool received_media_; |
417 bool received_fec_; | 450 bool received_fec_; |
418 bool header_extensions_enabled_; | 451 bool header_extensions_enabled_; |
419 RTPHeader prev_header_; | 452 RTPHeader prev_header_; |
420 }; | 453 }; |
421 | 454 |
422 TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) { | 455 TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) { |
423 FecObserver test(true); | 456 FecObserver test(true, false, true, "VP8"); |
424 | |
425 RunBaseTest(&test); | 457 RunBaseTest(&test); |
426 } | 458 } |
427 | 459 |
428 TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) { | 460 TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) { |
429 FecObserver test(false); | 461 FecObserver test(false, false, true, "VP8"); |
430 | |
431 RunBaseTest(&test); | 462 RunBaseTest(&test); |
432 } | 463 } |
433 | 464 |
465 // The FEC scheme used is not efficient for H264, so we should not use RED/FEC | |
466 // since we'll still have to re-request FEC packets, efficiently wasting | |
stefan-webrtc
2016/02/12 10:46:27
"effectively wasting"?
pbos-webrtc
2016/02/12 12:00:27
Done.
| |
467 // bandwidth. Also FEC packets are not stored on the sender, so retransmission | |
468 // requests for FEC packets are dropped. | |
stefan-webrtc
2016/02/12 10:46:27
I think the main issue is that we have to wait for
pbos-webrtc
2016/02/12 12:00:27
Done.
| |
469 TEST_F(VideoSendStreamTest, DoesNotUtilizeRedForH264WithNackEnabled) { | |
470 FecObserver test(false, true, false, "H264"); | |
471 RunBaseTest(&test); | |
472 } | |
473 | |
474 // Without retransmissions FEC for H264 is fine. | |
475 TEST_F(VideoSendStreamTest, DoesUtilizeRedForH264WithoutNackEnabled) { | |
476 FecObserver test(false, false, true, "H264"); | |
477 RunBaseTest(&test); | |
478 } | |
479 | |
480 TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp8WithNackEnabled) { | |
481 FecObserver test(false, true, true, "VP8"); | |
482 RunBaseTest(&test); | |
483 } | |
484 | |
485 TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp9WithNackEnabled) { | |
486 FecObserver test(false, true, true, "VP9"); | |
487 RunBaseTest(&test); | |
488 } | |
489 | |
434 void VideoSendStreamTest::TestNackRetransmission( | 490 void VideoSendStreamTest::TestNackRetransmission( |
435 uint32_t retransmit_ssrc, | 491 uint32_t retransmit_ssrc, |
436 uint8_t retransmit_payload_type) { | 492 uint8_t retransmit_payload_type) { |
437 class NackObserver : public test::SendTest { | 493 class NackObserver : public test::SendTest { |
438 public: | 494 public: |
439 explicit NackObserver(uint32_t retransmit_ssrc, | 495 explicit NackObserver(uint32_t retransmit_ssrc, |
440 uint8_t retransmit_payload_type) | 496 uint8_t retransmit_payload_type) |
441 : SendTest(kDefaultTimeoutMs), | 497 : SendTest(kDefaultTimeoutMs), |
442 send_count_(0), | 498 send_count_(0), |
443 retransmit_ssrc_(retransmit_ssrc), | 499 retransmit_ssrc_(retransmit_ssrc), |
(...skipping 1813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2257 observation_complete_.Set(); | 2313 observation_complete_.Set(); |
2258 } | 2314 } |
2259 } | 2315 } |
2260 } test; | 2316 } test; |
2261 | 2317 |
2262 RunBaseTest(&test); | 2318 RunBaseTest(&test); |
2263 } | 2319 } |
2264 #endif | 2320 #endif |
2265 | 2321 |
2266 } // namespace webrtc | 2322 } // namespace webrtc |
OLD | NEW |