Chromium Code Reviews| Index: webrtc/api/trackmediainfomap.cc | 
| diff --git a/webrtc/api/trackmediainfomap.cc b/webrtc/api/trackmediainfomap.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..3d8d729488a4d8c58d5ca37bdd4c36bf778a8142 | 
| --- /dev/null | 
| +++ b/webrtc/api/trackmediainfomap.cc | 
| @@ -0,0 +1,243 @@ | 
| +/* | 
| + * 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<> | 
| +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) { | 
| + RTC_DCHECK(ssrc_to_track.find(rtp_sender->ssrc()) == ssrc_to_track.end()); | 
| + ssrc_to_track[rtp_sender->ssrc()] = CheckedTrackCast<T>( | 
| + rtp_sender->track()); | 
| + } | 
| + // TODO(hbos): This uses a proxy to the signaling thread, and our | 
| + // implementation invokes on the worker thread. (This means one thread jump | 
| + // if on signaling thread and two thread jumps if on any other threads). Is | 
| + // there a way to avoid thread jumps per senders (and same for receivers)? | 
| + RtpParameters params = rtp_sender->GetParameters(); | 
| 
 
Taylor Brandstetter
2017/01/11 22:12:05
Given that currently, GetParameters will just retu
 
hbos
2017/01/12 11:03:14
Done.
 
 | 
| + 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 { | 
| + auto 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 { | 
| + auto it = 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 { | 
| + auto 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 { | 
| + auto 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 { | 
| + auto 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 { | 
| + auto 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 { | 
| + auto 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 { | 
| + auto 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 |