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 <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