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 <map> 32 #include <string> 33 #include <vector> 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/session/media/mediasession.h" 40 #include "webrtc/base/scoped_ref_ptr.h" 41 #include "webrtc/base/sigslot.h" 42 43 namespace rtc { 44 class Thread; 45 } // namespace rtc 46 47 namespace webrtc { 48 49 class RemoteMediaStreamFactory; 50 51 // A MediaStreamSignalingObserver is notified when events happen to 52 // MediaStreams, MediaStreamTracks or DataChannels associated with the observed 53 // MediaStreamSignaling object. The notifications identify the stream, track or 54 // channel. 55 class MediaStreamSignalingObserver { 56 public: 57 // Triggered when the remote SessionDescription has a new stream. 58 virtual void OnAddRemoteStream(MediaStreamInterface* stream) = 0; 59 60 // Triggered when the remote SessionDescription removes a stream. 61 virtual void OnRemoveRemoteStream(MediaStreamInterface* stream) = 0; 62 63 // Triggered when the remote SessionDescription has a new data channel. 64 virtual void OnAddDataChannel(DataChannelInterface* data_channel) = 0; 65 66 // Triggered when the remote SessionDescription has a new audio track. 67 virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream, 68 AudioTrackInterface* audio_track, 69 uint32 ssrc) = 0; 70 71 // Triggered when the remote SessionDescription has a new video track. 72 virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream, 73 VideoTrackInterface* video_track, 74 uint32 ssrc) = 0; 75 76 // Triggered when the remote SessionDescription has removed an audio track. 77 virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream, 78 AudioTrackInterface* audio_track) = 0; 79 80 // Triggered when the remote SessionDescription has removed a video track. 81 virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream, 82 VideoTrackInterface* video_track) = 0; 83 84 // Triggered when the local SessionDescription has a new audio track. 85 virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream, 86 AudioTrackInterface* audio_track, 87 uint32 ssrc) = 0; 88 89 // Triggered when the local SessionDescription has a new video track. 90 virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream, 91 VideoTrackInterface* video_track, 92 uint32 ssrc) = 0; 93 94 // Triggered when the local SessionDescription has removed an audio track. 95 virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream, 96 AudioTrackInterface* audio_track, 97 uint32 ssrc) = 0; 98 99 // Triggered when the local SessionDescription has removed a video track. 100 virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream, 101 VideoTrackInterface* video_track) = 0; 102 103 // Triggered when RemoveLocalStream is called. |stream| is no longer used 104 // when negotiating and all tracks in |stream| should stop providing data to 105 // this PeerConnection. This doesn't mean that the local session description 106 // has changed and OnRemoveLocalAudioTrack and OnRemoveLocalVideoTrack is not 107 // called for each individual track. 108 virtual void OnRemoveLocalStream(MediaStreamInterface* stream) = 0; 109 110 protected: 111 ~MediaStreamSignalingObserver() {} 112 }; 113 114 // MediaStreamSignaling works as a glue between MediaStreams and a cricket 115 // classes for SessionDescriptions. 116 // It is used for creating cricket::MediaSessionOptions given the local 117 // MediaStreams and data channels. 118 // 119 // It is responsible for creating remote MediaStreams given a remote 120 // SessionDescription and creating cricket::MediaSessionOptions given 121 // local MediaStreams. 122 // 123 // To signal that a DataChannel should be established: 124 // 1. Call AddDataChannel with the new DataChannel. Next time 125 // GetMediaSessionOptions will include the description of the DataChannel. 126 // 2. When a local session description is set, call UpdateLocalStreams with the 127 // session description. This will set the SSRC used for sending data on 128 // this DataChannel. 129 // 3. When remote session description is set, call UpdateRemoteStream with the 130 // session description. If the DataChannel label and a SSRC is included in 131 // the description, the DataChannel is updated with SSRC that will be used 132 // for receiving data. 133 // 4. When both the local and remote SSRC of a DataChannel is set the state of 134 // the DataChannel change to kOpen. 135 // 136 // To setup a DataChannel initialized by the remote end. 137 // 1. When remote session description is set, call UpdateRemoteStream with the 138 // session description. If a label and a SSRC of a new DataChannel is found 139 // MediaStreamSignalingObserver::OnAddDataChannel with the label and SSRC is 140 // triggered. 141 // 2. Create a DataChannel instance with the label and set the remote SSRC. 142 // 3. Call AddDataChannel with this new DataChannel. GetMediaSessionOptions 143 // will include the description of the DataChannel. 144 // 4. Create a local session description and call UpdateLocalStreams. This will 145 // set the local SSRC used by the DataChannel. 146 // 5. When both the local and remote SSRC of a DataChannel is set the state of 147 // the DataChannel change to kOpen. 148 // 149 // To close a DataChannel: 150 // 1. Call DataChannel::Close. This will change the state of the DataChannel to 151 // kClosing. GetMediaSessionOptions will not 152 // include the description of the DataChannel. 153 // 2. When a local session description is set, call UpdateLocalStreams with the 154 // session description. The description will no longer contain the 155 // DataChannel label or SSRC. 156 // 3. When remote session description is set, call UpdateRemoteStream with the 157 // session description. The description will no longer contain the 158 // DataChannel label or SSRC. The DataChannel SSRC is updated with SSRC=0. 159 // The DataChannel change state to kClosed. 160 161 class MediaStreamSignaling : public sigslot::has_slots<> { 162 public: 163 typedef std::map<std::string, rtc::scoped_refptr<DataChannel> > 164 RtpDataChannels; 165 166 MediaStreamSignaling(rtc::Thread* signaling_thread, 167 MediaStreamSignalingObserver* stream_observer, 168 cricket::ChannelManager* channel_manager); 169 virtual ~MediaStreamSignaling(); 170 171 // Notify all referenced objects that MediaStreamSignaling will be teared 172 // down. This method must be called prior to the dtor. 173 void TearDown(); 174 175 // Set a factory for creating data channels that are initiated by the remote 176 // peer. 177 void SetDataChannelFactory(DataChannelFactory* data_channel_factory) { 178 data_channel_factory_ = data_channel_factory; 179 } 180 181 // Checks if |id| is available to be assigned to a new SCTP data channel. 182 bool IsSctpSidAvailable(int sid) const; 183 184 // Gets the first available SCTP id that is not assigned to any existing 185 // data channels. 186 bool AllocateSctpSid(rtc::SSLRole role, int* sid); 187 188 // Adds |local_stream| to the collection of known MediaStreams that will be 189 // offered in a SessionDescription. 190 bool AddLocalStream(MediaStreamInterface* local_stream); 191 192 // Removes |local_stream| from the collection of known MediaStreams that will 193 // be offered in a SessionDescription. 194 void RemoveLocalStream(MediaStreamInterface* local_stream); 195 196 // Checks if any data channel has been added. 197 bool HasDataChannels() const; 198 // Adds |data_channel| to the collection of DataChannels that will be 199 // be offered in a SessionDescription. 200 bool AddDataChannel(DataChannel* data_channel); 201 // After we receive an OPEN message, create a data channel and add it. 202 bool AddDataChannelFromOpenMessage(const cricket::ReceiveDataParams& params, 203 const rtc::Buffer& payload); 204 void RemoveSctpDataChannel(int sid); 205 206 // Returns a MediaSessionOptions struct with options decided by |options|, 207 // the local MediaStreams and DataChannels. 208 virtual bool GetOptionsForOffer( 209 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 210 cricket::MediaSessionOptions* session_options); 211 212 // Returns a MediaSessionOptions struct with options decided by 213 // |constraints|, the local MediaStreams and DataChannels. 214 virtual bool GetOptionsForAnswer( 215 const MediaConstraintsInterface* constraints, 216 cricket::MediaSessionOptions* options); 217 218 // Called when the remote session description has changed. The purpose is to 219 // update remote MediaStreams and DataChannels with the current 220 // session state. 221 // If the remote SessionDescription contain information about a new remote 222 // MediaStreams a new remote MediaStream is created and 223 // MediaStreamSignalingObserver::OnAddStream is called. 224 // If a remote MediaStream is missing from 225 // the remote SessionDescription MediaStreamSignalingObserver::OnRemoveStream 226 // is called. 227 // If the SessionDescription contains information about a new DataChannel, 228 // MediaStreamSignalingObserver::OnAddDataChannel is called with the 229 // DataChannel. 230 void OnRemoteDescriptionChanged(const SessionDescriptionInterface* desc); 231 232 // Called when the local session description has changed. The purpose is to 233 // update local and remote MediaStreams and DataChannels with the current 234 // session state. 235 // If |desc| indicates that the media type should be rejected, the method 236 // ends the remote MediaStreamTracks. 237 // It also updates local DataChannels with information about its local SSRC. 238 void OnLocalDescriptionChanged(const SessionDescriptionInterface* desc); 239 240 // Called when the audio channel closes. 241 void OnAudioChannelClose(); 242 // Called when the video channel closes. 243 void OnVideoChannelClose(); 244 // Called when the data channel closes. 245 void OnDataChannelClose(); 246 247 // Returns all current known local MediaStreams. 248 StreamCollectionInterface* local_streams() const { return local_streams_;} 249 250 // Returns all current remote MediaStreams. 251 StreamCollectionInterface* remote_streams() const { 252 return remote_streams_.get(); 253 } 254 void OnDataTransportCreatedForSctp(); 255 void OnDtlsRoleReadyForSctp(rtc::SSLRole role); 256 void OnRemoteSctpDataChannelClosed(uint32 sid); 257 258 private: 259 struct RemotePeerInfo { 260 RemotePeerInfo() 261 : msid_supported(false), 262 default_audio_track_needed(false), 263 default_video_track_needed(false) { 264 } 265 // True if it has been discovered that the remote peer support MSID. 266 bool msid_supported; 267 // The remote peer indicates in the session description that audio will be 268 // sent but no MSID is given. 269 bool default_audio_track_needed; 270 // The remote peer indicates in the session description that video will be 271 // sent but no MSID is given. 272 bool default_video_track_needed; 273 274 bool IsDefaultMediaStreamNeeded() { 275 return !msid_supported && (default_audio_track_needed || 276 default_video_track_needed); 277 } 278 }; 279 280 struct TrackInfo { 281 TrackInfo() : ssrc(0) {} 282 TrackInfo(const std::string& stream_label, 283 const std::string track_id, 284 uint32 ssrc) 285 : stream_label(stream_label), 286 track_id(track_id), 287 ssrc(ssrc) { 288 } 289 std::string stream_label; 290 std::string track_id; 291 uint32 ssrc; 292 }; 293 typedef std::vector<TrackInfo> TrackInfos; 294 295 // Makes sure a MediaStream Track is created for each StreamParam in 296 // |streams|. |media_type| is the type of the |streams| and can be either 297 // audio or video. 298 // If a new MediaStream is created it is added to |new_streams|. 299 void UpdateRemoteStreamsList( 300 const std::vector<cricket::StreamParams>& streams, 301 cricket::MediaType media_type, 302 StreamCollection* new_streams); 303 304 // Triggered when a remote track has been seen for the first time in a remote 305 // session description. It creates a remote MediaStreamTrackInterface 306 // implementation and triggers MediaStreamSignaling::OnAddRemoteAudioTrack or 307 // MediaStreamSignaling::OnAddRemoteVideoTrack. 308 void OnRemoteTrackSeen(const std::string& stream_label, 309 const std::string& track_id, 310 uint32 ssrc, 311 cricket::MediaType media_type); 312 313 // Triggered when a remote track has been removed from a remote session 314 // description. It removes the remote track with id |track_id| from a remote 315 // MediaStream and triggers MediaStreamSignaling::OnRemoveRemoteAudioTrack or 316 // MediaStreamSignaling::OnRemoveRemoteVideoTrack. 317 void OnRemoteTrackRemoved(const std::string& stream_label, 318 const std::string& track_id, 319 cricket::MediaType media_type); 320 321 // Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote 322 // tracks of type |media_type|. 323 void RejectRemoteTracks(cricket::MediaType media_type); 324 325 // Finds remote MediaStreams without any tracks and removes them from 326 // |remote_streams_| and notifies the observer that the MediaStream no longer 327 // exist. 328 void UpdateEndedRemoteMediaStreams(); 329 void MaybeCreateDefaultStream(); 330 TrackInfos* GetRemoteTracks(cricket::MediaType type); 331 332 // Returns a map of currently negotiated LocalTrackInfo of type |type|. 333 TrackInfos* GetLocalTracks(cricket::MediaType type); 334 bool FindLocalTrack(const std::string& track_id, cricket::MediaType type); 335 336 // Loops through the vector of |streams| and finds added and removed 337 // StreamParams since last time this method was called. 338 // For each new or removed StreamParam NotifyLocalTrackAdded or 339 // NotifyLocalTrackRemoved in invoked. 340 void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams, 341 cricket::MediaType media_type); 342 343 // Triggered when a local track has been seen for the first time in a local 344 // session description. 345 // This method triggers MediaStreamSignaling::OnAddLocalAudioTrack or 346 // MediaStreamSignaling::OnAddLocalVideoTrack if the rtp streams in the local 347 // SessionDescription can be mapped to a MediaStreamTrack in a MediaStream in 348 // |local_streams_| 349 void OnLocalTrackSeen(const std::string& stream_label, 350 const std::string& track_id, 351 uint32 ssrc, 352 cricket::MediaType media_type); 353 354 // Triggered when a local track has been removed from a local session 355 // description. 356 // This method triggers MediaStreamSignaling::OnRemoveLocalAudioTrack or 357 // MediaStreamSignaling::OnRemoveLocalVideoTrack if a stream has been removed 358 // from the local SessionDescription and the stream can be mapped to a 359 // MediaStreamTrack in a MediaStream in |local_streams_|. 360 void OnLocalTrackRemoved(const std::string& stream_label, 361 const std::string& track_id, 362 uint32 ssrc, 363 cricket::MediaType media_type); 364 365 void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams); 366 void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams); 367 void UpdateClosingDataChannels( 368 const std::vector<std::string>& active_channels, bool is_local_update); 369 void CreateRemoteDataChannel(const std::string& label, uint32 remote_ssrc); 370 371 const TrackInfo* FindTrackInfo(const TrackInfos& infos, 372 const std::string& stream_label, 373 const std::string track_id) const; 374 375 // Returns the index of the specified SCTP DataChannel in sctp_data_channels_, 376 // or -1 if not found. 377 int FindDataChannelBySid(int sid) const; 378 379 RemotePeerInfo remote_info_; 380 rtc::Thread* signaling_thread_; 381 DataChannelFactory* data_channel_factory_; 382 MediaStreamSignalingObserver* stream_observer_; 383 rtc::scoped_refptr<StreamCollection> local_streams_; 384 rtc::scoped_refptr<StreamCollection> remote_streams_; 385 rtc::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_; 386 387 TrackInfos remote_audio_tracks_; 388 TrackInfos remote_video_tracks_; 389 TrackInfos local_audio_tracks_; 390 TrackInfos local_video_tracks_; 391 392 int last_allocated_sctp_even_sid_; 393 int last_allocated_sctp_odd_sid_; 394 395 typedef std::vector<rtc::scoped_refptr<DataChannel> > SctpDataChannels; 396 397 RtpDataChannels rtp_data_channels_; 398 SctpDataChannels sctp_data_channels_; 399 }; 400 401 } // namespace webrtc 402 403 #endif // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_ 404