diff --git a/webrtc/pc/trackmediainfomap.cc b/webrtc/pc/trackmediainfomap.cc index d296c7f70e..33880b9380 100644 --- a/webrtc/pc/trackmediainfomap.cc +++ b/webrtc/pc/trackmediainfomap.cc @@ -31,10 +31,14 @@ const V* FindAddressOrNull(const std::map& map, const K& key) { void GetAudioAndVideoTrackBySsrc( const std::vector>& rtp_senders, const std::vector>& rtp_receivers, - std::map* audio_track_by_ssrc, - std::map* video_track_by_ssrc) { - RTC_DCHECK(audio_track_by_ssrc->empty()); - RTC_DCHECK(video_track_by_ssrc->empty()); + std::map* local_audio_track_by_ssrc, + std::map* local_video_track_by_ssrc, + std::map* remote_audio_track_by_ssrc, + std::map* remote_video_track_by_ssrc) { + RTC_DCHECK(local_audio_track_by_ssrc->empty()); + RTC_DCHECK(local_video_track_by_ssrc->empty()); + RTC_DCHECK(remote_audio_track_by_ssrc->empty()); + RTC_DCHECK(remote_video_track_by_ssrc->empty()); // TODO(hbos): RTP senders/receivers uses a proxy to the signaling thread, and // our sender/receiver implementations invokes on the worker thread. (This // means one thread jump if on signaling thread and two thread jumps if on any @@ -53,13 +57,15 @@ void GetAudioAndVideoTrackBySsrc( uint32_t ssrc = rtp_sender->ssrc(); if (ssrc != 0) { if (media_type == cricket::MEDIA_TYPE_AUDIO) { - RTC_DCHECK(audio_track_by_ssrc->find(ssrc) == - audio_track_by_ssrc->end()); - (*audio_track_by_ssrc)[ssrc] = static_cast(track); + RTC_DCHECK(local_audio_track_by_ssrc->find(ssrc) == + local_audio_track_by_ssrc->end()); + (*local_audio_track_by_ssrc)[ssrc] = + static_cast(track); } else { - RTC_DCHECK(video_track_by_ssrc->find(ssrc) == - video_track_by_ssrc->end()); - (*video_track_by_ssrc)[ssrc] = static_cast(track); + RTC_DCHECK(local_video_track_by_ssrc->find(ssrc) == + local_video_track_by_ssrc->end()); + (*local_video_track_by_ssrc)[ssrc] = + static_cast(track); } } } @@ -77,14 +83,14 @@ void GetAudioAndVideoTrackBySsrc( continue; } if (media_type == cricket::MEDIA_TYPE_AUDIO) { - RTC_DCHECK(audio_track_by_ssrc->find(*encoding.ssrc) == - audio_track_by_ssrc->end()); - (*audio_track_by_ssrc)[*encoding.ssrc] = + RTC_DCHECK(remote_audio_track_by_ssrc->find(*encoding.ssrc) == + remote_audio_track_by_ssrc->end()); + (*remote_audio_track_by_ssrc)[*encoding.ssrc] = static_cast(track); } else { - RTC_DCHECK(video_track_by_ssrc->find(*encoding.ssrc) == - video_track_by_ssrc->end()); - (*video_track_by_ssrc)[*encoding.ssrc] = + RTC_DCHECK(remote_video_track_by_ssrc->find(*encoding.ssrc) == + remote_video_track_by_ssrc->end()); + (*remote_video_track_by_ssrc)[*encoding.ssrc] = static_cast(track); } } @@ -100,14 +106,20 @@ TrackMediaInfoMap::TrackMediaInfoMap( const std::vector>& rtp_receivers) : voice_media_info_(std::move(voice_media_info)), video_media_info_(std::move(video_media_info)) { - std::map audio_track_by_ssrc; - std::map video_track_by_ssrc; - GetAudioAndVideoTrackBySsrc(rtp_senders, rtp_receivers, &audio_track_by_ssrc, - &video_track_by_ssrc); + std::map local_audio_track_by_ssrc; + std::map local_video_track_by_ssrc; + std::map remote_audio_track_by_ssrc; + std::map remote_video_track_by_ssrc; + GetAudioAndVideoTrackBySsrc(rtp_senders, + rtp_receivers, + &local_audio_track_by_ssrc, + &local_video_track_by_ssrc, + &remote_audio_track_by_ssrc, + &remote_video_track_by_ssrc); if (voice_media_info_) { for (auto& sender_info : voice_media_info_->senders) { AudioTrackInterface* associated_track = - FindValueOrNull(audio_track_by_ssrc, sender_info.ssrc()); + FindValueOrNull(local_audio_track_by_ssrc, sender_info.ssrc()); if (associated_track) { // One sender is associated with at most one track. // One track may be associated with multiple senders. @@ -117,7 +129,7 @@ TrackMediaInfoMap::TrackMediaInfoMap( } for (auto& receiver_info : voice_media_info_->receivers) { AudioTrackInterface* associated_track = - FindValueOrNull(audio_track_by_ssrc, receiver_info.ssrc()); + FindValueOrNull(remote_audio_track_by_ssrc, receiver_info.ssrc()); if (associated_track) { // One receiver is associated with at most one track, which is uniquely // associated with that receiver. @@ -131,7 +143,7 @@ TrackMediaInfoMap::TrackMediaInfoMap( if (video_media_info_) { for (auto& sender_info : video_media_info_->senders) { VideoTrackInterface* associated_track = - FindValueOrNull(video_track_by_ssrc, sender_info.ssrc()); + FindValueOrNull(local_video_track_by_ssrc, sender_info.ssrc()); if (associated_track) { // One sender is associated with at most one track. // One track may be associated with multiple senders. @@ -141,7 +153,7 @@ TrackMediaInfoMap::TrackMediaInfoMap( } for (auto& receiver_info : video_media_info_->receivers) { VideoTrackInterface* associated_track = - FindValueOrNull(video_track_by_ssrc, receiver_info.ssrc()); + FindValueOrNull(remote_video_track_by_ssrc, receiver_info.ssrc()); if (associated_track) { // One receiver is associated with at most one track, which is uniquely // associated with that receiver. diff --git a/webrtc/pc/trackmediainfomap_unittest.cc b/webrtc/pc/trackmediainfomap_unittest.cc index 2786214d95..07436800f8 100644 --- a/webrtc/pc/trackmediainfomap_unittest.cc +++ b/webrtc/pc/trackmediainfomap_unittest.cc @@ -345,6 +345,43 @@ TEST_F(TrackMediaInfoMapTest, MultipleMultiSsrcSendersPerTrack) { local_video_track_.get()); } +// SSRCs can be reused for send and receive in loopback. +TEST_F(TrackMediaInfoMapTest, SingleSenderReceiverPerTrackWithSsrcNotUnique) { + AddRtpSenderWithSsrcs({1}, local_audio_track_); + AddRtpReceiverWithSsrcs({1}, remote_audio_track_); + AddRtpSenderWithSsrcs({2}, local_video_track_); + AddRtpReceiverWithSsrcs({2}, remote_video_track_); + CreateMap(); + + // Local audio track <-> RTP audio senders + ASSERT_TRUE(map_->GetVoiceSenderInfos(*local_audio_track_)); + EXPECT_EQ( + *map_->GetVoiceSenderInfos(*local_audio_track_), + std::vector({&voice_media_info_->senders[0]})); + EXPECT_EQ(map_->GetAudioTrack(voice_media_info_->senders[0]), + local_audio_track_.get()); + + // Remote audio track <-> RTP audio receiver + EXPECT_EQ(map_->GetVoiceReceiverInfo(*remote_audio_track_), + &voice_media_info_->receivers[0]); + EXPECT_EQ(map_->GetAudioTrack(voice_media_info_->receivers[0]), + remote_audio_track_.get()); + + // Local video track <-> RTP video senders + ASSERT_TRUE(map_->GetVideoSenderInfos(*local_video_track_)); + EXPECT_EQ( + *map_->GetVideoSenderInfos(*local_video_track_), + std::vector({&video_media_info_->senders[0]})); + EXPECT_EQ(map_->GetVideoTrack(video_media_info_->senders[0]), + local_video_track_.get()); + + // Remote video track <-> RTP video receiver + EXPECT_EQ(map_->GetVideoReceiverInfo(*remote_video_track_), + &video_media_info_->receivers[0]); + EXPECT_EQ(map_->GetVideoTrack(video_media_info_->receivers[0]), + remote_video_track_.get()); +} + // Death tests. // Disabled on Android because death tests misbehave on Android, see // base/test/gtest_util.h. @@ -368,15 +405,6 @@ TEST_F(TrackMediaInfoMapDeathTest, MultipleMultiSsrcReceiversPerTrack) { EXPECT_DEATH(CreateMap(), ""); } -TEST_F(TrackMediaInfoMapDeathTest, - SingleSenderReceiverPerTrackWithSsrcNotUnique) { - AddRtpSenderWithSsrcs({1}, local_audio_track_); - AddRtpReceiverWithSsrcs({1}, remote_audio_track_); - AddRtpSenderWithSsrcs({2}, local_video_track_); - AddRtpReceiverWithSsrcs({2}, remote_video_track_); - EXPECT_DEATH(CreateMap(), ""); -} - #endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) } // namespace webrtc