From c72af93cff8e79e97987c3bee1493668b7826e37 Mon Sep 17 00:00:00 2001 From: Harald Alvestrand Date: Thu, 11 Jan 2018 17:18:19 +0100 Subject: [PATCH] Reland "Move stats ID generation from SSRC to local ID" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a reland of e357a4dd4e3b015f8281813f246de793589bd537 Original change's description: > Move stats ID generation from SSRC to local ID > > This generates stats IDs for Track stats (which > represents stats on the attachment of a track to > a PeerConnection) from being SSRC-based to being > based on an ID that is allocated when connecting the > track to the PC. > > This is a prerequisite to generating stats before > the PeerConnection is connected. > > Bug: webrtc:8673 > Change-Id: I82f6e521646b0c92b3af4dffb2cdee75e6dc10d4 > Reviewed-on: https://webrtc-review.googlesource.com/38360 > Commit-Queue: Harald Alvestrand > Reviewed-by: Fredrik Solenberg > Reviewed-by: Henrik Boström > Cr-Commit-Position: refs/heads/master@{#21582} TBR=solenberg@webrtc.org Bug: webrtc:8673 Change-Id: I610302efc5393919569b77e3b59aa3384a9b88a5 Reviewed-on: https://webrtc-review.googlesource.com/38842 Reviewed-by: Harald Alvestrand Commit-Queue: Harald Alvestrand Cr-Commit-Position: refs/heads/master@{#21589} --- api/rtpreceiverinterface.h | 8 + api/rtpsenderinterface.h | 10 +- api/test/mock_rtpreceiver.h | 1 + api/test/mock_rtpsender.h | 1 + pc/peerconnectioninterface_unittest.cc | 25 ++++ pc/rtcstatscollector.cc | 199 ++++++++++++------------- pc/rtcstatscollector_unittest.cc | 182 ++++++---------------- pc/rtpreceiver.cc | 17 ++- pc/rtpreceiver.h | 3 + pc/rtpsender.cc | 23 ++- pc/rtpsender.h | 5 + pc/trackmediainfomap.cc | 15 ++ pc/trackmediainfomap.h | 13 ++ pc/trackmediainfomap_unittest.cc | 10 ++ 14 files changed, 265 insertions(+), 247 deletions(-) diff --git a/api/rtpreceiverinterface.h b/api/rtpreceiverinterface.h index 311971d951..ac2e090dad 100644 --- a/api/rtpreceiverinterface.h +++ b/api/rtpreceiverinterface.h @@ -127,6 +127,13 @@ class RtpReceiverInterface : public rtc::RefCountInterface { virtual std::vector GetSources() const { return std::vector(); } + // TODO(hta): Remove default implementation or move function to + // an internal interface. content::FakeRtpReceiver in Chromium needs this. + + // Returns an ID that changes if the attached track changes, but + // otherwise remains constant. Used to generate IDs for stats. + // The special value zero means that no track is attached. + virtual int AttachmentId() const { return 0; } protected: virtual ~RtpReceiverInterface() {} @@ -146,6 +153,7 @@ BEGIN_SIGNALING_PROXY_MAP(RtpReceiver) PROXY_METHOD1(bool, SetParameters, const RtpParameters&) PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*); PROXY_CONSTMETHOD0(std::vector, GetSources); + PROXY_CONSTMETHOD0(int, AttachmentId); END_PROXY_MAP() } // namespace webrtc diff --git a/api/rtpsenderinterface.h b/api/rtpsenderinterface.h index a7fbbda46b..a7d7edc4b0 100644 --- a/api/rtpsenderinterface.h +++ b/api/rtpsenderinterface.h @@ -59,6 +59,13 @@ class RtpSenderInterface : public rtc::RefCountInterface { // Returns null for a video sender. virtual rtc::scoped_refptr GetDtmfSender() const = 0; + // Returns an ID that changes every time SetTrack() is called, but + // otherwise remains constant. Used to generate IDs for stats. + // The special value zero means that no track is attached. + // TODO(hta): Remove default implementation when callers have updated, + // or move function to an internal interface. + virtual int AttachmentId() const { return 0; } + protected: virtual ~RtpSenderInterface() {} }; @@ -77,7 +84,8 @@ BEGIN_SIGNALING_PROXY_MAP(RtpSender) PROXY_CONSTMETHOD0(RtpParameters, GetParameters); PROXY_METHOD1(bool, SetParameters, const RtpParameters&) PROXY_CONSTMETHOD0(rtc::scoped_refptr, GetDtmfSender); -END_PROXY_MAP() + PROXY_CONSTMETHOD0(int, AttachmentId); + END_PROXY_MAP() } // namespace webrtc diff --git a/api/test/mock_rtpreceiver.h b/api/test/mock_rtpreceiver.h index 7097adc02d..53c04b965f 100644 --- a/api/test/mock_rtpreceiver.h +++ b/api/test/mock_rtpreceiver.h @@ -29,6 +29,7 @@ class MockRtpReceiver : public rtc::RefCountedObject { MOCK_METHOD1(SetParameters, bool(const RtpParameters&)); MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*)); MOCK_CONST_METHOD0(GetSources, std::vector()); + MOCK_CONST_METHOD0(AttachmentId, int()); }; } // namespace webrtc diff --git a/api/test/mock_rtpsender.h b/api/test/mock_rtpsender.h index a89fa9264a..35d048c18a 100644 --- a/api/test/mock_rtpsender.h +++ b/api/test/mock_rtpsender.h @@ -30,6 +30,7 @@ class MockRtpSender : public rtc::RefCountedObject { MOCK_CONST_METHOD0(GetParameters, RtpParameters()); MOCK_METHOD1(SetParameters, bool(const RtpParameters&)); MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr()); + MOCK_CONST_METHOD0(AttachmentId, int()); }; } // namespace webrtc diff --git a/pc/peerconnectioninterface_unittest.cc b/pc/peerconnectioninterface_unittest.cc index bc6b5e5b80..a06ed50086 100644 --- a/pc/peerconnectioninterface_unittest.cc +++ b/pc/peerconnectioninterface_unittest.cc @@ -1506,6 +1506,31 @@ TEST_F(PeerConnectionInterfaceTest, AddTrackBeforeConnecting) { EXPECT_TRUE(DoGetStats(nullptr)); } +TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddTrack) { + CreatePeerConnectionWithoutDtls(); + rtc::scoped_refptr audio_track( + pc_factory_->CreateAudioTrack("audio_track", nullptr)); + rtc::scoped_refptr video_track( + pc_factory_->CreateVideoTrack( + "video_track", pc_factory_->CreateVideoSource( + std::unique_ptr( + new cricket::FakeVideoCapturer())))); + auto audio_sender = pc_->AddTrack(audio_track, std::vector()); + auto video_sender = pc_->AddTrack(video_track, std::vector()); + EXPECT_TRUE(audio_sender.ok()); + EXPECT_TRUE(video_sender.ok()); + EXPECT_NE(0, video_sender.value()->AttachmentId()); + EXPECT_NE(0, audio_sender.value()->AttachmentId()); +} + +TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddStream) { + CreatePeerConnectionWithoutDtls(); + AddVideoStream(kStreamLabel1); + auto senders = pc_->GetSenders(); + EXPECT_EQ(1u, senders.size()); + EXPECT_NE(0, senders[0]->AttachmentId()); +} + TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) { InitiateCall(); WaitAndVerifyOnAddStream(kStreamLabel1); diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc index e777a2672c..0f4dc3de2b 100644 --- a/pc/rtcstatscollector.cc +++ b/pc/rtcstatscollector.cc @@ -57,8 +57,11 @@ std::string RTCIceCandidatePairStatsIDFromConnectionInfo( info.remote_candidate.id(); } -std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - bool is_local, const char* kind, const std::string& id, uint32_t ssrc) { +std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + bool is_local, + const char* kind, + const std::string& id, + int attachment_id) { RTC_DCHECK(kind == MediaStreamTrackInterface::kAudioKind || kind == MediaStreamTrackInterface::kVideoKind); std::ostringstream oss; @@ -66,7 +69,7 @@ std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( : "RTCMediaStreamTrack_remote_"); oss << kind << "_"; oss << id << "_"; - oss << ssrc; + oss << attachment_id; return oss.str(); } @@ -375,14 +378,14 @@ std::unique_ptr ProduceMediaStreamTrackStatsFromVoiceSenderInfo( int64_t timestamp_us, const AudioTrackInterface& audio_track, - const cricket::VoiceSenderInfo& voice_sender_info) { + const cricket::VoiceSenderInfo& voice_sender_info, + int attachment_id) { std::unique_ptr audio_track_stats( new RTCMediaStreamTrackStats( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( true, MediaStreamTrackInterface::kAudioKind, audio_track.id(), - voice_sender_info.ssrc()), - timestamp_us, - RTCMediaStreamTrackKind::kAudio)); + attachment_id), + timestamp_us, RTCMediaStreamTrackKind::kAudio)); SetMediaStreamTrackStatsFromMediaStreamTrackInterface( audio_track, audio_track_stats.get()); audio_track_stats->remote_source = false; @@ -409,14 +412,16 @@ std::unique_ptr ProduceMediaStreamTrackStatsFromVoiceReceiverInfo( int64_t timestamp_us, const AudioTrackInterface& audio_track, - const cricket::VoiceReceiverInfo& voice_receiver_info) { + const cricket::VoiceReceiverInfo& voice_receiver_info, + int attachment_id) { + // Since receiver tracks can't be reattached, we use the SSRC as + // an attachment identifier. std::unique_ptr audio_track_stats( new RTCMediaStreamTrackStats( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( false, MediaStreamTrackInterface::kAudioKind, audio_track.id(), - voice_receiver_info.ssrc()), - timestamp_us, - RTCMediaStreamTrackKind::kAudio)); + attachment_id), + timestamp_us, RTCMediaStreamTrackKind::kAudio)); SetMediaStreamTrackStatsFromMediaStreamTrackInterface( audio_track, audio_track_stats.get()); audio_track_stats->remote_source = true; @@ -443,14 +448,14 @@ std::unique_ptr ProduceMediaStreamTrackStatsFromVideoSenderInfo( int64_t timestamp_us, const VideoTrackInterface& video_track, - const cricket::VideoSenderInfo& video_sender_info) { + const cricket::VideoSenderInfo& video_sender_info, + int attachment_id) { std::unique_ptr video_track_stats( new RTCMediaStreamTrackStats( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( true, MediaStreamTrackInterface::kVideoKind, video_track.id(), - video_sender_info.ssrc()), - timestamp_us, - RTCMediaStreamTrackKind::kVideo)); + attachment_id), + timestamp_us, RTCMediaStreamTrackKind::kVideo)); SetMediaStreamTrackStatsFromMediaStreamTrackInterface( video_track, video_track_stats.get()); video_track_stats->remote_source = false; @@ -469,14 +474,16 @@ std::unique_ptr ProduceMediaStreamTrackStatsFromVideoReceiverInfo( int64_t timestamp_us, const VideoTrackInterface& video_track, - const cricket::VideoReceiverInfo& video_receiver_info) { + const cricket::VideoReceiverInfo& video_receiver_info, + int attachment_id) { + // Since receiver tracks can't be reattached, we use the SSRC as + // attachment ID. std::unique_ptr video_track_stats( new RTCMediaStreamTrackStats( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( false, MediaStreamTrackInterface::kVideoKind, video_track.id(), - video_receiver_info.ssrc()), - timestamp_us, - RTCMediaStreamTrackKind::kVideo)); + attachment_id), + timestamp_us, RTCMediaStreamTrackKind::kVideo)); SetMediaStreamTrackStatsFromMediaStreamTrackInterface( video_track, video_track_stats.get()); video_track_stats->remote_source = true; @@ -526,8 +533,8 @@ void ProduceSenderMediaTrackStats( RTC_CHECK(voice_sender_info) << "No voice sender info for sender with ssrc " << sender->ssrc(); std::unique_ptr audio_track_stats = - ProduceMediaStreamTrackStatsFromVoiceSenderInfo(timestamp_us, *track, - *voice_sender_info); + ProduceMediaStreamTrackStatsFromVoiceSenderInfo( + timestamp_us, *track, *voice_sender_info, sender->AttachmentId()); report->AddStats(std::move(audio_track_stats)); } else if (sender->media_type() == cricket::MEDIA_TYPE_VIDEO) { VideoTrackInterface* track = @@ -539,8 +546,8 @@ void ProduceSenderMediaTrackStats( RTC_CHECK(video_sender_info) << "No video sender info for sender with ssrc " << sender->ssrc(); std::unique_ptr video_track_stats = - ProduceMediaStreamTrackStatsFromVideoSenderInfo(timestamp_us, *track, - *video_sender_info); + ProduceMediaStreamTrackStatsFromVideoSenderInfo( + timestamp_us, *track, *video_sender_info, sender->AttachmentId()); report->AddStats(std::move(video_track_stats)); } else { RTC_NOTREACHED(); @@ -565,7 +572,8 @@ void ProduceReceiverMediaTrackStats( } std::unique_ptr audio_track_stats = ProduceMediaStreamTrackStatsFromVoiceReceiverInfo( - timestamp_us, *track, *voice_receiver_info); + timestamp_us, *track, *voice_receiver_info, + receiver->AttachmentId()); report->AddStats(std::move(audio_track_stats)); } else if (receiver->media_type() == cricket::MEDIA_TYPE_VIDEO) { VideoTrackInterface* track = @@ -577,7 +585,8 @@ void ProduceReceiverMediaTrackStats( } std::unique_ptr video_track_stats = ProduceMediaStreamTrackStatsFromVideoReceiverInfo( - timestamp_us, *track, *video_receiver_info); + timestamp_us, *track, *video_receiver_info, + receiver->AttachmentId()); report->AddStats(std::move(video_track_stats)); } else { RTC_NOTREACHED(); @@ -608,59 +617,37 @@ void ProduceMediaStreamStats( // TODO(hta): Revisit in conjunction with https://bugs.webrtc.org/8674 if (is_local) { for (auto audio_track : stream->GetAudioTracks()) { - auto sender_infos = - track_media_info_map.GetVoiceSenderInfos(*audio_track); - // There is no map entry on unconnected tracks. - // https://bugs.webrtc.org/8673 - if (!sender_infos) - continue; - for (const auto& sender_info : *sender_infos) { - // In the WebRTC implementation, SSRC 0 means unconnected, - // and should not occur in the map. - // https://bugs.webrtc.org/8694 - RTC_DCHECK_NE(0, sender_info->ssrc()); - stream_stats->track_ids->push_back( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - is_local, MediaStreamTrackInterface::kAudioKind, - audio_track->id(), sender_info->ssrc())); - } + stream_stats->track_ids->push_back( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + is_local, MediaStreamTrackInterface::kAudioKind, + audio_track->id(), + track_media_info_map.GetAttachmentIdByTrack(audio_track) + .value())); } for (auto video_track : stream->GetVideoTracks()) { - auto sender_infos = - track_media_info_map.GetVideoSenderInfos(*video_track); - // There is no map entry on unconnected tracks. - // https://bugs.webrtc.org/8673 - if (!sender_infos) - continue; - for (const auto& sender_info : *sender_infos) { - // SSRC must not be zero. https://bugs.webrtc.org/8694 - RTC_DCHECK_NE(0, sender_info->ssrc()); - stream_stats->track_ids->push_back( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - is_local, MediaStreamTrackInterface::kVideoKind, - video_track->id(), sender_info->ssrc())); - } + stream_stats->track_ids->push_back( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + is_local, MediaStreamTrackInterface::kVideoKind, + video_track->id(), + track_media_info_map.GetAttachmentIdByTrack(video_track) + .value())); } } else { for (auto audio_track : stream->GetAudioTracks()) { - auto receiver_info = - track_media_info_map.GetVoiceReceiverInfo(*audio_track); - if (receiver_info) { - stream_stats->track_ids->push_back( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - is_local, MediaStreamTrackInterface::kAudioKind, - audio_track->id(), receiver_info->ssrc())); - } + stream_stats->track_ids->push_back( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + is_local, MediaStreamTrackInterface::kAudioKind, + audio_track->id(), + track_media_info_map.GetAttachmentIdByTrack(audio_track) + .value())); } for (auto video_track : stream->GetVideoTracks()) { - auto receiver_info = - track_media_info_map.GetVideoReceiverInfo(*video_track); - if (receiver_info) { - stream_stats->track_ids->push_back( - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - is_local, MediaStreamTrackInterface::kVideoKind, - video_track->id(), receiver_info->ssrc())); - } + stream_stats->track_ids->push_back( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + is_local, MediaStreamTrackInterface::kVideoKind, + video_track->id(), + track_media_info_map.GetAttachmentIdByTrack(video_track) + .value())); } } report->AddStats(std::move(stream_stats)); @@ -1077,22 +1064,21 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( if (voice_receiver_info.ssrc() == 0) continue; std::unique_ptr inbound_audio( - new RTCInboundRTPStreamStats( - RTCInboundRTPStreamStatsIDFromSSRC( - true, voice_receiver_info.ssrc()), - timestamp_us)); + new RTCInboundRTPStreamStats(RTCInboundRTPStreamStatsIDFromSSRC( + true, voice_receiver_info.ssrc()), + timestamp_us)); SetInboundRTPStreamStatsFromVoiceReceiverInfo( voice_receiver_info, inbound_audio.get()); + // TODO(hta): This lookup should look for the sender, not the track. rtc::scoped_refptr audio_track = track_media_info_map_->GetAudioTrack(voice_receiver_info); if (audio_track) { RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end()); - inbound_audio->track_id = - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - false, - MediaStreamTrackInterface::kAudioKind, - track_to_id_.find(audio_track.get())->second, - voice_receiver_info.ssrc()); + inbound_audio + ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + false, MediaStreamTrackInterface::kAudioKind, + track_to_id_.find(audio_track.get())->second, + track_media_info_map_->GetAttachmentIdByTrack(audio_track).value()); } inbound_audio->transport_id = transport_id; report->AddStats(std::move(inbound_audio)); @@ -1115,12 +1101,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( track_media_info_map_->GetAudioTrack(voice_sender_info); if (audio_track) { RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end()); - outbound_audio->track_id = - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - true, - MediaStreamTrackInterface::kAudioKind, - track_to_id_.find(audio_track.get())->second, - voice_sender_info.ssrc()); + outbound_audio + ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + true, MediaStreamTrackInterface::kAudioKind, + track_to_id_.find(audio_track.get())->second, + track_media_info_map.GetAttachmentIdByTrack(audio_track).value()); } outbound_audio->transport_id = transport_id; report->AddStats(std::move(outbound_audio)); @@ -1151,12 +1136,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( track_media_info_map_->GetVideoTrack(video_receiver_info); if (video_track) { RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end()); - inbound_video->track_id = - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - false, - MediaStreamTrackInterface::kVideoKind, - track_to_id_.find(video_track.get())->second, - video_receiver_info.ssrc()); + inbound_video + ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + false, MediaStreamTrackInterface::kVideoKind, + track_to_id_.find(video_track.get())->second, + track_media_info_map_->GetAttachmentIdByTrack(video_track).value()); } inbound_video->transport_id = transport_id; report->AddStats(std::move(inbound_video)); @@ -1169,22 +1153,20 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( if (video_sender_info.ssrc() == 0) continue; std::unique_ptr outbound_video( - new RTCOutboundRTPStreamStats( - RTCOutboundRTPStreamStatsIDFromSSRC( - false, video_sender_info.ssrc()), - timestamp_us)); + new RTCOutboundRTPStreamStats(RTCOutboundRTPStreamStatsIDFromSSRC( + false, video_sender_info.ssrc()), + timestamp_us)); SetOutboundRTPStreamStatsFromVideoSenderInfo( video_sender_info, outbound_video.get()); rtc::scoped_refptr video_track = track_media_info_map_->GetVideoTrack(video_sender_info); if (video_track) { RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end()); - outbound_video->track_id = - RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( - true, - MediaStreamTrackInterface::kVideoKind, - track_to_id_.find(video_track.get())->second, - video_sender_info.ssrc()); + outbound_video + ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment( + true, MediaStreamTrackInterface::kVideoKind, + track_to_id_.find(video_track.get())->second, + track_media_info_map_->GetAttachmentIdByTrack(video_track).value()); } outbound_video->transport_id = transport_id; report->AddStats(std::move(outbound_video)); @@ -1310,6 +1292,9 @@ RTCStatsCollector::PrepareTrackMediaInfoMap_s() const { std::map RTCStatsCollector::PrepareTrackToID_s() const { + // TODO(hta): Remove this method, and vector its callers via + // senders / receivers instead. + // It ignores tracks that are multiply connected to the PC. RTC_DCHECK(signaling_thread_->IsCurrent()); std::map track_to_id; for (auto sender : pc_->GetSenders()) { diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc index 2149695005..141a3cff85 100644 --- a/pc/rtcstatscollector_unittest.cc +++ b/pc/rtcstatscollector_unittest.cc @@ -238,7 +238,8 @@ rtc::scoped_refptr CreateFakeTrack( rtc::scoped_refptr CreateMockSender( const rtc::scoped_refptr& track, - uint32_t ssrc) { + uint32_t ssrc, + int attachment_id) { rtc::scoped_refptr sender( new rtc::RefCountedObject()); EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track)); @@ -253,12 +254,14 @@ rtc::scoped_refptr CreateMockSender( params.encodings[0].ssrc = ssrc; return params; })); + EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id)); return sender; } rtc::scoped_refptr CreateMockReceiver( const rtc::scoped_refptr& track, - uint32_t ssrc) { + uint32_t ssrc, + int attachment_id) { rtc::scoped_refptr receiver( new rtc::RefCountedObject()); EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track)); @@ -272,6 +275,7 @@ rtc::scoped_refptr CreateMockReceiver( params.encodings[0].ssrc = ssrc; return params; })); + EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id)); return receiver; } @@ -349,7 +353,8 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { } } - rtc::scoped_refptr sender = CreateMockSender(track, ssrc); + rtc::scoped_refptr sender = + CreateMockSender(track, ssrc, 50); EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( std::vector>({ rtc::scoped_refptr(sender.get()) }))); @@ -379,7 +384,7 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { } rtc::scoped_refptr receiver = - CreateMockReceiver(track, ssrc); + CreateMockReceiver(track, ssrc, 62); EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( std::vector>({ rtc::scoped_refptr(receiver.get()) }))); @@ -404,6 +409,7 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { rtp_senders_.clear(); rtp_receivers_.clear(); // Local audio tracks and voice sender infos + int attachment_id = 147; for (auto& pair : local_audio_track_info_pairs) { MediaStreamTrackInterface* local_audio_track = pair.first; const cricket::VoiceSenderInfo& voice_sender_info = pair.second; @@ -411,14 +417,14 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { MediaStreamTrackInterface::kAudioKind); voice_media_info_->senders.push_back(voice_sender_info); - rtc::scoped_refptr rtp_sender = - CreateMockSender(rtc::scoped_refptr( - local_audio_track), - voice_sender_info.local_stats[0].ssrc); + rtc::scoped_refptr rtp_sender = CreateMockSender( + rtc::scoped_refptr(local_audio_track), + voice_sender_info.local_stats[0].ssrc, attachment_id++); rtp_senders_.push_back(rtc::scoped_refptr( rtp_sender.get())); } // Remote audio tracks and voice receiver infos + attachment_id = 181; for (auto& pair : remote_audio_track_info_pairs) { MediaStreamTrackInterface* remote_audio_track = pair.first; const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second; @@ -426,14 +432,14 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { MediaStreamTrackInterface::kAudioKind); voice_media_info_->receivers.push_back(voice_receiver_info); - rtc::scoped_refptr rtp_receiver = - CreateMockReceiver(rtc::scoped_refptr( - remote_audio_track), - voice_receiver_info.local_stats[0].ssrc); + rtc::scoped_refptr rtp_receiver = CreateMockReceiver( + rtc::scoped_refptr(remote_audio_track), + voice_receiver_info.local_stats[0].ssrc, attachment_id++); rtp_receivers_.push_back(rtc::scoped_refptr( rtp_receiver.get())); } // Local video tracks and video sender infos + attachment_id = 151; for (auto& pair : local_video_track_info_pairs) { MediaStreamTrackInterface* local_video_track = pair.first; const cricket::VideoSenderInfo& video_sender_info = pair.second; @@ -441,14 +447,14 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { MediaStreamTrackInterface::kVideoKind); video_media_info_->senders.push_back(video_sender_info); - rtc::scoped_refptr rtp_sender = - CreateMockSender(rtc::scoped_refptr( - local_video_track), - video_sender_info.local_stats[0].ssrc); + rtc::scoped_refptr rtp_sender = CreateMockSender( + rtc::scoped_refptr(local_video_track), + video_sender_info.local_stats[0].ssrc, attachment_id++); rtp_senders_.push_back(rtc::scoped_refptr( rtp_sender.get())); } // Remote video tracks and video receiver infos + attachment_id = 191; for (auto& pair : remote_video_track_info_pairs) { MediaStreamTrackInterface* remote_video_track = pair.first; const cricket::VideoReceiverInfo& video_receiver_info = pair.second; @@ -456,10 +462,9 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { MediaStreamTrackInterface::kVideoKind); video_media_info_->receivers.push_back(video_receiver_info); - rtc::scoped_refptr rtp_receiver = - CreateMockReceiver(rtc::scoped_refptr( - remote_video_track), - video_receiver_info.local_stats[0].ssrc); + rtc::scoped_refptr rtp_receiver = CreateMockReceiver( + rtc::scoped_refptr(remote_video_track), + video_receiver_info.local_stats[0].ssrc, attachment_id++); rtp_receivers_.push_back(rtc::scoped_refptr( rtp_receiver.get())); } @@ -1524,15 +1529,6 @@ TEST_F(RTCStatsCollectorTest, voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0; voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0; - // Uses default values, the corresponding stats object should contain - // undefined members. - cricket::VoiceSenderInfo voice_sender_info_ssrc2; - voice_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo()); - voice_sender_info_ssrc2.local_stats[0].ssrc = 2; - voice_sender_info_ssrc2.audio_level = 0; - voice_sender_info_ssrc2.total_input_energy = 0.0; - voice_sender_info_ssrc2.total_input_duration = 0.0; - // Remote audio track rtc::scoped_refptr remote_audio_track = CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", @@ -1552,10 +1548,8 @@ TEST_F(RTCStatsCollectorTest, voice_receiver_info.jitter_buffer_delay_seconds = 3456; test_->CreateMockRtpSendersReceiversAndChannels( - { std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1), - std::make_pair(local_audio_track.get(), voice_sender_info_ssrc2) }, - { std::make_pair(remote_audio_track.get(), voice_receiver_info) }, - {}, {}); + {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, + {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {}, {}); rtc::scoped_refptr report = GetStatsReport(); @@ -1563,8 +1557,7 @@ TEST_F(RTCStatsCollectorTest, "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us()); expected_local_stream.stream_identifier = local_stream->label(); expected_local_stream.track_ids = std::vector( - { "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1", - "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2" }); + {"RTCMediaStreamTrack_local_audio_LocalAudioTrackID_147"}); ASSERT_TRUE(report->Get(expected_local_stream.id())); EXPECT_EQ(expected_local_stream, report->Get(expected_local_stream.id())->cast_to< @@ -1573,15 +1566,17 @@ TEST_F(RTCStatsCollectorTest, RTCMediaStreamStats expected_remote_stream( "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us()); expected_remote_stream.stream_identifier = remote_stream->label(); - expected_remote_stream.track_ids = std::vector({ - "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3" }); + expected_remote_stream.track_ids = std::vector( + {"RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_181"}); ASSERT_TRUE(report->Get(expected_remote_stream.id())); EXPECT_EQ(expected_remote_stream, report->Get(expected_remote_stream.id())->cast_to< RTCMediaStreamStats>()); + // TODO(hta): Remove hardcoded stats IDs from the tests + // We should verify that they link properly rather than hardcoding them. RTCMediaStreamTrackStats expected_local_audio_track_ssrc1( - "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1", + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_147", report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id(); expected_local_audio_track_ssrc1.remote_source = false; @@ -1597,25 +1592,8 @@ TEST_F(RTCStatsCollectorTest, report->Get(expected_local_audio_track_ssrc1.id())->cast_to< RTCMediaStreamTrackStats>()); - RTCMediaStreamTrackStats expected_local_audio_track_ssrc2( - "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2", - report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); - expected_local_audio_track_ssrc2.track_identifier = local_audio_track->id(); - expected_local_audio_track_ssrc2.remote_source = false; - expected_local_audio_track_ssrc2.ended = true; - expected_local_audio_track_ssrc2.detached = false; - expected_local_audio_track_ssrc2.audio_level = 0.0; - expected_local_audio_track_ssrc2.total_audio_energy = 0.0; - expected_local_audio_track_ssrc2.total_samples_duration = 0.0; - // Should be undefined: |expected_local_audio_track_ssrc2.echo_return_loss| - // and |expected_local_audio_track_ssrc2.echo_return_loss_enhancement|. - ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc2.id())); - EXPECT_EQ(expected_local_audio_track_ssrc2, - report->Get(expected_local_audio_track_ssrc2.id())->cast_to< - RTCMediaStreamTrackStats>()); - RTCMediaStreamTrackStats expected_remote_audio_track( - "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3", + "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_181", report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); expected_remote_audio_track.track_identifier = remote_audio_track->id(); expected_remote_audio_track.remote_source = true; @@ -1666,13 +1644,6 @@ TEST_F(RTCStatsCollectorTest, video_sender_info_ssrc1.send_frame_height = 4321; video_sender_info_ssrc1.frames_encoded = 11; - cricket::VideoSenderInfo video_sender_info_ssrc2; - video_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo()); - video_sender_info_ssrc2.local_stats[0].ssrc = 2; - video_sender_info_ssrc2.send_frame_width = 4321; - video_sender_info_ssrc2.send_frame_height = 1234; - video_sender_info_ssrc2.frames_encoded = 22; - // Remote video track with values rtc::scoped_refptr remote_video_track_ssrc3 = CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3", @@ -1689,39 +1660,19 @@ TEST_F(RTCStatsCollectorTest, video_receiver_info_ssrc3.frames_decoded = 995; video_receiver_info_ssrc3.frames_rendered = 990; - // Remote video track with undefined (default) values - rtc::scoped_refptr remote_video_track_ssrc4 = - CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID4", - MediaStreamTrackInterface::kLive); - remote_stream->AddTrack(static_cast( - remote_video_track_ssrc4.get())); - - cricket::VideoReceiverInfo video_receiver_info_ssrc4; - video_receiver_info_ssrc4.local_stats.push_back(cricket::SsrcReceiverInfo()); - video_receiver_info_ssrc4.local_stats[0].ssrc = 4; - video_receiver_info_ssrc4.frame_width = 0; - video_receiver_info_ssrc4.frame_height = 0; - video_receiver_info_ssrc4.frames_received = 0; - video_receiver_info_ssrc4.frames_decoded = 0; - video_receiver_info_ssrc4.frames_rendered = 0; - test_->CreateMockRtpSendersReceiversAndChannels( {}, {}, - { std::make_pair(local_video_track.get(), video_sender_info_ssrc1), - std::make_pair(local_video_track.get(), video_sender_info_ssrc2) }, - { std::make_pair(remote_video_track_ssrc3.get(), - video_receiver_info_ssrc3), - std::make_pair(remote_video_track_ssrc4.get(), - video_receiver_info_ssrc4) }); + {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, + {std::make_pair(remote_video_track_ssrc3.get(), + video_receiver_info_ssrc3)}); rtc::scoped_refptr report = GetStatsReport(); RTCMediaStreamStats expected_local_stream( "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us()); expected_local_stream.stream_identifier = local_stream->label(); - expected_local_stream.track_ids = std::vector({ - "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1", - "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2" }); + expected_local_stream.track_ids = std::vector( + {"RTCMediaStreamTrack_local_video_LocalVideoTrackID_151"}); ASSERT_TRUE(report->Get(expected_local_stream.id())); EXPECT_EQ(expected_local_stream, report->Get(expected_local_stream.id())->cast_to< @@ -1730,16 +1681,15 @@ TEST_F(RTCStatsCollectorTest, RTCMediaStreamStats expected_remote_stream( "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us()); expected_remote_stream.stream_identifier = remote_stream->label(); - expected_remote_stream.track_ids = std::vector({ - "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3", - "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4" }); + expected_remote_stream.track_ids = std::vector( + {"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_191"}); ASSERT_TRUE(report->Get(expected_remote_stream.id())); EXPECT_EQ(expected_remote_stream, report->Get(expected_remote_stream.id())->cast_to< RTCMediaStreamStats>()); RTCMediaStreamTrackStats expected_local_video_track_ssrc1( - "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1", + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_151", report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); expected_local_video_track_ssrc1.track_identifier = local_video_track->id(); expected_local_video_track_ssrc1.remote_source = false; @@ -1753,23 +1703,8 @@ TEST_F(RTCStatsCollectorTest, report->Get(expected_local_video_track_ssrc1.id())->cast_to< RTCMediaStreamTrackStats>()); - RTCMediaStreamTrackStats expected_local_video_track_ssrc2( - "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2", - report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); - expected_local_video_track_ssrc2.track_identifier = local_video_track->id(); - expected_local_video_track_ssrc2.remote_source = false; - expected_local_video_track_ssrc2.ended = false; - expected_local_video_track_ssrc2.detached = false; - expected_local_video_track_ssrc2.frame_width = 4321; - expected_local_video_track_ssrc2.frame_height = 1234; - expected_local_video_track_ssrc2.frames_sent = 22; - ASSERT_TRUE(report->Get(expected_local_video_track_ssrc2.id())); - EXPECT_EQ(expected_local_video_track_ssrc2, - report->Get(expected_local_video_track_ssrc2.id())->cast_to< - RTCMediaStreamTrackStats>()); - RTCMediaStreamTrackStats expected_remote_video_track_ssrc3( - "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3", + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_191", report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); expected_remote_video_track_ssrc3.track_identifier = remote_video_track_ssrc3->id(); @@ -1785,24 +1720,6 @@ TEST_F(RTCStatsCollectorTest, EXPECT_EQ(expected_remote_video_track_ssrc3, report->Get(expected_remote_video_track_ssrc3.id())->cast_to< RTCMediaStreamTrackStats>()); - - RTCMediaStreamTrackStats expected_remote_video_track_ssrc4( - "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4", - report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); - expected_remote_video_track_ssrc4.track_identifier = - remote_video_track_ssrc4->id(); - expected_remote_video_track_ssrc4.remote_source = true; - expected_remote_video_track_ssrc4.ended = false; - expected_remote_video_track_ssrc4.detached = false; - expected_remote_video_track_ssrc4.frames_received = 0; - expected_remote_video_track_ssrc4.frames_decoded = 0; - expected_remote_video_track_ssrc4.frames_dropped = 0; - // Should be undefined: |expected_remote_video_track_ssrc4.frame_width| and - // |expected_remote_video_track_ssrc4.frame_height|. - ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc4.id())); - EXPECT_EQ(expected_remote_video_track_ssrc4, - report->Get(expected_remote_video_track_ssrc4.id())->cast_to< - RTCMediaStreamTrackStats>()); } TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { @@ -1866,7 +1783,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.track_id = - "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_1"; + "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_62"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_audio.codec_id = "RTCCodec_InboundAudio_42"; @@ -1875,7 +1792,6 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.packets_lost = -1; expected_audio.jitter = 4.5; expected_audio.fraction_lost = 5.5; - ASSERT_TRUE(report->Get(expected_audio.id())); EXPECT_EQ( report->Get(expected_audio.id())->cast_to(), @@ -1949,7 +1865,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { expected_video.is_remote = false; expected_video.media_type = "video"; expected_video.track_id = - "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_1"; + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_62"; expected_video.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_video.codec_id = "RTCCodec_InboundVideo_42"; @@ -2043,7 +1959,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.track_id = - "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1"; + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_50"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; @@ -2125,7 +2041,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.is_remote = false; expected_video.media_type = "video"; expected_video.track_id = - "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1"; + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_50"; expected_video.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_video.codec_id = "RTCCodec_OutboundVideo_42"; @@ -2381,7 +2297,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.track_id = - "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1"; + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_50"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); @@ -2410,7 +2326,7 @@ TEST_F(RTCStatsCollectorTest, StatsNotReportedOnZeroSsrc) { rtc::scoped_refptr track = CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack", MediaStreamTrackInterface::kLive); - rtc::scoped_refptr sender = CreateMockSender(track, 0); + rtc::scoped_refptr sender = CreateMockSender(track, 0, 49); EXPECT_CALL(test_->pc(), GetSenders()) .WillRepeatedly( Return(std::vector>( diff --git a/pc/rtpreceiver.cc b/pc/rtpreceiver.cc index 98c501c22b..e318c17e14 100644 --- a/pc/rtpreceiver.cc +++ b/pc/rtpreceiver.cc @@ -21,6 +21,17 @@ namespace webrtc { +namespace { + +// This function is only expected to be called on the signalling thread. +int GenerateUniqueId() { + static int g_unique_id = 0; + + return ++g_unique_id; +} + +} // namespace + AudioRtpReceiver::AudioRtpReceiver( rtc::Thread* worker_thread, const std::string& receiver_id, @@ -35,7 +46,8 @@ AudioRtpReceiver::AudioRtpReceiver( AudioTrack::Create( receiver_id, RemoteAudioSource::Create(worker_thread, media_channel, ssrc)))), - cached_track_enabled_(track_->enabled()) { + cached_track_enabled_(track_->enabled()), + attachment_id_(GenerateUniqueId()) { RTC_DCHECK(worker_thread_); RTC_DCHECK(track_->GetSource()->remote()); track_->RegisterObserver(this); @@ -207,7 +219,8 @@ VideoRtpReceiver::VideoRtpReceiver( VideoTrackSourceProxy::Create(rtc::Thread::Current(), worker_thread, source_), - worker_thread))) { + worker_thread))), + attachment_id_(GenerateUniqueId()) { RTC_DCHECK(worker_thread_); SetStreams(streams); source_->SetState(MediaSourceInterface::kLive); diff --git a/pc/rtpreceiver.h b/pc/rtpreceiver.h index e3848a7c5b..82c3134a26 100644 --- a/pc/rtpreceiver.h +++ b/pc/rtpreceiver.h @@ -107,6 +107,7 @@ class AudioRtpReceiver : public ObserverInterface, void SetMediaChannel(cricket::VoiceMediaChannel* media_channel); std::vector GetSources() const override; + int AttachmentId() const override { return attachment_id_; } private: void Reconfigure(); @@ -123,6 +124,7 @@ class AudioRtpReceiver : public ObserverInterface, bool stopped_ = false; RtpReceiverObserverInterface* observer_ = nullptr; bool received_first_packet_ = false; + int attachment_id_ = 0; }; class VideoRtpReceiver : public rtc::RefCountedObject { @@ -192,6 +194,7 @@ class VideoRtpReceiver : public rtc::RefCountedObject { bool stopped_ = false; RtpReceiverObserverInterface* observer_ = nullptr; bool received_first_packet_ = false; + int attachment_id_ = 0; }; } // namespace webrtc diff --git a/pc/rtpsender.cc b/pc/rtpsender.cc index 91e84d73bd..cad86f2f77 100644 --- a/pc/rtpsender.cc +++ b/pc/rtpsender.cc @@ -20,6 +20,17 @@ namespace webrtc { +namespace { + +// This function is only expected to be called on the signalling thread. +int GenerateUniqueId() { + static int g_unique_id = 0; + + return ++g_unique_id; +} + +} // namespace + LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {} LocalAudioSinkAdapter::~LocalAudioSinkAdapter() { @@ -60,7 +71,8 @@ AudioRtpSender::AudioRtpSender(rtc::scoped_refptr track, rtc::Thread::Current(), DtmfSender::Create(track_, rtc::Thread::Current(), this))), cached_track_enabled_(track ? track->enabled() : false), - sink_adapter_(new LocalAudioSinkAdapter()) { + sink_adapter_(new LocalAudioSinkAdapter()), + attachment_id_(track ? GenerateUniqueId() : 0) { // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are // supported. RTC_DCHECK_EQ(stream_labels.size(), 1u); @@ -165,6 +177,7 @@ bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) { } else if (prev_can_send_track) { ClearAudioSend(); } + attachment_id_ = GenerateUniqueId(); return true; } @@ -276,9 +289,10 @@ VideoRtpSender::VideoRtpSender(rtc::scoped_refptr track, stream_ids_(stream_labels), track_(track), cached_track_enabled_(track ? track->enabled() : false), - cached_track_content_hint_( - track ? track->content_hint() - : VideoTrackInterface::ContentHint::kNone) { + cached_track_content_hint_(track + ? track->content_hint() + : VideoTrackInterface::ContentHint::kNone), + attachment_id_(track ? GenerateUniqueId() : 0) { // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are // supported. RTC_DCHECK_EQ(stream_labels.size(), 1u); @@ -340,6 +354,7 @@ bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) { } else if (prev_can_send_track) { ClearVideoSend(); } + attachment_id_ = GenerateUniqueId(); return true; } diff --git a/pc/rtpsender.h b/pc/rtpsender.h index a0c759ad1c..eb09d0b13f 100644 --- a/pc/rtpsender.h +++ b/pc/rtpsender.h @@ -137,6 +137,8 @@ class AudioRtpSender : public DtmfProviderInterface, void Stop() override; + int AttachmentId() const override { return attachment_id_; } + // Does not take ownership. // Should call SetChannel(nullptr) before |channel| is destroyed. void SetChannel(cricket::VoiceChannel* channel) { channel_ = channel; } @@ -168,6 +170,7 @@ class AudioRtpSender : public DtmfProviderInterface, // Used to pass the data callback from the |track_| to the other end of // cricket::AudioSource. std::unique_ptr sink_adapter_; + int attachment_id_ = 0; }; class VideoRtpSender : public ObserverInterface, @@ -220,6 +223,7 @@ class VideoRtpSender : public ObserverInterface, } void Stop() override; + int AttachmentId() const override { return attachment_id_; } // Does not take ownership. // Should call SetChannel(nullptr) before |channel| is destroyed. @@ -244,6 +248,7 @@ class VideoRtpSender : public ObserverInterface, VideoTrackInterface::ContentHint cached_track_content_hint_ = VideoTrackInterface::ContentHint::kNone; bool stopped_ = false; + int attachment_id_ = 0; }; } // namespace webrtc diff --git a/pc/trackmediainfomap.cc b/pc/trackmediainfomap.cc index 3fbe3faae7..36e4eb3a95 100644 --- a/pc/trackmediainfomap.cc +++ b/pc/trackmediainfomap.cc @@ -125,6 +125,14 @@ TrackMediaInfoMap::TrackMediaInfoMap( &local_video_track_by_ssrc, &remote_audio_track_by_ssrc, &remote_video_track_by_ssrc, &unsignaled_audio_track, &unsignaled_video_track); + + for (auto& sender : rtp_senders) { + attachment_id_by_track_[sender->track()] = sender->AttachmentId(); + } + for (auto& receiver : rtp_receivers) { + attachment_id_by_track_[receiver->track()] = receiver->AttachmentId(); + } + if (voice_media_info_) { for (auto& sender_info : voice_media_info_->senders) { AudioTrackInterface* associated_track = @@ -258,4 +266,11 @@ rtc::scoped_refptr TrackMediaInfoMap::GetVideoTrack( return FindValueOrNull(video_track_by_receiver_info_, &video_receiver_info); } +rtc::Optional TrackMediaInfoMap::GetAttachmentIdByTrack( + const MediaStreamTrackInterface* track) const { + auto it = attachment_id_by_track_.find(track); + return it != attachment_id_by_track_.end() ? rtc::Optional(it->second) + : rtc::nullopt; +} + } // namespace webrtc diff --git a/pc/trackmediainfomap.h b/pc/trackmediainfomap.h index fd9a98e637..c427c47998 100644 --- a/pc/trackmediainfomap.h +++ b/pc/trackmediainfomap.h @@ -74,6 +74,13 @@ class TrackMediaInfoMap { rtc::scoped_refptr GetVideoTrack( const cricket::VideoReceiverInfo& video_receiver_info) const; + // TODO(hta): Remove this function, and redesign the callers not to need it. + // It is not going to work if a track is attached multiple times, and + // it is not going to work if a received track is attached as a sending + // track (loopback). + rtc::Optional GetAttachmentIdByTrack( + const MediaStreamTrackInterface* track) const; + private: std::unique_ptr voice_media_info_; std::unique_ptr video_media_info_; @@ -102,6 +109,12 @@ class TrackMediaInfoMap { std::map> video_track_by_receiver_info_; + // Map of tracks to attachment IDs. + // Necessary because senders and receivers live on the signaling thread, + // but the attachment IDs are needed while building stats on the networking + // thread, so we can't look them up in the senders/receivers without + // thread jumping. + std::map attachment_id_by_track_; // These maps map SSRCs to the corresponding voice or video info objects. std::map voice_info_by_sender_ssrc_; std::map voice_info_by_receiver_ssrc_; diff --git a/pc/trackmediainfomap_unittest.cc b/pc/trackmediainfomap_unittest.cc index c05abe17a0..583aa89d73 100644 --- a/pc/trackmediainfomap_unittest.cc +++ b/pc/trackmediainfomap_unittest.cc @@ -60,6 +60,7 @@ rtc::scoped_refptr CreateMockRtpSender( .WillRepeatedly(testing::Return(media_type)); EXPECT_CALL(*sender, GetParameters()) .WillRepeatedly(testing::Return(CreateRtpParametersWithSsrcs(ssrcs))); + EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(testing::Return(1)); return sender; } @@ -75,6 +76,7 @@ rtc::scoped_refptr CreateMockRtpReceiver( .WillRepeatedly(testing::Return(media_type)); EXPECT_CALL(*receiver, GetParameters()) .WillRepeatedly(testing::Return(CreateRtpParametersWithSsrcs(ssrcs))); + EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(testing::Return(1)); return receiver; } @@ -400,6 +402,14 @@ TEST_F(TrackMediaInfoMapTest, SsrcLookupFunction) { EXPECT_FALSE(map_->GetVoiceSenderInfoBySsrc(1024)); } +TEST_F(TrackMediaInfoMapTest, GetAttachmentIdByTrack) { + AddRtpSenderWithSsrcs({1}, local_audio_track_); + CreateMap(); + EXPECT_EQ(rtp_senders_[0]->AttachmentId(), + map_->GetAttachmentIdByTrack(local_audio_track_)); + EXPECT_EQ(rtc::nullopt, map_->GetAttachmentIdByTrack(local_video_track_)); +} + // Death tests. // Disabled on Android because death tests misbehave on Android, see // base/test/gtest_util.h.