1 /*
2  *  Copyright 2016 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 "pc/track_media_info_map.h"
12 
13 #include <set>
14 #include <string>
15 #include <utility>
16 
17 #include "rtc_base/thread.h"
18 
19 namespace webrtc {
20 
21 namespace {
22 
23 template <typename K, typename V>
FindValueOrNull(const std::map<K,V> & map,const K & key)24 V FindValueOrNull(const std::map<K, V>& map, const K& key) {
25   auto it = map.find(key);
26   return (it != map.end()) ? it->second : nullptr;
27 }
28 
29 template <typename K, typename V>
FindAddressOrNull(const std::map<K,V> & map,const K & key)30 const V* FindAddressOrNull(const std::map<K, V>& map, const K& key) {
31   auto it = map.find(key);
32   return (it != map.end()) ? &it->second : nullptr;
33 }
34 
GetAudioAndVideoTrackBySsrc(const std::vector<rtc::scoped_refptr<RtpSenderInternal>> & rtp_senders,const std::vector<rtc::scoped_refptr<RtpReceiverInternal>> & rtp_receivers,std::map<uint32_t,AudioTrackInterface * > * local_audio_track_by_ssrc,std::map<uint32_t,VideoTrackInterface * > * local_video_track_by_ssrc,std::map<uint32_t,AudioTrackInterface * > * remote_audio_track_by_ssrc,std::map<uint32_t,VideoTrackInterface * > * remote_video_track_by_ssrc,AudioTrackInterface ** unsignaled_audio_track,VideoTrackInterface ** unsignaled_video_track)35 void GetAudioAndVideoTrackBySsrc(
36     const std::vector<rtc::scoped_refptr<RtpSenderInternal>>& rtp_senders,
37     const std::vector<rtc::scoped_refptr<RtpReceiverInternal>>& rtp_receivers,
38     std::map<uint32_t, AudioTrackInterface*>* local_audio_track_by_ssrc,
39     std::map<uint32_t, VideoTrackInterface*>* local_video_track_by_ssrc,
40     std::map<uint32_t, AudioTrackInterface*>* remote_audio_track_by_ssrc,
41     std::map<uint32_t, VideoTrackInterface*>* remote_video_track_by_ssrc,
42     AudioTrackInterface** unsignaled_audio_track,
43     VideoTrackInterface** unsignaled_video_track) {
44   RTC_DCHECK(local_audio_track_by_ssrc->empty());
45   RTC_DCHECK(local_video_track_by_ssrc->empty());
46   RTC_DCHECK(remote_audio_track_by_ssrc->empty());
47   RTC_DCHECK(remote_video_track_by_ssrc->empty());
48   for (const auto& rtp_sender : rtp_senders) {
49     cricket::MediaType media_type = rtp_sender->media_type();
50     MediaStreamTrackInterface* track = rtp_sender->track();
51     if (!track) {
52       continue;
53     }
54     // TODO(deadbeef): |ssrc| should be removed in favor of |GetParameters|.
55     uint32_t ssrc = rtp_sender->ssrc();
56     if (ssrc != 0) {
57       if (media_type == cricket::MEDIA_TYPE_AUDIO) {
58         RTC_DCHECK(local_audio_track_by_ssrc->find(ssrc) ==
59                    local_audio_track_by_ssrc->end());
60         (*local_audio_track_by_ssrc)[ssrc] =
61             static_cast<AudioTrackInterface*>(track);
62       } else {
63         RTC_DCHECK(local_video_track_by_ssrc->find(ssrc) ==
64                    local_video_track_by_ssrc->end());
65         (*local_video_track_by_ssrc)[ssrc] =
66             static_cast<VideoTrackInterface*>(track);
67       }
68     }
69   }
70   for (const auto& rtp_receiver : rtp_receivers) {
71     cricket::MediaType media_type = rtp_receiver->media_type();
72     MediaStreamTrackInterface* track = rtp_receiver->track();
73     RTC_DCHECK(track);
74     RtpParameters params = rtp_receiver->GetParameters();
75     for (const RtpEncodingParameters& encoding : params.encodings) {
76       if (!encoding.ssrc) {
77         if (media_type == cricket::MEDIA_TYPE_AUDIO) {
78           *unsignaled_audio_track = static_cast<AudioTrackInterface*>(track);
79         } else {
80           RTC_DCHECK(media_type == cricket::MEDIA_TYPE_VIDEO);
81           *unsignaled_video_track = static_cast<VideoTrackInterface*>(track);
82         }
83         continue;
84       }
85       if (media_type == cricket::MEDIA_TYPE_AUDIO) {
86         RTC_DCHECK(remote_audio_track_by_ssrc->find(*encoding.ssrc) ==
87                    remote_audio_track_by_ssrc->end());
88         (*remote_audio_track_by_ssrc)[*encoding.ssrc] =
89             static_cast<AudioTrackInterface*>(track);
90       } else {
91         RTC_DCHECK(remote_video_track_by_ssrc->find(*encoding.ssrc) ==
92                    remote_video_track_by_ssrc->end());
93         (*remote_video_track_by_ssrc)[*encoding.ssrc] =
94             static_cast<VideoTrackInterface*>(track);
95       }
96     }
97   }
98 }
99 
100 }  // namespace
101 
TrackMediaInfoMap(std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info,std::unique_ptr<cricket::VideoMediaInfo> video_media_info,const std::vector<rtc::scoped_refptr<RtpSenderInternal>> & rtp_senders,const std::vector<rtc::scoped_refptr<RtpReceiverInternal>> & rtp_receivers)102 TrackMediaInfoMap::TrackMediaInfoMap(
103     std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info,
104     std::unique_ptr<cricket::VideoMediaInfo> video_media_info,
105     const std::vector<rtc::scoped_refptr<RtpSenderInternal>>& rtp_senders,
106     const std::vector<rtc::scoped_refptr<RtpReceiverInternal>>& rtp_receivers)
107     : voice_media_info_(std::move(voice_media_info)),
108       video_media_info_(std::move(video_media_info)) {
109   rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
110 
111   std::map<uint32_t, AudioTrackInterface*> local_audio_track_by_ssrc;
112   std::map<uint32_t, VideoTrackInterface*> local_video_track_by_ssrc;
113   std::map<uint32_t, AudioTrackInterface*> remote_audio_track_by_ssrc;
114   std::map<uint32_t, VideoTrackInterface*> remote_video_track_by_ssrc;
115   AudioTrackInterface* unsignaled_audio_track = nullptr;
116   VideoTrackInterface* unsignaled_video_track = nullptr;
117   GetAudioAndVideoTrackBySsrc(
118       rtp_senders, rtp_receivers, &local_audio_track_by_ssrc,
119       &local_video_track_by_ssrc, &remote_audio_track_by_ssrc,
120       &remote_video_track_by_ssrc, &unsignaled_audio_track,
121       &unsignaled_video_track);
122 
123   for (const auto& sender : rtp_senders) {
124     attachment_id_by_track_[sender->track()] = sender->AttachmentId();
125   }
126   for (const auto& receiver : rtp_receivers) {
127     attachment_id_by_track_[receiver->track()] = receiver->AttachmentId();
128   }
129 
130   if (voice_media_info_) {
131     for (auto& sender_info : voice_media_info_->senders) {
132       AudioTrackInterface* associated_track =
133           FindValueOrNull(local_audio_track_by_ssrc, sender_info.ssrc());
134       if (associated_track) {
135         // One sender is associated with at most one track.
136         // One track may be associated with multiple senders.
137         audio_track_by_sender_info_[&sender_info] = associated_track;
138         voice_infos_by_local_track_[associated_track].push_back(&sender_info);
139       }
140       if (sender_info.ssrc() == 0)
141         continue;  // Unconnected SSRC. bugs.webrtc.org/8673
142       RTC_CHECK(voice_info_by_sender_ssrc_.count(sender_info.ssrc()) == 0)
143           << "Duplicate voice sender SSRC: " << sender_info.ssrc();
144       voice_info_by_sender_ssrc_[sender_info.ssrc()] = &sender_info;
145     }
146     for (auto& receiver_info : voice_media_info_->receivers) {
147       AudioTrackInterface* associated_track =
148           FindValueOrNull(remote_audio_track_by_ssrc, receiver_info.ssrc());
149       if (associated_track) {
150         // One receiver is associated with at most one track, which is uniquely
151         // associated with that receiver.
152         audio_track_by_receiver_info_[&receiver_info] = associated_track;
153         RTC_DCHECK(voice_info_by_remote_track_.find(associated_track) ==
154                    voice_info_by_remote_track_.end());
155         voice_info_by_remote_track_[associated_track] = &receiver_info;
156       } else if (unsignaled_audio_track) {
157         audio_track_by_receiver_info_[&receiver_info] = unsignaled_audio_track;
158         voice_info_by_remote_track_[unsignaled_audio_track] = &receiver_info;
159       }
160       RTC_CHECK(voice_info_by_receiver_ssrc_.count(receiver_info.ssrc()) == 0)
161           << "Duplicate voice receiver SSRC: " << receiver_info.ssrc();
162       voice_info_by_receiver_ssrc_[receiver_info.ssrc()] = &receiver_info;
163     }
164   }
165   if (video_media_info_) {
166     for (auto& sender_info : video_media_info_->senders) {
167       std::set<uint32_t> ssrcs;
168       ssrcs.insert(sender_info.ssrc());
169       for (auto& ssrc_group : sender_info.ssrc_groups) {
170         for (auto ssrc : ssrc_group.ssrcs) {
171           ssrcs.insert(ssrc);
172         }
173       }
174       for (auto ssrc : ssrcs) {
175         VideoTrackInterface* associated_track =
176             FindValueOrNull(local_video_track_by_ssrc, ssrc);
177         if (associated_track) {
178           // One sender is associated with at most one track.
179           // One track may be associated with multiple senders.
180           video_track_by_sender_info_[&sender_info] = associated_track;
181           video_infos_by_local_track_[associated_track].push_back(&sender_info);
182           break;
183         }
184       }
185     }
186     for (auto& sender_info : video_media_info_->aggregated_senders) {
187       if (sender_info.ssrc() == 0)
188         continue;  // Unconnected SSRC. bugs.webrtc.org/8673
189       RTC_DCHECK(video_info_by_sender_ssrc_.count(sender_info.ssrc()) == 0)
190           << "Duplicate video sender SSRC: " << sender_info.ssrc();
191       video_info_by_sender_ssrc_[sender_info.ssrc()] = &sender_info;
192       VideoTrackInterface* associated_track =
193           FindValueOrNull(local_video_track_by_ssrc, sender_info.ssrc());
194       if (associated_track) {
195         video_track_by_sender_info_[&sender_info] = associated_track;
196       }
197     }
198     for (auto& receiver_info : video_media_info_->receivers) {
199       VideoTrackInterface* associated_track =
200           FindValueOrNull(remote_video_track_by_ssrc, receiver_info.ssrc());
201       if (associated_track) {
202         // One receiver is associated with at most one track, which is uniquely
203         // associated with that receiver.
204         video_track_by_receiver_info_[&receiver_info] = associated_track;
205         RTC_DCHECK(video_info_by_remote_track_.find(associated_track) ==
206                    video_info_by_remote_track_.end());
207         video_info_by_remote_track_[associated_track] = &receiver_info;
208       } else if (unsignaled_video_track) {
209         video_track_by_receiver_info_[&receiver_info] = unsignaled_video_track;
210         video_info_by_remote_track_[unsignaled_video_track] = &receiver_info;
211       }
212       RTC_DCHECK(video_info_by_receiver_ssrc_.count(receiver_info.ssrc()) == 0)
213           << "Duplicate video receiver SSRC: " << receiver_info.ssrc();
214       video_info_by_receiver_ssrc_[receiver_info.ssrc()] = &receiver_info;
215     }
216   }
217 }
218 
219 const std::vector<cricket::VoiceSenderInfo*>*
GetVoiceSenderInfos(const AudioTrackInterface & local_audio_track) const220 TrackMediaInfoMap::GetVoiceSenderInfos(
221     const AudioTrackInterface& local_audio_track) const {
222   return FindAddressOrNull(voice_infos_by_local_track_, &local_audio_track);
223 }
224 
GetVoiceReceiverInfo(const AudioTrackInterface & remote_audio_track) const225 const cricket::VoiceReceiverInfo* TrackMediaInfoMap::GetVoiceReceiverInfo(
226     const AudioTrackInterface& remote_audio_track) const {
227   return FindValueOrNull(voice_info_by_remote_track_, &remote_audio_track);
228 }
229 
230 const std::vector<cricket::VideoSenderInfo*>*
GetVideoSenderInfos(const VideoTrackInterface & local_video_track) const231 TrackMediaInfoMap::GetVideoSenderInfos(
232     const VideoTrackInterface& local_video_track) const {
233   return FindAddressOrNull(video_infos_by_local_track_, &local_video_track);
234 }
235 
GetVideoReceiverInfo(const VideoTrackInterface & remote_video_track) const236 const cricket::VideoReceiverInfo* TrackMediaInfoMap::GetVideoReceiverInfo(
237     const VideoTrackInterface& remote_video_track) const {
238   return FindValueOrNull(video_info_by_remote_track_, &remote_video_track);
239 }
240 
GetVoiceSenderInfoBySsrc(uint32_t ssrc) const241 const cricket::VoiceSenderInfo* TrackMediaInfoMap::GetVoiceSenderInfoBySsrc(
242     uint32_t ssrc) const {
243   return FindValueOrNull(voice_info_by_sender_ssrc_, ssrc);
244 }
GetVoiceReceiverInfoBySsrc(uint32_t ssrc) const245 const cricket::VoiceReceiverInfo* TrackMediaInfoMap::GetVoiceReceiverInfoBySsrc(
246     uint32_t ssrc) const {
247   return FindValueOrNull(voice_info_by_receiver_ssrc_, ssrc);
248 }
249 
GetVideoSenderInfoBySsrc(uint32_t ssrc) const250 const cricket::VideoSenderInfo* TrackMediaInfoMap::GetVideoSenderInfoBySsrc(
251     uint32_t ssrc) const {
252   return FindValueOrNull(video_info_by_sender_ssrc_, ssrc);
253 }
254 
GetVideoReceiverInfoBySsrc(uint32_t ssrc) const255 const cricket::VideoReceiverInfo* TrackMediaInfoMap::GetVideoReceiverInfoBySsrc(
256     uint32_t ssrc) const {
257   return FindValueOrNull(video_info_by_receiver_ssrc_, ssrc);
258 }
259 
GetAudioTrack(const cricket::VoiceSenderInfo & voice_sender_info) const260 rtc::scoped_refptr<AudioTrackInterface> TrackMediaInfoMap::GetAudioTrack(
261     const cricket::VoiceSenderInfo& voice_sender_info) const {
262   return FindValueOrNull(audio_track_by_sender_info_, &voice_sender_info);
263 }
264 
GetAudioTrack(const cricket::VoiceReceiverInfo & voice_receiver_info) const265 rtc::scoped_refptr<AudioTrackInterface> TrackMediaInfoMap::GetAudioTrack(
266     const cricket::VoiceReceiverInfo& voice_receiver_info) const {
267   return FindValueOrNull(audio_track_by_receiver_info_, &voice_receiver_info);
268 }
269 
GetVideoTrack(const cricket::VideoSenderInfo & video_sender_info) const270 rtc::scoped_refptr<VideoTrackInterface> TrackMediaInfoMap::GetVideoTrack(
271     const cricket::VideoSenderInfo& video_sender_info) const {
272   return FindValueOrNull(video_track_by_sender_info_, &video_sender_info);
273 }
274 
GetVideoTrack(const cricket::VideoReceiverInfo & video_receiver_info) const275 rtc::scoped_refptr<VideoTrackInterface> TrackMediaInfoMap::GetVideoTrack(
276     const cricket::VideoReceiverInfo& video_receiver_info) const {
277   return FindValueOrNull(video_track_by_receiver_info_, &video_receiver_info);
278 }
279 
GetAttachmentIdByTrack(const MediaStreamTrackInterface * track) const280 absl::optional<int> TrackMediaInfoMap::GetAttachmentIdByTrack(
281     const MediaStreamTrackInterface* track) const {
282   auto it = attachment_id_by_track_.find(track);
283   return it != attachment_id_by_track_.end() ? absl::optional<int>(it->second)
284                                              : absl::nullopt;
285 }
286 
287 }  // namespace webrtc
288