Home | History | Annotate | Download | only in webrtc
      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