Index: webrtc/api/trackmediainfomap.cc |
diff --git a/webrtc/api/trackmediainfomap.cc b/webrtc/api/trackmediainfomap.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d1acefe0958195df291d34c6b7cd91961fafeba8 |
--- /dev/null |
+++ b/webrtc/api/trackmediainfomap.cc |
@@ -0,0 +1,255 @@ |
+/* |
+ * Copyright 2016 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/api/trackmediainfomap.h" |
+ |
+#include <utility> |
+ |
+namespace webrtc { |
+ |
+namespace { |
+ |
+template<typename T> |
+T* CheckedTrackCast(MediaStreamTrackInterface* track); |
+ |
+template<> |
hta-webrtc
2017/01/11 12:34:24
C++ ignorance: Why is there value in having the te
hbos
2017/01/11 15:55:32
Without the DCHECK I could remove this function an
|
+AudioTrackInterface* CheckedTrackCast(MediaStreamTrackInterface* track) { |
+ RTC_DCHECK_EQ(track->kind(), MediaStreamTrackInterface::kAudioKind); |
+ return static_cast<AudioTrackInterface*>(track); |
+} |
+ |
+template<> |
+VideoTrackInterface* CheckedTrackCast(MediaStreamTrackInterface* track) { |
+ RTC_DCHECK_EQ(track->kind(), MediaStreamTrackInterface::kVideoKind); |
+ return static_cast<VideoTrackInterface*>(track); |
+} |
+ |
+// |T|: |AudioTrackInterface| or |VideoTrackInterface|, must match with |
+// |media_type|. |
+template<typename T> |
+std::map<uint32_t, T*> GetSsrcToTrack( |
+ cricket::MediaType media_type, |
+ const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& rtp_senders, |
+ const std::vector<rtc::scoped_refptr<RtpReceiverInterface>>& |
+ rtp_receivers) { |
+ std::map<uint32_t, T*> ssrc_to_track; |
+ for (const rtc::scoped_refptr<RtpSenderInterface>& rtp_sender : rtp_senders) { |
+ if (rtp_sender->media_type() != media_type || !rtp_sender->track()) { |
+ continue; |
+ } |
+ // TODO(deadbeef): |ssrc| should be removed in favor of |GetParameters|. |
+ if (rtp_sender->ssrc() != 0) { |
hta-webrtc
2017/01/11 12:34:23
Why isn't it correct to loop over all the ssrcs in
hbos
2017/01/11 15:55:32
If I understand correctly, it's because the first
|
+ RTC_DCHECK(ssrc_to_track.find(rtp_sender->ssrc()) == ssrc_to_track.end()); |
+ ssrc_to_track[rtp_sender->ssrc()] = CheckedTrackCast<T>( |
+ rtp_sender->track()); |
+ } |
+ RtpParameters params = rtp_sender->GetParameters(); |
Taylor Brandstetter
2017/01/10 17:29:24
Something I wanted to point out before I forget: t
hbos
2017/01/11 15:55:32
Thanks, I didn't realize [1] occurred. Ugh, but I'
Taylor Brandstetter
2017/01/11 22:12:05
Yes, if you call GetSenders you'll get proxies. Bu
|
+ for (const RtpEncodingParameters& encoding : params.encodings) { |
+ if (!encoding.ssrc || *encoding.ssrc == rtp_sender->ssrc()) { |
+ continue; |
+ } |
+ RTC_DCHECK(ssrc_to_track.find(*encoding.ssrc) == ssrc_to_track.end()); |
+ ssrc_to_track[*encoding.ssrc] = CheckedTrackCast<T>(rtp_sender->track()); |
+ } |
+ } |
+ for (const rtc::scoped_refptr<RtpReceiverInterface>& rtp_receiver : |
+ rtp_receivers) { |
+ if (rtp_receiver->media_type() != media_type) { |
+ continue; |
+ } |
+ RTC_DCHECK(rtp_receiver->track()); |
+ RtpParameters params = rtp_receiver->GetParameters(); |
+ for (const RtpEncodingParameters& encoding : params.encodings) { |
+ if (!encoding.ssrc) { |
+ continue; |
+ } |
+ RTC_DCHECK(ssrc_to_track.find(*encoding.ssrc) == ssrc_to_track.end()); |
+ ssrc_to_track[*encoding.ssrc] = CheckedTrackCast<T>( |
+ rtp_receiver->track()); |
+ } |
+ } |
+ return ssrc_to_track; |
+} |
+ |
+// Template in order to support both the audio and video case. |
+template<typename TrackType, typename InfoType> |
+TrackType* GetAssociatedTrack( |
+ const std::map<uint32_t, TrackType*>& ssrc_to_track, |
+ const InfoType& info) { |
+ typename std::map<uint32_t, TrackType*>::const_iterator it = |
+ ssrc_to_track.find(info.ssrc()); |
+ if (it == ssrc_to_track.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+// Template in order to support both the audio and video case. |
+template<typename TrackType, |
+ typename MediaInfoType, |
+ typename SenderInfoToTrackType, |
+ typename LocalTrackToInfosType, |
+ typename ReceiverInfoToTrackType, |
+ typename RemoteTrackToInfosType> |
+void MapTracksAndInfos( |
+ const std::map<uint32_t, TrackType*>& ssrc_to_track, |
+ MediaInfoType* media_info, |
+ SenderInfoToTrackType* sender_info_to_track, |
+ LocalTrackToInfosType* local_track_to_infos, |
+ ReceiverInfoToTrackType* receiver_info_to_track, |
+ RemoteTrackToInfosType* remote_track_to_info) { |
+ for (auto& sender_info : media_info->senders) { |
+ TrackType* associated_track = GetAssociatedTrack<TrackType>( |
+ ssrc_to_track, sender_info); |
+ if (associated_track) { |
+ // One sender is associated with at most one track. |
+ // One track may be associated with multiple senders. |
+ (*sender_info_to_track)[&sender_info] = associated_track; |
+ (*local_track_to_infos)[associated_track].push_back(&sender_info); |
+ } |
+ } |
+ for (auto& receiver_info : media_info->receivers) { |
+ TrackType* associated_track = GetAssociatedTrack<TrackType>( |
+ ssrc_to_track, receiver_info); |
+ if (associated_track) { |
+ // One receiver is associated with at most one track, which is uniquely |
+ // associated with that receiver. |
+ (*receiver_info_to_track)[&receiver_info] = associated_track; |
+ RTC_DCHECK(remote_track_to_info->find(associated_track) == |
+ remote_track_to_info->end()); |
+ (*remote_track_to_info)[associated_track] = &receiver_info; |
+ } |
+ } |
+} |
+ |
+} // namespace |
+ |
+TrackMediaInfoMap::TrackMediaInfoMap( |
+ std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info, |
+ std::unique_ptr<cricket::VideoMediaInfo> video_media_info, |
+ const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& rtp_senders, |
+ const std::vector<rtc::scoped_refptr<RtpReceiverInterface>>& rtp_receivers) |
+ : voice_media_info_(std::move(voice_media_info)), |
+ video_media_info_(std::move(video_media_info)) { |
+ if (voice_media_info_) { |
+ std::map<uint32_t, AudioTrackInterface*> ssrc_to_audio_track = |
+ GetSsrcToTrack<AudioTrackInterface>( |
+ cricket::MEDIA_TYPE_AUDIO, rtp_senders, rtp_receivers); |
+ MapTracksAndInfos<AudioTrackInterface>(ssrc_to_audio_track, |
+ voice_media_info_.get(), |
+ &voice_sender_info_to_track_, |
+ &local_audio_track_to_infos_, |
+ &voice_receiver_info_to_track_, |
+ &remote_audio_track_to_info_); |
+ } |
+ if (video_media_info_) { |
+ std::map<uint32_t, VideoTrackInterface*> ssrc_to_video_track = |
+ GetSsrcToTrack<VideoTrackInterface>( |
+ cricket::MEDIA_TYPE_VIDEO, rtp_senders, rtp_receivers); |
+ MapTracksAndInfos<VideoTrackInterface>(ssrc_to_video_track, |
+ video_media_info_.get(), |
+ &video_sender_info_to_track_, |
+ &local_video_track_to_infos_, |
+ &video_receiver_info_to_track_, |
+ &remote_video_track_to_info_); |
+ } |
+} |
+ |
+const std::vector<cricket::VoiceSenderInfo*>* |
+TrackMediaInfoMap::GetVoiceSenderInfos( |
+ const AudioTrackInterface& local_audio_track) const { |
+ std::map<const AudioTrackInterface*, |
+ std::vector<cricket::VoiceSenderInfo*>>::const_iterator it = |
+ local_audio_track_to_infos_.find(&local_audio_track); |
+ if (it == local_audio_track_to_infos_.end()) { |
+ return nullptr; |
+ } |
+ return &it->second; |
+} |
+ |
+const cricket::VoiceReceiverInfo* TrackMediaInfoMap::GetVoiceReceiverInfo( |
+ const AudioTrackInterface& remote_audio_track) const { |
+ std::map<const AudioTrackInterface*, |
+ cricket::VoiceReceiverInfo*>::const_iterator it = |
hta-webrtc
2017/01/11 12:34:23
Would "auto" be usable here? Seems that C++ alread
hbos
2017/01/11 15:55:33
Done.
|
+ remote_audio_track_to_info_.find(&remote_audio_track); |
+ if (it == remote_audio_track_to_info_.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+const std::vector<cricket::VideoSenderInfo*>* |
+TrackMediaInfoMap::GetVideoSenderInfos( |
+ const VideoTrackInterface& local_video_track) const { |
+ std::map<const VideoTrackInterface*, |
+ std::vector<cricket::VideoSenderInfo*>>::const_iterator it = |
+ local_video_track_to_infos_.find(&local_video_track); |
+ if (it == local_video_track_to_infos_.end()) { |
+ return nullptr; |
+ } |
+ return &it->second; |
+} |
+ |
+const cricket::VideoReceiverInfo* TrackMediaInfoMap::GetVideoReceiverInfo( |
+ const VideoTrackInterface& remote_video_track) const { |
+ std::map<const VideoTrackInterface*, |
+ cricket::VideoReceiverInfo*>::const_iterator it = |
+ remote_video_track_to_info_.find(&remote_video_track); |
+ if (it == remote_video_track_to_info_.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+rtc::scoped_refptr<AudioTrackInterface> TrackMediaInfoMap::GetAudioTrack( |
+ const cricket::VoiceSenderInfo& voice_sender_info) const { |
+ std::map<const cricket::VoiceSenderInfo*, |
+ rtc::scoped_refptr<AudioTrackInterface>>::const_iterator it = |
+ voice_sender_info_to_track_.find(&voice_sender_info); |
+ if (it == voice_sender_info_to_track_.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+rtc::scoped_refptr<AudioTrackInterface> TrackMediaInfoMap::GetAudioTrack( |
+ const cricket::VoiceReceiverInfo& voice_receiver_info) const { |
+ std::map<const cricket::VoiceReceiverInfo*, |
+ rtc::scoped_refptr<AudioTrackInterface>>::const_iterator it = |
+ voice_receiver_info_to_track_.find(&voice_receiver_info); |
+ if (it == voice_receiver_info_to_track_.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+rtc::scoped_refptr<VideoTrackInterface> TrackMediaInfoMap::GetVideoTrack( |
+ const cricket::VideoSenderInfo& video_sender_info) const { |
+ std::map<const cricket::VideoSenderInfo*, |
+ rtc::scoped_refptr<VideoTrackInterface>>::const_iterator it = |
+ video_sender_info_to_track_.find(&video_sender_info); |
+ if (it == video_sender_info_to_track_.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+rtc::scoped_refptr<VideoTrackInterface> TrackMediaInfoMap::GetVideoTrack( |
+ const cricket::VideoReceiverInfo& video_receiver_info) const { |
+ std::map<const cricket::VideoReceiverInfo*, |
+ rtc::scoped_refptr<VideoTrackInterface>>::const_iterator it = |
+ video_receiver_info_to_track_.find(&video_receiver_info); |
+ if (it == video_receiver_info_to_track_.end()) { |
+ return nullptr; |
+ } |
+ return it->second; |
+} |
+ |
+} // namespace webrtc |