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 |