| /* |
| * 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 "webrtc/call/rtp_demuxer.h" |
| |
| #include "webrtc/call/rsid_resolution_observer.h" |
| #include "webrtc/call/rtp_packet_sink_interface.h" |
| #include "webrtc/call/rtp_rtcp_demuxer_helper.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
| #include "webrtc/rtc_base/checks.h" |
| #include "webrtc/rtc_base/logging.h" |
| |
| namespace webrtc { |
| |
| RtpDemuxer::RtpDemuxer() = default; |
| |
| RtpDemuxer::~RtpDemuxer() { |
| RTC_DCHECK(ssrc_sinks_.empty()); |
| RTC_DCHECK(rsid_sinks_.empty()); |
| } |
| |
| void RtpDemuxer::AddSink(uint32_t ssrc, RtpPacketSinkInterface* sink) { |
| RTC_DCHECK(sink); |
| RecordSsrcToSinkAssociation(ssrc, sink); |
| } |
| |
| void RtpDemuxer::AddSink(const std::string& rsid, |
| RtpPacketSinkInterface* sink) { |
| RTC_DCHECK(StreamId::IsLegalName(rsid)); |
| RTC_DCHECK(sink); |
| RTC_DCHECK(!MultimapAssociationExists(rsid_sinks_, rsid, sink)); |
| |
| rsid_sinks_.emplace(rsid, sink); |
| } |
| |
| bool RtpDemuxer::RemoveSink(const RtpPacketSinkInterface* sink) { |
| RTC_DCHECK(sink); |
| return (RemoveFromMultimapByValue(&ssrc_sinks_, sink) + |
| RemoveFromMultimapByValue(&rsid_sinks_, sink)) > 0; |
| } |
| |
| void RtpDemuxer::RecordSsrcToSinkAssociation(uint32_t ssrc, |
| RtpPacketSinkInterface* sink) { |
| RTC_DCHECK(sink); |
| // The association might already have been set by a different |
| // configuration source. |
| if (!MultimapAssociationExists(ssrc_sinks_, ssrc, sink)) { |
| ssrc_sinks_.emplace(ssrc, sink); |
| } |
| } |
| |
| bool RtpDemuxer::OnRtpPacket(const RtpPacketReceived& packet) { |
| // TODO(eladalon): This will now check every single packet, but soon a CL will |
| // be added which will change the many-to-many association of packets to sinks |
| // to a many-to-one, meaning each packet will be associated with one sink |
| // at most. Then, only packets with an unknown SSRC will be checked for RSID. |
| ResolveRsidToSsrcAssociations(packet); |
| |
| auto it_range = ssrc_sinks_.equal_range(packet.Ssrc()); |
| for (auto it = it_range.first; it != it_range.second; ++it) { |
| it->second->OnRtpPacket(packet); |
| } |
| return it_range.first != it_range.second; |
| } |
| |
| void RtpDemuxer::RegisterRsidResolutionObserver( |
| RsidResolutionObserver* observer) { |
| RTC_DCHECK(observer); |
| RTC_DCHECK(!ContainerHasKey(rsid_resolution_observers_, observer)); |
| |
| rsid_resolution_observers_.push_back(observer); |
| } |
| |
| void RtpDemuxer::DeregisterRsidResolutionObserver( |
| const RsidResolutionObserver* observer) { |
| RTC_DCHECK(observer); |
| auto it = std::find(rsid_resolution_observers_.begin(), |
| rsid_resolution_observers_.end(), observer); |
| RTC_DCHECK(it != rsid_resolution_observers_.end()); |
| rsid_resolution_observers_.erase(it); |
| } |
| |
| void RtpDemuxer::ResolveRsidToSsrcAssociations( |
| const RtpPacketReceived& packet) { |
| std::string rsid; |
| if (packet.GetExtension<RtpStreamId>(&rsid)) { |
| // All streams associated with this RSID need to be marked as associated |
| // with this SSRC (if they aren't already). |
| auto it_range = rsid_sinks_.equal_range(rsid); |
| for (auto it = it_range.first; it != it_range.second; ++it) { |
| RecordSsrcToSinkAssociation(packet.Ssrc(), it->second); |
| } |
| |
| NotifyObserversOfRsidResolution(rsid, packet.Ssrc()); |
| |
| // To prevent memory-overuse attacks, forget this RSID. Future packets |
| // with this RSID, but a different SSRC, will not spawn new associations. |
| rsid_sinks_.erase(it_range.first, it_range.second); |
| } |
| } |
| |
| void RtpDemuxer::NotifyObserversOfRsidResolution(const std::string& rsid, |
| uint32_t ssrc) { |
| for (auto* observer : rsid_resolution_observers_) { |
| observer->OnRsidResolved(rsid, ssrc); |
| } |
| } |
| |
| } // namespace webrtc |