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/base/sigslot.h"
     41 #include "talk/session/media/mediasession.h"
     42 
     43 namespace talk_base {
     44 class Thread;
     45 }  // namespace talk_base
     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   MediaStreamSignaling(talk_base::Thread* signaling_thread,
    164                        MediaStreamSignalingObserver* stream_observer,
    165                        cricket::ChannelManager* channel_manager);
    166   virtual ~MediaStreamSignaling();
    167 
    168   // Notify all referenced objects that MediaStreamSignaling will be teared
    169   // down. This method must be called prior to the dtor.
    170   void TearDown();
    171 
    172   // Set a factory for creating data channels that are initiated by the remote
    173   // peer.
    174   void SetDataChannelFactory(DataChannelFactory* data_channel_factory) {
    175     data_channel_factory_ = data_channel_factory;
    176   }
    177 
    178   // Checks if |id| is available to be assigned to a new SCTP data channel.
    179   bool IsSctpSidAvailable(int sid) const;
    180 
    181   // Gets the first available SCTP id that is not assigned to any existing
    182   // data channels.
    183   bool AllocateSctpSid(talk_base::SSLRole role, int* sid);
    184 
    185   // Adds |local_stream| to the collection of known MediaStreams that will be
    186   // offered in a SessionDescription.
    187   bool AddLocalStream(MediaStreamInterface* local_stream);
    188 
    189   // Removes |local_stream| from the collection of known MediaStreams that will
    190   // be offered in a SessionDescription.
    191   void RemoveLocalStream(MediaStreamInterface* local_stream);
    192 
    193   // Checks if any data channel has been added.
    194   bool HasDataChannels() const;
    195   // Adds |data_channel| to the collection of DataChannels that will be
    196   // be offered in a SessionDescription.
    197   bool AddDataChannel(DataChannel* data_channel);
    198   // After we receive an OPEN message, create a data channel and add it.
    199   bool AddDataChannelFromOpenMessage(const cricket::ReceiveDataParams& params,
    200                                      const talk_base::Buffer& payload);
    201   void RemoveSctpDataChannel(int sid);
    202 
    203   // Returns a MediaSessionOptions struct with options decided by |constraints|,
    204   // the local MediaStreams and DataChannels.
    205   virtual bool GetOptionsForOffer(
    206       const MediaConstraintsInterface* constraints,
    207       cricket::MediaSessionOptions* options);
    208 
    209   // Returns a MediaSessionOptions struct with options decided by
    210   // |constraints|, the local MediaStreams and DataChannels.
    211   virtual bool GetOptionsForAnswer(
    212       const MediaConstraintsInterface* constraints,
    213       cricket::MediaSessionOptions* options);
    214 
    215   // Called when the remote session description has changed. The purpose is to
    216   // update remote MediaStreams and DataChannels with the current
    217   // session state.
    218   // If the remote SessionDescription contain information about a new remote
    219   // MediaStreams a new remote MediaStream is created and
    220   // MediaStreamSignalingObserver::OnAddStream is called.
    221   // If a remote MediaStream is missing from
    222   // the remote SessionDescription MediaStreamSignalingObserver::OnRemoveStream
    223   // is called.
    224   // If the SessionDescription contains information about a new DataChannel,
    225   // MediaStreamSignalingObserver::OnAddDataChannel is called with the
    226   // DataChannel.
    227   void OnRemoteDescriptionChanged(const SessionDescriptionInterface* desc);
    228 
    229   // Called when the local session description has changed. The purpose is to
    230   // update local and remote MediaStreams and DataChannels with the current
    231   // session state.
    232   // If |desc| indicates that the media type should be rejected, the method
    233   // ends the remote MediaStreamTracks.
    234   // It also updates local DataChannels with information about its local SSRC.
    235   void OnLocalDescriptionChanged(const SessionDescriptionInterface* desc);
    236 
    237   // Called when the audio channel closes.
    238   void OnAudioChannelClose();
    239   // Called when the video channel closes.
    240   void OnVideoChannelClose();
    241   // Called when the data channel closes.
    242   void OnDataChannelClose();
    243 
    244   // Returns all current known local MediaStreams.
    245   StreamCollectionInterface* local_streams() const { return local_streams_;}
    246 
    247   // Returns all current remote MediaStreams.
    248   StreamCollectionInterface* remote_streams() const {
    249     return remote_streams_.get();
    250   }
    251   void OnDataTransportCreatedForSctp();
    252   void OnDtlsRoleReadyForSctp(talk_base::SSLRole role);
    253   void OnRemoteSctpDataChannelClosed(uint32 sid);
    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::vector<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                            uint32 ssrc,
    362                            cricket::MediaType media_type);
    363 
    364   void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
    365   void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams);
    366   void UpdateClosingDataChannels(
    367       const std::vector<std::string>& active_channels, bool is_local_update);
    368   void CreateRemoteDataChannel(const std::string& label, uint32 remote_ssrc);
    369 
    370   const TrackInfo* FindTrackInfo(const TrackInfos& infos,
    371                                  const std::string& stream_label,
    372                                  const std::string track_id) const;
    373 
    374   // Returns the index of the specified SCTP DataChannel in sctp_data_channels_,
    375   // or -1 if not found.
    376   int FindDataChannelBySid(int sid) const;
    377 
    378   RemotePeerInfo remote_info_;
    379   talk_base::Thread* signaling_thread_;
    380   DataChannelFactory* data_channel_factory_;
    381   cricket::MediaSessionOptions options_;
    382   MediaStreamSignalingObserver* stream_observer_;
    383   talk_base::scoped_refptr<StreamCollection> local_streams_;
    384   talk_base::scoped_refptr<StreamCollection> remote_streams_;
    385   talk_base::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::map<std::string, talk_base::scoped_refptr<DataChannel> >
    396       RtpDataChannels;
    397   typedef std::vector<talk_base::scoped_refptr<DataChannel> > SctpDataChannels;
    398 
    399   RtpDataChannels rtp_data_channels_;
    400   SctpDataChannels sctp_data_channels_;
    401 };
    402 
    403 }  // namespace webrtc
    404 
    405 #endif  // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_
    406