blob: 738109fa43d1b576bbe480911cfb149d01b417ac [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
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stddef.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <algorithm>
16#include <utility>
17
18#include "absl/types/optional.h"
Patrik Höglund3e113432017-12-15 14:40:10 +010019#include "api/rtp_headers.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "call/rtcp_packet_sink_interface.h"
21#include "call/rtp_rtcp_demuxer_helper.h"
Niels Möllera7de6982019-03-21 15:48:49 +010022#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/checks.h"
eladalona52722f2017-06-26 11:23:54 -070024
25namespace webrtc {
26
27RtcpDemuxer::RtcpDemuxer() = default;
28
29RtcpDemuxer::~RtcpDemuxer() {
30 RTC_DCHECK(ssrc_sinks_.empty());
31 RTC_DCHECK(rsid_sinks_.empty());
32 RTC_DCHECK(broadcast_sinks_.empty());
33}
34
35void RtcpDemuxer::AddSink(uint32_t sender_ssrc, RtcpPacketSinkInterface* sink) {
36 RTC_DCHECK(sink);
37 RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
38 RTC_DCHECK(!MultimapAssociationExists(ssrc_sinks_, sender_ssrc, sink));
39 ssrc_sinks_.emplace(sender_ssrc, sink);
40}
41
42void RtcpDemuxer::AddSink(const std::string& rsid,
43 RtcpPacketSinkInterface* sink) {
Niels Möllera7de6982019-03-21 15:48:49 +010044 RTC_DCHECK(IsLegalRsidName(rsid));
eladalona52722f2017-06-26 11:23:54 -070045 RTC_DCHECK(sink);
46 RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
47 RTC_DCHECK(!MultimapAssociationExists(rsid_sinks_, rsid, sink));
48 rsid_sinks_.emplace(rsid, sink);
49}
50
51void RtcpDemuxer::AddBroadcastSink(RtcpPacketSinkInterface* sink) {
52 RTC_DCHECK(sink);
53 RTC_DCHECK(!MultimapHasValue(ssrc_sinks_, sink));
54 RTC_DCHECK(!MultimapHasValue(rsid_sinks_, sink));
55 RTC_DCHECK(!ContainerHasKey(broadcast_sinks_, sink));
56 broadcast_sinks_.push_back(sink);
57}
58
59void RtcpDemuxer::RemoveSink(const RtcpPacketSinkInterface* sink) {
60 RTC_DCHECK(sink);
61 size_t removal_count = RemoveFromMultimapByValue(&ssrc_sinks_, sink) +
62 RemoveFromMultimapByValue(&rsid_sinks_, sink);
63 RTC_DCHECK_GT(removal_count, 0);
64}
65
66void RtcpDemuxer::RemoveBroadcastSink(const RtcpPacketSinkInterface* sink) {
67 RTC_DCHECK(sink);
68 auto it = std::find(broadcast_sinks_.begin(), broadcast_sinks_.end(), sink);
69 RTC_DCHECK(it != broadcast_sinks_.end());
70 broadcast_sinks_.erase(it);
71}
72
73void RtcpDemuxer::OnRtcpPacket(rtc::ArrayView<const uint8_t> packet) {
74 // Perform sender-SSRC-based demuxing for packets with a sender-SSRC.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020075 absl::optional<uint32_t> sender_ssrc = ParseRtcpPacketSenderSsrc(packet);
eladalona52722f2017-06-26 11:23:54 -070076 if (sender_ssrc) {
77 auto it_range = ssrc_sinks_.equal_range(*sender_ssrc);
78 for (auto it = it_range.first; it != it_range.second; ++it) {
79 it->second->OnRtcpPacket(packet);
80 }
81 }
82
83 // All packets, even those without a sender-SSRC, are broadcast to sinks
84 // which listen to broadcasts.
85 for (RtcpPacketSinkInterface* sink : broadcast_sinks_) {
86 sink->OnRtcpPacket(packet);
87 }
88}
89
Steve Antonb3329172017-08-17 15:23:51 -070090void RtcpDemuxer::OnSsrcBoundToRsid(const std::string& rsid, uint32_t ssrc) {
eladalona52722f2017-06-26 11:23:54 -070091 // Record the new SSRC association for all of the sinks that were associated
92 // with the RSID.
93 auto it_range = rsid_sinks_.equal_range(rsid);
94 for (auto it = it_range.first; it != it_range.second; ++it) {
95 RtcpPacketSinkInterface* sink = it->second;
96 // Watch out for pre-existing SSRC-based associations.
97 if (!MultimapAssociationExists(ssrc_sinks_, ssrc, sink)) {
98 AddSink(ssrc, sink);
99 }
100 }
101
102 // RSIDs are uniquely associated with SSRCs; no need to keep in memory
103 // the RSID-to-sink association of resolved RSIDs.
104 rsid_sinks_.erase(it_range.first, it_range.second);
105}
106
107} // namespace webrtc