blob: 87eede6305d26ad1956b74a7f3808e430b1e800b [file] [log] [blame]
/*
* libjingle
* Copyright 2012 Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_
#define TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_
#include <map>
#include <string>
#include <vector>
#include "talk/app/webrtc/datachannel.h"
#include "talk/app/webrtc/mediastream.h"
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/app/webrtc/streamcollection.h"
#include "talk/session/media/mediasession.h"
#include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/base/sigslot.h"
namespace rtc {
class Thread;
} // namespace rtc
namespace webrtc {
class RemoteMediaStreamFactory;
// A MediaStreamSignalingObserver is notified when events happen to
// MediaStreams, MediaStreamTracks or DataChannels associated with the observed
// MediaStreamSignaling object. The notifications identify the stream, track or
// channel.
class MediaStreamSignalingObserver {
public:
// Triggered when the remote SessionDescription has a new stream.
virtual void OnAddRemoteStream(MediaStreamInterface* stream) = 0;
// Triggered when the remote SessionDescription removes a stream.
virtual void OnRemoveRemoteStream(MediaStreamInterface* stream) = 0;
// Triggered when the remote SessionDescription has a new data channel.
virtual void OnAddDataChannel(DataChannelInterface* data_channel) = 0;
// Triggered when the remote SessionDescription has a new audio track.
virtual void OnAddRemoteAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32 ssrc) = 0;
// Triggered when the remote SessionDescription has a new video track.
virtual void OnAddRemoteVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32 ssrc) = 0;
// Triggered when the remote SessionDescription has removed an audio track.
virtual void OnRemoveRemoteAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track) = 0;
// Triggered when the remote SessionDescription has removed a video track.
virtual void OnRemoveRemoteVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track) = 0;
// Triggered when the local SessionDescription has a new audio track.
virtual void OnAddLocalAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32 ssrc) = 0;
// Triggered when the local SessionDescription has a new video track.
virtual void OnAddLocalVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track,
uint32 ssrc) = 0;
// Triggered when the local SessionDescription has removed an audio track.
virtual void OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
AudioTrackInterface* audio_track,
uint32 ssrc) = 0;
// Triggered when the local SessionDescription has removed a video track.
virtual void OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
VideoTrackInterface* video_track) = 0;
// Triggered when RemoveLocalStream is called. |stream| is no longer used
// when negotiating and all tracks in |stream| should stop providing data to
// this PeerConnection. This doesn't mean that the local session description
// has changed and OnRemoveLocalAudioTrack and OnRemoveLocalVideoTrack is not
// called for each individual track.
virtual void OnRemoveLocalStream(MediaStreamInterface* stream) = 0;
protected:
~MediaStreamSignalingObserver() {}
};
// MediaStreamSignaling works as a glue between MediaStreams and a cricket
// classes for SessionDescriptions.
// It is used for creating cricket::MediaSessionOptions given the local
// MediaStreams and data channels.
//
// It is responsible for creating remote MediaStreams given a remote
// SessionDescription and creating cricket::MediaSessionOptions given
// local MediaStreams.
//
// To signal that a DataChannel should be established:
// 1. Call AddDataChannel with the new DataChannel. Next time
// GetMediaSessionOptions will include the description of the DataChannel.
// 2. When a local session description is set, call UpdateLocalStreams with the
// session description. This will set the SSRC used for sending data on
// this DataChannel.
// 3. When remote session description is set, call UpdateRemoteStream with the
// session description. If the DataChannel label and a SSRC is included in
// the description, the DataChannel is updated with SSRC that will be used
// for receiving data.
// 4. When both the local and remote SSRC of a DataChannel is set the state of
// the DataChannel change to kOpen.
//
// To setup a DataChannel initialized by the remote end.
// 1. When remote session description is set, call UpdateRemoteStream with the
// session description. If a label and a SSRC of a new DataChannel is found
// MediaStreamSignalingObserver::OnAddDataChannel with the label and SSRC is
// triggered.
// 2. Create a DataChannel instance with the label and set the remote SSRC.
// 3. Call AddDataChannel with this new DataChannel. GetMediaSessionOptions
// will include the description of the DataChannel.
// 4. Create a local session description and call UpdateLocalStreams. This will
// set the local SSRC used by the DataChannel.
// 5. When both the local and remote SSRC of a DataChannel is set the state of
// the DataChannel change to kOpen.
//
// To close a DataChannel:
// 1. Call DataChannel::Close. This will change the state of the DataChannel to
// kClosing. GetMediaSessionOptions will not
// include the description of the DataChannel.
// 2. When a local session description is set, call UpdateLocalStreams with the
// session description. The description will no longer contain the
// DataChannel label or SSRC.
// 3. When remote session description is set, call UpdateRemoteStream with the
// session description. The description will no longer contain the
// DataChannel label or SSRC. The DataChannel SSRC is updated with SSRC=0.
// The DataChannel change state to kClosed.
class MediaStreamSignaling : public sigslot::has_slots<> {
public:
typedef std::map<std::string, rtc::scoped_refptr<DataChannel> >
RtpDataChannels;
typedef std::vector<rtc::scoped_refptr<DataChannel>> SctpDataChannels;
MediaStreamSignaling(rtc::Thread* signaling_thread,
MediaStreamSignalingObserver* stream_observer,
cricket::ChannelManager* channel_manager);
virtual ~MediaStreamSignaling();
// Notify all referenced objects that MediaStreamSignaling will be teared
// down. This method must be called prior to the dtor.
void TearDown();
// Set a factory for creating data channels that are initiated by the remote
// peer.
void SetDataChannelFactory(DataChannelFactory* data_channel_factory) {
data_channel_factory_ = data_channel_factory;
}
// Checks if |id| is available to be assigned to a new SCTP data channel.
bool IsSctpSidAvailable(int sid) const;
// Gets the first available SCTP id that is not assigned to any existing
// data channels.
bool AllocateSctpSid(rtc::SSLRole role, int* sid);
// Adds |local_stream| to the collection of known MediaStreams that will be
// offered in a SessionDescription.
bool AddLocalStream(MediaStreamInterface* local_stream);
// Removes |local_stream| from the collection of known MediaStreams that will
// be offered in a SessionDescription.
void RemoveLocalStream(MediaStreamInterface* local_stream);
// Checks if any data channel has been added.
bool HasDataChannels() const;
// Adds |data_channel| to the collection of DataChannels that will be
// be offered in a SessionDescription.
bool AddDataChannel(DataChannel* data_channel);
// After we receive an OPEN message, create a data channel and add it.
bool AddDataChannelFromOpenMessage(const cricket::ReceiveDataParams& params,
const rtc::Buffer& payload);
void RemoveSctpDataChannel(int sid);
// Returns a MediaSessionOptions struct with options decided by |options|,
// the local MediaStreams and DataChannels.
virtual bool GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options);
// Returns a MediaSessionOptions struct with options decided by
// |constraints|, the local MediaStreams and DataChannels.
virtual bool GetOptionsForAnswer(
const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* options);
// Called when the remote session description has changed. The purpose is to
// update remote MediaStreams and DataChannels with the current
// session state.
// If the remote SessionDescription contain information about a new remote
// MediaStreams a new remote MediaStream is created and
// MediaStreamSignalingObserver::OnAddStream is called.
// If a remote MediaStream is missing from
// the remote SessionDescription MediaStreamSignalingObserver::OnRemoveStream
// is called.
// If the SessionDescription contains information about a new DataChannel,
// MediaStreamSignalingObserver::OnAddDataChannel is called with the
// DataChannel.
void OnRemoteDescriptionChanged(const SessionDescriptionInterface* desc);
// Called when the local session description has changed. The purpose is to
// update local and remote MediaStreams and DataChannels with the current
// session state.
// If |desc| indicates that the media type should be rejected, the method
// ends the remote MediaStreamTracks.
// It also updates local DataChannels with information about its local SSRC.
void OnLocalDescriptionChanged(const SessionDescriptionInterface* desc);
// Called when the audio channel closes.
void OnAudioChannelClose();
// Called when the video channel closes.
void OnVideoChannelClose();
// Called when the data channel closes.
void OnDataChannelClose();
// Returns all current known local MediaStreams.
StreamCollectionInterface* local_streams() const { return local_streams_;}
// Returns all current remote MediaStreams.
StreamCollectionInterface* remote_streams() const {
return remote_streams_.get();
}
void OnDataTransportCreatedForSctp();
void OnDtlsRoleReadyForSctp(rtc::SSLRole role);
void OnRemoteSctpDataChannelClosed(uint32 sid);
const SctpDataChannels& sctp_data_channels() const {
return sctp_data_channels_;
}
private:
struct RemotePeerInfo {
RemotePeerInfo()
: msid_supported(false),
default_audio_track_needed(false),
default_video_track_needed(false) {
}
// True if it has been discovered that the remote peer support MSID.
bool msid_supported;
// The remote peer indicates in the session description that audio will be
// sent but no MSID is given.
bool default_audio_track_needed;
// The remote peer indicates in the session description that video will be
// sent but no MSID is given.
bool default_video_track_needed;
bool IsDefaultMediaStreamNeeded() {
return !msid_supported && (default_audio_track_needed ||
default_video_track_needed);
}
};
struct TrackInfo {
TrackInfo() : ssrc(0) {}
TrackInfo(const std::string& stream_label,
const std::string track_id,
uint32 ssrc)
: stream_label(stream_label),
track_id(track_id),
ssrc(ssrc) {
}
std::string stream_label;
std::string track_id;
uint32 ssrc;
};
typedef std::vector<TrackInfo> TrackInfos;
// Makes sure a MediaStream Track is created for each StreamParam in
// |streams|. |media_type| is the type of the |streams| and can be either
// audio or video.
// If a new MediaStream is created it is added to |new_streams|.
void UpdateRemoteStreamsList(
const std::vector<cricket::StreamParams>& streams,
cricket::MediaType media_type,
StreamCollection* new_streams);
// Triggered when a remote track has been seen for the first time in a remote
// session description. It creates a remote MediaStreamTrackInterface
// implementation and triggers MediaStreamSignaling::OnAddRemoteAudioTrack or
// MediaStreamSignaling::OnAddRemoteVideoTrack.
void OnRemoteTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32 ssrc,
cricket::MediaType media_type);
// Triggered when a remote track has been removed from a remote session
// description. It removes the remote track with id |track_id| from a remote
// MediaStream and triggers MediaStreamSignaling::OnRemoveRemoteAudioTrack or
// MediaStreamSignaling::OnRemoveRemoteVideoTrack.
void OnRemoteTrackRemoved(const std::string& stream_label,
const std::string& track_id,
cricket::MediaType media_type);
// Set the MediaStreamTrackInterface::TrackState to |kEnded| on all remote
// tracks of type |media_type|.
void RejectRemoteTracks(cricket::MediaType media_type);
// Finds remote MediaStreams without any tracks and removes them from
// |remote_streams_| and notifies the observer that the MediaStream no longer
// exist.
void UpdateEndedRemoteMediaStreams();
void MaybeCreateDefaultStream();
TrackInfos* GetRemoteTracks(cricket::MediaType type);
// Returns a map of currently negotiated LocalTrackInfo of type |type|.
TrackInfos* GetLocalTracks(cricket::MediaType type);
bool FindLocalTrack(const std::string& track_id, cricket::MediaType type);
// Loops through the vector of |streams| and finds added and removed
// StreamParams since last time this method was called.
// For each new or removed StreamParam NotifyLocalTrackAdded or
// NotifyLocalTrackRemoved in invoked.
void UpdateLocalTracks(const std::vector<cricket::StreamParams>& streams,
cricket::MediaType media_type);
// Triggered when a local track has been seen for the first time in a local
// session description.
// This method triggers MediaStreamSignaling::OnAddLocalAudioTrack or
// MediaStreamSignaling::OnAddLocalVideoTrack if the rtp streams in the local
// SessionDescription can be mapped to a MediaStreamTrack in a MediaStream in
// |local_streams_|
void OnLocalTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32 ssrc,
cricket::MediaType media_type);
// Triggered when a local track has been removed from a local session
// description.
// This method triggers MediaStreamSignaling::OnRemoveLocalAudioTrack or
// MediaStreamSignaling::OnRemoveLocalVideoTrack if a stream has been removed
// from the local SessionDescription and the stream can be mapped to a
// MediaStreamTrack in a MediaStream in |local_streams_|.
void OnLocalTrackRemoved(const std::string& stream_label,
const std::string& track_id,
uint32 ssrc,
cricket::MediaType media_type);
void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams);
void UpdateClosingDataChannels(
const std::vector<std::string>& active_channels, bool is_local_update);
void CreateRemoteDataChannel(const std::string& label, uint32 remote_ssrc);
const TrackInfo* FindTrackInfo(const TrackInfos& infos,
const std::string& stream_label,
const std::string track_id) const;
// Returns the index of the specified SCTP DataChannel in sctp_data_channels_,
// or -1 if not found.
int FindDataChannelBySid(int sid) const;
RemotePeerInfo remote_info_;
rtc::Thread* signaling_thread_;
DataChannelFactory* data_channel_factory_;
MediaStreamSignalingObserver* stream_observer_;
rtc::scoped_refptr<StreamCollection> local_streams_;
rtc::scoped_refptr<StreamCollection> remote_streams_;
rtc::scoped_ptr<RemoteMediaStreamFactory> remote_stream_factory_;
TrackInfos remote_audio_tracks_;
TrackInfos remote_video_tracks_;
TrackInfos local_audio_tracks_;
TrackInfos local_video_tracks_;
int last_allocated_sctp_even_sid_;
int last_allocated_sctp_odd_sid_;
RtpDataChannels rtp_data_channels_;
SctpDataChannels sctp_data_channels_;
};
} // namespace webrtc
#endif // TALK_APP_WEBRTC_MEDIASTREAMSIGNALING_H_