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::EndToEndTest { | 311 class FecObserver : public test::SendTest { |
312 public: | 312 public: |
313 FecObserver(bool header_extensions_enabled, | 313 explicit FecObserver(bool header_extensions_enabled) |
314 bool use_nack, | 314 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs), |
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), | |
321 send_count_(0), | 315 send_count_(0), |
322 received_media_(false), | 316 received_media_(false), |
323 received_fec_(false), | 317 received_fec_(false), |
324 header_extensions_enabled_(header_extensions_enabled) { | 318 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 } | |
335 | 319 |
336 private: | 320 private: |
337 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 321 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
338 RTPHeader header; | 322 RTPHeader header; |
339 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | 323 EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
340 | 324 |
341 ++send_count_; | 325 // Send lossy receive reports to trigger FEC enabling. |
| 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 |
342 int encapsulated_payload_type = -1; | 343 int encapsulated_payload_type = -1; |
343 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) { | 344 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 } | |
351 } else { | 350 } else { |
352 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType, | 351 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType, |
353 header.payloadType); | 352 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 } | |
360 } | 353 } |
361 | 354 |
362 if (header_extensions_enabled_) { | 355 if (header_extensions_enabled_) { |
363 EXPECT_TRUE(header.extension.hasAbsoluteSendTime); | 356 EXPECT_TRUE(header.extension.hasAbsoluteSendTime); |
364 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2; | 357 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2; |
365 if (header.extension.absoluteSendTime <= kHalf24BitsSpace && | 358 if (header.extension.absoluteSendTime <= kHalf24BitsSpace && |
366 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) { | 359 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) { |
367 // 24 bits wrap. | 360 // 24 bits wrap. |
368 EXPECT_GT(prev_header_.extension.absoluteSendTime, | 361 EXPECT_GT(prev_header_.extension.absoluteSendTime, |
369 header.extension.absoluteSendTime); | 362 header.extension.absoluteSendTime); |
370 } else { | 363 } else { |
371 EXPECT_GE(header.extension.absoluteSendTime, | 364 EXPECT_GE(header.extension.absoluteSendTime, |
372 prev_header_.extension.absoluteSendTime); | 365 prev_header_.extension.absoluteSendTime); |
373 } | 366 } |
374 EXPECT_TRUE(header.extension.hasTransportSequenceNumber); | 367 EXPECT_TRUE(header.extension.hasTransportSequenceNumber); |
375 uint16_t seq_num_diff = header.extension.transportSequenceNumber - | 368 uint16_t seq_num_diff = header.extension.transportSequenceNumber - |
376 prev_header_.extension.transportSequenceNumber; | 369 prev_header_.extension.transportSequenceNumber; |
377 EXPECT_EQ(1, seq_num_diff); | 370 EXPECT_EQ(1, seq_num_diff); |
378 } | 371 } |
379 | 372 |
380 if (encapsulated_payload_type != -1) { | 373 if (encapsulated_payload_type != -1) { |
381 if (encapsulated_payload_type == | 374 if (encapsulated_payload_type == |
382 VideoSendStreamTest::kUlpfecPayloadType) { | 375 VideoSendStreamTest::kUlpfecPayloadType) { |
383 received_fec_ = true; | 376 received_fec_ = true; |
384 } else { | 377 } else { |
385 received_media_ = true; | 378 received_media_ = true; |
386 } | 379 } |
387 } | 380 } |
388 | 381 |
389 if (send_count_ > 100 && received_media_) { | 382 if (received_media_ && received_fec_ && send_count_ > 100) |
390 if (received_fec_ || !expect_red_) | 383 observation_complete_.Set(); |
391 observation_complete_.Set(); | |
392 } | |
393 | 384 |
394 prev_header_ = header; | 385 prev_header_ = header; |
395 | 386 |
396 return SEND_PACKET; | 387 return SEND_PACKET; |
397 } | 388 } |
398 | 389 |
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 | |
410 void ModifyVideoConfigs( | 390 void ModifyVideoConfigs( |
411 VideoSendStream::Config* send_config, | 391 VideoSendStream::Config* send_config, |
412 std::vector<VideoReceiveStream::Config>* receive_configs, | 392 std::vector<VideoReceiveStream::Config>* receive_configs, |
413 VideoEncoderConfig* encoder_config) override { | 393 VideoEncoderConfig* encoder_config) override { |
414 transport_adapter_.reset( | 394 transport_adapter_.reset( |
415 new internal::TransportAdapter(send_config->send_transport)); | 395 new internal::TransportAdapter(send_config->send_transport)); |
416 transport_adapter_->Enable(); | 396 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_; | |
424 send_config->rtp.fec.red_payload_type = | 397 send_config->rtp.fec.red_payload_type = |
425 VideoSendStreamTest::kRedPayloadType; | 398 VideoSendStreamTest::kRedPayloadType; |
426 send_config->rtp.fec.ulpfec_payload_type = | 399 send_config->rtp.fec.ulpfec_payload_type = |
427 VideoSendStreamTest::kUlpfecPayloadType; | 400 VideoSendStreamTest::kUlpfecPayloadType; |
428 if (header_extensions_enabled_) { | 401 if (header_extensions_enabled_) { |
429 send_config->rtp.extensions.push_back(RtpExtension( | 402 send_config->rtp.extensions.push_back(RtpExtension( |
430 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); | 403 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); |
431 send_config->rtp.extensions.push_back( | 404 send_config->rtp.extensions.push_back( |
432 RtpExtension(RtpExtension::kTransportSequenceNumber, | 405 RtpExtension(RtpExtension::kTransportSequenceNumber, |
433 test::kTransportSequenceNumberExtensionId)); | 406 test::kTransportSequenceNumberExtensionId)); |
434 } | 407 } |
435 (*receive_configs)[0].rtp.fec.red_payload_type = | |
436 send_config->rtp.fec.red_payload_type; | |
437 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = | |
438 send_config->rtp.fec.ulpfec_payload_type; | |
439 } | 408 } |
440 | 409 |
441 void PerformTest() override { | 410 void PerformTest() override { |
442 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; | 411 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; |
443 } | 412 } |
444 | 413 |
445 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_; | 414 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_; |
446 rtc::scoped_ptr<VideoEncoder> encoder_; | |
447 const std::string payload_name_; | |
448 const bool use_nack_; | |
449 const bool expect_red_; | |
450 int send_count_; | 415 int send_count_; |
451 bool received_media_; | 416 bool received_media_; |
452 bool received_fec_; | 417 bool received_fec_; |
453 bool header_extensions_enabled_; | 418 bool header_extensions_enabled_; |
454 RTPHeader prev_header_; | 419 RTPHeader prev_header_; |
455 }; | 420 }; |
456 | 421 |
457 TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) { | 422 TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) { |
458 FecObserver test(true, false, true, "VP8"); | 423 FecObserver test(true); |
| 424 |
459 RunBaseTest(&test); | 425 RunBaseTest(&test); |
460 } | 426 } |
461 | 427 |
462 TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) { | 428 TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) { |
463 FecObserver test(false, false, true, "VP8"); | 429 FecObserver test(false); |
| 430 |
464 RunBaseTest(&test); | 431 RunBaseTest(&test); |
465 } | 432 } |
466 | 433 |
467 // The FEC scheme used is not efficient for H264, so we should not use RED/FEC | |
468 // since we'll still have to re-request FEC packets, effectively wasting | |
469 // bandwidth since the receiver has to wait for FEC retransmissions to determine | |
470 // that the received state is actually decodable. | |
471 TEST_F(VideoSendStreamTest, DoesNotUtilizeRedForH264WithNackEnabled) { | |
472 FecObserver test(false, true, false, "H264"); | |
473 RunBaseTest(&test); | |
474 } | |
475 | |
476 // Without retransmissions FEC for H264 is fine. | |
477 TEST_F(VideoSendStreamTest, DoesUtilizeRedForH264WithoutNackEnabled) { | |
478 FecObserver test(false, false, true, "H264"); | |
479 RunBaseTest(&test); | |
480 } | |
481 | |
482 TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp8WithNackEnabled) { | |
483 FecObserver test(false, true, true, "VP8"); | |
484 RunBaseTest(&test); | |
485 } | |
486 | |
487 TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp9WithNackEnabled) { | |
488 FecObserver test(false, true, true, "VP9"); | |
489 RunBaseTest(&test); | |
490 } | |
491 | |
492 void VideoSendStreamTest::TestNackRetransmission( | 434 void VideoSendStreamTest::TestNackRetransmission( |
493 uint32_t retransmit_ssrc, | 435 uint32_t retransmit_ssrc, |
494 uint8_t retransmit_payload_type) { | 436 uint8_t retransmit_payload_type) { |
495 class NackObserver : public test::SendTest { | 437 class NackObserver : public test::SendTest { |
496 public: | 438 public: |
497 explicit NackObserver(uint32_t retransmit_ssrc, | 439 explicit NackObserver(uint32_t retransmit_ssrc, |
498 uint8_t retransmit_payload_type) | 440 uint8_t retransmit_payload_type) |
499 : SendTest(kDefaultTimeoutMs), | 441 : SendTest(kDefaultTimeoutMs), |
500 send_count_(0), | 442 send_count_(0), |
501 retransmit_ssrc_(retransmit_ssrc), | 443 retransmit_ssrc_(retransmit_ssrc), |
(...skipping 1813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2315 observation_complete_.Set(); | 2257 observation_complete_.Set(); |
2316 } | 2258 } |
2317 } | 2259 } |
2318 } test; | 2260 } test; |
2319 | 2261 |
2320 RunBaseTest(&test); | 2262 RunBaseTest(&test); |
2321 } | 2263 } |
2322 #endif | 2264 #endif |
2323 | 2265 |
2324 } // namespace webrtc | 2266 } // namespace webrtc |
OLD | NEW |