Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 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 | 10 |
| 11 #include "webrtc/call/rtp_demuxer.h" | 11 #include "webrtc/call/rtp_demuxer.h" |
| 12 | 12 |
| 13 #include <memory> | 13 #include <memory> |
| 14 #include <string> | 14 #include <string> |
| 15 | 15 |
| 16 #include "webrtc/base/arraysize.h" | 16 #include "webrtc/base/arraysize.h" |
| 17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 18 #include "webrtc/base/ptr_util.h" | 18 #include "webrtc/base/ptr_util.h" |
| 19 #include "webrtc/call/rtp_packet_sink_interface.h" | 19 #include "webrtc/call/rtp_packet_sink_interface.h" |
| 20 #include "webrtc/common_types.h" | |
| 20 #include "webrtc/modules/rtp_rtcp/include/rtp_header_extension_map.h" | 21 #include "webrtc/modules/rtp_rtcp/include/rtp_header_extension_map.h" |
| 21 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | 22 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
| 22 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" | 23 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
| 23 #include "webrtc/test/gmock.h" | 24 #include "webrtc/test/gmock.h" |
| 24 #include "webrtc/test/gtest.h" | 25 #include "webrtc/test/gtest.h" |
| 25 | 26 |
| 26 namespace webrtc { | 27 namespace webrtc { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 30 using ::testing::_; | 31 using ::testing::_; |
| 31 using ::testing::AtLeast; | 32 using ::testing::AtLeast; |
| 32 using ::testing::InSequence; | 33 using ::testing::InSequence; |
| 33 using ::testing::NiceMock; | 34 using ::testing::NiceMock; |
| 34 | 35 |
| 35 class MockRtpPacketSink : public RtpPacketSinkInterface { | 36 class MockRtpPacketSink : public RtpPacketSinkInterface { |
| 36 public: | 37 public: |
| 37 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&)); | 38 MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived&)); |
| 38 }; | 39 }; |
| 39 | 40 |
| 41 class MockRsidResolutionObserver : public RsidResolutionObserver { | |
| 42 public: | |
| 43 MOCK_METHOD2(OnRsidResolved, void(const std::string& rsid, uint32_t ssrc)); | |
| 44 }; | |
| 45 | |
| 40 MATCHER_P(SamePacketAs, other, "") { | 46 MATCHER_P(SamePacketAs, other, "") { |
| 41 return arg.Ssrc() == other.Ssrc() && | 47 return arg.Ssrc() == other.Ssrc() && |
| 42 arg.SequenceNumber() == other.SequenceNumber(); | 48 arg.SequenceNumber() == other.SequenceNumber(); |
| 43 } | 49 } |
| 44 | 50 |
| 45 std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived( | 51 std::unique_ptr<RtpPacketReceived> CreateRtpPacketReceived( |
| 46 uint32_t ssrc, | 52 uint32_t ssrc, |
| 47 size_t sequence_number = 0) { | 53 size_t sequence_number = 0) { |
| 48 // |sequence_number| is declared |size_t| to prevent ugly casts when calling | 54 // |sequence_number| is declared |size_t| to prevent ugly casts when calling |
| 49 // the function, but should in reality always be a |uint16_t|. | 55 // the function, but should in reality always be a |uint16_t|. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 | 118 |
| 113 // Test tear-down | 119 // Test tear-down |
| 114 for (const auto& sink : sinks) { | 120 for (const auto& sink : sinks) { |
| 115 demuxer.RemoveSink(&sink); | 121 demuxer.RemoveSink(&sink); |
| 116 } | 122 } |
| 117 } | 123 } |
| 118 | 124 |
| 119 TEST(RtpDemuxerTest, PacketsDeliveredInRightOrder) { | 125 TEST(RtpDemuxerTest, PacketsDeliveredInRightOrder) { |
| 120 RtpDemuxer demuxer; | 126 RtpDemuxer demuxer; |
| 121 | 127 |
| 122 constexpr uint32_t ssrcs[] = {101, 202, 303}; | 128 constexpr uint32_t ssrc = 101; |
|
danilchap
2017/06/16 16:46:18
avoid doing small unrated changes in a large CL.
W
eladalon
2017/06/19 11:28:46
I understand; I'll try to do so in the future.
FYI
| |
| 123 MockRtpPacketSink sinks[arraysize(ssrcs)]; | 129 MockRtpPacketSink sink; |
| 124 for (size_t i = 0; i < arraysize(ssrcs); i++) { | 130 demuxer.AddSink(ssrc, &sink); |
| 125 demuxer.AddSink(ssrcs[i], &sinks[i]); | |
| 126 } | |
| 127 | 131 |
| 128 std::unique_ptr<RtpPacketReceived> packets[5]; | 132 std::unique_ptr<RtpPacketReceived> packets[5]; |
| 129 for (size_t i = 0; i < arraysize(packets); i++) { | 133 for (size_t i = 0; i < arraysize(packets); i++) { |
| 130 packets[i] = CreateRtpPacketReceived(ssrcs[0], i); | 134 packets[i] = CreateRtpPacketReceived(ssrc, i); |
| 131 } | 135 } |
| 132 | 136 |
| 133 InSequence sequence; | 137 InSequence sequence; |
| 134 for (const auto& packet : packets) { | 138 for (const auto& packet : packets) { |
| 135 EXPECT_CALL(sinks[0], OnRtpPacket(SamePacketAs(*packet))).Times(1); | 139 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); |
| 136 } | 140 } |
| 137 | 141 |
| 138 for (const auto& packet : packets) { | 142 for (const auto& packet : packets) { |
| 139 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); | 143 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); |
| 140 } | 144 } |
| 141 | 145 |
| 142 // Test tear-down | 146 // Test tear-down |
| 143 for (const auto& sink : sinks) { | 147 demuxer.RemoveSink(&sink); |
| 144 demuxer.RemoveSink(&sink); | |
| 145 } | |
| 146 } | 148 } |
| 147 | 149 |
| 148 TEST(RtpDemuxerTest, MultipleSinksMappedToSameSsrc) { | 150 TEST(RtpDemuxerTest, MultipleSinksMappedToSameSsrc) { |
| 149 RtpDemuxer demuxer; | 151 RtpDemuxer demuxer; |
| 150 | 152 |
| 151 MockRtpPacketSink sinks[3]; | 153 MockRtpPacketSink sinks[3]; |
| 152 constexpr uint32_t ssrc = 404; | 154 constexpr uint32_t ssrc = 404; |
| 153 for (auto& sink : sinks) { | 155 for (auto& sink : sinks) { |
| 154 demuxer.AddSink(ssrc, &sink); | 156 demuxer.AddSink(ssrc, &sink); |
| 155 } | 157 } |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 auto packet = | 419 auto packet = |
| 418 CreateRtpPacketReceivedWithRsid(rsids[i], ssrc, sequence_number); | 420 CreateRtpPacketReceivedWithRsid(rsids[i], ssrc, sequence_number); |
| 419 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 421 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); |
| 420 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); | 422 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); |
| 421 } | 423 } |
| 422 | 424 |
| 423 // Test tear-down | 425 // Test tear-down |
| 424 demuxer.RemoveSink(&sink); | 426 demuxer.RemoveSink(&sink); |
| 425 } | 427 } |
| 426 | 428 |
| 429 TEST(RtpDemuxerTest, RsidUsedByMultipleSinks) { | |
| 430 RtpDemuxer demuxer; | |
| 431 | |
| 432 MockRtpPacketSink sinks[3]; | |
| 433 const std::string shared_rsid = "a"; | |
| 434 | |
| 435 for (MockRtpPacketSink& sink : sinks) { | |
| 436 demuxer.AddSink(shared_rsid, &sink); | |
| 437 } | |
| 438 | |
| 439 constexpr uint32_t shared_ssrc = 888; | |
| 440 auto packet = CreateRtpPacketReceivedWithRsid(shared_rsid, shared_ssrc); | |
| 441 | |
| 442 for (auto& sink : sinks) { | |
| 443 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | |
| 444 } | |
| 445 | |
| 446 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); | |
| 447 | |
| 448 // Test tear-down | |
| 449 for (MockRtpPacketSink& sink : sinks) { | |
| 450 demuxer.RemoveSink(&sink); | |
| 451 } | |
| 452 } | |
| 453 | |
| 427 TEST(RtpDemuxerTest, SinkWithBothRsidAndSsrcAssociations) { | 454 TEST(RtpDemuxerTest, SinkWithBothRsidAndSsrcAssociations) { |
| 428 RtpDemuxer demuxer; | 455 RtpDemuxer demuxer; |
| 429 | 456 |
| 430 MockRtpPacketSink sink; | 457 MockRtpPacketSink sink; |
| 431 constexpr uint32_t standalone_ssrc = 10101; | 458 constexpr uint32_t standalone_ssrc = 10101; |
| 432 constexpr uint32_t rsid_ssrc = 20202; | 459 constexpr uint32_t rsid_ssrc = 20202; |
| 433 const std::string rsid = "a"; | 460 const std::string rsid = "a"; |
| 434 | 461 |
| 435 demuxer.AddSink(standalone_ssrc, &sink); | 462 demuxer.AddSink(standalone_ssrc, &sink); |
| 436 demuxer.AddSink(rsid, &sink); | 463 demuxer.AddSink(rsid, &sink); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 461 | 488 |
| 462 constexpr uint16_t seq_num = 999; | 489 constexpr uint16_t seq_num = 999; |
| 463 auto packet = CreateRtpPacketReceivedWithRsid(rsid, ssrc, seq_num); | 490 auto packet = CreateRtpPacketReceivedWithRsid(rsid, ssrc, seq_num); |
| 464 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 491 EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); |
| 465 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); | 492 EXPECT_TRUE(demuxer.OnRtpPacket(*packet)); |
| 466 | 493 |
| 467 // Test tear-down | 494 // Test tear-down |
| 468 demuxer.RemoveSink(&sink); | 495 demuxer.RemoveSink(&sink); |
| 469 } | 496 } |
| 470 | 497 |
| 498 TEST(RtpDemuxerTest, RsidObserversInformedOfResolutions) { | |
| 499 RtpDemuxer demuxer; | |
| 500 | |
| 501 constexpr uint32_t ssrc = 111; | |
| 502 const std::string rsid = "a"; | |
| 503 | |
| 504 MockRsidResolutionObserver rsid_resolution_observers[3]; | |
| 505 for (auto& observer : rsid_resolution_observers) { | |
| 506 demuxer.RegisterRsidResolutionObserver(&observer); | |
| 507 EXPECT_CALL(observer, OnRsidResolved(rsid, ssrc)).Times(1); | |
| 508 } | |
| 509 | |
| 510 // The expected calls to OnRsidResolved() will be triggered by this. | |
| 511 demuxer.OnRtpPacket(*CreateRtpPacketReceivedWithRsid(rsid, ssrc)); | |
| 512 | |
| 513 // Test tear-down | |
| 514 for (auto& observer : rsid_resolution_observers) { | |
| 515 demuxer.DeregisterRsidResolutionObserver(&observer); | |
| 516 } | |
| 517 } | |
| 518 | |
| 519 // Normally, we only produce one notification per resolution (though no such | |
| 520 // guarantee is made), but when a new observer is added, we reset | |
| 521 // this suppression - we "re-resolve" associations for the benefit of the | |
| 522 // new observer.. | |
| 523 TEST(RtpDemuxerTest, NotificationSuppressionResetWhenNewObserverAdded) { | |
| 524 RtpDemuxer demuxer; | |
| 525 | |
| 526 constexpr uint32_t ssrc = 111; | |
| 527 const std::string rsid = "a"; | |
| 528 | |
| 529 // First observer registered, then gets a notification. | |
| 530 NiceMock<MockRsidResolutionObserver> first_observer; | |
| 531 demuxer.RegisterRsidResolutionObserver(&first_observer); | |
| 532 demuxer.OnRtpPacket(*CreateRtpPacketReceivedWithRsid(rsid, ssrc)); | |
| 533 | |
| 534 // Second observer registered, then gets a notification. No guarantee is made | |
| 535 // about whether the first observer would get an additional notification. | |
| 536 MockRsidResolutionObserver second_observer; | |
| 537 demuxer.RegisterRsidResolutionObserver(&second_observer); | |
| 538 EXPECT_CALL(first_observer, OnRsidResolved(rsid, ssrc)).Times(AtLeast(0)); | |
| 539 EXPECT_CALL(second_observer, OnRsidResolved(rsid, ssrc)).Times(1); | |
| 540 demuxer.OnRtpPacket(*CreateRtpPacketReceivedWithRsid(rsid, ssrc)); | |
| 541 | |
| 542 // Test tear-down | |
| 543 demuxer.DeregisterRsidResolutionObserver(&first_observer); | |
| 544 demuxer.DeregisterRsidResolutionObserver(&second_observer); | |
| 545 } | |
| 546 | |
| 547 TEST(RtpDemuxerTest, DeregisteredRsidObserversNotInformedOfResolutions) { | |
| 548 RtpDemuxer demuxer; | |
| 549 | |
| 550 constexpr uint32_t ssrc = 111; | |
| 551 const std::string rsid = "a"; | |
| 552 NiceMock<MockRtpPacketSink> sink; | |
| 553 demuxer.AddSink(rsid, &sink); | |
| 554 | |
| 555 // Register several, then deregister only one, to show that not all of the | |
| 556 // observers had been forgotten when one was removed. | |
| 557 MockRsidResolutionObserver observer_1; | |
| 558 MockRsidResolutionObserver observer_2_removed; | |
| 559 MockRsidResolutionObserver observer_3; | |
| 560 | |
| 561 demuxer.RegisterRsidResolutionObserver(&observer_1); | |
| 562 demuxer.RegisterRsidResolutionObserver(&observer_2_removed); | |
| 563 demuxer.RegisterRsidResolutionObserver(&observer_3); | |
| 564 | |
| 565 demuxer.DeregisterRsidResolutionObserver(&observer_2_removed); | |
| 566 | |
| 567 EXPECT_CALL(observer_1, OnRsidResolved(rsid, ssrc)).Times(1); | |
| 568 EXPECT_CALL(observer_2_removed, OnRsidResolved(_, _)).Times(0); | |
| 569 EXPECT_CALL(observer_3, OnRsidResolved(rsid, ssrc)).Times(1); | |
| 570 | |
| 571 // The expected calls to OnRsidResolved() will be triggered by this. | |
| 572 demuxer.OnRtpPacket(*CreateRtpPacketReceivedWithRsid(rsid, ssrc)); | |
| 573 | |
| 574 // Test tear-down | |
| 575 demuxer.RemoveSink(&sink); | |
| 576 demuxer.DeregisterRsidResolutionObserver(&observer_1); | |
| 577 demuxer.DeregisterRsidResolutionObserver(&observer_3); | |
| 578 } | |
| 579 | |
| 471 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 580 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
| 472 TEST(RtpDemuxerTest, RsidMustBeNonEmpty) { | 581 TEST(RtpDemuxerTest, RsidMustBeNonEmpty) { |
| 473 RtpDemuxer demuxer; | 582 RtpDemuxer demuxer; |
| 474 MockRtpPacketSink sink; | 583 MockRtpPacketSink sink; |
| 475 EXPECT_DEATH(demuxer.AddSink("", &sink), ""); | 584 EXPECT_DEATH(demuxer.AddSink("", &sink), ""); |
| 476 } | 585 } |
| 477 | 586 |
| 478 TEST(RtpDemuxerTest, RsidMustBeAlphaNumeric) { | 587 TEST(RtpDemuxerTest, RsidMustBeAlphaNumeric) { |
| 479 RtpDemuxer demuxer; | 588 RtpDemuxer demuxer; |
| 480 MockRtpPacketSink sink; | 589 MockRtpPacketSink sink; |
| 481 EXPECT_DEATH(demuxer.AddSink("a_3", &sink), ""); | 590 EXPECT_DEATH(demuxer.AddSink("a_3", &sink), ""); |
| 482 } | 591 } |
| 483 | 592 |
| 484 TEST(RtpDemuxerTest, RsidMustNotExceedMaximumLength) { | 593 TEST(RtpDemuxerTest, RsidMustNotExceedMaximumLength) { |
| 485 RtpDemuxer demuxer; | 594 RtpDemuxer demuxer; |
| 486 MockRtpPacketSink sink; | 595 MockRtpPacketSink sink; |
| 487 std::string rsid(StreamId::kMaxSize + 1, 'a'); | 596 std::string rsid(StreamId::kMaxSize + 1, 'a'); |
| 488 EXPECT_DEATH(demuxer.AddSink(rsid, &sink), ""); | 597 EXPECT_DEATH(demuxer.AddSink(rsid, &sink), ""); |
| 489 } | 598 } |
| 490 | 599 |
| 491 TEST(RtpDemuxerTest, RepeatedRsidAssociationsDisallowed) { | 600 TEST(RtpDemuxerTest, RepeatedRsidAssociationsDisallowed) { |
| 492 RtpDemuxer demuxer; | 601 RtpDemuxer demuxer; |
| 493 MockRtpPacketSink sink; | 602 MockRtpPacketSink sink; |
| 494 demuxer.AddSink("a", &sink); | 603 demuxer.AddSink("a", &sink); |
| 495 EXPECT_DEATH(demuxer.AddSink("a", &sink), ""); | 604 EXPECT_DEATH(demuxer.AddSink("a", &sink), ""); |
| 605 demuxer.RemoveSink(&sink); | |
| 496 } | 606 } |
| 607 | |
| 608 TEST(RtpDemuxerTest, | |
| 609 DoubleRegisterationOfNeverRegisteredRsidResolutionObserverDisallowed) { | |
| 610 RtpDemuxer demuxer; | |
| 611 MockRsidResolutionObserver observer; | |
| 612 demuxer.RegisterRsidResolutionObserver(&observer); | |
| 613 EXPECT_DEATH(demuxer.RegisterRsidResolutionObserver(&observer), ""); | |
| 614 demuxer.DeregisterRsidResolutionObserver(&observer); | |
| 615 } | |
| 616 | |
| 617 TEST(RtpDemuxerTest, | |
| 618 DregisterationOfNeverRegisteredRsidResolutionObserverDisallowed) { | |
| 619 RtpDemuxer demuxer; | |
| 620 MockRsidResolutionObserver observer; | |
| 621 EXPECT_DEATH(demuxer.DeregisterRsidResolutionObserver(&observer), ""); | |
| 622 } | |
| 623 | |
| 497 #endif | 624 #endif |
| 498 | 625 |
| 499 } // namespace | 626 } // namespace |
| 500 } // namespace webrtc | 627 } // namespace webrtc |
| OLD | NEW |