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   virtual ~MediaStreamSignaling();
    164 
    165   // Notify all referenced objects that MediaStreamSignaling will be teared
    166   // down. This method must be called prior to the dtor.
    167   void TearDown();
    168 
    169   // Set a factory for creating data channels that are initiated by the remote
    170   // peer.
    171   void SetDataChannelFactory(DataChannelFactory* data_channel_factory) {
    172     data_channel_factory_ = data_channel_factory;
    173   }
    174 
    175   // Checks if |id| is available to be assigned to a new SCTP data channel.
    176   bool IsSctpIdAvailable(int id) const;
    177 
    178   // Gets the first available SCTP id that is not assigned to any existing
    179   // data channels.
    180   bool AllocateSctpId(int* id);
    181 
    182   // Adds |local_stream| to the collection of known MediaStreams that will be
    183   // offered in a SessionDescription.
    184   bool AddLocalStream(MediaStreamInterface* local_stream);
    185 
    186   // Removes |local_stream| from the collection of known MediaStreams that will
    187   // be offered in a SessionDescription.
    188   void RemoveLocalStream(MediaStreamInterface* local_stream);
    189 
    190   // Adds |data_channel| to the collection of DataChannels that will be
    191   // be offered in a SessionDescription.
    192   bool AddDataChannel(DataChannel* data_channel);
    193   // After we receive an OPEN message, create a data channel and add it.
    194   bool AddDataChannelFromOpenMessage(
    195       const std::string& label, const DataChannelInit& config);
    196   bool ParseDataChannelOpenMessage(
    197       const talk_base::Buffer& payload, std::string* label,
    198       DataChannelInit* config);
    199   bool WriteDataChannelOpenMessage(
    200       const std::string& label, const DataChannelInit& config,
    201       talk_base::Buffer* payload);
    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 the SSRC for a given track.
    245   bool GetRemoteAudioTrackSsrc(const std::string& track_id, uint32* ssrc) const;
    246   bool GetRemoteVideoTrackSsrc(const std::string& track_id, uint32* ssrc) const;
    247 
    248   // Returns all current known local MediaStreams.
    249   StreamCollectionInterface* local_streams() const { return local_streams_;}
    250 
    251   // Returns all current remote MediaStreams.
    252   StreamCollectionInterface* remote_streams() const {
    253     return remote_streams_.get();
    254   }
    255   void UpdateLocalSctpDataChannels();
    256   void UpdateRemoteSctpDataChannels();
    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::map<std::string, TrackInfo> TrackInfos;
    294 
    295   void UpdateSessionOptions();
    296 
    297   // Makes sure a MediaStream Track is created for each StreamParam in
    298   // |streams|. |media_type| is the type of the |streams| and can be either
    299   // audio or video.
    300   // If a new MediaStream is created it is added to |new_streams|.
    301   void UpdateRemoteStreamsList(
    302       const std::vector<cricket::StreamParams>& streams,
    303       cricket::MediaType media_type,
    304       StreamCollection* new_streams);
    305 
    306   // Triggered when a remote track has been seen for the first time in a remote
    307   // session description. It creates a remote MediaStreamTrackInterface
    308   // implementation and triggers MediaStreamSignaling::OnAddRemoteAudioTrack or
    309   // MediaStreamSignaling::OnAddRemoteVideoTrack.
    310   void OnRemoteTrackSeen(const std::string& stream_label,
    311                          const std::string& track_id,
    312                          uint32 ssrc,
    313                          cricket::MediaType media_type);
    314 
    315   // Triggered when a remote track has been removed from a remote session
    316   // description. It removes the remote track with id |track_id| from a remote
    317   // MediaStream and triggers MediaStreamSignaling::OnRemoveRemoteAudioTrack or
    318   // MediaStreamSignaling::OnRemoveRemoteVideoTrack.
    319   void OnRemoteTrackRemoved(const std::string& stream_label,
    320                             const std::string& track_id,
    321                             cricket::MediaType media_type);
    322 
    323   // Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote
    324   // tracks of type |media_type|.
    325   void RejectRemoteTracks(cricket::MediaType media_type);
    326 
    327   // Finds remote MediaStreams without any tracks and removes them from
    328   // |remote_streams_| and notifies the observer that the MediaStream no longer
    329   // exist.
    330   void UpdateEndedRemoteMediaStreams();
    331   void MaybeCreateDefaultStream();
    332   TrackInfos* GetRemoteTracks(cricket::MediaType type);
    333 
    334   // Returns a map of currently negotiated LocalTrackInfo of type |type|.
    335   TrackInfos* GetLocalTracks(cricket::MediaType type);
    336   bool FindLocalTrack(const std::string& track_id, cricket::MediaType type);
    337 
    338   // Loops through the vector of |streams| and finds added and removed
    339   // StreamParams since last time this method was called.
    340   // For each new or removed StreamParam NotifyLocalTrackAdded or
    341   // NotifyLocalTrackRemoved in invoked.
    342   void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams,
    343                          cricket::MediaType media_type);
    344 
    345   // Triggered when a local track has been seen for the first time in a local
    346   // session description.
    347   // This method triggers MediaStreamSignaling::OnAddLocalAudioTrack or
    348   // MediaStreamSignaling::OnAddLocalVideoTrack if the rtp streams in the local
    349   // SessionDescription can be mapped to a MediaStreamTrack in a MediaStream in
    350   // |local_streams_|
    351   void OnLocalTrackSeen(const std::string& stream_label,
    352                         const std::string& track_id,
    353                         uint32 ssrc,
    354                         cricket::MediaType media_type);
    355 
    356   // Triggered when a local track has been removed from a local session
    357   // description.
    358   // This method triggers MediaStreamSignaling::OnRemoveLocalAudioTrack or
    359   // MediaStreamSignaling::OnRemoveLocalVideoTrack if a stream has been removed
    360   // from the local SessionDescription and the stream can be mapped to a
    361   // MediaStreamTrack in a MediaStream in |local_streams_|.
    362   void OnLocalTrackRemoved(const std::string& stream_label,
    363                            const std::string& track_id,
    364                            cricket::MediaType media_type);
    365 
    366   void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
    367   void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams);
    368   void UpdateClosingDataChannels(
    369       const std::vector<std::string>& active_channels, bool is_local_update);
    370   void CreateRemoteDataChannel(const std::string& label, uint32 remote_ssrc);
    371 
    372   RemotePeerInfo remote_info_;
    373   talk_base::Thread* signaling_thread_;
    374   DataChannelFactory* data_channel_factory_;
    375   cricket::MediaSessionOptions options_;
    376   MediaStreamSignalingObserver* stream_observer_;
    377   talk_base::scoped_refptr<StreamCollection> local_streams_;
    378   talk_base::scoped_refptr<StreamCollection> remote_streams_;
    379   talk_base::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_;
    380 
    381   TrackInfos remote_audio_tracks_;
    382   TrackInfos remote_video_tracks_;
    383   TrackInfos local_audio_tracks_;
    384   TrackInfos local_video_tracks_;
    385 
    386   int last_allocated_sctp_id_;
    387   typedef std::map<std::string, talk_base::scoped_refptr<DataChannel> >
    388       DataChannels;
    389   DataChannels data_channels_;
    390 };
    391 
    392 }  // namespace webrtc
    393 
    394 #endif  // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_
    395