From 81c3a0300486f49ca5dae5c0a7f50ae858dd78fa Mon Sep 17 00:00:00 2001 From: zhihuang Date: Thu, 17 Nov 2016 12:06:24 -0800 Subject: [PATCH] Added a callback function OnAddTrack to PeerConnectionObserver Added the callback in native c++ API. The callback function is called when a track is added and a new RtpReceiver is created. The application can tell when tracks are added to the streams by listening to this callback. BUG=webrtc:6112 Review-Url: https://codereview.webrtc.org/2505173002 Cr-Commit-Position: refs/heads/master@{#15142} --- webrtc/api/peerconnection.cc | 21 +++++-- webrtc/api/peerconnectioninterface.h | 7 +++ .../api/peerconnectioninterface_unittest.cc | 61 ++++++++++++++++--- 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/webrtc/api/peerconnection.cc b/webrtc/api/peerconnection.cc index a1ce6ab05c..46bdec594a 100644 --- a/webrtc/api/peerconnection.cc +++ b/webrtc/api/peerconnection.cc @@ -1426,20 +1426,29 @@ void PeerConnection::OnMessage(rtc::Message* msg) { void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream, const std::string& track_id, uint32_t ssrc) { - receivers_.push_back( - RtpReceiverProxyWithInternal::Create( + rtc::scoped_refptr> + receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), new AudioRtpReceiver(stream, track_id, ssrc, - session_->voice_channel()))); + session_->voice_channel())); + + receivers_.push_back(receiver); + std::vector> streams; + streams.push_back(rtc::scoped_refptr(stream)); + observer_->OnAddTrack(receiver, streams); } void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream, const std::string& track_id, uint32_t ssrc) { - receivers_.push_back( - RtpReceiverProxyWithInternal::Create( + rtc::scoped_refptr> + receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), new VideoRtpReceiver(stream, track_id, factory_->worker_thread(), - ssrc, session_->video_channel()))); + ssrc, session_->video_channel())); + receivers_.push_back(receiver); + std::vector> streams; + streams.push_back(rtc::scoped_refptr(stream)); + observer_->OnAddTrack(receiver, streams); } // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h index a597c986b1..b304b144e8 100644 --- a/webrtc/api/peerconnectioninterface.h +++ b/webrtc/api/peerconnectioninterface.h @@ -598,6 +598,13 @@ class PeerConnectionObserver { // Called when the ICE connection receiving status changes. virtual void OnIceConnectionReceivingChange(bool receiving) {} + // Called when a track is added to streams. + // TODO(zhihuang) Make this a pure virtual method when all its subclasses + // implement it. + virtual void OnAddTrack( + rtc::scoped_refptr receiver, + std::vector> streams) {} + protected: // Dtor protected as objects shouldn't be deleted via this interface. ~PeerConnectionObserver() {} diff --git a/webrtc/api/peerconnectioninterface_unittest.cc b/webrtc/api/peerconnectioninterface_unittest.cc index 245e81c1c1..c35141224c 100644 --- a/webrtc/api/peerconnectioninterface_unittest.cc +++ b/webrtc/api/peerconnectioninterface_unittest.cc @@ -91,6 +91,25 @@ static const char kSdpStringWithStream1[] = "a=ssrc:2 mslabel:stream1\r\n" "a=ssrc:2 label:videotrack0\r\n"; +// Reference SDP with a MediaStream with label "stream1" and audio track with +// id "audio_1"; +static const char kSdpStringWithStream1AudioTrackOnly[] = + "v=0\r\n" + "o=- 0 0 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=ice-ufrag:e5785931\r\n" + "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n" + "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:" + "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n" + "m=audio 1 RTP/AVPF 103\r\n" + "a=mid:audio\r\n" + "a=sendrecv\r\n" + "a=rtpmap:103 ISAC/16000\r\n" + "a=ssrc:1 cname:stream1\r\n" + "a=ssrc:1 mslabel:stream1\r\n" + "a=ssrc:1 label:audiotrack0\r\n"; + // Reference SDP with two MediaStreams with label "stream1" and "stream2. Each // MediaStreams have one audio track and one video track. // This uses MSID. @@ -499,13 +518,13 @@ class MockPeerConnectionObserver : public PeerConnectionObserver { void OnIceConnectionChange( PeerConnectionInterface::IceConnectionState new_state) override { EXPECT_EQ(pc_->ice_connection_state(), new_state); - callback_triggered = true; + callback_triggered_ = true; } void OnIceGatheringChange( PeerConnectionInterface::IceGatheringState new_state) override { EXPECT_EQ(pc_->ice_gathering_state(), new_state); ice_complete_ = new_state == PeerConnectionInterface::kIceGatheringComplete; - callback_triggered = true; + callback_triggered_ = true; } void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override { EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, @@ -517,16 +536,24 @@ class MockPeerConnectionObserver : public PeerConnectionObserver { last_candidate_.reset(webrtc::CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(), sdp, NULL)); EXPECT_TRUE(last_candidate_.get() != NULL); - callback_triggered = true; + callback_triggered_ = true; } void OnIceCandidatesRemoved( const std::vector& candidates) override { - callback_triggered = true; + callback_triggered_ = true; } void OnIceConnectionReceivingChange(bool receiving) override { - callback_triggered = true; + callback_triggered_ = true; + } + + void OnAddTrack(rtc::scoped_refptr receiver, + std::vector> + streams) override { + EXPECT_TRUE(receiver != nullptr); + num_added_tracks_++; + last_added_track_label_ = receiver->id(); } // Returns the label of the last added stream. @@ -549,7 +576,9 @@ class MockPeerConnectionObserver : public PeerConnectionObserver { rtc::scoped_refptr remote_streams_; bool renegotiation_needed_ = false; bool ice_complete_ = false; - bool callback_triggered = false; + bool callback_triggered_ = false; + int num_added_tracks_ = 0; + std::string last_added_track_label_; private: rtc::scoped_refptr last_added_stream_; @@ -1070,7 +1099,7 @@ TEST_F(PeerConnectionInterfaceTest, CloseAndTestCallbackFunctions) { pc->Close(); // No callbacks is expected to be called. - observer_.callback_triggered = false; + observer_.callback_triggered_ = false; std::vector candidates; pc_factory_for_test_->transport_controller->SignalGatheringState( cricket::IceGatheringState{}); @@ -1081,7 +1110,7 @@ TEST_F(PeerConnectionInterfaceTest, CloseAndTestCallbackFunctions) { pc_factory_for_test_->transport_controller->SignalCandidatesRemoved( candidates); pc_factory_for_test_->transport_controller->SignalReceiving(false); - EXPECT_FALSE(observer_.callback_triggered); + EXPECT_FALSE(observer_.callback_triggered_); } // Generate different CNAMEs when PeerConnections are created. @@ -2666,6 +2695,22 @@ TEST_F(PeerConnectionInterfaceTest, EXPECT_TRUE(ContainsSender(new_senders, kVideoTracks[0], kStreams[1])); } +// This tests that PeerConnectionObserver::OnAddTrack is correctly called. +TEST_F(PeerConnectionInterfaceTest, OnAddTrackCallback) { + FakeConstraints constraints; + constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, + true); + CreatePeerConnection(&constraints); + CreateAndSetRemoteOffer(kSdpStringWithStream1AudioTrackOnly); + EXPECT_EQ(observer_.num_added_tracks_, 1); + EXPECT_EQ(observer_.last_added_track_label_, kAudioTracks[0]); + + // Create and set the updated remote SDP. + CreateAndSetRemoteOffer(kSdpStringWithStream1); + EXPECT_EQ(observer_.num_added_tracks_, 2); + EXPECT_EQ(observer_.last_added_track_label_, kVideoTracks[0]); +} + class PeerConnectionMediaConfigTest : public testing::Test { protected: void SetUp() override {