Index: talk/session/media/channel.cc |
diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc |
index dc7a478510ccd0fb1eb482005b715467bf64081f..8de8d379962e2aec5936ce9a2e04d11860c629e1 100644 |
--- a/talk/session/media/channel.cc |
+++ b/talk/session/media/channel.cc |
@@ -150,6 +150,31 @@ static const MediaContentDescription* GetContentDescription( |
return static_cast<const MediaContentDescription*>(cinfo->description); |
} |
+template <class Codec> |
+void RtpParametersFromMediaDescription( |
+ const MediaContentDescriptionImpl<Codec>* desc, |
+ RtpParameters<Codec>* 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 <class Codec, class Options> |
+void RtpSendParametersFromMediaDescription( |
+ const MediaContentDescriptionImpl<Codec>* desc, |
+ RtpSendParameters<Codec, Options>* 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<CryptoParams>& cryptos, |
@@ -911,42 +962,6 @@ bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& 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<CryptoParams>& 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<RtpHeaderExtension>& 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<AudioCodec>::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); |
- |
- 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"; |
- } |
- } |
+ 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 everything worked, see if we can start sending. |
- if (ret) { |
- ChangeState(); |
- } else { |
- LOG(LS_WARNING) << "Failed to set remote voice description"; |
+ // 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; |
} |
- 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; |
- // If everything worked, see if we can start receiving. |
- if (ret) { |
- std::vector<VideoCodec>::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"; |
+ // 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; |
} |
- 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; |
- } |
- } |
- ret &= SetBaseRemoteContent_w(content, action, error_desc); |
+ if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) { |
+ return false; |
+ } |
- 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); |
- } |
+ 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 (!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<DataCodec>::const_iterator it = data->codecs().begin(); |
- for (; it != data->codecs().end(); ++it) { |
- bundle_filter()->AddPayloadType(it->id); |
+ // 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; |
+ } |
+ if (data_channel_type_ == DCT_RTP) { |
+ for (const DataCodec& codec : data->codecs()) { |
+ bundle_filter()->AddPayloadType(codec.id); |
} |
- ChangeState(); |
- } else { |
- LOG(LS_WARNING) << "Failed to set local data description"; |
} |
- return ret; |
+ 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; |
- } |
- } |
+ LOG(LS_INFO) << "Setting remote data description"; |
+ if (data_channel_type_ == DCT_RTP && |
+ !SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) { |
+ return 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; |
- } |
- } |
+ DataSendParameters send_params = last_send_params_; |
+ RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params); |
+ if (!media_channel()->SetSendParameters(send_params)) { |
+ SafeSetError("Failed to set remote data description send parameters.", |
+ error_desc); |
+ return false; |
} |
+ last_send_params_ = send_params; |
- // If everything worked, see if we can start sending. |
- if (ret) { |
- ChangeState(); |
- } else { |
- LOG(LS_WARNING) << "Failed to set remote data description"; |
+ // 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; |
} |
- return ret; |
+ |
+ set_remote_content_direction(content->direction()); |
+ ChangeState(); |
+ return true; |
} |
void DataChannel::ChangeState() { |