blob: 2a7fe9cf4981b4ab05475636e4777f1a404ddcef [file] [log] [blame]
hbos1f8239c2017-01-16 04:24:10 -08001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "pc/trackmediainfomap.h"
hbos1f8239c2017-01-16 04:24:10 -080012
13#include <utility>
14
15namespace webrtc {
16
17namespace {
18
deadbeef804c1af2017-02-11 19:07:31 -080019template <typename K, typename V>
hbos1f8239c2017-01-16 04:24:10 -080020V FindValueOrNull(const std::map<K, V>& map, const K& key) {
21 auto it = map.find(key);
22 return (it != map.end()) ? it->second : nullptr;
23}
24
deadbeef804c1af2017-02-11 19:07:31 -080025template <typename K, typename V>
hbos1f8239c2017-01-16 04:24:10 -080026const V* FindAddressOrNull(const std::map<K, V>& map, const K& key) {
27 auto it = map.find(key);
28 return (it != map.end()) ? &it->second : nullptr;
29}
30
31void GetAudioAndVideoTrackBySsrc(
32 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& rtp_senders,
33 const std::vector<rtc::scoped_refptr<RtpReceiverInterface>>& rtp_receivers,
hbosfe90ad12017-02-20 02:05:13 -080034 std::map<uint32_t, AudioTrackInterface*>* local_audio_track_by_ssrc,
35 std::map<uint32_t, VideoTrackInterface*>* local_video_track_by_ssrc,
36 std::map<uint32_t, AudioTrackInterface*>* remote_audio_track_by_ssrc,
zhihuangf8164932017-05-19 13:09:47 -070037 std::map<uint32_t, VideoTrackInterface*>* remote_video_track_by_ssrc,
38 AudioTrackInterface** unsignaled_audio_track,
39 VideoTrackInterface** unsignaled_video_track) {
hbosfe90ad12017-02-20 02:05:13 -080040 RTC_DCHECK(local_audio_track_by_ssrc->empty());
41 RTC_DCHECK(local_video_track_by_ssrc->empty());
42 RTC_DCHECK(remote_audio_track_by_ssrc->empty());
43 RTC_DCHECK(remote_video_track_by_ssrc->empty());
hbos1f8239c2017-01-16 04:24:10 -080044 // TODO(hbos): RTP senders/receivers uses a proxy to the signaling thread, and
45 // our sender/receiver implementations invokes on the worker thread. (This
46 // means one thread jump if on signaling thread and two thread jumps if on any
47 // other threads). Is there a way to avoid thread jump(s) on a per
48 // sender/receiver, per method basis?
49 for (const rtc::scoped_refptr<RtpSenderInterface>& rtp_sender : rtp_senders) {
50 cricket::MediaType media_type = rtp_sender->media_type();
51 MediaStreamTrackInterface* track = rtp_sender->track();
52 if (!track) {
53 continue;
54 }
deadbeef804c1af2017-02-11 19:07:31 -080055 RTC_DCHECK_EQ(track->kind(), media_type == cricket::MEDIA_TYPE_AUDIO
56 ? MediaStreamTrackInterface::kAudioKind
57 : MediaStreamTrackInterface::kVideoKind);
hbos1f8239c2017-01-16 04:24:10 -080058 // TODO(deadbeef): |ssrc| should be removed in favor of |GetParameters|.
59 uint32_t ssrc = rtp_sender->ssrc();
60 if (ssrc != 0) {
61 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbosfe90ad12017-02-20 02:05:13 -080062 RTC_DCHECK(local_audio_track_by_ssrc->find(ssrc) ==
63 local_audio_track_by_ssrc->end());
64 (*local_audio_track_by_ssrc)[ssrc] =
65 static_cast<AudioTrackInterface*>(track);
hbos1f8239c2017-01-16 04:24:10 -080066 } else {
hbosfe90ad12017-02-20 02:05:13 -080067 RTC_DCHECK(local_video_track_by_ssrc->find(ssrc) ==
68 local_video_track_by_ssrc->end());
69 (*local_video_track_by_ssrc)[ssrc] =
70 static_cast<VideoTrackInterface*>(track);
hbos1f8239c2017-01-16 04:24:10 -080071 }
72 }
73 }
74 for (const rtc::scoped_refptr<RtpReceiverInterface>& rtp_receiver :
75 rtp_receivers) {
76 cricket::MediaType media_type = rtp_receiver->media_type();
77 MediaStreamTrackInterface* track = rtp_receiver->track();
78 RTC_DCHECK(track);
deadbeef804c1af2017-02-11 19:07:31 -080079 RTC_DCHECK_EQ(track->kind(), media_type == cricket::MEDIA_TYPE_AUDIO
80 ? MediaStreamTrackInterface::kAudioKind
81 : MediaStreamTrackInterface::kVideoKind);
hbos1f8239c2017-01-16 04:24:10 -080082 RtpParameters params = rtp_receiver->GetParameters();
83 for (const RtpEncodingParameters& encoding : params.encodings) {
84 if (!encoding.ssrc) {
zhihuangf8164932017-05-19 13:09:47 -070085 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
86 *unsignaled_audio_track = static_cast<AudioTrackInterface*>(track);
87 } else {
88 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_VIDEO);
89 *unsignaled_video_track = static_cast<VideoTrackInterface*>(track);
90 }
hbos1f8239c2017-01-16 04:24:10 -080091 continue;
92 }
93 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbosfe90ad12017-02-20 02:05:13 -080094 RTC_DCHECK(remote_audio_track_by_ssrc->find(*encoding.ssrc) ==
95 remote_audio_track_by_ssrc->end());
96 (*remote_audio_track_by_ssrc)[*encoding.ssrc] =
hbos1f8239c2017-01-16 04:24:10 -080097 static_cast<AudioTrackInterface*>(track);
98 } else {
hbosfe90ad12017-02-20 02:05:13 -080099 RTC_DCHECK(remote_video_track_by_ssrc->find(*encoding.ssrc) ==
100 remote_video_track_by_ssrc->end());
101 (*remote_video_track_by_ssrc)[*encoding.ssrc] =
hbos1f8239c2017-01-16 04:24:10 -0800102 static_cast<VideoTrackInterface*>(track);
103 }
104 }
105 }
106}
107
108} // namespace
109
110TrackMediaInfoMap::TrackMediaInfoMap(
111 std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info,
112 std::unique_ptr<cricket::VideoMediaInfo> video_media_info,
113 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& rtp_senders,
114 const std::vector<rtc::scoped_refptr<RtpReceiverInterface>>& rtp_receivers)
115 : voice_media_info_(std::move(voice_media_info)),
116 video_media_info_(std::move(video_media_info)) {
hbosfe90ad12017-02-20 02:05:13 -0800117 std::map<uint32_t, AudioTrackInterface*> local_audio_track_by_ssrc;
118 std::map<uint32_t, VideoTrackInterface*> local_video_track_by_ssrc;
119 std::map<uint32_t, AudioTrackInterface*> remote_audio_track_by_ssrc;
120 std::map<uint32_t, VideoTrackInterface*> remote_video_track_by_ssrc;
zhihuangf8164932017-05-19 13:09:47 -0700121 AudioTrackInterface* unsignaled_audio_track = nullptr;
122 VideoTrackInterface* unsignaled_video_track = nullptr;
123 GetAudioAndVideoTrackBySsrc(
124 rtp_senders, rtp_receivers, &local_audio_track_by_ssrc,
125 &local_video_track_by_ssrc, &remote_audio_track_by_ssrc,
126 &remote_video_track_by_ssrc, &unsignaled_audio_track,
127 &unsignaled_video_track);
hbos1f8239c2017-01-16 04:24:10 -0800128 if (voice_media_info_) {
129 for (auto& sender_info : voice_media_info_->senders) {
130 AudioTrackInterface* associated_track =
hbosfe90ad12017-02-20 02:05:13 -0800131 FindValueOrNull(local_audio_track_by_ssrc, sender_info.ssrc());
hbos1f8239c2017-01-16 04:24:10 -0800132 if (associated_track) {
133 // One sender is associated with at most one track.
134 // One track may be associated with multiple senders.
135 audio_track_by_sender_info_[&sender_info] = associated_track;
136 voice_infos_by_local_track_[associated_track].push_back(&sender_info);
137 }
138 }
139 for (auto& receiver_info : voice_media_info_->receivers) {
140 AudioTrackInterface* associated_track =
hbosfe90ad12017-02-20 02:05:13 -0800141 FindValueOrNull(remote_audio_track_by_ssrc, receiver_info.ssrc());
hbos1f8239c2017-01-16 04:24:10 -0800142 if (associated_track) {
143 // One receiver is associated with at most one track, which is uniquely
144 // associated with that receiver.
145 audio_track_by_receiver_info_[&receiver_info] = associated_track;
146 RTC_DCHECK(voice_info_by_remote_track_.find(associated_track) ==
147 voice_info_by_remote_track_.end());
148 voice_info_by_remote_track_[associated_track] = &receiver_info;
zhihuangf8164932017-05-19 13:09:47 -0700149 } else if (unsignaled_audio_track) {
150 audio_track_by_receiver_info_[&receiver_info] = unsignaled_audio_track;
151 voice_info_by_remote_track_[unsignaled_audio_track] = &receiver_info;
hbos1f8239c2017-01-16 04:24:10 -0800152 }
153 }
154 }
155 if (video_media_info_) {
156 for (auto& sender_info : video_media_info_->senders) {
157 VideoTrackInterface* associated_track =
hbosfe90ad12017-02-20 02:05:13 -0800158 FindValueOrNull(local_video_track_by_ssrc, sender_info.ssrc());
hbos1f8239c2017-01-16 04:24:10 -0800159 if (associated_track) {
160 // One sender is associated with at most one track.
161 // One track may be associated with multiple senders.
162 video_track_by_sender_info_[&sender_info] = associated_track;
163 video_infos_by_local_track_[associated_track].push_back(&sender_info);
164 }
165 }
166 for (auto& receiver_info : video_media_info_->receivers) {
167 VideoTrackInterface* associated_track =
hbosfe90ad12017-02-20 02:05:13 -0800168 FindValueOrNull(remote_video_track_by_ssrc, receiver_info.ssrc());
hbos1f8239c2017-01-16 04:24:10 -0800169 if (associated_track) {
170 // One receiver is associated with at most one track, which is uniquely
171 // associated with that receiver.
172 video_track_by_receiver_info_[&receiver_info] = associated_track;
173 RTC_DCHECK(video_info_by_remote_track_.find(associated_track) ==
174 video_info_by_remote_track_.end());
175 video_info_by_remote_track_[associated_track] = &receiver_info;
zhihuangf8164932017-05-19 13:09:47 -0700176 } else if (unsignaled_video_track) {
177 video_track_by_receiver_info_[&receiver_info] = unsignaled_video_track;
178 video_info_by_remote_track_[unsignaled_video_track] = &receiver_info;
hbos1f8239c2017-01-16 04:24:10 -0800179 }
180 }
181 }
182}
183
184const std::vector<cricket::VoiceSenderInfo*>*
185TrackMediaInfoMap::GetVoiceSenderInfos(
186 const AudioTrackInterface& local_audio_track) const {
187 return FindAddressOrNull(voice_infos_by_local_track_, &local_audio_track);
188}
189
190const cricket::VoiceReceiverInfo* TrackMediaInfoMap::GetVoiceReceiverInfo(
191 const AudioTrackInterface& remote_audio_track) const {
192 return FindValueOrNull(voice_info_by_remote_track_, &remote_audio_track);
193}
194
195const std::vector<cricket::VideoSenderInfo*>*
196TrackMediaInfoMap::GetVideoSenderInfos(
197 const VideoTrackInterface& local_video_track) const {
198 return FindAddressOrNull(video_infos_by_local_track_, &local_video_track);
199}
200
201const cricket::VideoReceiverInfo* TrackMediaInfoMap::GetVideoReceiverInfo(
202 const VideoTrackInterface& remote_video_track) const {
203 return FindValueOrNull(video_info_by_remote_track_, &remote_video_track);
204}
205
206rtc::scoped_refptr<AudioTrackInterface> TrackMediaInfoMap::GetAudioTrack(
207 const cricket::VoiceSenderInfo& voice_sender_info) const {
208 return FindValueOrNull(audio_track_by_sender_info_, &voice_sender_info);
209}
210
211rtc::scoped_refptr<AudioTrackInterface> TrackMediaInfoMap::GetAudioTrack(
212 const cricket::VoiceReceiverInfo& voice_receiver_info) const {
213 return FindValueOrNull(audio_track_by_receiver_info_, &voice_receiver_info);
214}
215
216rtc::scoped_refptr<VideoTrackInterface> TrackMediaInfoMap::GetVideoTrack(
217 const cricket::VideoSenderInfo& video_sender_info) const {
218 return FindValueOrNull(video_track_by_sender_info_, &video_sender_info);
219}
220
221rtc::scoped_refptr<VideoTrackInterface> TrackMediaInfoMap::GetVideoTrack(
222 const cricket::VideoReceiverInfo& video_receiver_info) const {
223 return FindValueOrNull(video_track_by_receiver_info_, &video_receiver_info);
224}
225
226} // namespace webrtc