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
42namespace talk_base {
43class Thread;
44}  // namespace talk_base
45
46namespace webrtc {
47
48class 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.
54class 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
159class 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