#pragma once class CaptureOp; class PeerConnection : public webrtc::PeerConnectionObserver, public webrtc::CreateSessionDescriptionObserver { public: PeerConnection(); ~PeerConnection() override; void SetPeerImpl( rtc::scoped_refptr peer) ; using ConnectedCallback = Callback<>; void RegisterConnectedCallback(ConnectedCallback&& callback) { std::lock_guard lock{connected_callback_mutex_}; connected_callback_ = std::move(callback); } using LocalSdpReadytoSendCallback = Callback; void RegisterLocalSdpReadytoSendCallback( LocalSdpReadytoSendCallback&& callback) { std::lock_guard lock{local_sdp_ready_to_send_callback_mutex_}; local_sdp_ready_to_send_callback_ = std::move(callback); } using IceCandidateReadytoSendCallback = Callback; void RegisterIceCandidateReadytoSendCallback( IceCandidateReadytoSendCallback&& callback) { std::lock_guard lock{ice_candidate_ready_to_send_callback_mutex_}; ice_candidate_ready_to_send_callback_ = std::move(callback); } using RenegotiationNeededCallback = Callback<>; void RegisterRenegotiationNeededCallback( RenegotiationNeededCallback&& callback) { std::lock_guard lock{renegotiation_needed_callback_mutex_}; renegotiation_needed_callback_ = std::move(callback); } using TrackAddedCallback = Callback<>; void RegisterTrackAddedCallback(TrackAddedCallback&& callback) { std::lock_guard lock{track_added_callback_mutex_}; track_added_callback_ = std::move(callback); } using TrackRemovedCallback = Callback<>; void RegisterTrackRemovedCallback(TrackRemovedCallback&& callback) { std::lock_guard lock{track_removed_callback_mutex_}; track_removed_callback_ = std::move(callback); } void RegisterLocalVideoFrameCallback( I420FrameReadyCallback callback) { if (local_video_observer_) { local_video_observer_->SetCallback(std::move(callback)); } } void RegisterLocalVideoFrameCallback( ARGBFrameReadyCallback callback) { if (local_video_observer_) { local_video_observer_->SetCallback(std::move(callback)); } } void RegisterRemoteVideoFrameCallback( I420FrameReadyCallback callback) { if (remote_video_observer_) { remote_video_observer_->SetCallback(std::move(callback)); } } void RegisterRemoteVideoFrameCallback( ARGBFrameReadyCallback callback) { if (remote_video_observer_) { remote_video_observer_->SetCallback(std::move(callback)); } } void RegisterDataChannelCallback( DataChannelMessageCallback message_callback, DataChannelBufferingCallback buffering_callback, DataChannelStateCallback state_callback); bool AddLocalVideoTrack( rtc::scoped_refptr video_track,const std::string& stream) ; void RemoveLocalVideoTrack() ; bool AddLocalAudioTrack( rtc::scoped_refptr audio_track) ; void RemoveLocalAudioTrack() ; mrsResult AddDataChannel( const char* label, bool ordered, bool reliable//, // DataChannelMessageCallback message_callback, // DataChannelBufferingCallback buffering_callback, // DataChannelStateCallback state_callba ) ; bool RemoveDataChannel() ; /* bool RemoveDataChannel(const char* label) ;*/ /// Remove all the existing data tracks from the peer connection. /* void RemoveAllDataTracks() ;*/ bool SendDataChannelMessage(const void* data, uint64_t size) ; bool AddIceCandidate(const char* sdp_mid, const int sdp_mline_index, const char* candidate) ; bool CreateOffer() ; bool CreateAnswer() ; bool SetRemoteDescription(const char* type, const char* sdp) ; #ifdef WEBRTC_LINUX void RegisterCaptureOp(std::unique_ptr& op); void SwitchCapture(bool front); void SetOtherCtx(void * data); void* GetCurrentCtx(); #endif // WEBRTC_LINUX protected: // PeerConnectionObserver interface // Triggered when the SignalingState changed. void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override; // Triggered when media is received on a new stream from remote peer. void OnAddStream(rtc::scoped_refptr stream) override; // Triggered when a remote peer closes a stream. void OnRemoveStream(rtc::scoped_refptr stream) override; // Triggered when a remote peer opens a data channel. void OnDataChannel( rtc::scoped_refptr data_channel) override; // Triggered when renegotiation is needed. For example, an ICE restart // has begun. void OnRenegotiationNeeded() override; // Called any time the IceConnectionState changes. // // Note that our ICE states lag behind the standard slightly. The most // notable differences include the fact that "failed" occurs after 15 // seconds, not 30, and this actually represents a combination ICE + DTLS // state, so it may be "failed" if DTLS fails while ICE succeeds. void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState /*new_state*/) override {} // Called any time the IceGatheringState changes. void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState /*new_state*/) override {} // A new ICE candidate has been gathered. void OnIceCandidate( const webrtc::IceCandidateInterface* candidate) override; // Callback on track added. void OnAddTrack( rtc::scoped_refptr receiver, const std::vector>& streams) override; // Callback on track removed. void OnRemoveTrack(rtc::scoped_refptr receiver) override; protected: // CreateSessionDescriptionObserver interface // This callback transfers the ownership of the |desc|. // TODO(deadbeef): Make this take an std::unique_ptr<> to avoid confusion // around ownership. void OnSuccess(webrtc::SessionDescriptionInterface* desc) override; // The OnFailure callback takes an RTCError, which consists of an // error code and a string. // RTCError is non-copyable, so it must be passed using std::move. // Earlier versions of the API used a string argument. This version // is deprecated; in order to let clients remove the old version, it has a // default implementation. If both versions are unimplemented, the // result will be a runtime error (stack overflow). This is intentional. void OnFailure(webrtc::RTCError error) override {} protected: rtc::scoped_refptr peer_; ConnectedCallback connected_callback_; LocalSdpReadytoSendCallback local_sdp_ready_to_send_callback_; IceCandidateReadytoSendCallback ice_candidate_ready_to_send_callback_; RenegotiationNeededCallback renegotiation_needed_callback_; TrackAddedCallback track_added_callback_; TrackRemovedCallback track_removed_callback_; DataChannelMessageCallback data_channel_message_callback_; DataChannelBufferingCallback data_channel_buffering_callback_; DataChannelStateCallback data_channel_state_callback_; std::mutex connected_callback_mutex_; std::mutex local_sdp_ready_to_send_callback_mutex_; std::mutex ice_candidate_ready_to_send_callback_mutex_; std::mutex renegotiation_needed_callback_mutex_; std::mutex track_added_callback_mutex_; std::mutex track_removed_callback_mutex_; rtc::scoped_refptr local_video_track_; rtc::scoped_refptr local_audio_track_; rtc::scoped_refptr local_video_sender_; rtc::scoped_refptr local_audio_sender_; std::vector> remote_streams_; #ifdef WEBRTC_LINUX std::unique_ptr _capture; #endif /// Collection of data channels from their unique ID. /// This contains only data channels pre-negotiated or opened by the remote /// peer, as data channels opened locally won't have immediately a unique ID. // std::unordered_map> // data_channel_from_id_; // // /// Collection of data channels from their label. // /// This contains only data channels with a non-empty label. // std::unordered_multimap> // data_channel_from_label_; std::unique_ptr channel_ob_server; //< TODO - Clarify lifetime of those, for now same as this PeerConnection std::unique_ptr local_audio_observer_; std::unique_ptr remote_audio_observer_; std::unique_ptr local_video_observer_; std::unique_ptr remote_video_observer_; /// Flag to indicate if SCTP was negotiated during the initial SDP handshake /// (m=application), which allows subsequently to use data channels. If this /// is false then data channels will never connnect. This is set to true if a /// data channel is created before the connection is established, which will /// force the connection to negotiate the necessary SCTP information. See /// https://stackoverflow.com/questions/43788872/how-are-data-channels-negotiated-between-two-peers-with-webrtc bool sctp_negotiated_ = true; private: PeerConnection(const PeerConnection&) = delete; PeerConnection& operator=(const PeerConnection&) = delete; };