1 /* 2 * libjingle 3 * Copyright 2012, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ 29 #define TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ 30 31 #include <string> 32 #include <vector> 33 #include <map> 34 35 #include "talk/app/webrtc/datachannel.h" 36 #include "talk/app/webrtc/mediastream.h" 37 #include "talk/app/webrtc/peerconnectioninterface.h" 38 #include "talk/app/webrtc/streamcollection.h" 39 #include "talk/base/scoped_ref_ptr.h" 40 #include "talk/session/media/mediasession.h" 41 42 namespace talk_base { 43 class Thread; 44 } // namespace talk_base 45 46 namespace webrtc { 47 48 class RemoteMediaStreamFactory; 49 50 // A MediaStreamSignalingObserver is notified when events happen to 51 // MediaStreams, MediaStreamTracks or DataChannels associated with the observed 52 // MediaStreamSignaling object. The notifications identify the stream, track or 53 // channel. 54 class MediaStreamSignalingObserver { 55 public: 56 // Triggered when the remote SessionDescription has a new stream. 57 virtual void OnAddRemoteStream(MediaStreamInterface* stream) = 0; 58 59 // Triggered when the remote SessionDescription removes a stream. 60 virtual void OnRemoveRemoteStream(MediaStreamInterface* stream) = 0; 61 62 // Triggered when the remote SessionDescription has a new data channel. 63 virtual void OnAddDataChannel(DataChannelInterface* data_channel) = 0; 64 65 // Triggered when the remote SessionDescription has a new audio track. 66 virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream, 67 AudioTrackInterface* audio_track, 68 uint32 ssrc) = 0; 69 70 // Triggered when the remote SessionDescription has a new video track. 71 virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream, 72 VideoTrackInterface* video_track, 73 uint32 ssrc) = 0; 74 75 // Triggered when the remote SessionDescription has removed an audio track. 76 virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream, 77 AudioTrackInterface* audio_track) = 0; 78 79 // Triggered when the remote SessionDescription has removed a video track. 80 virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream, 81 VideoTrackInterface* video_track) = 0; 82 83 // Triggered when the local SessionDescription has a new audio track. 84 virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream, 85 AudioTrackInterface* audio_track, 86 uint32 ssrc) = 0; 87 88 // Triggered when the local SessionDescription has a new video track. 89 virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream, 90 VideoTrackInterface* video_track, 91 uint32 ssrc) = 0; 92 93 // Triggered when the local SessionDescription has removed an audio track. 94 virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream, 95 AudioTrackInterface* audio_track) = 0; 96 97 // Triggered when the local SessionDescription has removed a video track. 98 virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream, 99 VideoTrackInterface* video_track) = 0; 100 101 // Triggered when RemoveLocalStream is called. |stream| is no longer used 102 // when negotiating and all tracks in |stream| should stop providing data to 103 // this PeerConnection. This doesn't mean that the local session description 104 // has changed and OnRemoveLocalAudioTrack and OnRemoveLocalVideoTrack is not 105 // called for each individual track. 106 virtual void OnRemoveLocalStream(MediaStreamInterface* stream) = 0; 107 108 protected: 109 ~MediaStreamSignalingObserver() {} 110 }; 111 112 // MediaStreamSignaling works as a glue between MediaStreams and a cricket 113 // classes for SessionDescriptions. 114 // It is used for creating cricket::MediaSessionOptions given the local 115 // MediaStreams and data channels. 116 // 117 // It is responsible for creating remote MediaStreams given a remote 118 // SessionDescription and creating cricket::MediaSessionOptions given 119 // local MediaStreams. 120 // 121 // To signal that a DataChannel should be established: 122 // 1. Call AddDataChannel with the new DataChannel. Next time 123 // GetMediaSessionOptions will include the description of the DataChannel. 124 // 2. When a local session description is set, call UpdateLocalStreams with the 125 // session description. This will set the SSRC used for sending data on 126 // this DataChannel. 127 // 3. When remote session description is set, call UpdateRemoteStream with the 128 // session description. If the DataChannel label and a SSRC is included in 129 // the description, the DataChannel is updated with SSRC that will be used 130 // for receiving data. 131 // 4. When both the local and remote SSRC of a DataChannel is set the state of 132 // the DataChannel change to kOpen. 133 // 134 // To setup a DataChannel initialized by the remote end. 135 // 1. When remote session description is set, call UpdateRemoteStream with the 136 // session description. If a label and a SSRC of a new DataChannel is found 137 // MediaStreamSignalingObserver::OnAddDataChannel with the label and SSRC is 138 // triggered. 139 // 2. Create a DataChannel instance with the label and set the remote SSRC. 140 // 3. Call AddDataChannel with this new DataChannel. GetMediaSessionOptions 141 // will include the description of the DataChannel. 142 // 4. Create a local session description and call UpdateLocalStreams. This will 143 // set the local SSRC used by the DataChannel. 144 // 5. When both the local and remote SSRC of a DataChannel is set the state of 145 // the DataChannel change to kOpen. 146 // 147 // To close a DataChannel: 148 // 1. Call DataChannel::Close. This will change the state of the DataChannel to 149 // kClosing. GetMediaSessionOptions will not 150 // include the description of the DataChannel. 151 // 2. When a local session description is set, call UpdateLocalStreams with the 152 // session description. The description will no longer contain the 153 // DataChannel label or SSRC. 154 // 3. When remote session description is set, call UpdateRemoteStream with the 155 // session description. The description will no longer contain the 156 // DataChannel label or SSRC. The DataChannel SSRC is updated with SSRC=0. 157 // The DataChannel change state to kClosed. 158 159 class MediaStreamSignaling { 160 public: 161 MediaStreamSignaling(talk_base::Thread* signaling_thread, 162 MediaStreamSignalingObserver* stream_observer, 163 cricket::ChannelManager* channel_manager); 164 virtual ~MediaStreamSignaling(); 165 166 // Notify all referenced objects that MediaStreamSignaling will be teared 167 // down. This method must be called prior to the dtor. 168 void TearDown(); 169 170 // Set a factory for creating data channels that are initiated by the remote 171 // peer. 172 void SetDataChannelFactory(DataChannelFactory* data_channel_factory) { 173 data_channel_factory_ = data_channel_factory; 174 } 175 176 // Checks if |id| is available to be assigned to a new SCTP data channel. 177 bool IsSctpSidAvailable(int sid) const; 178 179 // Gets the first available SCTP id that is not assigned to any existing 180 // data channels. 181 bool AllocateSctpSid(talk_base::SSLRole role, int* sid); 182 183 // Adds |local_stream| to the collection of known MediaStreams that will be 184 // offered in a SessionDescription. 185 bool AddLocalStream(MediaStreamInterface* local_stream); 186 187 // Removes |local_stream| from the collection of known MediaStreams that will 188 // be offered in a SessionDescription. 189 void RemoveLocalStream(MediaStreamInterface* local_stream); 190 191 // Checks if any data channel has been added. 192 bool HasDataChannels() const; 193 // Adds |data_channel| to the collection of DataChannels that will be 194 // be offered in a SessionDescription. 195 bool AddDataChannel(DataChannel* data_channel); 196 // After we receive an OPEN message, create a data channel and add it. 197 bool AddDataChannelFromOpenMessage( 198 const std::string& label, const DataChannelInit& config); 199 200 // Returns a MediaSessionOptions struct with options decided by |constraints|, 201 // the local MediaStreams and DataChannels. 202 virtual bool GetOptionsForOffer( 203 const MediaConstraintsInterface* constraints, 204 cricket::MediaSessionOptions* options); 205 206 // Returns a MediaSessionOptions struct with options decided by 207 // |constraints|, the local MediaStreams and DataChannels. 208 virtual bool GetOptionsForAnswer( 209 const MediaConstraintsInterface* constraints, 210 cricket::MediaSessionOptions* options); 211 212 // Called when the remote session description has changed. The purpose is to 213 // update remote MediaStreams and DataChannels with the current 214 // session state. 215 // If the remote SessionDescription contain information about a new remote 216 // MediaStreams a new remote MediaStream is created and 217 // MediaStreamSignalingObserver::OnAddStream is called. 218 // If a remote MediaStream is missing from 219 // the remote SessionDescription MediaStreamSignalingObserver::OnRemoveStream 220 // is called. 221 // If the SessionDescription contains information about a new DataChannel, 222 // MediaStreamSignalingObserver::OnAddDataChannel is called with the 223 // DataChannel. 224 void OnRemoteDescriptionChanged(const SessionDescriptionInterface* desc); 225 226 // Called when the local session description has changed. The purpose is to 227 // update local and remote MediaStreams and DataChannels with the current 228 // session state. 229 // If |desc| indicates that the media type should be rejected, the method 230 // ends the remote MediaStreamTracks. 231 // It also updates local DataChannels with information about its local SSRC. 232 void OnLocalDescriptionChanged(const SessionDescriptionInterface* desc); 233 234 // Called when the audio channel closes. 235 void OnAudioChannelClose(); 236 // Called when the video channel closes. 237 void OnVideoChannelClose(); 238 // Called when the data channel closes. 239 void OnDataChannelClose(); 240 241 // Returns the SSRC for a given track. 242 bool GetRemoteAudioTrackSsrc(const std::string& track_id, uint32* ssrc) const; 243 bool GetRemoteVideoTrackSsrc(const std::string& track_id, uint32* ssrc) const; 244 245 // Returns all current known local MediaStreams. 246 StreamCollectionInterface* local_streams() const { return local_streams_;} 247 248 // Returns all current remote MediaStreams. 249 StreamCollectionInterface* remote_streams() const { 250 return remote_streams_.get(); 251 } 252 void OnDataTransportCreatedForSctp(); 253 void OnDtlsRoleReadyForSctp(talk_base::SSLRole role); 254 255 private: 256 struct RemotePeerInfo { 257 RemotePeerInfo() 258 : msid_supported(false), 259 default_audio_track_needed(false), 260 default_video_track_needed(false) { 261 } 262 // True if it has been discovered that the remote peer support MSID. 263 bool msid_supported; 264 // The remote peer indicates in the session description that audio will be 265 // sent but no MSID is given. 266 bool default_audio_track_needed; 267 // The remote peer indicates in the session description that video will be 268 // sent but no MSID is given. 269 bool default_video_track_needed; 270 271 bool IsDefaultMediaStreamNeeded() { 272 return !msid_supported && (default_audio_track_needed || 273 default_video_track_needed); 274 } 275 }; 276 277 struct TrackInfo { 278 TrackInfo() : ssrc(0) {} 279 TrackInfo(const std::string& stream_label, 280 const std::string track_id, 281 uint32 ssrc) 282 : stream_label(stream_label), 283 track_id(track_id), 284 ssrc(ssrc) { 285 } 286 std::string stream_label; 287 std::string track_id; 288 uint32 ssrc; 289 }; 290 typedef std::map<std::string, TrackInfo> TrackInfos; 291 292 void UpdateSessionOptions(); 293 294 // Makes sure a MediaStream Track is created for each StreamParam in 295 // |streams|. |media_type| is the type of the |streams| and can be either 296 // audio or video. 297 // If a new MediaStream is created it is added to |new_streams|. 298 void UpdateRemoteStreamsList( 299 const std::vector<cricket::StreamParams>& streams, 300 cricket::MediaType media_type, 301 StreamCollection* new_streams); 302 303 // Triggered when a remote track has been seen for the first time in a remote 304 // session description. It creates a remote MediaStreamTrackInterface 305 // implementation and triggers MediaStreamSignaling::OnAddRemoteAudioTrack or 306 // MediaStreamSignaling::OnAddRemoteVideoTrack. 307 void OnRemoteTrackSeen(const std::string& stream_label, 308 const std::string& track_id, 309 uint32 ssrc, 310 cricket::MediaType media_type); 311 312 // Triggered when a remote track has been removed from a remote session 313 // description. It removes the remote track with id |track_id| from a remote 314 // MediaStream and triggers MediaStreamSignaling::OnRemoveRemoteAudioTrack or 315 // MediaStreamSignaling::OnRemoveRemoteVideoTrack. 316 void OnRemoteTrackRemoved(const std::string& stream_label, 317 const std::string& track_id, 318 cricket::MediaType media_type); 319 320 // Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote 321 // tracks of type |media_type|. 322 void RejectRemoteTracks(cricket::MediaType media_type); 323 324 // Finds remote MediaStreams without any tracks and removes them from 325 // |remote_streams_| and notifies the observer that the MediaStream no longer 326 // exist. 327 void UpdateEndedRemoteMediaStreams(); 328 void MaybeCreateDefaultStream(); 329 TrackInfos* GetRemoteTracks(cricket::MediaType type); 330 331 // Returns a map of currently negotiated LocalTrackInfo of type |type|. 332 TrackInfos* GetLocalTracks(cricket::MediaType type); 333 bool FindLocalTrack(const std::string& track_id, cricket::MediaType type); 334 335 // Loops through the vector of |streams| and finds added and removed 336 // StreamParams since last time this method was called. 337 // For each new or removed StreamParam NotifyLocalTrackAdded or 338 // NotifyLocalTrackRemoved in invoked. 339 void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams, 340 cricket::MediaType media_type); 341 342 // Triggered when a local track has been seen for the first time in a local 343 // session description. 344 // This method triggers MediaStreamSignaling::OnAddLocalAudioTrack or 345 // MediaStreamSignaling::OnAddLocalVideoTrack if the rtp streams in the local 346 // SessionDescription can be mapped to a MediaStreamTrack in a MediaStream in 347 // |local_streams_| 348 void OnLocalTrackSeen(const std::string& stream_label, 349 const std::string& track_id, 350 uint32 ssrc, 351 cricket::MediaType media_type); 352 353 // Triggered when a local track has been removed from a local session 354 // description. 355 // This method triggers MediaStreamSignaling::OnRemoveLocalAudioTrack or 356 // MediaStreamSignaling::OnRemoveLocalVideoTrack if a stream has been removed 357 // from the local SessionDescription and the stream can be mapped to a 358 // MediaStreamTrack in a MediaStream in |local_streams_|. 359 void OnLocalTrackRemoved(const std::string& stream_label, 360 const std::string& track_id, 361 cricket::MediaType media_type); 362 363 void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams); 364 void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams); 365 void UpdateClosingDataChannels( 366 const std::vector<std::string>& active_channels, bool is_local_update); 367 void CreateRemoteDataChannel(const std::string& label, uint32 remote_ssrc); 368 369 RemotePeerInfo remote_info_; 370 talk_base::Thread* signaling_thread_; 371 DataChannelFactory* data_channel_factory_; 372 cricket::MediaSessionOptions options_; 373 MediaStreamSignalingObserver* stream_observer_; 374 talk_base::scoped_refptr<StreamCollection> local_streams_; 375 talk_base::scoped_refptr<StreamCollection> remote_streams_; 376 talk_base::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_; 377 378 TrackInfos remote_audio_tracks_; 379 TrackInfos remote_video_tracks_; 380 TrackInfos local_audio_tracks_; 381 TrackInfos local_video_tracks_; 382 383 int last_allocated_sctp_even_sid_; 384 int last_allocated_sctp_odd_sid_; 385 386 typedef std::map<std::string, talk_base::scoped_refptr<DataChannel> > 387 RtpDataChannels; 388 typedef std::vector<talk_base::scoped_refptr<DataChannel> > SctpDataChannels; 389 RtpDataChannels rtp_data_channels_; 390 SctpDataChannels sctp_data_channels_; 391 }; 392 393 } // namespace webrtc 394 395 #endif // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ 396