diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h index 492f136798..ed4142969b 100644 --- a/talk/media/base/mediachannel.h +++ b/talk/media/base/mediachannel.h @@ -138,6 +138,20 @@ static std::string ToStringIfSet(const char* key, const Settable& val) { return str; } +template +static std::string VectorToString(const std::vector& vals) { + std::ostringstream ost; + ost << "["; + for (size_t i = 0; i < vals.size(); ++i) { + if (i > 0) { + ost << ", "; + } + ost << vals[i].ToString(); + } + ost << "]"; + return ost.str(); +} + // Options that can be applied to a VoiceMediaChannel or a VoiceMediaEngine. // Used to be flags, but that makes it hard to selectively apply options. // We are moving all of the setting of options to structs like this, @@ -453,9 +467,6 @@ struct VideoOptions { struct RtpHeaderExtension { RtpHeaderExtension() : id(0) {} RtpHeaderExtension(const std::string& u, int i) : uri(u), id(i) {} - std::string uri; - int id; - // TODO(juberti): SendRecv direction; bool operator==(const RtpHeaderExtension& ext) const { // id is a reserved word in objective-c. Therefore the id attribute has to @@ -463,6 +474,19 @@ struct RtpHeaderExtension { return this->id == ext.id && uri == ext.uri; } + + std::string ToString() const { + std::ostringstream ost; + ost << "{"; + ost << "id: , " << id; + ost << "uri: " << uri; + ost << "}"; + return ost.str(); + } + + std::string uri; + int id; + // TODO(juberti): SendRecv direction; }; // Returns the named header extension if found among all extensions, NULL @@ -985,6 +1009,45 @@ struct DataMediaInfo { std::vector receivers; }; +template +struct RtpParameters { + virtual std::string ToString() { + std::ostringstream ost; + ost << "{"; + ost << "codecs: " << VectorToString(codecs) << ", "; + ost << "extensions: " << VectorToString(extensions); + ost << "}"; + return ost.str(); + } + + std::vector codecs; + std::vector extensions; + // TODO(pthatcher): Add streams. +}; + +template +struct RtpSendParameters : RtpParameters { + std::string ToString() override { + std::ostringstream ost; + ost << "{"; + ost << "codecs: " << VectorToString(this->codecs) << ", "; + ost << "extensions: " << VectorToString(this->extensions) << ", "; + ost << "max_bandiwidth_bps: " << max_bandwidth_bps << ", "; + ost << "options: " << options.ToString(); + ost << "}"; + return ost.str(); + } + + int max_bandwidth_bps = -1; + Options options; +}; + +struct AudioSendParameters : RtpSendParameters { +}; + +struct AudioRecvParameters : RtpParameters { +}; + class VoiceMediaChannel : public MediaChannel { public: enum Error { @@ -1010,6 +1073,22 @@ class VoiceMediaChannel : public MediaChannel { VoiceMediaChannel() {} virtual ~VoiceMediaChannel() {} + // TODO(pthatcher): Remove SetSendCodecs, + // SetSendRtpHeaderExtensions, SetMaxSendBandwidth, and SetOptions + // once all implementations implement SetSendParameters. + virtual bool SetSendParameters(const AudioSendParameters& params) { + return (SetSendCodecs(params.codecs) && + SetSendRtpHeaderExtensions(params.extensions) && + SetMaxSendBandwidth(params.max_bandwidth_bps) && + SetOptions(params.options)); + } + // TODO(pthatcher): Remove SetRecvCodecs and + // SetRecvRtpHeaderExtensions once all implementations implement + // SetRecvParameters. + virtual bool SetRecvParameters(const AudioRecvParameters& params) { + return (SetRecvCodecs(params.codecs) && + SetRecvRtpHeaderExtensions(params.extensions)); + } // Sets the codecs/payload types to be used for incoming media. virtual bool SetRecvCodecs(const std::vector& codecs) = 0; // Sets the codecs/payload types to be used for outgoing media. @@ -1065,6 +1144,12 @@ class VoiceMediaChannel : public MediaChannel { sigslot::signal2 SignalMediaError; }; +struct VideoSendParameters : RtpSendParameters { +}; + +struct VideoRecvParameters : RtpParameters { +}; + class VideoMediaChannel : public MediaChannel { public: enum Error { @@ -1086,6 +1171,22 @@ class VideoMediaChannel : public MediaChannel { virtual ~VideoMediaChannel() {} // Allow video channel to unhook itself from an associated voice channel. virtual void DetachVoiceChannel() = 0; + // TODO(pthatcher): Remove SetSendCodecs, + // SetSendRtpHeaderExtensions, SetMaxSendBandwidth, and SetOptions + // once all implementations implement SetSendParameters. + virtual bool SetSendParameters(const VideoSendParameters& params) { + return (SetSendCodecs(params.codecs) && + SetSendRtpHeaderExtensions(params.extensions) && + SetMaxSendBandwidth(params.max_bandwidth_bps) && + SetOptions(params.options)); + } + // TODO(pthatcher): Remove SetRecvCodecs and + // SetRecvRtpHeaderExtensions once all implementations implement + // SetRecvParameters. + virtual bool SetRecvParameters(const VideoRecvParameters& params) { + return (SetRecvCodecs(params.codecs) && + SetRecvRtpHeaderExtensions(params.extensions)); + } // Sets the codecs/payload types to be used for incoming media. virtual bool SetRecvCodecs(const std::vector& codecs) = 0; // Sets the codecs/payload types to be used for outgoing media. @@ -1189,6 +1290,27 @@ struct SendDataParams { enum SendDataResult { SDR_SUCCESS, SDR_ERROR, SDR_BLOCK }; +struct DataOptions { + std::string ToString() { + return "{}"; + } +}; + +struct DataSendParameters : RtpSendParameters { + std::string ToString() { + std::ostringstream ost; + // Options and extensions aren't used. + ost << "{"; + ost << "codecs: " << VectorToString(codecs) << ", "; + ost << "max_bandiwidth_bps: " << max_bandwidth_bps; + ost << "}"; + return ost.str(); + } +}; + +struct DataRecvParameters : RtpParameters { +}; + class DataMediaChannel : public MediaChannel { public: enum Error { @@ -1203,6 +1325,19 @@ class DataMediaChannel : public MediaChannel { virtual ~DataMediaChannel() {} + // TODO(pthatcher): Remove SetSendCodecs, + // SetSendRtpHeaderExtensions, SetMaxSendBandwidth, and SetOptions + // once all implementations implement SetSendParameters. + virtual bool SetSendParameters(const DataSendParameters& params) { + return (SetSendCodecs(params.codecs) && + SetMaxSendBandwidth(params.max_bandwidth_bps)); + } + // TODO(pthatcher): Remove SetRecvCodecs and + // SetRecvRtpHeaderExtensions once all implementations implement + // SetRecvParameters. + virtual bool SetRecvParameters(const DataRecvParameters& params) { + return SetRecvCodecs(params.codecs); + } virtual bool SetSendCodecs(const std::vector& codecs) = 0; virtual bool SetRecvCodecs(const std::vector& codecs) = 0; diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 3fd5690125..a3f8b8e7ac 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -856,6 +856,22 @@ WebRtcVideoChannel2::FilterSupportedCodecs( return supported_codecs; } +bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) { + // TODO(pbos): Refactor this to only recreate the send streams once + // instead of 4 times. + return (SetSendCodecs(params.codecs) && + SetSendRtpHeaderExtensions(params.extensions) && + SetMaxSendBandwidth(params.max_bandwidth_bps) && + SetOptions(params.options)); +} + +bool WebRtcVideoChannel2::SetRecvParameters(const VideoRecvParameters& params) { + // TODO(pbos): Refactor this to only recreate the recv streams once + // instead of twice. + return (SetRecvCodecs(params.codecs) && + SetRecvRtpHeaderExtensions(params.extensions)); +} + bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector& codecs) { TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvCodecs"); LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs); diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index 2cbebf81d6..9d04526f4b 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -187,6 +187,8 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, // VideoMediaChannel implementation void DetachVoiceChannel() override; + bool SetSendParameters(const VideoSendParameters& params) override; + bool SetRecvParameters(const VideoRecvParameters& params) override; bool SetRecvCodecs(const std::vector& codecs) override; bool SetSendCodecs(const std::vector& codecs) override; bool GetSendCodec(VideoCodec* send_codec) override; diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index 6a448c8311..e288e7040f 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -1743,6 +1743,24 @@ WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { DeleteChannel(voe_channel()); } +bool WebRtcVoiceMediaChannel::SetSendParameters( + const AudioSendParameters& params) { + // TODO(pthatcher): Refactor this to be more clean now that we have + // all the information at once. + return (SetSendCodecs(params.codecs) && + SetSendRtpHeaderExtensions(params.extensions) && + SetMaxSendBandwidth(params.max_bandwidth_bps) && + SetOptions(params.options)); +} + +bool WebRtcVoiceMediaChannel::SetRecvParameters( + const AudioRecvParameters& params) { + // TODO(pthatcher): Refactor this to be more clean now that we have + // all the information at once. + return (SetRecvCodecs(params.codecs) && + SetRecvRtpHeaderExtensions(params.extensions)); +} + bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { LOG(LS_INFO) << "Setting voice channel options: " << options.ToString(); diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h index c28721f899..c8e7980a3e 100644 --- a/talk/media/webrtc/webrtcvoiceengine.h +++ b/talk/media/webrtc/webrtcvoiceengine.h @@ -286,6 +286,8 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel, int voe_channel() const { return voe_channel_; } bool valid() const { return voe_channel_ != -1; } + bool SetSendParameters(const AudioSendParameters& params) override; + bool SetRecvParameters(const AudioRecvParameters& params) override; bool SetOptions(const AudioOptions& options) override; bool GetOptions(AudioOptions* options) const override { *options = options_; diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc index dc7a478510..8de8d37996 100644 --- a/talk/session/media/channel.cc +++ b/talk/session/media/channel.cc @@ -150,6 +150,31 @@ static const MediaContentDescription* GetContentDescription( return static_cast(cinfo->description); } +template +void RtpParametersFromMediaDescription( + const MediaContentDescriptionImpl* desc, + RtpParameters* params) { + // TODO(pthatcher): Remove this once we're sure no one will give us + // a description without codecs (currently a CA_UPDATE with just + // streams can). + if (desc->has_codecs()) { + params->codecs = desc->codecs(); + } + // TODO(pthatcher): See if we really need + // rtp_header_extensions_set() and remove it if we don't. + if (desc->rtp_header_extensions_set()) { + params->extensions = desc->rtp_header_extensions(); + } +} + +template +void RtpSendParametersFromMediaDescription( + const MediaContentDescriptionImpl* desc, + RtpSendParameters* send_params) { + RtpParametersFromMediaDescription(desc, send_params); + send_params->max_bandwidth_bps = desc->bandwidth(); +} + BaseChannel::BaseChannel(rtc::Thread* thread, MediaChannel* media_channel, BaseSession* session, const std::string& content_name, bool rtcp) @@ -897,6 +922,32 @@ void BaseChannel::ChannelNotWritable_w() { ChangeState(); } +bool BaseChannel::SetRtpTransportParameters_w( + const MediaContentDescription* content, + ContentAction action, + ContentSource src, + std::string* error_desc) { + if (action == CA_UPDATE) { + // These parameters never get changed by a CA_UDPATE. + return true; + } + + // Cache secure_required_ for belt and suspenders check on SendPacket + if (src == CS_LOCAL) { + set_secure_required(content->crypto_required() != CT_NONE); + } + + if (!SetSrtp_w(content->cryptos(), action, src, error_desc)) { + return false; + } + + if (!SetRtcpMux_w(content->rtcp_mux(), action, src, error_desc)) { + return false; + } + + return true; +} + // |dtls| will be set to true if DTLS is active for transport channel and // crypto is empty. bool BaseChannel::CheckSrtpConfig(const std::vector& cryptos, @@ -911,42 +962,6 @@ bool BaseChannel::CheckSrtpConfig(const std::vector& cryptos, return true; } -bool BaseChannel::SetRecvRtpHeaderExtensions_w( - const MediaContentDescription* content, - MediaChannel* media_channel, - std::string* error_desc) { - if (content->rtp_header_extensions_set()) { - if (!media_channel->SetRecvRtpHeaderExtensions( - content->rtp_header_extensions())) { - std::ostringstream desc; - desc << "Failed to set receive rtp header extensions for " - << MediaTypeToString(content->type()) << " content."; - SafeSetError(desc.str(), error_desc); - return false; - } - } - return true; -} - -bool BaseChannel::SetSendRtpHeaderExtensions_w( - const MediaContentDescription* content, - MediaChannel* media_channel, - std::string* error_desc) { - if (content->rtp_header_extensions_set()) { - if (!media_channel->SetSendRtpHeaderExtensions( - content->rtp_header_extensions())) { - std::ostringstream desc; - desc << "Failed to set send rtp header extensions for " - << MediaTypeToString(content->type()) << " content."; - SafeSetError(desc.str(), error_desc); - return false; - } else { - MaybeCacheRtpAbsSendTimeHeaderExtension(content->rtp_header_extensions()); - } - } - return true; -} - bool BaseChannel::SetSrtp_w(const std::vector& cryptos, ContentAction action, ContentSource src, @@ -1208,49 +1223,6 @@ bool BaseChannel::UpdateRemoteStreams_w( return ret; } -bool BaseChannel::SetBaseLocalContent_w(const MediaContentDescription* content, - ContentAction action, - std::string* error_desc) { - // Cache secure_required_ for belt and suspenders check on SendPacket - secure_required_ = content->crypto_required() != CT_NONE; - // Set local RTP header extensions. - bool ret = SetRecvRtpHeaderExtensions_w(content, media_channel(), error_desc); - // Set local SRTP parameters (what we will encrypt with). - ret &= SetSrtp_w(content->cryptos(), action, CS_LOCAL, error_desc); - // Set local RTCP mux parameters. - ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_LOCAL, error_desc); - - // Call UpdateLocalStreams_w last to make sure as many settings as possible - // are already set when creating streams. - ret &= UpdateLocalStreams_w(content->streams(), action, error_desc); - set_local_content_direction(content->direction()); - return ret; -} - -bool BaseChannel::SetBaseRemoteContent_w(const MediaContentDescription* content, - ContentAction action, - std::string* error_desc) { - // Set remote RTP header extensions. - bool ret = SetSendRtpHeaderExtensions_w(content, media_channel(), error_desc); - // Set remote SRTP parameters (what the other side will encrypt with). - ret &= SetSrtp_w(content->cryptos(), action, CS_REMOTE, error_desc); - // Set remote RTCP mux parameters. - ret &= SetRtcpMux_w(content->rtcp_mux(), action, CS_REMOTE, error_desc); - if (!media_channel()->SetMaxSendBandwidth(content->bandwidth())) { - std::ostringstream desc; - desc << "Failed to set max send bandwidth for " - << MediaTypeToString(content->type()) << " content."; - SafeSetError(desc.str(), error_desc); - ret = false; - } - - // Call UpdateRemoteStreams_w last to make sure as many settings as possible - // are already set when creating streams. - ret &= UpdateRemoteStreams_w(content->streams(), action, error_desc); - set_remote_content_direction(content->direction()); - return ret; -} - void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension( const std::vector& extensions) { const RtpHeaderExtension* send_time_extension = @@ -1501,28 +1473,34 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, return false; } - bool ret = SetBaseLocalContent_w(content, action, error_desc); - // Set local audio codecs (what we want to receive). - // TODO(whyuan): Change action != CA_UPDATE to !audio->partial() when partial - // is set properly. - if (action != CA_UPDATE || audio->has_codecs()) { - if (!media_channel()->SetRecvCodecs(audio->codecs())) { - SafeSetError("Failed to set audio receive codecs.", error_desc); - ret = false; - } + if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) { + return false; } - // If everything worked, see if we can start receiving. - if (ret) { - std::vector::const_iterator it = audio->codecs().begin(); - for (; it != audio->codecs().end(); ++it) { - bundle_filter()->AddPayloadType(it->id); - } - ChangeState(); - } else { - LOG(LS_WARNING) << "Failed to set local voice description"; + AudioRecvParameters recv_params = last_recv_params_; + RtpParametersFromMediaDescription(audio, &recv_params); + if (!media_channel()->SetRecvParameters(recv_params)) { + SafeSetError("Failed to set local video description recv parameters.", + error_desc); + return false; } - return ret; + for (const AudioCodec& codec : audio->codecs()) { + bundle_filter()->AddPayloadType(codec.id); + } + last_recv_params_ = recv_params; + + // TODO(pthatcher): Move local streams into AudioSendParameters, and + // only give it to the media channel once we have a remote + // description too (without a remote description, we won't be able + // to send them anyway). + if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) { + SafeSetError("Failed to set local audio description streams.", error_desc); + return false; + } + + set_local_content_direction(content->direction()); + ChangeState(); + return true; } bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, @@ -1539,43 +1517,37 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, return false; } - bool ret = true; - // Set remote video codecs (what the other side wants to receive). - if (action != CA_UPDATE || audio->has_codecs()) { - if (!media_channel()->SetSendCodecs(audio->codecs())) { - SafeSetError("Failed to set audio send codecs.", error_desc); - ret = false; - } + if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) { + return false; } - ret &= SetBaseRemoteContent_w(content, action, error_desc); + AudioSendParameters send_params = last_send_params_; + RtpSendParametersFromMediaDescription(audio, &send_params); + if (audio->conference_mode()) { + send_params.options.conference_mode.Set(true); + } + if (audio->agc_minus_10db()) { + send_params.options.adjust_agc_delta.Set(kAgcMinus10db); + } + if (!media_channel()->SetSendParameters(send_params)) { + SafeSetError("Failed to set remote audio description send parameters.", + error_desc); + return false; + } + last_send_params_ = send_params; - if (action != CA_UPDATE) { - // Tweak our audio processing settings, if needed. - AudioOptions audio_options; - if (!media_channel()->GetOptions(&audio_options)) { - LOG(LS_WARNING) << "Can not set audio options from on remote content."; - } else { - if (audio->conference_mode()) { - audio_options.conference_mode.Set(true); - } - if (audio->agc_minus_10db()) { - audio_options.adjust_agc_delta.Set(kAgcMinus10db); - } - if (!media_channel()->SetOptions(audio_options)) { - // Log an error on failure, but don't abort the call. - LOG(LS_ERROR) << "Failed to set voice channel options"; - } - } + // TODO(pthatcher): Move remote streams into AudioRecvParameters, + // and only give it to the media channel once we have a local + // description too (without a local description, we won't be able to + // recv them anyway). + if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) { + SafeSetError("Failed to set remote audio description streams.", error_desc); + return false; } - // If everything worked, see if we can start sending. - if (ret) { - ChangeState(); - } else { - LOG(LS_WARNING) << "Failed to set remote voice description"; - } - return ret; + set_remote_content_direction(content->direction()); + ChangeState(); + return true; } bool VoiceChannel::SetRingbackTone_w(const void* buf, int len) { @@ -1844,35 +1816,34 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, return false; } - bool ret = SetBaseLocalContent_w(content, action, error_desc); - // Set local video codecs (what we want to receive). - if (action != CA_UPDATE || video->has_codecs()) { - if (!media_channel()->SetRecvCodecs(video->codecs())) { - SafeSetError("Failed to set video receive codecs.", error_desc); - ret = false; - } + if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) { + return false; } - if (action != CA_UPDATE) { - VideoOptions video_options; - media_channel()->GetOptions(&video_options); - if (!media_channel()->SetOptions(video_options)) { - // Log an error on failure, but don't abort the call. - LOG(LS_ERROR) << "Failed to set video channel options"; - } + VideoRecvParameters recv_params = last_recv_params_; + RtpParametersFromMediaDescription(video, &recv_params); + if (!media_channel()->SetRecvParameters(recv_params)) { + SafeSetError("Failed to set local video description recv parameters.", + error_desc); + return false; + } + for (const VideoCodec& codec : video->codecs()) { + bundle_filter()->AddPayloadType(codec.id); + } + last_recv_params_ = recv_params; + + // TODO(pthatcher): Move local streams into VideoSendParameters, and + // only give it to the media channel once we have a remote + // description too (without a remote description, we won't be able + // to send them anyway). + if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) { + SafeSetError("Failed to set local video description streams.", error_desc); + return false; } - // If everything worked, see if we can start receiving. - if (ret) { - std::vector::const_iterator it = video->codecs().begin(); - for (; it != video->codecs().end(); ++it) { - bundle_filter()->AddPayloadType(it->id); - } - ChangeState(); - } else { - LOG(LS_WARNING) << "Failed to set local video description"; - } - return ret; + set_local_content_direction(content->direction()); + ChangeState(); + return true; } bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, @@ -1889,38 +1860,39 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, return false; } - bool ret = true; - // Set remote video codecs (what the other side wants to receive). - if (action != CA_UPDATE || video->has_codecs()) { - if (!media_channel()->SetSendCodecs(video->codecs())) { - SafeSetError("Failed to set video send codecs.", error_desc); - ret = false; - } + + if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) { + return false; } - ret &= SetBaseRemoteContent_w(content, action, error_desc); + VideoSendParameters send_params = last_send_params_; + RtpSendParametersFromMediaDescription(video, &send_params); + if (video->conference_mode()) { + send_params.options.conference_mode.Set(true); + } + if (!media_channel()->SetSendParameters(send_params)) { + SafeSetError("Failed to set remote video description send parameters.", + error_desc); + return false; + } + last_send_params_ = send_params; - if (action != CA_UPDATE) { - // Tweak our video processing settings, if needed. - VideoOptions video_options; - media_channel()->GetOptions(&video_options); - if (video->conference_mode()) { - video_options.conference_mode.Set(true); - } - - if (!media_channel()->SetOptions(video_options)) { - // Log an error on failure, but don't abort the call. - LOG(LS_ERROR) << "Failed to set video channel options"; - } + // TODO(pthatcher): Move remote streams into VideoRecvParameters, + // and only give it to the media channel once we have a local + // description too (without a local description, we won't be able to + // recv them anyway). + if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) { + SafeSetError("Failed to set remote video description streams.", error_desc); + return false; } - // If everything worked, see if we can start sending. - if (ret) { - ChangeState(); - } else { - LOG(LS_WARNING) << "Failed to set remote video description"; + if (video->rtp_header_extensions_set()) { + MaybeCacheRtpAbsSendTimeHeaderExtension(video->rtp_header_extensions()); } - return ret; + + set_remote_content_direction(content->direction()); + ChangeState(); + return true; } bool VideoChannel::ApplyViewRequest_w(const ViewRequest& request) { @@ -2224,44 +2196,45 @@ bool DataChannel::SetLocalContent_w(const MediaContentDescription* content, return false; } - bool ret = false; if (!SetDataChannelTypeFromContent(data, error_desc)) { return false; } - if (data_channel_type_ == DCT_SCTP) { - // SCTP data channels don't need the rest of the stuff. - ret = UpdateLocalStreams_w(data->streams(), action, error_desc); - if (ret) { - set_local_content_direction(content->direction()); - // As in SetRemoteContent_w, make sure we set the local SCTP port - // number as specified in our DataContentDescription. - if (!media_channel()->SetRecvCodecs(data->codecs())) { - SafeSetError("Failed to set data receive codecs.", error_desc); - ret = false; - } - } - } else { - ret = SetBaseLocalContent_w(content, action, error_desc); - if (action != CA_UPDATE || data->has_codecs()) { - if (!media_channel()->SetRecvCodecs(data->codecs())) { - SafeSetError("Failed to set data receive codecs.", error_desc); - ret = false; - } + if (data_channel_type_ == DCT_RTP) { + if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) { + return false; } } - // If everything worked, see if we can start receiving. - if (ret) { - std::vector::const_iterator it = data->codecs().begin(); - for (; it != data->codecs().end(); ++it) { - bundle_filter()->AddPayloadType(it->id); - } - ChangeState(); - } else { - LOG(LS_WARNING) << "Failed to set local data description"; + // FYI: We send the SCTP port number (not to be confused with the + // underlying UDP port number) as a codec parameter. So even SCTP + // data channels need codecs. + DataRecvParameters recv_params = last_recv_params_; + RtpParametersFromMediaDescription(data, &recv_params); + if (!media_channel()->SetRecvParameters(recv_params)) { + SafeSetError("Failed to set remote data description recv parameters.", + error_desc); + return false; } - return ret; + if (data_channel_type_ == DCT_RTP) { + for (const DataCodec& codec : data->codecs()) { + bundle_filter()->AddPayloadType(codec.id); + } + } + last_recv_params_ = recv_params; + + // TODO(pthatcher): Move local streams into DataSendParameters, and + // only give it to the media channel once we have a remote + // description too (without a remote description, we won't be able + // to send them anyway). + if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) { + SafeSetError("Failed to set local data description streams.", error_desc); + return false; + } + + set_local_content_direction(content->direction()); + ChangeState(); + return true; } bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content, @@ -2277,62 +2250,45 @@ bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content, return false; } - bool ret = true; + // If the remote data doesn't have codecs and isn't an update, it + // must be empty, so ignore it. + if (!data->has_codecs() && action != CA_UPDATE) { + return true; + } + if (!SetDataChannelTypeFromContent(data, error_desc)) { return false; } - if (data_channel_type_ == DCT_SCTP) { - LOG(LS_INFO) << "Setting SCTP remote data description"; - // SCTP data channels don't need the rest of the stuff. - ret = UpdateRemoteStreams_w(content->streams(), action, error_desc); - if (ret) { - set_remote_content_direction(content->direction()); - // We send the SCTP port number (not to be confused with the underlying - // UDP port number) as a codec parameter. Make sure it gets there. - if (!media_channel()->SetSendCodecs(data->codecs())) { - SafeSetError("Failed to set data send codecs.", error_desc); - ret = false; - } - } - } else { - // If the remote data doesn't have codecs and isn't an update, it - // must be empty, so ignore it. - if (action != CA_UPDATE && !data->has_codecs()) { - return true; - } - LOG(LS_INFO) << "Setting remote data description"; - - // Set remote video codecs (what the other side wants to receive). - if (action != CA_UPDATE || data->has_codecs()) { - if (!media_channel()->SetSendCodecs(data->codecs())) { - SafeSetError("Failed to set data send codecs.", error_desc); - ret = false; - } - } - - if (ret) { - ret &= SetBaseRemoteContent_w(content, action, error_desc); - } - - if (action != CA_UPDATE) { - int bandwidth_bps = data->bandwidth(); - if (!media_channel()->SetMaxSendBandwidth(bandwidth_bps)) { - std::ostringstream desc; - desc << "Failed to set max send bandwidth for data content."; - SafeSetError(desc.str(), error_desc); - ret = false; - } - } + LOG(LS_INFO) << "Setting remote data description"; + if (data_channel_type_ == DCT_RTP && + !SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) { + return false; } - // If everything worked, see if we can start sending. - if (ret) { - ChangeState(); - } else { - LOG(LS_WARNING) << "Failed to set remote data description"; + + DataSendParameters send_params = last_send_params_; + RtpSendParametersFromMediaDescription(data, &send_params); + if (!media_channel()->SetSendParameters(send_params)) { + SafeSetError("Failed to set remote data description send parameters.", + error_desc); + return false; } - return ret; + last_send_params_ = send_params; + + // TODO(pthatcher): Move remote streams into DataRecvParameters, + // and only give it to the media channel once we have a local + // description too (without a local description, we won't be able to + // recv them anyway). + if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) { + SafeSetError("Failed to set remote data description streams.", + error_desc); + return false; + } + + set_remote_content_direction(content->direction()); + ChangeState(); + return true; } void DataChannel::ChangeState() { diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h index 420141c000..5f51c07a28 100644 --- a/talk/session/media/channel.h +++ b/talk/session/media/channel.h @@ -189,6 +189,9 @@ class BaseChannel void set_remote_content_direction(MediaContentDirection direction) { remote_content_direction_ = direction; } + void set_secure_required(bool secure_required) { + secure_required_ = secure_required; + } bool IsReadyToReceive() const; bool IsReadyToSend() const; rtc::Thread* signaling_thread() { return session_->signaling_thread(); } @@ -255,31 +258,22 @@ class BaseChannel bool UpdateRemoteStreams_w(const std::vector& streams, ContentAction action, std::string* error_desc); - bool SetBaseLocalContent_w(const MediaContentDescription* content, - ContentAction action, - std::string* error_desc); virtual bool SetLocalContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) = 0; - bool SetBaseRemoteContent_w(const MediaContentDescription* content, - ContentAction action, - std::string* error_desc); virtual bool SetRemoteContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) = 0; + bool SetRtpTransportParameters_w(const MediaContentDescription* content, + ContentAction action, + ContentSource src, + std::string* error_desc); // Helper method to get RTP Absoulute SendTime extension header id if // present in remote supported extensions list. void MaybeCacheRtpAbsSendTimeHeaderExtension( const std::vector& extensions); - bool SetRecvRtpHeaderExtensions_w(const MediaContentDescription* content, - MediaChannel* media_channel, - std::string* error_desc); - bool SetSendRtpHeaderExtensions_w(const MediaContentDescription* content, - MediaChannel* media_channel, - std::string* error_desc); - bool CheckSrtpConfig(const std::vector& cryptos, bool* dtls, std::string* error_desc); @@ -446,6 +440,13 @@ class VoiceChannel : public BaseChannel { rtc::scoped_ptr media_monitor_; rtc::scoped_ptr audio_monitor_; rtc::scoped_ptr typing_monitor_; + + // Last AudioSendParameters sent down to the media_channel() via + // SetSendParameters. + AudioSendParameters last_send_params_; + // Last AudioRecvParameters sent down to the media_channel() via + // SetRecvParameters. + AudioRecvParameters last_recv_params_; }; // VideoChannel is a specialization for video. @@ -536,6 +537,13 @@ class VideoChannel : public BaseChannel { rtc::scoped_ptr media_monitor_; rtc::WindowEvent previous_we_; + + // Last VideoSendParameters sent down to the media_channel() via + // SetSendParameters. + VideoSendParameters last_send_params_; + // Last VideoRecvParameters sent down to the media_channel() via + // SetRecvParameters. + VideoRecvParameters last_recv_params_; }; // DataChannel is a specialization for data. @@ -654,6 +662,13 @@ class DataChannel : public BaseChannel { // RtpDataChannel instead of using this. DataChannelType data_channel_type_; bool ready_to_send_data_; + + // Last DataSendParameters sent down to the media_channel() via + // SetSendParameters. + DataSendParameters last_send_params_; + // Last DataRecvParameters sent down to the media_channel() via + // SetRecvParameters. + DataRecvParameters last_recv_params_; }; } // namespace cricket