blob: 0e78ddea186a519c9e8fa171155c43bda0b671cc [file] [log] [blame]
eladalona52722f2017-06-26 11:23:54 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "call/rtcp_demuxer.h"
eladalona52722f2017-06-26 11:23:54 -070012
Patrik Höglund3e113432017-12-15 14:40:10 +010013#include "api/rtp_headers.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "call/rtcp_packet_sink_interface.h"
15#include "call/rtp_rtcp_demuxer_helper.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020016#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
eladalona52722f2017-06-26 11:23:54 -070018
19namespace webrtc {
20
21RtcpDemuxer::RtcpDemuxer() = default;
22
23RtcpDemuxer::~RtcpDemuxer() {
24 RTC_DCHECK(ssrc_sinks_.empty());
25 RTC_DCHECK(rsid_sinks_.empty());
26 RTC_DCHECK(broadcast_sinks_.empty());
27}
28
29void RtcpDemuxer::AddSink(uint32_t sender_ssrc, RtcpPacketSinkInterface* sink) {
30 RTC_DCHECK(sink);
31 RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
32 RTC_DCHECK(!MultimapAssociationExists(ssrc_sinks_, sender_ssrc, sink));
33 ssrc_sinks_.emplace(sender_ssrc, sink);
34}
35
36void RtcpDemuxer::AddSink(const std::string& rsid,
37 RtcpPacketSinkInterface* sink) {
38 RTC_DCHECK(StreamId::IsLegalName(rsid));
39 RTC_DCHECK(sink);
40 RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
41 RTC_DCHECK(!MultimapAssociationExists(rsid_sinks_, rsid, sink));
42 rsid_sinks_.emplace(rsid, sink);
43}
44
45void RtcpDemuxer::AddBroadcastSink(RtcpPacketSinkInterface* sink) {
46 RTC_DCHECK(sink);
47 RTC_DCHECK(!MultimapHasValue(ssrc_sinks_, sink));
48 RTC_DCHECK(!MultimapHasValue(rsid_sinks_, sink));
49 RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
50 broadcast_sinks_.push_back(sink);
51}
52
53void RtcpDemuxer::RemoveSink(const RtcpPacketSinkInterface* sink) {
54 RTC_DCHECK(sink);
55 size_t removal_count = RemoveFromMultimapByValue(&ssrc_sinks_, sink) +
56 RemoveFromMultimapByValue(&rsid_sinks_, sink);
57 RTC_DCHECK_GT(removal_count, 0);
58}
59
60void RtcpDemuxer::RemoveBroadcastSink(const RtcpPacketSinkInterface* sink) {
61 RTC_DCHECK(sink);
62 auto it = std::find(broadcast_sinks_.begin(), broadcast_sinks_.end(), sink);
63 RTC_DCHECK(it != broadcast_sinks_.end());
64 broadcast_sinks_.erase(it);
65}
66
67void RtcpDemuxer::OnRtcpPacket(rtc::ArrayView<const uint8_t> packet) {
68 // Perform sender-SSRC-based demuxing for packets with a sender-SSRC.
69 rtc::Optional<uint32_t> sender_ssrc = ParseRtcpPacketSenderSsrc(packet);
70 if (sender_ssrc) {
71 auto it_range = ssrc_sinks_.equal_range(*sender_ssrc);
72 for (auto it = it_range.first; it != it_range.second; ++it) {
73 it->second->OnRtcpPacket(packet);
74 }
75 }
76
77 // All packets, even those without a sender-SSRC, are broadcast to sinks
78 // which listen to broadcasts.
79 for (RtcpPacketSinkInterface* sink : broadcast_sinks_) {
80 sink->OnRtcpPacket(packet);
81 }
82}
83
Steve Antonb3329172017-08-17 15:23:51 -070084void RtcpDemuxer::OnSsrcBoundToRsid(const std::string& rsid, uint32_t ssrc) {
eladalona52722f2017-06-26 11:23:54 -070085 // Record the new SSRC association for all of the sinks that were associated
86 // with the RSID.
87 auto it_range = rsid_sinks_.equal_range(rsid);
88 for (auto it = it_range.first; it != it_range.second; ++it) {
89 RtcpPacketSinkInterface* sink = it->second;
90 // Watch out for pre-existing SSRC-based associations.
91 if (!MultimapAssociationExists(ssrc_sinks_, ssrc, sink)) {
92 AddSink(ssrc, sink);
93 }
94 }
95
96 // RSIDs are uniquely associated with SSRCs; no need to keep in memory
97 // the RSID-to-sink association of resolved RSIDs.
98 rsid_sinks_.erase(it_range.first, it_range.second);
99}
100
101} // namespace webrtc