| /* | 
 |  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "call/rtp_demuxer.h" | 
 |  | 
 | #include <memory> | 
 | #include <set> | 
 | #include <string> | 
 |  | 
 | #include "absl/memory/memory.h" | 
 | #include "call/ssrc_binding_observer.h" | 
 | #include "call/test/mock_rtp_packet_sink_interface.h" | 
 | #include "common_types.h"  // NOLINT(build/include) | 
 | #include "modules/rtp_rtcp/include/rtp_header_extension_map.h" | 
 | #include "modules/rtp_rtcp/source/rtp_header_extensions.h" | 
 | #include "modules/rtp_rtcp/source/rtp_packet_received.h" | 
 | #include "rtc_base/arraysize.h" | 
 | #include "rtc_base/checks.h" | 
 | #include "rtc_base/numerics/safe_conversions.h" | 
 | #include "test/gmock.h" | 
 | #include "test/gtest.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | namespace { | 
 |  | 
 | using ::testing::_; | 
 | using ::testing::AtLeast; | 
 | using ::testing::AtMost; | 
 | using ::testing::InSequence; | 
 | using ::testing::NiceMock; | 
 |  | 
 | class MockSsrcBindingObserver : public SsrcBindingObserver { | 
 |  public: | 
 |   MOCK_METHOD2(OnSsrcBoundToRsid, void(const std::string& rsid, uint32_t ssrc)); | 
 |   MOCK_METHOD2(OnSsrcBoundToMid, void(const std::string& mid, uint32_t ssrc)); | 
 |   MOCK_METHOD3(OnSsrcBoundToMidRsid, | 
 |                void(const std::string& mid, | 
 |                     const std::string& rsid, | 
 |                     uint32_t ssrc)); | 
 |   MOCK_METHOD2(OnSsrcBoundToPayloadType, | 
 |                void(uint8_t payload_type, uint32_t ssrc)); | 
 | }; | 
 |  | 
 | class RtpDemuxerTest : public testing::Test { | 
 |  protected: | 
 |   ~RtpDemuxerTest() { | 
 |     for (auto* sink : sinks_to_tear_down_) { | 
 |       demuxer_.RemoveSink(sink); | 
 |     } | 
 |     for (auto* observer : observers_to_tear_down_) { | 
 |       demuxer_.DeregisterSsrcBindingObserver(observer); | 
 |     } | 
 |   } | 
 |  | 
 |   // These are convenience methods for calling demuxer.AddSink with different | 
 |   // parameters and will ensure that the sink is automatically removed when the | 
 |   // test case finishes. | 
 |  | 
 |   bool AddSink(const RtpDemuxerCriteria& criteria, | 
 |                RtpPacketSinkInterface* sink) { | 
 |     bool added = demuxer_.AddSink(criteria, sink); | 
 |     if (added) { | 
 |       sinks_to_tear_down_.insert(sink); | 
 |     } | 
 |     return added; | 
 |   } | 
 |  | 
 |   bool AddSinkOnlySsrc(uint32_t ssrc, RtpPacketSinkInterface* sink) { | 
 |     RtpDemuxerCriteria criteria; | 
 |     criteria.ssrcs = {ssrc}; | 
 |     return AddSink(criteria, sink); | 
 |   } | 
 |  | 
 |   bool AddSinkOnlyRsid(const std::string& rsid, RtpPacketSinkInterface* sink) { | 
 |     RtpDemuxerCriteria criteria; | 
 |     criteria.rsid = rsid; | 
 |     return AddSink(criteria, sink); | 
 |   } | 
 |  | 
 |   bool AddSinkOnlyMid(const std::string& mid, RtpPacketSinkInterface* sink) { | 
 |     RtpDemuxerCriteria criteria; | 
 |     criteria.mid = mid; | 
 |     return AddSink(criteria, sink); | 
 |   } | 
 |  | 
 |   bool AddSinkBothMidRsid(const std::string& mid, | 
 |                           const std::string& rsid, | 
 |                           RtpPacketSinkInterface* sink) { | 
 |     RtpDemuxerCriteria criteria; | 
 |     criteria.mid = mid; | 
 |     criteria.rsid = rsid; | 
 |     return AddSink(criteria, sink); | 
 |   } | 
 |  | 
 |   bool RemoveSink(RtpPacketSinkInterface* sink) { | 
 |     sinks_to_tear_down_.erase(sink); | 
 |     return demuxer_.RemoveSink(sink); | 
 |   } | 
 |  | 
 |   // These are convenience methods for calling | 
 |   // demuxer.{Register|Unregister}SsrcBindingObserver such that observers are | 
 |   // automatically removed when the test finishes. | 
 |  | 
 |   void RegisterSsrcBindingObserver(SsrcBindingObserver* observer) { | 
 |     demuxer_.RegisterSsrcBindingObserver(observer); | 
 |     observers_to_tear_down_.insert(observer); | 
 |   } | 
 |  | 
 |   void DeregisterSsrcBindingObserver(SsrcBindingObserver* observer) { | 
 |     demuxer_.DeregisterSsrcBindingObserver(observer); | 
 |     observers_to_tear_down_.erase(observer); | 
 |   } | 
 |  | 
 |   // The CreatePacket* methods are helpers for creating new RTP packets with | 
 |   // various attributes set. Tests should use the helper that provides the | 
 |   // minimum information needed to exercise the behavior under test. Tests also | 
 |   // should not rely on any behavior which is not clearly described in the | 
 |   // helper name/arguments. Any additional settings that are not covered by the | 
 |   // helper should be set manually on the packet once it has been returned. | 
 |   // For example, most tests in this file do not care about the RTP sequence | 
 |   // number, but to ensure that the returned packets are valid the helpers will | 
 |   // auto-increment the sequence number starting with 1. Tests that rely on | 
 |   // specific sequence number behavior should call SetSequenceNumber manually on | 
 |   // the returned packet. | 
 |  | 
 |   // Intended for use only by other CreatePacket* helpers. | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacket( | 
 |       uint32_t ssrc, | 
 |       RtpPacketReceived::ExtensionManager* extension_manager) { | 
 |     auto packet = absl::make_unique<RtpPacketReceived>(extension_manager); | 
 |     packet->SetSsrc(ssrc); | 
 |     packet->SetSequenceNumber(next_sequence_number_++); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrc(uint32_t ssrc) { | 
 |     return CreatePacket(ssrc, nullptr); | 
 |   } | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcMid( | 
 |       uint32_t ssrc, | 
 |       const std::string& mid) { | 
 |     RtpPacketReceived::ExtensionManager extension_manager; | 
 |     extension_manager.Register<RtpMid>(11); | 
 |  | 
 |     auto packet = CreatePacket(ssrc, &extension_manager); | 
 |     packet->SetExtension<RtpMid>(mid); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcRsid( | 
 |       uint32_t ssrc, | 
 |       const std::string& rsid) { | 
 |     RtpPacketReceived::ExtensionManager extension_manager; | 
 |     extension_manager.Register<RtpStreamId>(6); | 
 |  | 
 |     auto packet = CreatePacket(ssrc, &extension_manager); | 
 |     packet->SetExtension<RtpStreamId>(rsid); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcRrid( | 
 |       uint32_t ssrc, | 
 |       const std::string& rrid) { | 
 |     RtpPacketReceived::ExtensionManager extension_manager; | 
 |     extension_manager.Register<RepairedRtpStreamId>(7); | 
 |  | 
 |     auto packet = CreatePacket(ssrc, &extension_manager); | 
 |     packet->SetExtension<RepairedRtpStreamId>(rrid); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcMidRsid( | 
 |       uint32_t ssrc, | 
 |       const std::string& mid, | 
 |       const std::string& rsid) { | 
 |     RtpPacketReceived::ExtensionManager extension_manager; | 
 |     extension_manager.Register<RtpMid>(11); | 
 |     extension_manager.Register<RtpStreamId>(6); | 
 |  | 
 |     auto packet = CreatePacket(ssrc, &extension_manager); | 
 |     packet->SetExtension<RtpMid>(mid); | 
 |     packet->SetExtension<RtpStreamId>(rsid); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcRsidRrid( | 
 |       uint32_t ssrc, | 
 |       const std::string& rsid, | 
 |       const std::string& rrid) { | 
 |     RtpPacketReceived::ExtensionManager extension_manager; | 
 |     extension_manager.Register<RtpStreamId>(6); | 
 |     extension_manager.Register<RepairedRtpStreamId>(7); | 
 |  | 
 |     auto packet = CreatePacket(ssrc, &extension_manager); | 
 |     packet->SetExtension<RtpStreamId>(rsid); | 
 |     packet->SetExtension<RepairedRtpStreamId>(rrid); | 
 |     return packet; | 
 |   } | 
 |  | 
 |   RtpDemuxer demuxer_; | 
 |   std::set<RtpPacketSinkInterface*> sinks_to_tear_down_; | 
 |   std::set<SsrcBindingObserver*> observers_to_tear_down_; | 
 |   uint16_t next_sequence_number_ = 1; | 
 | }; | 
 |  | 
 | MATCHER_P(SamePacketAs, other, "") { | 
 |   return arg.Ssrc() == other.Ssrc() && | 
 |          arg.SequenceNumber() == other.SequenceNumber(); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, CanAddSinkBySsrc) { | 
 |   MockRtpPacketSink sink; | 
 |   constexpr uint32_t ssrc = 1; | 
 |  | 
 |   EXPECT_TRUE(AddSinkOnlySsrc(ssrc, &sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, AllowAddSinkWithOverlappingPayloadTypesIfDifferentMid) { | 
 |   const std::string mid1 = "v"; | 
 |   const std::string mid2 = "a"; | 
 |   constexpr uint8_t pt1 = 30; | 
 |   constexpr uint8_t pt2 = 31; | 
 |   constexpr uint8_t pt3 = 32; | 
 |  | 
 |   RtpDemuxerCriteria pt1_pt2; | 
 |   pt1_pt2.mid = mid1; | 
 |   pt1_pt2.payload_types = {pt1, pt2}; | 
 |   MockRtpPacketSink sink1; | 
 |   AddSink(pt1_pt2, &sink1); | 
 |  | 
 |   RtpDemuxerCriteria pt1_pt3; | 
 |   pt1_pt2.mid = mid2; | 
 |   pt1_pt3.payload_types = {pt1, pt3}; | 
 |   MockRtpPacketSink sink2; | 
 |   EXPECT_TRUE(AddSink(pt1_pt3, &sink2)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RejectAddSinkForSameMidOnly) { | 
 |   const std::string mid = "mid"; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |   EXPECT_FALSE(AddSinkOnlyMid(mid, &sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RejectAddSinkForSameMidRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |  | 
 |   MockRtpPacketSink sink1; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink1); | 
 |  | 
 |   MockRtpPacketSink sink2; | 
 |   EXPECT_FALSE(AddSinkBothMidRsid(mid, rsid, &sink2)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RejectAddSinkForConflictingMidAndMidRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |  | 
 |   MockRtpPacketSink mid_sink; | 
 |   AddSinkOnlyMid(mid, &mid_sink); | 
 |  | 
 |   // This sink would never get any packets routed to it because the above sink | 
 |   // would receive them all. | 
 |   MockRtpPacketSink mid_rsid_sink; | 
 |   EXPECT_FALSE(AddSinkBothMidRsid(mid, rsid, &mid_rsid_sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RejectAddSinkForConflictingMidRsidAndMid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = ""; | 
 |  | 
 |   MockRtpPacketSink mid_rsid_sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &mid_rsid_sink); | 
 |  | 
 |   // This sink would shadow the above sink. | 
 |   MockRtpPacketSink mid_sink; | 
 |   EXPECT_FALSE(AddSinkOnlyMid(mid, &mid_sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, AddSinkFailsIfCalledForTwoSinksWithSameSsrc) { | 
 |   MockRtpPacketSink sink_a; | 
 |   MockRtpPacketSink sink_b; | 
 |   constexpr uint32_t ssrc = 1; | 
 |   ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sink_a)); | 
 |  | 
 |   EXPECT_FALSE(AddSinkOnlySsrc(ssrc, &sink_b)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, AddSinkFailsIfCalledTwiceEvenIfSameSinkWithSameSsrc) { | 
 |   MockRtpPacketSink sink; | 
 |   constexpr uint32_t ssrc = 1; | 
 |   ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sink)); | 
 |  | 
 |   EXPECT_FALSE(AddSinkOnlySsrc(ssrc, &sink)); | 
 | } | 
 |  | 
 | // TODO(steveanton): Currently fails because payload type validation is not | 
 | // complete in AddSink (see note in rtp_demuxer.cc). | 
 | TEST_F(RtpDemuxerTest, DISABLED_RejectAddSinkForSamePayloadTypes) { | 
 |   constexpr uint8_t pt1 = 30; | 
 |   constexpr uint8_t pt2 = 31; | 
 |  | 
 |   RtpDemuxerCriteria pt1_pt2; | 
 |   pt1_pt2.payload_types = {pt1, pt2}; | 
 |   MockRtpPacketSink sink1; | 
 |   AddSink(pt1_pt2, &sink1); | 
 |  | 
 |   RtpDemuxerCriteria pt2_pt1; | 
 |   pt2_pt1.payload_types = {pt2, pt1}; | 
 |   MockRtpPacketSink sink2; | 
 |   EXPECT_FALSE(AddSink(pt2_pt1, &sink2)); | 
 | } | 
 |  | 
 | // Routing Tests | 
 |  | 
 | TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkBySsrc) { | 
 |   constexpr uint32_t ssrcs[] = {101, 202, 303}; | 
 |   MockRtpPacketSink sinks[arraysize(ssrcs)]; | 
 |   for (size_t i = 0; i < arraysize(ssrcs); i++) { | 
 |     AddSinkOnlySsrc(ssrcs[i], &sinks[i]); | 
 |   } | 
 |  | 
 |   for (size_t i = 0; i < arraysize(ssrcs); i++) { | 
 |     auto packet = CreatePacketWithSsrc(ssrcs[i]); | 
 |     EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByRsid) { | 
 |   const std::string rsids[] = {"a", "b", "c"}; | 
 |   MockRtpPacketSink sinks[arraysize(rsids)]; | 
 |   for (size_t i = 0; i < arraysize(rsids); i++) { | 
 |     AddSinkOnlyRsid(rsids[i], &sinks[i]); | 
 |   } | 
 |  | 
 |   for (size_t i = 0; i < arraysize(rsids); i++) { | 
 |     auto packet = | 
 |         CreatePacketWithSsrcRsid(rtc::checked_cast<uint32_t>(i), rsids[i]); | 
 |     EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByMid) { | 
 |   const std::string mids[] = {"a", "v", "s"}; | 
 |   MockRtpPacketSink sinks[arraysize(mids)]; | 
 |   for (size_t i = 0; i < arraysize(mids); i++) { | 
 |     AddSinkOnlyMid(mids[i], &sinks[i]); | 
 |   } | 
 |  | 
 |   for (size_t i = 0; i < arraysize(mids); i++) { | 
 |     auto packet = | 
 |         CreatePacketWithSsrcMid(rtc::checked_cast<uint32_t>(i), mids[i]); | 
 |     EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByMidAndRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByRepairedRsid) { | 
 |   const std::string rrid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlyRsid(rrid, &sink); | 
 |  | 
 |   auto packet_with_rrid = CreatePacketWithSsrcRrid(ssrc, rrid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_rrid))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_rrid)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByPayloadType) { | 
 |   constexpr uint32_t ssrc = 10; | 
 |   constexpr uint8_t payload_type = 30; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.payload_types = {payload_type}; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   packet->SetPayloadType(payload_type); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, PacketsDeliveredInRightOrder) { | 
 |   constexpr uint32_t ssrc = 101; | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlySsrc(ssrc, &sink); | 
 |  | 
 |   std::unique_ptr<RtpPacketReceived> packets[5]; | 
 |   for (size_t i = 0; i < arraysize(packets); i++) { | 
 |     packets[i] = CreatePacketWithSsrc(ssrc); | 
 |     packets[i]->SetSequenceNumber(rtc::checked_cast<uint16_t>(i)); | 
 |   } | 
 |  | 
 |   InSequence sequence; | 
 |   for (const auto& packet : packets) { | 
 |     EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   } | 
 |  | 
 |   for (const auto& packet : packets) { | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, SinkMappedToMultipleSsrcs) { | 
 |   constexpr uint32_t ssrcs[] = {404, 505, 606}; | 
 |   MockRtpPacketSink sink; | 
 |   for (uint32_t ssrc : ssrcs) { | 
 |     AddSinkOnlySsrc(ssrc, &sink); | 
 |   } | 
 |  | 
 |   // The sink which is associated with multiple SSRCs gets the callback | 
 |   // triggered for each of those SSRCs. | 
 |   for (uint32_t ssrc : ssrcs) { | 
 |     auto packet = CreatePacketWithSsrc(ssrc); | 
 |     EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedBeforeFirstPacket) { | 
 |   constexpr uint32_t ssrc = 404; | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlySsrc(ssrc, &sink); | 
 |  | 
 |   ASSERT_TRUE(RemoveSink(&sink)); | 
 |  | 
 |   // The removed sink does not get callbacks. | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);  // Not called. | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedAfterFirstPacket) { | 
 |   constexpr uint32_t ssrc = 404; | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlySsrc(ssrc, &sink); | 
 |  | 
 |   InSequence sequence; | 
 |   for (size_t i = 0; i < 10; i++) { | 
 |     ASSERT_TRUE(demuxer_.OnRtpPacket(*CreatePacketWithSsrc(ssrc))); | 
 |   } | 
 |  | 
 |   ASSERT_TRUE(RemoveSink(&sink)); | 
 |  | 
 |   // The removed sink does not get callbacks. | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);  // Not called. | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // An SSRC may only be mapped to a single sink. However, since configuration | 
 | // of this associations might come from the network, we need to fail gracefully. | 
 | TEST_F(RtpDemuxerTest, OnlyOneSinkPerSsrcGetsOnRtpPacketTriggered) { | 
 |   MockRtpPacketSink sinks[3]; | 
 |   constexpr uint32_t ssrc = 404; | 
 |   ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sinks[0])); | 
 |   ASSERT_FALSE(AddSinkOnlySsrc(ssrc, &sinks[1])); | 
 |   ASSERT_FALSE(AddSinkOnlySsrc(ssrc, &sinks[2])); | 
 |  | 
 |   // The first sink associated with the SSRC remains active; other sinks | 
 |   // were not really added, and so do not get OnRtpPacket() called. | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sinks[0], OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_CALL(sinks[1], OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sinks[2], OnRtpPacket(_)).Times(0); | 
 |   ASSERT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoRepeatedCallbackOnRepeatedAddSinkForSameSink) { | 
 |   constexpr uint32_t ssrc = 111; | 
 |   MockRtpPacketSink sink; | 
 |  | 
 |   ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sink)); | 
 |   ASSERT_FALSE(AddSinkOnlySsrc(ssrc, &sink)); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RemoveSinkReturnsFalseForNeverAddedSink) { | 
 |   MockRtpPacketSink sink; | 
 |   EXPECT_FALSE(RemoveSink(&sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RemoveSinkReturnsTrueForPreviouslyAddedSsrcSink) { | 
 |   constexpr uint32_t ssrc = 101; | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlySsrc(ssrc, &sink); | 
 |  | 
 |   EXPECT_TRUE(RemoveSink(&sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, | 
 |        RemoveSinkReturnsTrueForUnresolvedPreviouslyAddedRsidSink) { | 
 |   const std::string rsid = "a"; | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   EXPECT_TRUE(RemoveSink(&sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, | 
 |        RemoveSinkReturnsTrueForResolvedPreviouslyAddedRsidSink) { | 
 |   const std::string rsid = "a"; | 
 |   constexpr uint32_t ssrc = 101; | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |   ASSERT_TRUE(demuxer_.OnRtpPacket(*CreatePacketWithSsrcRsid(ssrc, rsid))); | 
 |  | 
 |   EXPECT_TRUE(RemoveSink(&sink)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RsidLearnedAndLaterPacketsDeliveredWithOnlySsrc) { | 
 |   MockRtpPacketSink sink; | 
 |   const std::string rsid = "a"; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   // Create a sequence of RTP packets, where only the first one actually | 
 |   // mentions the RSID. | 
 |   std::unique_ptr<RtpPacketReceived> packets[5]; | 
 |   constexpr uint32_t rsid_ssrc = 111; | 
 |   packets[0] = CreatePacketWithSsrcRsid(rsid_ssrc, rsid); | 
 |   for (size_t i = 1; i < arraysize(packets); i++) { | 
 |     packets[i] = CreatePacketWithSsrc(rsid_ssrc); | 
 |   } | 
 |  | 
 |   // The first packet associates the RSID with the SSRC, thereby allowing the | 
 |   // demuxer to correctly demux all of the packets. | 
 |   InSequence sequence; | 
 |   for (const auto& packet : packets) { | 
 |     EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   } | 
 |   for (const auto& packet : packets) { | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedBeforeFirstPacket) { | 
 |   MockRtpPacketSink sink; | 
 |   const std::string rsid = "a"; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   // Sink removed - it won't get triggers even if packets with its RSID arrive. | 
 |   ASSERT_TRUE(RemoveSink(&sink)); | 
 |  | 
 |   constexpr uint32_t ssrc = 111; | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);  // Not called. | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedAfterFirstPacket) { | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   const std::string rsid = "a"; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   InSequence sequence; | 
 |   constexpr uint32_t ssrc = 111; | 
 |   for (size_t i = 0; i < 10; i++) { | 
 |     auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |     ASSERT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 |  | 
 |   // Sink removed - it won't get triggers even if packets with its RSID arrive. | 
 |   ASSERT_TRUE(RemoveSink(&sink)); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);  // Not called. | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnMidSinkRemovedBeforeFirstPacket) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |   RemoveSink(&sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnMidSinkRemovedAfterFirstPacket) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   auto p1 = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   demuxer_.OnRtpPacket(*p1); | 
 |  | 
 |   RemoveSink(&sink); | 
 |  | 
 |   auto p2 = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*p2)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, NoCallbackOnMidRsidSinkRemovedAfterFirstPacket) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   auto p1 = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   demuxer_.OnRtpPacket(*p1); | 
 |  | 
 |   RemoveSink(&sink); | 
 |  | 
 |   auto p2 = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*p2)); | 
 | } | 
 |  | 
 | // The RSID to SSRC mapping should be one-to-one. If we end up receiving | 
 | // two (or more) packets with the same SSRC, but different RSIDs, we guarantee | 
 | // delivery to one of them but not both. | 
 | TEST_F(RtpDemuxerTest, FirstSsrcAssociatedWithAnRsidIsNotForgotten) { | 
 |   // Each sink has a distinct RSID. | 
 |   MockRtpPacketSink sink_a; | 
 |   const std::string rsid_a = "a"; | 
 |   AddSinkOnlyRsid(rsid_a, &sink_a); | 
 |  | 
 |   MockRtpPacketSink sink_b; | 
 |   const std::string rsid_b = "b"; | 
 |   AddSinkOnlyRsid(rsid_b, &sink_b); | 
 |  | 
 |   InSequence sequence;  // Verify that the order of delivery is unchanged. | 
 |  | 
 |   constexpr uint32_t shared_ssrc = 100; | 
 |  | 
 |   // First a packet with |rsid_a| is received, and |sink_a| is associated with | 
 |   // its SSRC. | 
 |   auto packet_a = CreatePacketWithSsrcRsid(shared_ssrc, rsid_a); | 
 |   EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_a))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_a)); | 
 |  | 
 |   // Second, a packet with |rsid_b| is received. We guarantee that |sink_b| | 
 |   // receives it. | 
 |   auto packet_b = CreatePacketWithSsrcRsid(shared_ssrc, rsid_b); | 
 |   EXPECT_CALL(sink_a, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink_b, OnRtpPacket(SamePacketAs(*packet_b))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_b)); | 
 |  | 
 |   // Known edge-case; adding a new RSID association makes us re-examine all | 
 |   // SSRCs. |sink_b| may or may not be associated with the SSRC now; we make | 
 |   // no promises on that. However, since the RSID is specified and it cannot be | 
 |   // found the packet should be dropped. | 
 |   MockRtpPacketSink sink_c; | 
 |   const std::string rsid_c = "c"; | 
 |   constexpr uint32_t some_other_ssrc = shared_ssrc + 1; | 
 |   AddSinkOnlySsrc(some_other_ssrc, &sink_c); | 
 |  | 
 |   auto packet_c = CreatePacketWithSsrcMid(shared_ssrc, rsid_c); | 
 |   EXPECT_CALL(sink_a, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink_b, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink_c, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet_c)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, MultipleRsidsOnSameSink) { | 
 |   MockRtpPacketSink sink; | 
 |   const std::string rsids[] = {"a", "b", "c"}; | 
 |  | 
 |   for (const std::string& rsid : rsids) { | 
 |     AddSinkOnlyRsid(rsid, &sink); | 
 |   } | 
 |  | 
 |   InSequence sequence; | 
 |   for (size_t i = 0; i < arraysize(rsids); i++) { | 
 |     // Assign different SSRCs and sequence numbers to all packets. | 
 |     const uint32_t ssrc = 1000 + static_cast<uint32_t>(i); | 
 |     const uint16_t sequence_number = 50 + static_cast<uint16_t>(i); | 
 |     auto packet = CreatePacketWithSsrcRsid(ssrc, rsids[i]); | 
 |     packet->SetSequenceNumber(sequence_number); | 
 |     EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | // RSIDs are given higher priority than SSRC because we believe senders are less | 
 | // likely to mislabel packets with RSID than mislabel them with SSRCs. | 
 | TEST_F(RtpDemuxerTest, SinkWithBothRsidAndSsrcAssociations) { | 
 |   MockRtpPacketSink sink; | 
 |   constexpr uint32_t standalone_ssrc = 10101; | 
 |   constexpr uint32_t rsid_ssrc = 20202; | 
 |   const std::string rsid = "1"; | 
 |  | 
 |   AddSinkOnlySsrc(standalone_ssrc, &sink); | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   InSequence sequence; | 
 |  | 
 |   auto ssrc_packet = CreatePacketWithSsrc(standalone_ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*ssrc_packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*ssrc_packet)); | 
 |  | 
 |   auto rsid_packet = CreatePacketWithSsrcRsid(rsid_ssrc, rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*rsid_packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*rsid_packet)); | 
 | } | 
 |  | 
 | // Packets are always guaranteed to be routed to only one sink. | 
 | TEST_F(RtpDemuxerTest, AssociatingByRsidAndBySsrcCannotTriggerDoubleCall) { | 
 |   constexpr uint32_t ssrc = 10101; | 
 |   const std::string rsid = "a"; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlySsrc(ssrc, &sink); | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, ObserversNotifiedOfSsrcBoundToMid) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   EXPECT_CALL(observer, OnSsrcBoundToMid(mid, ssrc)); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, ObserversNotifiedOfSsrcBoundToRsid) { | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 111; | 
 |  | 
 |   // Only RSIDs which the demuxer knows may be resolved. | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   NiceMock<MockSsrcBindingObserver> rsid_resolution_observers[3]; | 
 |   for (auto& observer : rsid_resolution_observers) { | 
 |     RegisterSsrcBindingObserver(&observer); | 
 |     EXPECT_CALL(observer, OnSsrcBoundToRsid(rsid, ssrc)).Times(1); | 
 |   } | 
 |  | 
 |   // The expected calls to OnSsrcBoundToRsid() will be triggered by this. | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, ObserversNotifiedOfSsrcBoundToMidRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   EXPECT_CALL(observer, OnSsrcBoundToMidRsid(mid, rsid, ssrc)); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, ObserversNotifiedOfSsrcBoundToPayloadType) { | 
 |   constexpr uint8_t payload_type = 3; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.payload_types = {payload_type}; | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   packet->SetPayloadType(payload_type); | 
 |   EXPECT_CALL(observer, OnSsrcBoundToPayloadType(payload_type, ssrc)); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // If one sink is associated with SSRC x, and another sink with RSID y, then if | 
 | // we receive a packet with both SSRC x and RSID y, route that to only the sink | 
 | // for RSID y since we believe RSID tags to be more trustworthy than signaled | 
 | // SSRCs. | 
 | TEST_F(RtpDemuxerTest, | 
 |        PacketFittingBothRsidSinkAndSsrcSinkGivenOnlyToRsidSink) { | 
 |   constexpr uint32_t ssrc = 111; | 
 |   MockRtpPacketSink ssrc_sink; | 
 |   AddSinkOnlySsrc(ssrc, &ssrc_sink); | 
 |  | 
 |   const std::string rsid = "a"; | 
 |   MockRtpPacketSink rsid_sink; | 
 |   AddSinkOnlyRsid(rsid, &rsid_sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |  | 
 |   EXPECT_CALL(ssrc_sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(rsid_sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // We're not expecting RSIDs to be resolved to SSRCs which were previously | 
 | // mapped to sinks, and make no guarantees except for graceful handling. | 
 | TEST_F(RtpDemuxerTest, | 
 |        GracefullyHandleRsidBeingMappedToPrevouslyAssociatedSsrc) { | 
 |   constexpr uint32_t ssrc = 111; | 
 |   NiceMock<MockRtpPacketSink> ssrc_sink; | 
 |   AddSinkOnlySsrc(ssrc, &ssrc_sink); | 
 |  | 
 |   const std::string rsid = "a"; | 
 |   NiceMock<MockRtpPacketSink> rsid_sink; | 
 |   AddSinkOnlyRsid(rsid, &rsid_sink); | 
 |  | 
 |   NiceMock<MockSsrcBindingObserver> observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   // The SSRC was mapped to an SSRC sink, but was even active (packets flowed | 
 |   // over it). | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   demuxer_.OnRtpPacket(*packet); | 
 |  | 
 |   // If the SSRC sink is ever removed, the RSID sink *might* receive indications | 
 |   // of packets, and observers *might* be informed. Only graceful handling | 
 |   // is guaranteed. | 
 |   RemoveSink(&ssrc_sink); | 
 |   EXPECT_CALL(rsid_sink, OnRtpPacket(SamePacketAs(*packet))).Times(AtLeast(0)); | 
 |   EXPECT_CALL(observer, OnSsrcBoundToRsid(rsid, ssrc)).Times(AtLeast(0)); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // Tests that when one MID sink is configured, packets that include the MID | 
 | // extension will get routed to that sink and any packets that use the same | 
 | // SSRC as one of those packets later will also get routed to the sink, even | 
 | // if a new SSRC is introduced for the same MID. | 
 | TEST_F(RtpDemuxerTest, RoutedByMidWhenSsrcAdded) { | 
 |   const std::string mid = "v"; | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   constexpr uint32_t ssrc1 = 10; | 
 |   constexpr uint32_t ssrc2 = 11; | 
 |  | 
 |   auto packet_ssrc1_mid = CreatePacketWithSsrcMid(ssrc1, mid); | 
 |   demuxer_.OnRtpPacket(*packet_ssrc1_mid); | 
 |   auto packet_ssrc2_mid = CreatePacketWithSsrcMid(ssrc2, mid); | 
 |   demuxer_.OnRtpPacket(*packet_ssrc2_mid); | 
 |  | 
 |   auto packet_ssrc1_only = CreatePacketWithSsrc(ssrc1); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc1_only))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc1_only)); | 
 |  | 
 |   auto packet_ssrc2_only = CreatePacketWithSsrc(ssrc2); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc2_only))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc2_only)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DontLearnMidSsrcBindingBeforeSinkAdded) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   auto packet_ssrc_mid = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_ssrc_mid)); | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   auto packet_ssrc_only = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet_ssrc_only)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DontForgetMidSsrcBindingWhenSinkRemoved) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink1; | 
 |   AddSinkOnlyMid(mid, &sink1); | 
 |  | 
 |   auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   demuxer_.OnRtpPacket(*packet_with_mid); | 
 |  | 
 |   RemoveSink(&sink1); | 
 |  | 
 |   MockRtpPacketSink sink2; | 
 |   AddSinkOnlyMid(mid, &sink2); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink2, OnRtpPacket(SamePacketAs(*packet_with_ssrc))); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | // If a sink is added with only a MID, then any packet with that MID no matter | 
 | // the RSID should be routed to that sink. | 
 | TEST_F(RtpDemuxerTest, RoutedByMidWithAnyRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid1 = "1"; | 
 |   const std::string rsid2 = "2"; | 
 |   constexpr uint32_t ssrc1 = 10; | 
 |   constexpr uint32_t ssrc2 = 11; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   InSequence sequence; | 
 |  | 
 |   auto packet_ssrc1_rsid1 = CreatePacketWithSsrcMidRsid(ssrc1, mid, rsid1); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc1_rsid1))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc1_rsid1)); | 
 |  | 
 |   auto packet_ssrc2_rsid2 = CreatePacketWithSsrcMidRsid(ssrc2, mid, rsid2); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc2_rsid2))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc2_rsid2)); | 
 | } | 
 |  | 
 | // These two tests verify that for a sink added with a MID, RSID pair, if the | 
 | // MID and RSID are learned in separate packets (e.g., because the header | 
 | // extensions are sent separately), then a later packet with just SSRC will get | 
 | // routed to that sink. | 
 | // The first test checks that the functionality works when MID is learned first. | 
 | // The second test checks that the functionality works when RSID is learned | 
 | // first. | 
 | TEST_F(RtpDemuxerTest, LearnMidThenRsidSeparatelyAndRouteBySsrc) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_with_mid)); | 
 |  | 
 |   auto packet_with_rsid = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_with_rsid)); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, LearnRsidThenMidSeparatelyAndRouteBySsrc) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   auto packet_with_rsid = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_with_rsid)); | 
 |  | 
 |   auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_with_mid)); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DontLearnMidRsidBindingBeforeSinkAdded) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   auto packet_with_both = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_with_both)); | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DontForgetMidRsidBindingWhenSinkRemoved) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink1; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink1); | 
 |  | 
 |   auto packet_with_both = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   demuxer_.OnRtpPacket(*packet_with_both); | 
 |  | 
 |   RemoveSink(&sink1); | 
 |  | 
 |   MockRtpPacketSink sink2; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink2); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink2, OnRtpPacket(SamePacketAs(*packet_with_ssrc))); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, LearnMidRsidBindingAfterSinkAdded) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   auto packet_with_both = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid); | 
 |   demuxer_.OnRtpPacket(*packet_with_both); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DropByPayloadTypeIfNoSink) { | 
 |   constexpr uint8_t payload_type = 30; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   packet->SetPayloadType(payload_type); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // For legacy applications, it's possible for us to demux if the payload type is | 
 | // unique. But if multiple sinks are registered with different MIDs and the same | 
 | // payload types, then we cannot route a packet with just payload type because | 
 | // it is ambiguous which sink it should be sent to. | 
 | TEST_F(RtpDemuxerTest, DropByPayloadTypeIfAddedInMultipleSinks) { | 
 |   const std::string mid1 = "v"; | 
 |   const std::string mid2 = "a"; | 
 |   constexpr uint8_t payload_type = 30; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   RtpDemuxerCriteria mid1_pt; | 
 |   mid1_pt.mid = mid1; | 
 |   mid1_pt.payload_types = {payload_type}; | 
 |   MockRtpPacketSink sink1; | 
 |   AddSink(mid1_pt, &sink1); | 
 |  | 
 |   RtpDemuxerCriteria mid2_pt; | 
 |   mid2_pt.mid = mid2; | 
 |   mid2_pt.payload_types = {payload_type}; | 
 |   MockRtpPacketSink sink2; | 
 |   AddSink(mid2_pt, &sink2); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   packet->SetPayloadType(payload_type); | 
 |  | 
 |   EXPECT_CALL(sink1, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink2, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // If two sinks are added with different MIDs but the same payload types, then | 
 | // we cannot demux on the payload type only unless one of the sinks is removed. | 
 | TEST_F(RtpDemuxerTest, RoutedByPayloadTypeIfAmbiguousSinkRemoved) { | 
 |   const std::string mid1 = "v"; | 
 |   const std::string mid2 = "a"; | 
 |   constexpr uint8_t payload_type = 30; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   RtpDemuxerCriteria mid1_pt; | 
 |   mid1_pt.mid = mid1; | 
 |   mid1_pt.payload_types = {payload_type}; | 
 |   MockRtpPacketSink sink1; | 
 |   AddSink(mid1_pt, &sink1); | 
 |  | 
 |   RtpDemuxerCriteria mid2_pt; | 
 |   mid2_pt.mid = mid2; | 
 |   mid2_pt.payload_types = {payload_type}; | 
 |   MockRtpPacketSink sink2; | 
 |   AddSink(mid2_pt, &sink2); | 
 |  | 
 |   RemoveSink(&sink1); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   packet->SetPayloadType(payload_type); | 
 |  | 
 |   EXPECT_CALL(sink1, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink2, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |  | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RoutedByPayloadTypeLatchesSsrc) { | 
 |   constexpr uint8_t payload_type = 30; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   RtpDemuxerCriteria pt; | 
 |   pt.payload_types = {payload_type}; | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSink(pt, &sink); | 
 |  | 
 |   auto packet_with_pt = CreatePacketWithSsrc(ssrc); | 
 |   packet_with_pt->SetPayloadType(payload_type); | 
 |   ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_with_pt)); | 
 |  | 
 |   auto packet_with_ssrc = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc)); | 
 | } | 
 |  | 
 | // RSIDs are scoped within MID, so if two sinks are registered with the same | 
 | // RSIDs but different MIDs, then packets containing both extensions should be | 
 | // routed to the correct one. | 
 | TEST_F(RtpDemuxerTest, PacketWithSameRsidDifferentMidRoutedToProperSink) { | 
 |   const std::string mid1 = "mid1"; | 
 |   const std::string mid2 = "mid2"; | 
 |   const std::string rsid = "rsid"; | 
 |   constexpr uint32_t ssrc1 = 10; | 
 |   constexpr uint32_t ssrc2 = 11; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> mid1_sink; | 
 |   AddSinkBothMidRsid(mid1, rsid, &mid1_sink); | 
 |  | 
 |   MockRtpPacketSink mid2_sink; | 
 |   AddSinkBothMidRsid(mid2, rsid, &mid2_sink); | 
 |  | 
 |   auto packet_mid1 = CreatePacketWithSsrcMidRsid(ssrc1, mid1, rsid); | 
 |   ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_mid1)); | 
 |  | 
 |   auto packet_mid2 = CreatePacketWithSsrcMidRsid(ssrc2, mid2, rsid); | 
 |   EXPECT_CALL(mid2_sink, OnRtpPacket(SamePacketAs(*packet_mid2))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_mid2)); | 
 | } | 
 |  | 
 | // If a sink is first bound to a given SSRC by signaling but later a new sink is | 
 | // bound to a given MID by a later signaling, then when a packet arrives with | 
 | // both the SSRC and MID, then the signaled MID sink should take precedence. | 
 | TEST_F(RtpDemuxerTest, SignaledMidShouldOverwriteSignaledSsrc) { | 
 |   constexpr uint32_t ssrc = 11; | 
 |   const std::string mid = "mid"; | 
 |  | 
 |   MockRtpPacketSink ssrc_sink; | 
 |   AddSinkOnlySsrc(ssrc, &ssrc_sink); | 
 |  | 
 |   MockRtpPacketSink mid_sink; | 
 |   AddSinkOnlyMid(mid, &mid_sink); | 
 |  | 
 |   auto p = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   EXPECT_CALL(ssrc_sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(mid_sink, OnRtpPacket(SamePacketAs(*p))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*p)); | 
 | } | 
 |  | 
 | // Extends the previous test to also ensure that later packets that do not | 
 | // specify MID are still routed to the MID sink rather than the overwritten SSRC | 
 | // sink. | 
 | TEST_F(RtpDemuxerTest, SignaledMidShouldOverwriteSignalledSsrcPersistent) { | 
 |   constexpr uint32_t ssrc = 11; | 
 |   const std::string mid = "mid"; | 
 |  | 
 |   MockRtpPacketSink ssrc_sink; | 
 |   AddSinkOnlySsrc(ssrc, &ssrc_sink); | 
 |  | 
 |   NiceMock<MockRtpPacketSink> mid_sink; | 
 |   AddSinkOnlyMid(mid, &mid_sink); | 
 |  | 
 |   EXPECT_CALL(ssrc_sink, OnRtpPacket(_)).Times(0); | 
 |  | 
 |   auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   demuxer_.OnRtpPacket(*packet_with_mid); | 
 |  | 
 |   auto packet_without_mid = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(mid_sink, OnRtpPacket(SamePacketAs(*packet_without_mid))) | 
 |       .Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_without_mid)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RouteByPayloadTypeMultipleMatch) { | 
 |   constexpr uint32_t ssrc = 10; | 
 |   constexpr uint8_t pt1 = 30; | 
 |   constexpr uint8_t pt2 = 31; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.payload_types = {pt1, pt2}; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   auto packet_with_pt1 = CreatePacketWithSsrc(ssrc); | 
 |   packet_with_pt1->SetPayloadType(pt1); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_pt1))); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_pt1)); | 
 |  | 
 |   auto packet_with_pt2 = CreatePacketWithSsrc(ssrc); | 
 |   packet_with_pt2->SetPayloadType(pt2); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_pt2))); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_pt2)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DontDemuxOnMidAloneIfAddedWithRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   MockRtpPacketSink sink; | 
 |   AddSinkBothMidRsid(mid, rsid, &sink); | 
 |  | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMid(ssrc, mid); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DemuxBySsrcEvenWithMidAndRsid) { | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.rsid = rsid; | 
 |   criteria.mid = mid; | 
 |   criteria.ssrcs = {ssrc}; | 
 |   MockRtpPacketSink sink; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // In slight deviation from the BUNDLE spec, if we match a sink according to | 
 | // SSRC, then we do not verify payload type against the criteria and defer to | 
 | // the sink to check that it is correct. | 
 | TEST_F(RtpDemuxerTest, DoNotCheckPayloadTypeIfMatchedByOtherCriteria) { | 
 |   constexpr uint32_t ssrc = 10; | 
 |   constexpr uint8_t payload_type = 30; | 
 |   constexpr uint8_t different_payload_type = payload_type + 1; | 
 |  | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.ssrcs = {ssrc}; | 
 |   criteria.payload_types = {payload_type}; | 
 |   MockRtpPacketSink sink; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrc(ssrc); | 
 |   packet->SetPayloadType(different_payload_type); | 
 |   EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // If a repair packet includes an RSID it should be ignored and the packet | 
 | // should be routed by its RRID. | 
 | TEST_F(RtpDemuxerTest, PacketWithRsidAndRridRoutedByRrid) { | 
 |   const std::string rsid = "1"; | 
 |   const std::string rrid = "1r"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   MockRtpPacketSink sink_rsid; | 
 |   AddSinkOnlyRsid(rsid, &sink_rsid); | 
 |  | 
 |   MockRtpPacketSink sink_rrid; | 
 |   AddSinkOnlyRsid(rrid, &sink_rrid); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcRsidRrid(ssrc, rsid, rrid); | 
 |   EXPECT_CALL(sink_rsid, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink_rrid, OnRtpPacket(SamePacketAs(*packet))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // Same test as above but checks that the latched SSRC routes to the RRID sink. | 
 | TEST_F(RtpDemuxerTest, PacketWithRsidAndRridLatchesSsrcToRrid) { | 
 |   const std::string rsid = "1"; | 
 |   const std::string rrid = "1r"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   MockRtpPacketSink sink_rsid; | 
 |   AddSinkOnlyRsid(rsid, &sink_rsid); | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink_rrid; | 
 |   AddSinkOnlyRsid(rrid, &sink_rrid); | 
 |  | 
 |   auto packet_rsid_rrid = CreatePacketWithSsrcRsidRrid(ssrc, rsid, rrid); | 
 |   demuxer_.OnRtpPacket(*packet_rsid_rrid); | 
 |  | 
 |   auto packet_ssrc_only = CreatePacketWithSsrc(ssrc); | 
 |   EXPECT_CALL(sink_rsid, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_CALL(sink_rrid, OnRtpPacket(SamePacketAs(*packet_ssrc_only))).Times(1); | 
 |   EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc_only)); | 
 | } | 
 |  | 
 | // Tests that a packet which includes MID and RSID is dropped and not routed by | 
 | // SSRC if the MID and RSID do not match an added sink. | 
 | TEST_F(RtpDemuxerTest, PacketWithMidAndUnknownRsidIsNotRoutedBySsrc) { | 
 |   constexpr uint32_t ssrc = 10; | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   const std::string wrong_rsid = "2"; | 
 |  | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.mid = mid; | 
 |   criteria.rsid = rsid; | 
 |   criteria.ssrcs = {ssrc}; | 
 |   MockRtpPacketSink sink; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, wrong_rsid); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // Tests that a packet which includes MID and RSID is dropped and not routed by | 
 | // payload type if the MID and RSID do not match an added sink. | 
 | TEST_F(RtpDemuxerTest, PacketWithMidAndUnknownRsidIsNotRoutedByPayloadType) { | 
 |   constexpr uint32_t ssrc = 10; | 
 |   const std::string mid = "v"; | 
 |   const std::string rsid = "1"; | 
 |   const std::string wrong_rsid = "2"; | 
 |   constexpr uint8_t payload_type = 30; | 
 |  | 
 |   RtpDemuxerCriteria criteria; | 
 |   criteria.mid = mid; | 
 |   criteria.rsid = rsid; | 
 |   criteria.payload_types = {payload_type}; | 
 |   MockRtpPacketSink sink; | 
 |   AddSink(criteria, &sink); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, wrong_rsid); | 
 |   packet->SetPayloadType(payload_type); | 
 |   EXPECT_CALL(sink, OnRtpPacket(_)).Times(0); | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*packet)); | 
 | } | 
 |  | 
 | // Observers are only notified of an SSRC binding to an RSID if we care about | 
 | // the RSID (i.e., have a sink added for that RSID). | 
 | TEST_F(RtpDemuxerTest, ObserversNotNotifiedOfUntrackedRsids) { | 
 |   const std::string rsid = "1"; | 
 |   constexpr uint32_t ssrc = 111; | 
 |  | 
 |   MockSsrcBindingObserver rsid_resolution_observers[3]; | 
 |   for (auto& observer : rsid_resolution_observers) { | 
 |     RegisterSsrcBindingObserver(&observer); | 
 |     EXPECT_CALL(observer, OnSsrcBoundToRsid(_, _)).Times(0); | 
 |   } | 
 |  | 
 |   // Since no sink is registered for this SSRC/RSID, expect the packet to not be | 
 |   // routed and no observers notified of the SSRC -> RSID binding. | 
 |   EXPECT_FALSE(demuxer_.OnRtpPacket(*CreatePacketWithSsrcRsid(ssrc, rsid))); | 
 | } | 
 |  | 
 | // Ensure that observers are notified of SSRC bindings only once per unique | 
 | // binding source (e.g., SSRC -> MID, SSRC -> RSID, etc.) | 
 | TEST_F(RtpDemuxerTest, ObserversNotifiedOfSsrcBoundtoMidOnlyOnce) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc = 10; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   EXPECT_CALL(observer, OnSsrcBoundToMid(mid, ssrc)).Times(1); | 
 |  | 
 |   demuxer_.OnRtpPacket(*CreatePacketWithSsrcMid(ssrc, mid)); | 
 |   demuxer_.OnRtpPacket(*CreatePacketWithSsrcMid(ssrc, mid)); | 
 | } | 
 |  | 
 | // Ensure that when a new SSRC -> MID binding is discovered observers are also | 
 | // notified of that, even if there has already been an SSRC bound to the MID. | 
 | TEST_F(RtpDemuxerTest, ObserversNotifiedOfSsrcBoundtoMidWhenSsrcChanges) { | 
 |   const std::string mid = "v"; | 
 |   constexpr uint32_t ssrc1 = 10; | 
 |   constexpr uint32_t ssrc2 = 11; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   InSequence seq; | 
 |   EXPECT_CALL(observer, OnSsrcBoundToMid(mid, ssrc1)).Times(1); | 
 |   EXPECT_CALL(observer, OnSsrcBoundToMid(mid, ssrc2)).Times(1); | 
 |  | 
 |   auto p1 = CreatePacketWithSsrcMid(ssrc1, mid); | 
 |   demuxer_.OnRtpPacket(*p1); | 
 |  | 
 |   auto p2 = CreatePacketWithSsrcMid(ssrc2, mid); | 
 |   demuxer_.OnRtpPacket(*p2); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DeregisteredRsidObserversNotInformedOfResolutions) { | 
 |   constexpr uint32_t ssrc = 111; | 
 |   const std::string rsid = "a"; | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyRsid(rsid, &sink); | 
 |  | 
 |   // Register several, then deregister only one, to show that not all of the | 
 |   // observers had been forgotten when one was removed. | 
 |   MockSsrcBindingObserver observer_1; | 
 |   MockSsrcBindingObserver observer_2_removed; | 
 |   MockSsrcBindingObserver observer_3; | 
 |  | 
 |   RegisterSsrcBindingObserver(&observer_1); | 
 |   RegisterSsrcBindingObserver(&observer_2_removed); | 
 |   RegisterSsrcBindingObserver(&observer_3); | 
 |  | 
 |   DeregisterSsrcBindingObserver(&observer_2_removed); | 
 |  | 
 |   EXPECT_CALL(observer_1, OnSsrcBoundToRsid(rsid, ssrc)).Times(1); | 
 |   EXPECT_CALL(observer_2_removed, OnSsrcBoundToRsid(_, _)).Times(0); | 
 |   EXPECT_CALL(observer_3, OnSsrcBoundToRsid(rsid, ssrc)).Times(1); | 
 |  | 
 |   // The expected calls to OnSsrcBoundToRsid() will be triggered by this. | 
 |   demuxer_.OnRtpPacket(*CreatePacketWithSsrcRsid(ssrc, rsid)); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, | 
 |        PacketFittingBothRsidSinkAndSsrcSinkTriggersResolutionCallbacks) { | 
 |   constexpr uint32_t ssrc = 111; | 
 |   NiceMock<MockRtpPacketSink> ssrc_sink; | 
 |   AddSinkOnlySsrc(ssrc, &ssrc_sink); | 
 |  | 
 |   const std::string rsid = "a"; | 
 |   NiceMock<MockRtpPacketSink> rsid_sink; | 
 |   AddSinkOnlyRsid(rsid, &rsid_sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   auto packet = CreatePacketWithSsrcRsid(ssrc, rsid); | 
 |   EXPECT_CALL(observer, OnSsrcBoundToRsid(rsid, ssrc)).Times(1); | 
 |   demuxer_.OnRtpPacket(*packet); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, MaliciousPeerCannotCauseMemoryOveruse) { | 
 |   const std::string mid = "v"; | 
 |  | 
 |   NiceMock<MockRtpPacketSink> sink; | 
 |   AddSinkOnlyMid(mid, &sink); | 
 |  | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |  | 
 |   EXPECT_CALL(observer, OnSsrcBoundToMid(_, _)) | 
 |       .Times(AtMost(RtpDemuxer::kMaxSsrcBindings)); | 
 |  | 
 |   for (int i = 0; i < RtpDemuxer::kMaxSsrcBindings + 1; i++) { | 
 |     auto packet = CreatePacketWithSsrcMid(i, mid); | 
 |     EXPECT_TRUE(demuxer_.OnRtpPacket(*packet)); | 
 |   } | 
 | } | 
 |  | 
 | #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 
 |  | 
 | TEST_F(RtpDemuxerTest, CriteriaMustBeNonEmpty) { | 
 |   MockRtpPacketSink sink; | 
 |   RtpDemuxerCriteria criteria; | 
 |   EXPECT_DEATH(AddSink(criteria, &sink), ""); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RsidMustBeAlphaNumeric) { | 
 |   MockRtpPacketSink sink; | 
 |   EXPECT_DEATH(AddSinkOnlyRsid("a_3", &sink), ""); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, MidMustBeToken) { | 
 |   MockRtpPacketSink sink; | 
 |   EXPECT_DEATH(AddSinkOnlyMid("a(3)", &sink), ""); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, RsidMustNotExceedMaximumLength) { | 
 |   MockRtpPacketSink sink; | 
 |   std::string rsid(StreamId::kMaxSize + 1, 'a'); | 
 |   EXPECT_DEATH(AddSinkOnlyRsid(rsid, &sink), ""); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, MidMustNotExceedMaximumLength) { | 
 |   MockRtpPacketSink sink; | 
 |   std::string mid(Mid::kMaxSize + 1, 'a'); | 
 |   EXPECT_DEATH(AddSinkOnlyMid(mid, &sink), ""); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, DoubleRegisterationOfSsrcBindingObserverDisallowed) { | 
 |   MockSsrcBindingObserver observer; | 
 |   RegisterSsrcBindingObserver(&observer); | 
 |   EXPECT_DEATH(RegisterSsrcBindingObserver(&observer), ""); | 
 | } | 
 |  | 
 | TEST_F(RtpDemuxerTest, | 
 |        DregisterationOfNeverRegisteredSsrcBindingObserverDisallowed) { | 
 |   MockSsrcBindingObserver observer; | 
 |   EXPECT_DEATH(DeregisterSsrcBindingObserver(&observer), ""); | 
 | } | 
 |  | 
 | #endif | 
 |  | 
 | }  // namespace | 
 | }  // namespace webrtc |