#include <vector>
#include "talk/app/webrtc/audiotrack.h"
-#include "talk/app/webrtc/mediastreamproxy.h"
#include "talk/app/webrtc/mediaconstraintsinterface.h"
+#include "talk/app/webrtc/mediastreamproxy.h"
#include "talk/app/webrtc/mediastreamtrackproxy.h"
#include "talk/app/webrtc/remoteaudiosource.h"
#include "talk/app/webrtc/remotevideocapturer.h"
#include "talk/app/webrtc/sctputils.h"
#include "talk/app/webrtc/videosource.h"
#include "talk/app/webrtc/videotrack.h"
-#include "talk/base/bytebuffer.h"
-#include "talk/base/stringutils.h"
#include "talk/media/sctp/sctpdataengine.h"
+#include "webrtc/base/bytebuffer.h"
+#include "webrtc/base/stringutils.h"
static const char kDefaultStreamLabel[] = "default";
static const char kDefaultAudioTrackLabel[] = "defaulta0";
namespace webrtc {
-using talk_base::scoped_ptr;
-using talk_base::scoped_refptr;
+using rtc::scoped_ptr;
+using rtc::scoped_refptr;
-static bool ParseConstraints(
+static bool ParseConstraintsForAnswer(
const MediaConstraintsInterface* constraints,
- cricket::MediaSessionOptions* options, bool is_answer) {
+ cricket::MediaSessionOptions* options) {
bool value;
size_t mandatory_constraints_satisfied = 0;
// kOfferToReceiveVideo defaults to false according to spec. But
// if it is an answer and video is offered, we should still accept video
// per default.
- options->has_video |= is_answer;
+ options->has_video = true;
}
if (FindConstraint(constraints,
(options.has_audio || options.has_video || options.has_data());
}
+static bool MediaContentDirectionHasSend(cricket::MediaContentDirection dir) {
+ return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV;
+}
+
+static bool IsValidOfferToReceiveMedia(int value) {
+ typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
+ return (value >= Options::kUndefined) &&
+ (value <= Options::kMaxOfferToReceiveMedia);
+}
+
+// Add the stream and RTP data channel info to |session_options|.
+static void SetStreams(
+ cricket::MediaSessionOptions* session_options,
+ rtc::scoped_refptr<StreamCollection> streams,
+ const MediaStreamSignaling::RtpDataChannels& rtp_data_channels) {
+ session_options->streams.clear();
+ if (streams != NULL) {
+ for (size_t i = 0; i < streams->count(); ++i) {
+ MediaStreamInterface* stream = streams->at(i);
+
+ AudioTrackVector audio_tracks(stream->GetAudioTracks());
+
+ // For each audio track in the stream, add it to the MediaSessionOptions.
+ for (size_t j = 0; j < audio_tracks.size(); ++j) {
+ scoped_refptr<MediaStreamTrackInterface> track(audio_tracks[j]);
+ session_options->AddStream(
+ cricket::MEDIA_TYPE_AUDIO, track->id(), stream->label());
+ }
+
+ VideoTrackVector video_tracks(stream->GetVideoTracks());
+
+ // For each video track in the stream, add it to the MediaSessionOptions.
+ for (size_t j = 0; j < video_tracks.size(); ++j) {
+ scoped_refptr<MediaStreamTrackInterface> track(video_tracks[j]);
+ session_options->AddStream(
+ cricket::MEDIA_TYPE_VIDEO, track->id(), stream->label());
+ }
+ }
+ }
+
+ // Check for data channels.
+ MediaStreamSignaling::RtpDataChannels::const_iterator data_channel_it =
+ rtp_data_channels.begin();
+ for (; data_channel_it != rtp_data_channels.end(); ++data_channel_it) {
+ const DataChannel* channel = data_channel_it->second;
+ if (channel->state() == DataChannel::kConnecting ||
+ channel->state() == DataChannel::kOpen) {
+ // |streamid| and |sync_label| are both set to the DataChannel label
+ // here so they can be signaled the same way as MediaStreams and Tracks.
+ // For MediaStreams, the sync_label is the MediaStream label and the
+ // track label is the same as |streamid|.
+ const std::string& streamid = channel->label();
+ const std::string& sync_label = channel->label();
+ session_options->AddStream(
+ cricket::MEDIA_TYPE_DATA, streamid, sync_label);
+ }
+ }
+}
+
// Factory class for creating remote MediaStreams and MediaStreamTracks.
class RemoteMediaStreamFactory {
public:
- explicit RemoteMediaStreamFactory(talk_base::Thread* signaling_thread,
+ explicit RemoteMediaStreamFactory(rtc::Thread* signaling_thread,
cricket::ChannelManager* channel_manager)
: signaling_thread_(signaling_thread),
channel_manager_(channel_manager) {
}
- talk_base::scoped_refptr<MediaStreamInterface> CreateMediaStream(
+ rtc::scoped_refptr<MediaStreamInterface> CreateMediaStream(
const std::string& stream_label) {
return MediaStreamProxy::Create(
signaling_thread_, MediaStream::Create(stream_label));
template <typename TI, typename T, typename TP, typename S>
TI* AddTrack(MediaStreamInterface* stream, const std::string& track_id,
S* source) {
- talk_base::scoped_refptr<TI> track(
+ rtc::scoped_refptr<TI> track(
TP::Create(signaling_thread_, T::Create(track_id, source)));
track->set_state(webrtc::MediaStreamTrackInterface::kLive);
if (stream->AddTrack(track)) {
return NULL;
}
- talk_base::Thread* signaling_thread_;
+ rtc::Thread* signaling_thread_;
cricket::ChannelManager* channel_manager_;
};
MediaStreamSignaling::MediaStreamSignaling(
- talk_base::Thread* signaling_thread,
+ rtc::Thread* signaling_thread,
MediaStreamSignalingObserver* stream_observer,
cricket::ChannelManager* channel_manager)
: signaling_thread_(signaling_thread),
channel_manager)),
last_allocated_sctp_even_sid_(-2),
last_allocated_sctp_odd_sid_(-1) {
- options_.has_video = false;
- options_.has_audio = false;
}
MediaStreamSignaling::~MediaStreamSignaling() {
// SSL_CLIENT, the allocated id starts from 0 and takes even numbers; otherwise,
// the id starts from 1 and takes odd numbers. Returns false if no id can be
// allocated.
-bool MediaStreamSignaling::AllocateSctpSid(talk_base::SSLRole role, int* sid) {
- int& last_id = (role == talk_base::SSL_CLIENT) ?
+bool MediaStreamSignaling::AllocateSctpSid(rtc::SSLRole role, int* sid) {
+ int& last_id = (role == rtc::SSL_CLIENT) ?
last_allocated_sctp_even_sid_ : last_allocated_sctp_odd_sid_;
do {
bool MediaStreamSignaling::AddDataChannelFromOpenMessage(
const cricket::ReceiveDataParams& params,
- const talk_base::Buffer& payload) {
+ const rtc::Buffer& payload) {
if (!data_channel_factory_) {
LOG(LS_WARNING) << "Remote peer requested a DataChannel but DataChannels "
<< "are not supported.";
LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
return false;
}
- sctp_data_channels_.push_back(channel);
+
stream_observer_->OnAddDataChannel(channel);
return true;
}
void MediaStreamSignaling::RemoveSctpDataChannel(int sid) {
+ ASSERT(sid >= 0);
for (SctpDataChannels::iterator iter = sctp_data_channels_.begin();
iter != sctp_data_channels_.end();
++iter) {
if ((*iter)->id() == sid) {
sctp_data_channels_.erase(iter);
- if (talk_base::IsEven(sid) && sid <= last_allocated_sctp_even_sid_) {
+ if (rtc::IsEven(sid) && sid <= last_allocated_sctp_even_sid_) {
last_allocated_sctp_even_sid_ = sid - 2;
- } else if (talk_base::IsOdd(sid) && sid <= last_allocated_sctp_odd_sid_) {
+ } else if (rtc::IsOdd(sid) && sid <= last_allocated_sctp_odd_sid_) {
last_allocated_sctp_odd_sid_ = sid - 2;
}
return;
}
bool MediaStreamSignaling::GetOptionsForOffer(
- const MediaConstraintsInterface* constraints,
- cricket::MediaSessionOptions* options) {
- UpdateSessionOptions();
- if (!ParseConstraints(constraints, &options_, false)) {
+ const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
+ cricket::MediaSessionOptions* session_options) {
+ typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
+ if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) ||
+ !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) {
return false;
}
- options_.bundle_enabled = EvaluateNeedForBundle(options_);
- *options = options_;
+
+ session_options->has_audio = false;
+ session_options->has_video = false;
+ SetStreams(session_options, local_streams_, rtp_data_channels_);
+
+ // If |offer_to_receive_[audio/video]| is undefined, respect the flags set
+ // from SetStreams. Otherwise, overwrite it based on |rtc_options|.
+ if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
+ session_options->has_audio = rtc_options.offer_to_receive_audio > 0;
+ }
+ if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
+ session_options->has_video = rtc_options.offer_to_receive_video > 0;
+ }
+
+ session_options->vad_enabled = rtc_options.voice_activity_detection;
+ session_options->transport_options.ice_restart = rtc_options.ice_restart;
+ session_options->bundle_enabled = rtc_options.use_rtp_mux;
+
+ session_options->bundle_enabled = EvaluateNeedForBundle(*session_options);
return true;
}
bool MediaStreamSignaling::GetOptionsForAnswer(
const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* options) {
- UpdateSessionOptions();
+ options->has_audio = false;
+ options->has_video = false;
+ SetStreams(options, local_streams_, rtp_data_channels_);
- // Copy the |options_| to not let the flag MediaSessionOptions::has_audio and
- // MediaSessionOptions::has_video affect subsequent offers.
- cricket::MediaSessionOptions current_options = options_;
- if (!ParseConstraints(constraints, ¤t_options, true)) {
+ if (!ParseConstraintsForAnswer(constraints, options)) {
return false;
}
- current_options.bundle_enabled = EvaluateNeedForBundle(current_options);
- *options = current_options;
+ options->bundle_enabled = EvaluateNeedForBundle(*options);
return true;
}
void MediaStreamSignaling::OnRemoteDescriptionChanged(
const SessionDescriptionInterface* desc) {
const cricket::SessionDescription* remote_desc = desc->description();
- talk_base::scoped_refptr<StreamCollection> new_streams(
+ rtc::scoped_refptr<StreamCollection> new_streams(
StreamCollection::Create());
// Find all audio rtp streams and create corresponding remote AudioTracks
audio_content->description);
UpdateRemoteStreamsList(desc->streams(), desc->type(), new_streams);
remote_info_.default_audio_track_needed =
- desc->direction() == cricket::MD_SENDRECV && desc->streams().empty();
+ MediaContentDirectionHasSend(desc->direction()) &&
+ desc->streams().empty();
}
// Find all video rtp streams and create corresponding remote VideoTracks
video_content->description);
UpdateRemoteStreamsList(desc->streams(), desc->type(), new_streams);
remote_info_.default_video_track_needed =
- desc->direction() == cricket::MD_SENDRECV && desc->streams().empty();
+ MediaContentDirectionHasSend(desc->direction()) &&
+ desc->streams().empty();
}
// Update the DataChannels with the information from the remote peer.
const cricket::DataContentDescription* data_desc =
static_cast<const cricket::DataContentDescription*>(
data_content->description);
- if (talk_base::starts_with(
+ if (rtc::starts_with(
data_desc->protocol().data(), cricket::kMediaProtocolRtpPrefix)) {
UpdateRemoteRtpDataChannels(data_desc->streams());
}
const cricket::DataContentDescription* data_desc =
static_cast<const cricket::DataContentDescription*>(
data_content->description);
- if (talk_base::starts_with(
+ if (rtc::starts_with(
data_desc->protocol().data(), cricket::kMediaProtocolRtpPrefix)) {
UpdateLocalRtpDataChannels(data_desc->streams());
}
}
}
-void MediaStreamSignaling::UpdateSessionOptions() {
- options_.streams.clear();
- if (local_streams_ != NULL) {
- for (size_t i = 0; i < local_streams_->count(); ++i) {
- MediaStreamInterface* stream = local_streams_->at(i);
-
- AudioTrackVector audio_tracks(stream->GetAudioTracks());
- if (!audio_tracks.empty()) {
- options_.has_audio = true;
- }
-
- // For each audio track in the stream, add it to the MediaSessionOptions.
- for (size_t j = 0; j < audio_tracks.size(); ++j) {
- scoped_refptr<MediaStreamTrackInterface> track(audio_tracks[j]);
- options_.AddStream(cricket::MEDIA_TYPE_AUDIO, track->id(),
- stream->label());
- }
-
- VideoTrackVector video_tracks(stream->GetVideoTracks());
- if (!video_tracks.empty()) {
- options_.has_video = true;
- }
- // For each video track in the stream, add it to the MediaSessionOptions.
- for (size_t j = 0; j < video_tracks.size(); ++j) {
- scoped_refptr<MediaStreamTrackInterface> track(video_tracks[j]);
- options_.AddStream(cricket::MEDIA_TYPE_VIDEO, track->id(),
- stream->label());
- }
- }
- }
-
- // Check for data channels.
- RtpDataChannels::const_iterator data_channel_it = rtp_data_channels_.begin();
- for (; data_channel_it != rtp_data_channels_.end(); ++data_channel_it) {
- const DataChannel* channel = data_channel_it->second;
- if (channel->state() == DataChannel::kConnecting ||
- channel->state() == DataChannel::kOpen) {
- // |streamid| and |sync_label| are both set to the DataChannel label
- // here so they can be signaled the same way as MediaStreams and Tracks.
- // For MediaStreams, the sync_label is the MediaStream label and the
- // track label is the same as |streamid|.
- const std::string& streamid = channel->label();
- const std::string& sync_label = channel->label();
- options_.AddStream(cricket::MEDIA_TYPE_DATA, streamid, sync_label);
- }
- }
-}
-
void MediaStreamSignaling::UpdateRemoteStreamsList(
const cricket::StreamParamsVec& streams,
cricket::MediaType media_type,
const std::string& track_id = it->id;
uint32 ssrc = it->first_ssrc();
- talk_base::scoped_refptr<MediaStreamInterface> stream =
+ rtc::scoped_refptr<MediaStreamInterface> stream =
remote_streams_->find(stream_label);
if (!stream) {
// This is a new MediaStream. Create a new remote MediaStream.
MediaStreamInterface* stream = remote_streams_->find(stream_label);
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
- talk_base::scoped_refptr<AudioTrackInterface> audio_track =
+ rtc::scoped_refptr<AudioTrackInterface> audio_track =
stream->FindAudioTrack(track_id);
if (audio_track) {
audio_track->set_state(webrtc::MediaStreamTrackInterface::kEnded);
stream_observer_->OnRemoveRemoteAudioTrack(stream, audio_track);
}
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
- talk_base::scoped_refptr<VideoTrackInterface> video_track =
+ rtc::scoped_refptr<VideoTrackInterface> video_track =
stream->FindVideoTrack(track_id);
if (video_track) {
video_track->set_state(webrtc::MediaStreamTrackInterface::kEnded);
// The data channel label is either the mslabel or the SSRC if the mslabel
// does not exist. Ex a=ssrc:444330170 mslabel:test1.
std::string label = it->sync_label.empty() ?
- talk_base::ToString(it->first_ssrc()) : it->sync_label;
+ rtc::ToString(it->first_ssrc()) : it->sync_label;
RtpDataChannels::iterator data_channel_it =
rtp_data_channels_.find(label);
if (data_channel_it == rtp_data_channels_.end()) {
}
}
-void MediaStreamSignaling::OnDtlsRoleReadyForSctp(talk_base::SSLRole role) {
+void MediaStreamSignaling::OnDtlsRoleReadyForSctp(rtc::SSLRole role) {
SctpDataChannels::iterator it = sctp_data_channels_.begin();
for (; it != sctp_data_channels_.end(); ++it) {
if ((*it)->id() < 0) {