1 /*
2  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3  *
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
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "call/rtcp_demuxer.h"
12 
13 #include "call/rtcp_packet_sink_interface.h"
14 #include "call/rtp_rtcp_demuxer_helper.h"
15 #include "common_types.h"  // NOLINT(build/include)
16 #include "rtc_base/checks.h"
17 
18 namespace webrtc {
19 
20 RtcpDemuxer::RtcpDemuxer() = default;
21 
~RtcpDemuxer()22 RtcpDemuxer::~RtcpDemuxer() {
23   RTC_DCHECK(ssrc_sinks_.empty());
24   RTC_DCHECK(rsid_sinks_.empty());
25   RTC_DCHECK(broadcast_sinks_.empty());
26 }
27 
AddSink(uint32_t sender_ssrc,RtcpPacketSinkInterface * sink)28 void RtcpDemuxer::AddSink(uint32_t sender_ssrc, RtcpPacketSinkInterface* sink) {
29   RTC_DCHECK(sink);
30   RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
31   RTC_DCHECK(!MultimapAssociationExists(ssrc_sinks_, sender_ssrc, sink));
32   ssrc_sinks_.emplace(sender_ssrc, sink);
33 }
34 
AddSink(const std::string & rsid,RtcpPacketSinkInterface * sink)35 void RtcpDemuxer::AddSink(const std::string& rsid,
36                           RtcpPacketSinkInterface* sink) {
37   RTC_DCHECK(StreamId::IsLegalName(rsid));
38   RTC_DCHECK(sink);
39   RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
40   RTC_DCHECK(!MultimapAssociationExists(rsid_sinks_, rsid, sink));
41   rsid_sinks_.emplace(rsid, sink);
42 }
43 
AddBroadcastSink(RtcpPacketSinkInterface * sink)44 void RtcpDemuxer::AddBroadcastSink(RtcpPacketSinkInterface* sink) {
45   RTC_DCHECK(sink);
46   RTC_DCHECK(!MultimapHasValue(ssrc_sinks_, sink));
47   RTC_DCHECK(!MultimapHasValue(rsid_sinks_, sink));
48   RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
49   broadcast_sinks_.push_back(sink);
50 }
51 
RemoveSink(const RtcpPacketSinkInterface * sink)52 void RtcpDemuxer::RemoveSink(const RtcpPacketSinkInterface* sink) {
53   RTC_DCHECK(sink);
54   size_t removal_count = RemoveFromMultimapByValue(&ssrc_sinks_, sink) +
55                          RemoveFromMultimapByValue(&rsid_sinks_, sink);
56   RTC_DCHECK_GT(removal_count, 0);
57 }
58 
RemoveBroadcastSink(const RtcpPacketSinkInterface * sink)59 void RtcpDemuxer::RemoveBroadcastSink(const RtcpPacketSinkInterface* sink) {
60   RTC_DCHECK(sink);
61   auto it = std::find(broadcast_sinks_.begin(), broadcast_sinks_.end(), sink);
62   RTC_DCHECK(it != broadcast_sinks_.end());
63   broadcast_sinks_.erase(it);
64 }
65 
OnRtcpPacket(rtc::ArrayView<const uint8_t> packet)66 void RtcpDemuxer::OnRtcpPacket(rtc::ArrayView<const uint8_t> packet) {
67   // Perform sender-SSRC-based demuxing for packets with a sender-SSRC.
68   rtc::Optional<uint32_t> sender_ssrc = ParseRtcpPacketSenderSsrc(packet);
69   if (sender_ssrc) {
70     auto it_range = ssrc_sinks_.equal_range(*sender_ssrc);
71     for (auto it = it_range.first; it != it_range.second; ++it) {
72       it->second->OnRtcpPacket(packet);
73     }
74   }
75 
76   // All packets, even those without a sender-SSRC, are broadcast to sinks
77   // which listen to broadcasts.
78   for (RtcpPacketSinkInterface* sink : broadcast_sinks_) {
79     sink->OnRtcpPacket(packet);
80   }
81 }
82 
OnSsrcBoundToRsid(const std::string & rsid,uint32_t ssrc)83 void RtcpDemuxer::OnSsrcBoundToRsid(const std::string& rsid, uint32_t ssrc) {
84   // Record the new SSRC association for all of the sinks that were associated
85   // with the RSID.
86   auto it_range = rsid_sinks_.equal_range(rsid);
87   for (auto it = it_range.first; it != it_range.second; ++it) {
88     RtcpPacketSinkInterface* sink = it->second;
89     // Watch out for pre-existing SSRC-based associations.
90     if (!MultimapAssociationExists(ssrc_sinks_, ssrc, sink)) {
91       AddSink(ssrc, sink);
92     }
93   }
94 
95   // RSIDs are uniquely associated with SSRCs; no need to keep in memory
96   // the RSID-to-sink association of resolved RSIDs.
97   rsid_sinks_.erase(it_range.first, it_range.second);
98 }
99 
100 }  // namespace webrtc
101