#include #include #include #include #include #include #include #include #include namespace rtcutil { void ConductorObserver::onError(ErrorType type, std::string err) { if (type == ErrorType::WARNING) { fprintf(stderr, "Warning: %s\n", err.c_str()); } else { fprintf(stderr, "Error: %s\n", err.c_str()); abort(); } } class SetSessionDescriptionObserver: public webrtc::SetSessionDescriptionObserver { public: SetSessionDescriptionObserver(ConductorObserver &observer): observer_(observer) {} static SetSessionDescriptionObserver* Create(ConductorObserver &observer) { return new rtc::RefCountedObject(observer); } virtual void OnSuccess() {} virtual void OnFailure(webrtc::RTCError error) { observer_.onError(ConductorObserver::ErrorType::RECEIVE_OFFER, error.message()); } private: ConductorObserver &observer_; }; void Conductor::receiveOffer(const std::string &sdp) { printf("receive offer 1\n"); webrtc::SdpParseError error; std::unique_ptr desc = webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, sdp, &error); if (!desc.get()) { observer_.onError(ConductorObserver::ErrorType::RECEIVE_OFFER, std::move(error.description)); return; } receiveOffer(std::move(desc)); } void Conductor::receiveOffer(std::unique_ptr offer) { printf("receive offer 2\n"); ensurePeerConnection(); peer_conn_->SetRemoteDescription( SetSessionDescriptionObserver::Create(observer_), offer.release()); peer_conn_->CreateAnswer( this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions()); } void Conductor::receiveIceCandidate(std::string mid, int index, std::string sdp) { printf("receive ice candidate\n"); webrtc::SdpParseError error; std::unique_ptr candidate( webrtc::CreateIceCandidate(mid, index, sdp, &error)); if (!candidate.get()) { observer_.onError(ConductorObserver::ErrorType::WARNING, std::move(error.description)); return; } if (!peer_conn_->AddIceCandidate(candidate.get())) { observer_.onError(ConductorObserver::ErrorType::WARNING, "Failed to apply the received candidate"); return; } } void Conductor::ensurePeerConnection() { if (peer_conn_factory_.get()) return; peer_conn_factory_ = doCreatePeerConnectionFactory(); peer_conn_ = doCreatePeerConnection(*peer_conn_factory_); } void Conductor::OnAddTrack( rtc::scoped_refptr receiver, const std::vector> &streams) { observer_.onRemoteTrack(std::move(receiver->track())); } void Conductor::OnRemoveTrack( rtc::scoped_refptr receiver) { observer_.removeRemoteTrack(std::move(receiver->track())); } void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) { std::string sdp; if (!candidate->ToString(&sdp)) { observer_.onError(ConductorObserver::ErrorType::WARNING, "Failed to serialize candidate"); return; } observer_.onIceCandidate( std::move(candidate->sdp_mid()), candidate->sdp_mline_index(), std::move(sdp)); } rtc::scoped_refptr Conductor::doCreatePeerConnectionFactory() { return webrtc::CreatePeerConnectionFactory( nullptr /* network_thread */, nullptr /* worker_thread */, nullptr /* signaling_thread */, nullptr /* default_adm */, webrtc::CreateBuiltinAudioEncoderFactory(), webrtc::CreateBuiltinAudioDecoderFactory(), webrtc::CreateBuiltinVideoEncoderFactory(), webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */, nullptr /* audio_processing */); } rtc::scoped_refptr Conductor::doCreatePeerConnection(webrtc::PeerConnectionFactoryInterface &factory) { webrtc::PeerConnectionInterface::RTCConfiguration config; config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; webrtc::PeerConnectionInterface::IceServer server; const char *uri = getenv("WEBRTC_CONNECT"); if (uri) { server.uri = uri; } else { server.uri = "stun:stun.l.google.com:19302"; } config.servers.push_back(server); rtc::scoped_refptr conn = factory.CreatePeerConnection( config, nullptr, nullptr, this); doAddTracks(*conn); return conn; } void Conductor::OnSuccess(webrtc::SessionDescriptionInterface *desc) { fprintf(stderr, "on success; got answer\n"); peer_conn_->SetLocalDescription( SetSessionDescriptionObserver::Create(observer_), desc); std::string sdp; desc->ToString(&sdp); observer_.onAnswer(std::move(sdp)); } void Conductor::OnFailure(webrtc::RTCError error) { observer_.onError(ConductorObserver::ErrorType::WARNING, error.message()); } }