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 VideoSendStreamTest::kRedPayloadType; |
399 send_config->rtp.fec.ulpfec_payload_type = | 426 send_config->rtp.fec.ulpfec_payload_type = |
400 VideoSendStreamTest::kUlpfecPayloadType; | 427 VideoSendStreamTest::kUlpfecPayloadType; |
401 if (header_extensions_enabled_) { | 428 if (header_extensions_enabled_) { |
402 send_config->rtp.extensions.push_back(RtpExtension( | 429 send_config->rtp.extensions.push_back(RtpExtension( |
403 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); | 430 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); |
404 send_config->rtp.extensions.push_back( | 431 send_config->rtp.extensions.push_back( |
405 RtpExtension(RtpExtension::kTransportSequenceNumber, | 432 RtpExtension(RtpExtension::kTransportSequenceNumber, |
406 test::kTransportSequenceNumberExtensionId)); | 433 test::kTransportSequenceNumberExtensionId)); |
407 } | 434 } |
| 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; |
408 } | 439 } |
409 | 440 |
410 void PerformTest() override { | 441 void PerformTest() override { |
411 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; | 442 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets."; |
412 } | 443 } |
413 | 444 |
414 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_; | 445 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_; |
415 int send_count_; | 450 int send_count_; |
416 bool received_media_; | 451 bool received_media_; |
417 bool received_fec_; | 452 bool received_fec_; |
418 bool header_extensions_enabled_; | 453 bool header_extensions_enabled_; |
419 RTPHeader prev_header_; | 454 RTPHeader prev_header_; |
420 }; | 455 }; |
421 | 456 |
422 TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) { | 457 TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) { |
423 FecObserver test(true); | 458 FecObserver test(true, false, true, "VP8"); |
424 | |
425 RunBaseTest(&test); | 459 RunBaseTest(&test); |
426 } | 460 } |
427 | 461 |
428 TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) { | 462 TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) { |
429 FecObserver test(false); | 463 FecObserver test(false, false, true, "VP8"); |
430 | |
431 RunBaseTest(&test); | 464 RunBaseTest(&test); |
432 } | 465 } |
433 | 466 |
| 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 |
434 void VideoSendStreamTest::TestNackRetransmission( | 492 void VideoSendStreamTest::TestNackRetransmission( |
435 uint32_t retransmit_ssrc, | 493 uint32_t retransmit_ssrc, |
436 uint8_t retransmit_payload_type) { | 494 uint8_t retransmit_payload_type) { |
437 class NackObserver : public test::SendTest { | 495 class NackObserver : public test::SendTest { |
438 public: | 496 public: |
439 explicit NackObserver(uint32_t retransmit_ssrc, | 497 explicit NackObserver(uint32_t retransmit_ssrc, |
440 uint8_t retransmit_payload_type) | 498 uint8_t retransmit_payload_type) |
441 : SendTest(kDefaultTimeoutMs), | 499 : SendTest(kDefaultTimeoutMs), |
442 send_count_(0), | 500 send_count_(0), |
443 retransmit_ssrc_(retransmit_ssrc), | 501 retransmit_ssrc_(retransmit_ssrc), |
(...skipping 1813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2257 observation_complete_.Set(); | 2315 observation_complete_.Set(); |
2258 } | 2316 } |
2259 } | 2317 } |
2260 } test; | 2318 } test; |
2261 | 2319 |
2262 RunBaseTest(&test); | 2320 RunBaseTest(&test); |
2263 } | 2321 } |
2264 #endif | 2322 #endif |
2265 | 2323 |
2266 } // namespace webrtc | 2324 } // namespace webrtc |
OLD | NEW |