| /* |
| * libjingle |
| * Copyright 2012 Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ |
| #define TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "talk/app/webrtc/datachannel.h" |
| #include "talk/app/webrtc/mediastream.h" |
| #include "talk/app/webrtc/peerconnectioninterface.h" |
| #include "talk/app/webrtc/streamcollection.h" |
| #include "talk/session/media/mediasession.h" |
| #include "webrtc/base/scoped_ref_ptr.h" |
| #include "webrtc/base/sigslot.h" |
| |
| namespace rtc { |
| class Thread; |
| } // namespace rtc |
| |
| namespace webrtc { |
| |
| class RemoteMediaStreamFactory; |
| |
| // A MediaStreamSignalingObserver is notified when events happen to |
| // MediaStreams, MediaStreamTracks or DataChannels associated with the observed |
| // MediaStreamSignaling object. The notifications identify the stream, track or |
| // channel. |
| class MediaStreamSignalingObserver { |
| public: |
| // Triggered when the remote SessionDescription has a new stream. |
| virtual void OnAddRemoteStream(MediaStreamInterface* stream) = 0; |
| |
| // Triggered when the remote SessionDescription removes a stream. |
| virtual void OnRemoveRemoteStream(MediaStreamInterface* stream) = 0; |
| |
| // Triggered when the remote SessionDescription has a new data channel. |
| virtual void OnAddDataChannel(DataChannelInterface* data_channel) = 0; |
| |
| // Triggered when the remote SessionDescription has a new audio track. |
| virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream, |
| AudioTrackInterface* audio_track, |
| uint32 ssrc) = 0; |
| |
| // Triggered when the remote SessionDescription has a new video track. |
| virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream, |
| VideoTrackInterface* video_track, |
| uint32 ssrc) = 0; |
| |
| // Triggered when the remote SessionDescription has removed an audio track. |
| virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream, |
| AudioTrackInterface* audio_track) = 0; |
| |
| // Triggered when the remote SessionDescription has removed a video track. |
| virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream, |
| VideoTrackInterface* video_track) = 0; |
| |
| // Triggered when the local SessionDescription has a new audio track. |
| virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream, |
| AudioTrackInterface* audio_track, |
| uint32 ssrc) = 0; |
| |
| // Triggered when the local SessionDescription has a new video track. |
| virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream, |
| VideoTrackInterface* video_track, |
| uint32 ssrc) = 0; |
| |
| // Triggered when the local SessionDescription has removed an audio track. |
| virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream, |
| AudioTrackInterface* audio_track, |
| uint32 ssrc) = 0; |
| |
| // Triggered when the local SessionDescription has removed a video track. |
| virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream, |
| VideoTrackInterface* video_track) = 0; |
| |
| // Triggered when RemoveLocalStream is called. |stream| is no longer used |
| // when negotiating and all tracks in |stream| should stop providing data to |
| // this PeerConnection. This doesn't mean that the local session description |
| // has changed and OnRemoveLocalAudioTrack and OnRemoveLocalVideoTrack is not |
| // called for each individual track. |
| virtual void OnRemoveLocalStream(MediaStreamInterface* stream) = 0; |
| |
| protected: |
| ~MediaStreamSignalingObserver() {} |
| }; |
| |
| // MediaStreamSignaling works as a glue between MediaStreams and a cricket |
| // classes for SessionDescriptions. |
| // It is used for creating cricket::MediaSessionOptions given the local |
| // MediaStreams and data channels. |
| // |
| // It is responsible for creating remote MediaStreams given a remote |
| // SessionDescription and creating cricket::MediaSessionOptions given |
| // local MediaStreams. |
| // |
| // To signal that a DataChannel should be established: |
| // 1. Call AddDataChannel with the new DataChannel. Next time |
| // GetMediaSessionOptions will include the description of the DataChannel. |
| // 2. When a local session description is set, call UpdateLocalStreams with the |
| // session description. This will set the SSRC used for sending data on |
| // this DataChannel. |
| // 3. When remote session description is set, call UpdateRemoteStream with the |
| // session description. If the DataChannel label and a SSRC is included in |
| // the description, the DataChannel is updated with SSRC that will be used |
| // for receiving data. |
| // 4. When both the local and remote SSRC of a DataChannel is set the state of |
| // the DataChannel change to kOpen. |
| // |
| // To setup a DataChannel initialized by the remote end. |
| // 1. When remote session description is set, call UpdateRemoteStream with the |
| // session description. If a label and a SSRC of a new DataChannel is found |
| // MediaStreamSignalingObserver::OnAddDataChannel with the label and SSRC is |
| // triggered. |
| // 2. Create a DataChannel instance with the label and set the remote SSRC. |
| // 3. Call AddDataChannel with this new DataChannel. GetMediaSessionOptions |
| // will include the description of the DataChannel. |
| // 4. Create a local session description and call UpdateLocalStreams. This will |
| // set the local SSRC used by the DataChannel. |
| // 5. When both the local and remote SSRC of a DataChannel is set the state of |
| // the DataChannel change to kOpen. |
| // |
| // To close a DataChannel: |
| // 1. Call DataChannel::Close. This will change the state of the DataChannel to |
| // kClosing. GetMediaSessionOptions will not |
| // include the description of the DataChannel. |
| // 2. When a local session description is set, call UpdateLocalStreams with the |
| // session description. The description will no longer contain the |
| // DataChannel label or SSRC. |
| // 3. When remote session description is set, call UpdateRemoteStream with the |
| // session description. The description will no longer contain the |
| // DataChannel label or SSRC. The DataChannel SSRC is updated with SSRC=0. |
| // The DataChannel change state to kClosed. |
| |
| class MediaStreamSignaling : public sigslot::has_slots<> { |
| public: |
| typedef std::map<std::string, rtc::scoped_refptr<DataChannel> > |
| RtpDataChannels; |
| typedef std::vector<rtc::scoped_refptr<DataChannel>> SctpDataChannels; |
| |
| MediaStreamSignaling(rtc::Thread* signaling_thread, |
| MediaStreamSignalingObserver* stream_observer, |
| cricket::ChannelManager* channel_manager); |
| virtual ~MediaStreamSignaling(); |
| |
| // Notify all referenced objects that MediaStreamSignaling will be teared |
| // down. This method must be called prior to the dtor. |
| void TearDown(); |
| |
| // Set a factory for creating data channels that are initiated by the remote |
| // peer. |
| void SetDataChannelFactory(DataChannelFactory* data_channel_factory) { |
| data_channel_factory_ = data_channel_factory; |
| } |
| |
| // Checks if |id| is available to be assigned to a new SCTP data channel. |
| bool IsSctpSidAvailable(int sid) const; |
| |
| // Gets the first available SCTP id that is not assigned to any existing |
| // data channels. |
| bool AllocateSctpSid(rtc::SSLRole role, int* sid); |
| |
| // Adds |local_stream| to the collection of known MediaStreams that will be |
| // offered in a SessionDescription. |
| bool AddLocalStream(MediaStreamInterface* local_stream); |
| |
| // Removes |local_stream| from the collection of known MediaStreams that will |
| // be offered in a SessionDescription. |
| void RemoveLocalStream(MediaStreamInterface* local_stream); |
| |
| // Checks if any data channel has been added. |
| bool HasDataChannels() const; |
| // Adds |data_channel| to the collection of DataChannels that will be |
| // be offered in a SessionDescription. |
| bool AddDataChannel(DataChannel* data_channel); |
| // After we receive an OPEN message, create a data channel and add it. |
| bool AddDataChannelFromOpenMessage(const cricket::ReceiveDataParams& params, |
| const rtc::Buffer& payload); |
| void RemoveSctpDataChannel(int sid); |
| |
| // Returns a MediaSessionOptions struct with options decided by |options|, |
| // the local MediaStreams and DataChannels. |
| virtual bool GetOptionsForOffer( |
| const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
| cricket::MediaSessionOptions* session_options); |
| |
| // Returns a MediaSessionOptions struct with options decided by |
| // |constraints|, the local MediaStreams and DataChannels. |
| virtual bool GetOptionsForAnswer( |
| const MediaConstraintsInterface* constraints, |
| cricket::MediaSessionOptions* options); |
| |
| // Called when the remote session description has changed. The purpose is to |
| // update remote MediaStreams and DataChannels with the current |
| // session state. |
| // If the remote SessionDescription contain information about a new remote |
| // MediaStreams a new remote MediaStream is created and |
| // MediaStreamSignalingObserver::OnAddStream is called. |
| // If a remote MediaStream is missing from |
| // the remote SessionDescription MediaStreamSignalingObserver::OnRemoveStream |
| // is called. |
| // If the SessionDescription contains information about a new DataChannel, |
| // MediaStreamSignalingObserver::OnAddDataChannel is called with the |
| // DataChannel. |
| void OnRemoteDescriptionChanged(const SessionDescriptionInterface* desc); |
| |
| // Called when the local session description has changed. The purpose is to |
| // update local and remote MediaStreams and DataChannels with the current |
| // session state. |
| // If |desc| indicates that the media type should be rejected, the method |
| // ends the remote MediaStreamTracks. |
| // It also updates local DataChannels with information about its local SSRC. |
| void OnLocalDescriptionChanged(const SessionDescriptionInterface* desc); |
| |
| // Called when the audio channel closes. |
| void OnAudioChannelClose(); |
| // Called when the video channel closes. |
| void OnVideoChannelClose(); |
| // Called when the data channel closes. |
| void OnDataChannelClose(); |
| |
| // Returns all current known local MediaStreams. |
| StreamCollectionInterface* local_streams() const { return local_streams_;} |
| |
| // Returns all current remote MediaStreams. |
| StreamCollectionInterface* remote_streams() const { |
| return remote_streams_.get(); |
| } |
| void OnDataTransportCreatedForSctp(); |
| void OnDtlsRoleReadyForSctp(rtc::SSLRole role); |
| void OnRemoteSctpDataChannelClosed(uint32 sid); |
| |
| const SctpDataChannels& sctp_data_channels() const { |
| return sctp_data_channels_; |
| } |
| |
| private: |
| struct RemotePeerInfo { |
| RemotePeerInfo() |
| : msid_supported(false), |
| default_audio_track_needed(false), |
| default_video_track_needed(false) { |
| } |
| // True if it has been discovered that the remote peer support MSID. |
| bool msid_supported; |
| // The remote peer indicates in the session description that audio will be |
| // sent but no MSID is given. |
| bool default_audio_track_needed; |
| // The remote peer indicates in the session description that video will be |
| // sent but no MSID is given. |
| bool default_video_track_needed; |
| |
| bool IsDefaultMediaStreamNeeded() { |
| return !msid_supported && (default_audio_track_needed || |
| default_video_track_needed); |
| } |
| }; |
| |
| struct TrackInfo { |
| TrackInfo() : ssrc(0) {} |
| TrackInfo(const std::string& stream_label, |
| const std::string track_id, |
| uint32 ssrc) |
| : stream_label(stream_label), |
| track_id(track_id), |
| ssrc(ssrc) { |
| } |
| std::string stream_label; |
| std::string track_id; |
| uint32 ssrc; |
| }; |
| typedef std::vector<TrackInfo> TrackInfos; |
| |
| // Makes sure a MediaStream Track is created for each StreamParam in |
| // |streams|. |media_type| is the type of the |streams| and can be either |
| // audio or video. |
| // If a new MediaStream is created it is added to |new_streams|. |
| void UpdateRemoteStreamsList( |
| const std::vector<cricket::StreamParams>& streams, |
| cricket::MediaType media_type, |
| StreamCollection* new_streams); |
| |
| // Triggered when a remote track has been seen for the first time in a remote |
| // session description. It creates a remote MediaStreamTrackInterface |
| // implementation and triggers MediaStreamSignaling::OnAddRemoteAudioTrack or |
| // MediaStreamSignaling::OnAddRemoteVideoTrack. |
| void OnRemoteTrackSeen(const std::string& stream_label, |
| const std::string& track_id, |
| uint32 ssrc, |
| cricket::MediaType media_type); |
| |
| // Triggered when a remote track has been removed from a remote session |
| // description. It removes the remote track with id |track_id| from a remote |
| // MediaStream and triggers MediaStreamSignaling::OnRemoveRemoteAudioTrack or |
| // MediaStreamSignaling::OnRemoveRemoteVideoTrack. |
| void OnRemoteTrackRemoved(const std::string& stream_label, |
| const std::string& track_id, |
| cricket::MediaType media_type); |
| |
| // Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote |
| // tracks of type |media_type|. |
| void RejectRemoteTracks(cricket::MediaType media_type); |
| |
| // Finds remote MediaStreams without any tracks and removes them from |
| // |remote_streams_| and notifies the observer that the MediaStream no longer |
| // exist. |
| void UpdateEndedRemoteMediaStreams(); |
| void MaybeCreateDefaultStream(); |
| TrackInfos* GetRemoteTracks(cricket::MediaType type); |
| |
| // Returns a map of currently negotiated LocalTrackInfo of type |type|. |
| TrackInfos* GetLocalTracks(cricket::MediaType type); |
| bool FindLocalTrack(const std::string& track_id, cricket::MediaType type); |
| |
| // Loops through the vector of |streams| and finds added and removed |
| // StreamParams since last time this method was called. |
| // For each new or removed StreamParam NotifyLocalTrackAdded or |
| // NotifyLocalTrackRemoved in invoked. |
| void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams, |
| cricket::MediaType media_type); |
| |
| // Triggered when a local track has been seen for the first time in a local |
| // session description. |
| // This method triggers MediaStreamSignaling::OnAddLocalAudioTrack or |
| // MediaStreamSignaling::OnAddLocalVideoTrack if the rtp streams in the local |
| // SessionDescription can be mapped to a MediaStreamTrack in a MediaStream in |
| // |local_streams_| |
| void OnLocalTrackSeen(const std::string& stream_label, |
| const std::string& track_id, |
| uint32 ssrc, |
| cricket::MediaType media_type); |
| |
| // Triggered when a local track has been removed from a local session |
| // description. |
| // This method triggers MediaStreamSignaling::OnRemoveLocalAudioTrack or |
| // MediaStreamSignaling::OnRemoveLocalVideoTrack if a stream has been removed |
| // from the local SessionDescription and the stream can be mapped to a |
| // MediaStreamTrack in a MediaStream in |local_streams_|. |
| void OnLocalTrackRemoved(const std::string& stream_label, |
| const std::string& track_id, |
| uint32 ssrc, |
| cricket::MediaType media_type); |
| |
| void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams); |
| void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams); |
| void UpdateClosingDataChannels( |
| const std::vector<std::string>& active_channels, bool is_local_update); |
| void CreateRemoteDataChannel(const std::string& label, uint32 remote_ssrc); |
| |
| const TrackInfo* FindTrackInfo(const TrackInfos& infos, |
| const std::string& stream_label, |
| const std::string track_id) const; |
| |
| // Returns the index of the specified SCTP DataChannel in sctp_data_channels_, |
| // or -1 if not found. |
| int FindDataChannelBySid(int sid) const; |
| |
| RemotePeerInfo remote_info_; |
| rtc::Thread* signaling_thread_; |
| DataChannelFactory* data_channel_factory_; |
| MediaStreamSignalingObserver* stream_observer_; |
| rtc::scoped_refptr<StreamCollection> local_streams_; |
| rtc::scoped_refptr<StreamCollection> remote_streams_; |
| rtc::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_; |
| |
| TrackInfos remote_audio_tracks_; |
| TrackInfos remote_video_tracks_; |
| TrackInfos local_audio_tracks_; |
| TrackInfos local_video_tracks_; |
| |
| int last_allocated_sctp_even_sid_; |
| int last_allocated_sctp_odd_sid_; |
| |
| RtpDataChannels rtp_data_channels_; |
| SctpDataChannels sctp_data_channels_; |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ |