diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.cc b/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.cc index 06ce50a8e8..4b7863d540 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.cc +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.cc @@ -34,6 +34,7 @@ #include "talk/base/logging.h" #include "talk/session/phone/channel.h" #include "talk/session/phone/channelmanager.h" +#include "talk/session/phone/mediasession.h" using cricket::MediaContentDescription; @@ -59,13 +60,12 @@ WebRtcSession::WebRtcSession(cricket::ChannelManager* channel_manager, talk_base::Thread* signaling_thread, talk_base::Thread* worker_thread, cricket::PortAllocator* port_allocator) - : observer_(NULL), - cricket::BaseSession(signaling_thread, worker_thread, port_allocator, - talk_base::ToString(talk_base::CreateRandomId()), - cricket::NS_JINGLE_RTP, true) { - // TODO(mallinath) - Remove initiator flag from BaseSession. As it's being - // used only by cricket::Session. - channel_manager_ = channel_manager; + : cricket::BaseSession(signaling_thread, worker_thread, port_allocator, + talk_base::ToString(talk_base::CreateRandomId()), + cricket::NS_JINGLE_RTP, true), + channel_manager_(channel_manager), + observer_(NULL), + session_desc_factory_(channel_manager) { } WebRtcSession::~WebRtcSession() { @@ -85,30 +85,27 @@ void WebRtcSession::Terminate() { } } -void WebRtcSession::OnSignalUpdateSessionDescription( - const cricket::SessionDescription* local_desc, - const cricket::SessionDescription* remote_desc, - const cricket::Candidates& remote_candidates) { - // Session updates are not supported yet. If session is in progress state - // ignore this callback. - if (state() == STATE_INPROGRESS) { - ProcessSessionUpdate(local_desc, remote_desc); - if (remote_candidates.size() > 0) { - SetRemoteCandidates(remote_candidates); - } - return; +bool WebRtcSession::CreateChannels() { + voice_channel_.reset(channel_manager_->CreateVoiceChannel( + this, cricket::CN_AUDIO, true)); + if (!voice_channel_.get()) { + LOG(LS_ERROR) << "Failed to create voice channel"; + return false; } - // Local session and remote session descriptions are available before - // any state change. So for session it's doesn't matter it's initiator - // or receiver of the call. Session will be treated as initiator. - // Apply first local description - set_local_description(local_desc); - SetState(STATE_SENTINITIATE); - // Applying remote description on the session - set_remote_description(const_cast(remote_desc)); - SetState(STATE_RECEIVEDACCEPT); - // Set remote candidates - SetRemoteCandidates(remote_candidates); + + video_channel_.reset(channel_manager_->CreateVideoChannel( + this, cricket::CN_VIDEO, true, voice_channel_.get())); + if (!video_channel_.get()) { + LOG(LS_ERROR) << "Failed to create video channel"; + return false; + } + + // TransportProxies and TransportChannels will be created when + // CreateVoiceChannel and CreateVideoChannel are called. + // Try connecting all transport channels. This is necessary to generate + // ICE candidates. + SpeculativelyConnectAllTransportChannels(); + return true; } void WebRtcSession::SetRemoteCandidates( @@ -150,36 +147,13 @@ void WebRtcSession::SetRemoteCandidates( video_proxy->CompleteNegotiation(); // TODO(mallinath) - Add a interface to TransportProxy to accept // remote candidate list. - video_proxy->impl()->OnRemoteCandidates(audio_candidates); + video_proxy->impl()->OnRemoteCandidates(video_candidates); } else { LOG(LS_INFO) << "No video TransportProxy exists"; } } } -bool WebRtcSession::CreateChannels() { - voice_channel_.reset(channel_manager_->CreateVoiceChannel( - this, cricket::CN_AUDIO, true)); - if (!voice_channel_.get()) { - LOG(LS_ERROR) << "Failed to create voice channel"; - return false; - } - - video_channel_.reset(channel_manager_->CreateVideoChannel( - this, cricket::CN_VIDEO, true, voice_channel_.get())); - if (!video_channel_.get()) { - LOG(LS_ERROR) << "Failed to create video channel"; - return false; - } - - // TransportProxies and TransportChannels will be created when - // CreateVoiceChannel and CreateVideoChannel are called. - // Try connecting all transport channels. This is necessary to generate - // ICE candidates. - SpeculativelyConnectAllTransportChannels(); - return true; -} - void WebRtcSession::OnTransportRequestSignaling( cricket::Transport* transport) { ASSERT(signaling_thread()->IsCurrent()); @@ -212,12 +186,8 @@ void WebRtcSession::OnTransportCandidatesReady( if (local_candidates_.size() == kAllowedCandidates) return; InsertTransportCandidates(candidates); - if (local_candidates_.size() == kAllowedCandidates) { - if(observer_) - observer_->OnCandidatesReady(local_candidates_); - // TODO(mallinath) - Remove signal when a new interface added for - // PC signaling. - SignalCandidatesReady(this, local_candidates_); + if (local_candidates_.size() == kAllowedCandidates && observer_) { + observer_->OnCandidatesReady(local_candidates_); } } @@ -262,56 +232,6 @@ bool WebRtcSession::CheckCandidate(const std::string& name) { return ret; } -void WebRtcSession::ProcessSessionUpdate( - const cricket::SessionDescription* local_desc, - const cricket::SessionDescription* remote_desc) { - - if (local_desc) { - ProcessLocalMediaChanges(local_desc); - } - if (remote_desc) { - ProcessRemoteMediaChanges(remote_desc); - } -} - -bool WebRtcSession::GetAudioSourceParamInfo( - const cricket::SessionDescription* sdesc, - cricket::Sources* sources) { - bool ret = false; - const cricket::ContentInfo* content = GetFirstAudioContent(sdesc); - if (content) { - const MediaContentDescription* audio_desc = - static_cast (content->description); - *sources = audio_desc->sources(); - ret = true; - } - return ret; -} - -bool WebRtcSession::GetVideoSourceParamInfo( - const cricket::SessionDescription* sdesc, - cricket::Sources* sources) { - bool ret = false; - const cricket::ContentInfo* content = GetFirstVideoContent(sdesc); - if (content) { - const MediaContentDescription* video_desc = - static_cast (content->description); - *sources = video_desc->sources(); - ret = true; - } - return ret; -} - -void WebRtcSession::ProcessLocalMediaChanges( - const cricket::SessionDescription* sdesc) { - // TODO(mallinath) - Handling of local media stream changes in active session -} - -void WebRtcSession::ProcessRemoteMediaChanges( - const cricket::SessionDescription* sdesc) { - // TODO(mallinath) - Handling of remote media stream changes in active session -} - void WebRtcSession::SetCaptureDevice(uint32 ssrc, VideoCaptureModule* camera) { // should be called from a signaling thread @@ -331,4 +251,72 @@ void WebRtcSession::SetRemoteRenderer(uint32 ssrc, video_channel_->SetRenderer(ssrc, renderer); } +const cricket::SessionDescription* WebRtcSession::ProvideOffer( + const cricket::MediaSessionOptions& options) { + // TODO(mallinath) - Sanity check for options. + cricket::SessionDescription* offer( + session_desc_factory_.CreateOffer(options)); + set_local_description(offer); + return offer; +} + +const cricket::SessionDescription* WebRtcSession::SetRemoteSessionDescription( + const cricket::SessionDescription* remote_offer, + const std::vector& remote_candidates) { + set_remote_description( + const_cast(remote_offer)); + SetRemoteCandidates(remote_candidates); + return remote_offer; +} + +const cricket::SessionDescription* WebRtcSession::ProvideAnswer( + const cricket::MediaSessionOptions& options) { + cricket::SessionDescription* answer( + session_desc_factory_.CreateAnswer(remote_description(), options)); + set_local_description(answer); + return answer; +} + +void WebRtcSession::NegotiationDone() { + // No state change after state moved to progress state. + if (state() == STATE_INIT) { + SetState(STATE_SENTINITIATE); + SetState(STATE_RECEIVEDACCEPT); + } + + // Enabling channels + voice_channel_->Enable(true); + video_channel_->Enable(true); + + const cricket::ContentInfo* audio_info = + cricket::GetFirstAudioContent(local_description()); + if (audio_info) { + const cricket::MediaContentDescription* audio_content = + static_cast( + audio_info->description); + // Since channels are currently not supporting multiple send streams, + // we can remove stream from a session by muting it. + // TODO(mallinath) - Change needed when multiple send streams support + // is available. + if (audio_content->sources().size() == 0) { + voice_channel_->Mute(true); + } + } + + const cricket::ContentInfo* video_info = + cricket::GetFirstVideoContent(local_description()); + if (video_info) { + const cricket::MediaContentDescription* video_content = + static_cast( + video_info->description); + // Since channels are currently not supporting multiple send streams, + // we can remove stream from a session by muting it. + // TODO(mallinath) - Change needed when multiple send streams support + // is available. + if (video_content->sources().size() == 0) { + video_channel_->Mute(true); + } + } +} + } // namespace webrtc diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.h b/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.h index ab4b3e432c..407b45074d 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.h +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession.h @@ -31,13 +31,13 @@ #include #include +#include "talk/app/webrtc_dev/mediastreamprovider.h" +#include "talk/app/webrtc_dev/sessiondescriptionprovider.h" +#include "talk/app/webrtc_dev/webrtcsessionobserver.h" #include "talk/base/sigslot.h" #include "talk/base/thread.h" #include "talk/p2p/base/session.h" #include "talk/session/phone/mediasession.h" -#include "talk/app/webrtc_dev/mediastreamprovider.h" -#include "talk/app/webrtc_dev/sessiondescriptionprovider.h" -#include "talk/app/webrtc_dev/webrtcsessionobserver.h" namespace cricket { class ChannelManager; @@ -47,10 +47,6 @@ class VoiceChannel; } namespace webrtc { -class MediaStream; -class PeerConnectionMessage; -class PeerConnectionSignaling; -class StreamCollection; class WebRtcSession : public cricket::BaseSession, public MediaProviderInterface, @@ -64,6 +60,10 @@ class WebRtcSession : public cricket::BaseSession, bool Initialize(); + void RegisterObserver(WebRtcSessionObserver* observer) { + observer_ = observer; + } + const cricket::VoiceChannel* voice_channel() const { return voice_channel_.get(); } @@ -74,15 +74,18 @@ class WebRtcSession : public cricket::BaseSession, // Generic error message callback from WebRtcSession. // TODO(mallinath) - It may be necessary to supply error code as well. sigslot::signal0<> SignalError; - // This signal added for testing. Shouldn't be registered by other - // objects. - sigslot::signal2 SignalCandidatesReady; - - void ProcessSessionUpdate(const cricket::SessionDescription* local_desc, - const cricket::SessionDescription* remote_desc); private: + // Implements SessionDescriptionProvider + virtual const cricket::SessionDescription* ProvideOffer( + const cricket::MediaSessionOptions& options); + virtual const cricket::SessionDescription* SetRemoteSessionDescription( + const cricket::SessionDescription* remote_offer, + const std::vector& remote_candidates); + virtual const cricket::SessionDescription* ProvideAnswer( + const cricket::MediaSessionOptions& options); + virtual void NegotiationDone(); + // Implements MediaProviderInterface. virtual void SetCaptureDevice(uint32 ssrc, VideoCaptureModule* camera); virtual void SetLocalRenderer(uint32 ssrc, @@ -90,23 +93,6 @@ class WebRtcSession : public cricket::BaseSession, virtual void SetRemoteRenderer(uint32 ssrc, cricket::VideoRenderer* renderer); - //TODO mallinath: remove. - void OnSignalUpdateSessionDescription( - const cricket::SessionDescription* local_desc, - const cricket::SessionDescription* remote_desc, - const cricket::Candidates& remote_candidates); - - // Implements SessionDescriptionProvider - virtual const cricket::SessionDescription* ProvideOffer( - const cricket::MediaSessionOptions& options) {} - virtual const cricket::SessionDescription* SetRemoteSessionDescription( - const cricket::SessionDescription* remote_offer, - const cricket::Candidates& remote_candidates) {} - virtual const cricket::SessionDescription* ProvideAnswer( - const cricket::MediaSessionOptions& options) {} - virtual void NegotiationDone() {} - - // Transport related callbacks, override from cricket::BaseSession. virtual void OnTransportRequestSignaling(cricket::Transport* transport); virtual void OnTransportConnecting(cricket::Transport* transport); @@ -125,21 +111,13 @@ class WebRtcSession : public cricket::BaseSession, bool CheckCandidate(const std::string& name); void SetRemoteCandidates(const cricket::Candidates& candidates); - // Helper methods to get handle to the MediaContentDescription sources param. - bool GetAudioSourceParamInfo(const cricket::SessionDescription* sdesc, - cricket::Sources* sources); - bool GetVideoSourceParamInfo(const cricket::SessionDescription* sdesc, - cricket::Sources* sources); - - void ProcessLocalMediaChanges(const cricket::SessionDescription* sdesc); - void ProcessRemoteMediaChanges(const cricket::SessionDescription* sdesc); - private: - WebRtcSessionObserver* observer_; talk_base::scoped_ptr voice_channel_; talk_base::scoped_ptr video_channel_; cricket::ChannelManager* channel_manager_; cricket::Candidates local_candidates_; + WebRtcSessionObserver* observer_; + cricket::MediaSessionDescriptionFactory session_desc_factory_; }; } // namespace webrtc diff --git a/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession_unittest.cc b/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession_unittest.cc index d32feaca38..9aca7c9004 100644 --- a/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession_unittest.cc +++ b/third_party_mods/libjingle/source/talk/app/webrtc_dev/webrtcsession_unittest.cc @@ -32,24 +32,28 @@ #include "talk/session/phone/channelmanager.h" #include "talk/p2p/client/fakeportallocator.h" -class WebRtcSessionTest : public testing::Test, - public sigslot::has_slots<> { +class MockWebRtcSessionObserver : public webrtc::WebRtcSessionObserver { public: - cricket::MediaSessionDescriptionFactory* media_factory_; - WebRtcSessionTest() { - } - - ~WebRtcSessionTest() { + virtual void OnCandidatesReady( + const std::vector& candidates) { + for (cricket::Candidates::const_iterator iter = candidates.begin(); + iter != candidates.end(); ++iter) { + candidates_.push_back(*iter); + } } + std::vector candidates_; +}; +class WebRtcSessionTest : public testing::Test { + protected: virtual void SetUp() { signaling_thread_ = talk_base::Thread::Current(); worker_thread_ = talk_base::Thread::Current(); channel_manager_.reset(new cricket::ChannelManager(worker_thread_)); port_allocator_.reset( new cricket::FakePortAllocator(worker_thread_, NULL)); - media_factory_ = - new cricket::MediaSessionDescriptionFactory(channel_manager_.get()); + desc_factory_.reset( + new cricket::MediaSessionDescriptionFactory(channel_manager_.get())); } bool InitializeSession() { @@ -75,43 +79,53 @@ class WebRtcSessionTest : public testing::Test, session_.reset(new webrtc::WebRtcSession( channel_manager_.get(), worker_thread_, signaling_thread_, port_allocator_.get())); - session_->SignalCandidatesReady.connect( - this, &WebRtcSessionTest::OnCandidatesReady); + session_->RegisterObserver(&observer_); + desc_provider_ = session_.get(); EXPECT_TRUE(InitializeSession()); } - void OnCandidatesReady(webrtc::WebRtcSession* session, - cricket::Candidates& candidates) { - for (cricket::Candidates::iterator iter = candidates.begin(); - iter != candidates.end(); ++iter) { - local_candidates_.push_back(*iter); - } - } - cricket::Candidates& local_candidates() { - return local_candidates_; - } - cricket::SessionDescription* CreateOffer(bool video) { + + // Creates an offer with one source ssrc, if ssrc = 0 no source info + // video ssrc + 1 + void CreateOffer(uint32 ssrc) { cricket::MediaSessionOptions options; options.is_video = true; - // Source params not set - cricket::SessionDescription* sdp = media_factory_->CreateOffer(options); - return sdp; + if (ssrc != 0) { + options.audio_sources.push_back(cricket::SourceParam(ssrc, "", "")); + ++ssrc; + options.video_sources.push_back(cricket::SourceParam(ssrc, "", "")); + } + local_desc_ = desc_provider_->ProvideOffer(options); + ASSERT_TRUE(local_desc_ != NULL); } - cricket::SessionDescription* CreateAnswer( - cricket::SessionDescription* offer, bool video) { + void CreateAnswer(uint32 ssrc) { cricket::MediaSessionOptions options; - options.is_video = video; - cricket::SessionDescription* sdp = - media_factory_->CreateAnswer(offer, options); + options.is_video = true; + if (ssrc != 0) { + options.audio_sources.push_back(cricket::SourceParam(ssrc, "", "")); + ++ssrc; + options.video_sources.push_back(cricket::SourceParam(ssrc, "", "")); + } + remote_desc_ = desc_factory_->CreateAnswer(local_desc_, options); + ASSERT_TRUE(remote_desc_ != NULL); + } + void SetRemoteContents() { + desc_provider_->SetRemoteSessionDescription( + remote_desc_, observer_.candidates_); + } + void NegotiationDone() { + desc_provider_->NegotiationDone(); } - private: - cricket::Candidates local_candidates_; - cricket::Candidates remote_candidates_; + const cricket::SessionDescription* local_desc_; + const cricket::SessionDescription* remote_desc_; talk_base::Thread* signaling_thread_; talk_base::Thread* worker_thread_; talk_base::scoped_ptr port_allocator_; talk_base::scoped_ptr session_; + webrtc::SessionDescriptionProvider* desc_provider_; talk_base::scoped_ptr channel_manager_; + talk_base::scoped_ptr desc_factory_; + MockWebRtcSessionObserver observer_; }; TEST_F(WebRtcSessionTest, TestInitialize) { @@ -119,6 +133,14 @@ TEST_F(WebRtcSessionTest, TestInitialize) { EXPECT_TRUE(CheckChannels()); CheckTransportChannels(); talk_base::Thread::Current()->ProcessMessages(1000); - EXPECT_EQ(4u, local_candidates().size()); + EXPECT_EQ(4u, observer_.candidates_.size()); +} + +// TODO(mallinath) - Adding test cases for session. +TEST_F(WebRtcSessionTest, DISABLE_TestOfferAnswer) { + WebRtcSessionTest::Init(); + EXPECT_TRUE(CheckChannels()); + CheckTransportChannels(); + talk_base::Thread::Current()->ProcessMessages(1); }