Index: talk/media/webrtc/webrtcvoiceengine.cc |
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc |
index c4f5f99c989b23c00e4866ee1f933a39fb007145..0b7b07fef5dac17e4750ec2646739a1370f23042 100644 |
--- a/talk/media/webrtc/webrtcvoiceengine.cc |
+++ b/talk/media/webrtc/webrtcvoiceengine.cc |
@@ -204,11 +204,6 @@ bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) { |
return it == payload_types.end(); |
} |
-bool IsNackEnabled(const AudioCodec& codec) { |
- return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack, |
- kParamValueEmpty)); |
-} |
- |
// Return true if codec.params[feature] == "1", false otherwise. |
bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) { |
int value; |
@@ -331,6 +326,8 @@ class WebRtcVoiceCodecs final { |
rtc::ToString(kPreferredMaxPTime); |
} |
codec.SetParam(kCodecParamUseInbandFec, 1); |
+ codec.AddFeedbackParam( |
+ FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); |
// TODO(hellner): Add ptime, sprop-stereo, and stereo |
// when they can be set to values other than the default. |
@@ -943,6 +940,12 @@ RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const { |
capabilities.header_extensions.push_back( |
RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, |
kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); |
+ if (webrtc::field_trial::FindFullName("WebRTC-Audio-SendSideBwe") == |
+ "Enabled") { |
+ capabilities.header_extensions.push_back(RtpHeaderExtension( |
+ kRtpTransportSequenceNumberHeaderExtension, |
+ kRtpTransportSequenceNumberHeaderExtensionDefaultId)); |
+ } |
return capabilities; |
} |
@@ -1218,19 +1221,21 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream |
class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
public: |
- WebRtcAudioReceiveStream(int ch, uint32_t remote_ssrc, uint32_t local_ssrc, |
- bool use_combined_bwe, const std::string& sync_group, |
+ WebRtcAudioReceiveStream(int ch, |
+ uint32_t remote_ssrc, |
+ uint32_t local_ssrc, |
+ bool use_transport_cc, |
+ const std::string& sync_group, |
const std::vector<webrtc::RtpExtension>& extensions, |
webrtc::Call* call) |
- : call_(call), |
- config_() { |
+ : call_(call), config_() { |
RTC_DCHECK_GE(ch, 0); |
RTC_DCHECK(call); |
config_.rtp.remote_ssrc = remote_ssrc; |
config_.rtp.local_ssrc = local_ssrc; |
config_.voe_channel_id = ch; |
config_.sync_group = sync_group; |
- RecreateAudioReceiveStream(use_combined_bwe, extensions); |
+ RecreateAudioReceiveStream(use_transport_cc, extensions); |
} |
~WebRtcAudioReceiveStream() { |
@@ -1238,14 +1243,19 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
call_->DestroyAudioReceiveStream(stream_); |
} |
+ void RecreateAudioReceiveStream() { |
the sun
2016/01/21 13:26:24
Why do we need to recreate the stream if no config
stefan-webrtc
2016/01/21 15:09:09
I don't really know, but apparently tests are brea
the sun
2016/01/22 10:45:16
Then there is something with how the stream is bei
stefan-webrtc
2016/01/23 16:52:14
You are right, and the problem is that the tests a
|
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
+ RecreateAudioReceiveStream(config_.rtp.transport_cc, |
+ config_.rtp.extensions); |
+ } |
void RecreateAudioReceiveStream( |
const std::vector<webrtc::RtpExtension>& extensions) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
- RecreateAudioReceiveStream(config_.combined_audio_video_bwe, extensions); |
+ RecreateAudioReceiveStream(config_.rtp.transport_cc, extensions); |
} |
- void RecreateAudioReceiveStream(bool use_combined_bwe) { |
+ void RecreateAudioReceiveStream(bool use_transport_cc) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
- RecreateAudioReceiveStream(use_combined_bwe, config_.rtp.extensions); |
+ RecreateAudioReceiveStream(use_transport_cc, config_.rtp.extensions); |
} |
webrtc::AudioReceiveStream::Stats GetStats() const { |
@@ -1265,7 +1275,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
} |
private: |
- void RecreateAudioReceiveStream(bool use_combined_bwe, |
+ void RecreateAudioReceiveStream( |
+ bool use_transport_cc, |
const std::vector<webrtc::RtpExtension>& extensions) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
if (stream_) { |
@@ -1273,7 +1284,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { |
stream_ = nullptr; |
} |
config_.rtp.extensions = extensions; |
- config_.combined_audio_video_bwe = use_combined_bwe; |
+ config_.rtp.transport_cc = use_transport_cc; |
RTC_DCHECK(!stream_); |
stream_ = call_->CreateAudioReceiveStream(config_); |
RTC_CHECK(stream_); |
@@ -1369,7 +1380,6 @@ bool WebRtcVoiceMediaChannel::SetRecvParameters( |
it.second->RecreateAudioReceiveStream(recv_rtp_extensions_); |
} |
} |
- |
return true; |
} |
@@ -1403,8 +1413,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { |
// TODO(solenberg): Don't recreate unless options changed. |
for (auto& it : recv_streams_) { |
- it.second->RecreateAudioReceiveStream( |
- options_.combined_audio_video_bwe.value_or(false)); |
+ it.second->RecreateAudioReceiveStream(); |
the sun
2016/01/21 13:26:24
Not needed anymore. At least not in the current fo
stefan-webrtc
2016/01/21 15:09:09
See above
|
} |
LOG(LS_INFO) << "Set voice channel options. Current options: " |
@@ -1491,7 +1500,6 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( |
// Scan through the list to figure out the codec to use for sending, along |
// with the proper configuration for VAD. |
- bool found_send_codec = false; |
webrtc::CodecInst send_codec; |
memset(&send_codec, 0, sizeof(send_codec)); |
@@ -1499,53 +1507,33 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( |
bool enable_codec_fec = false; |
bool enable_opus_dtx = false; |
int opus_max_playback_rate = 0; |
+ int red_payload_type = -1; |
// Set send codec (the first non-telephone-event/CN codec) |
- for (const AudioCodec& codec : codecs) { |
- // Ignore codecs we don't know about. The negotiation step should prevent |
- // this, but double-check to be sure. |
- webrtc::CodecInst voe_codec; |
- if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) { |
- LOG(LS_WARNING) << "Unknown codec " << ToString(codec); |
- continue; |
- } |
- |
- if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { |
- // Skip telephone-event/CN codec, which will be handled later. |
- continue; |
- } |
- |
- // We'll use the first codec in the list to actually send audio data. |
- // Be sure to use the payload type requested by the remote side. |
- // "red", for RED audio, is a special case where the actual codec to be |
- // used is specified in params. |
- if (IsCodec(codec, kRedCodecName)) { |
- // Parse out the RED parameters. If we fail, just ignore RED; |
- // we don't support all possible params/usage scenarios. |
- if (!GetRedSendCodec(codec, codecs, &send_codec)) { |
- continue; |
- } |
- |
+ const AudioCodec* codec = |
+ GetPreferredCodec(codecs, &send_codec, &red_payload_type); |
+ if (codec) { |
+ if (red_payload_type != -1) { |
// Enable redundant encoding of the specified codec. Treat any |
// failure as a fatal internal error. |
LOG(LS_INFO) << "Enabling RED on channel " << channel; |
- if (engine()->voe()->rtp()->SetREDStatus(channel, true, codec.id) == -1) { |
- LOG_RTCERR3(SetREDStatus, channel, true, codec.id); |
+ if (engine()->voe()->rtp()->SetREDStatus(channel, true, |
+ red_payload_type) == -1) { |
+ LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type); |
return false; |
} |
} else { |
- send_codec = voe_codec; |
- nack_enabled = IsNackEnabled(codec); |
+ nack_enabled = HasNack(*codec); |
// For Opus as the send codec, we are to determine inband FEC, maximum |
// playback rate, and opus internal dtx. |
- if (IsCodec(codec, kOpusCodecName)) { |
- GetOpusConfig(codec, &send_codec, &enable_codec_fec, |
+ if (IsCodec(*codec, kOpusCodecName)) { |
+ GetOpusConfig(*codec, &send_codec, &enable_codec_fec, |
&opus_max_playback_rate, &enable_opus_dtx); |
} |
// Set packet size if the AudioCodec param kCodecParamPTime is set. |
int ptime_ms = 0; |
- if (codec.GetParam(kCodecParamPTime, &ptime_ms)) { |
+ if (codec->GetParam(kCodecParamPTime, &ptime_ms)) { |
if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) { |
LOG(LS_WARNING) << "Failed to set packet size for codec " |
<< send_codec.plname; |
@@ -1553,16 +1541,13 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( |
} |
} |
} |
- found_send_codec = true; |
- break; |
} |
if (nack_enabled_ != nack_enabled) { |
SetNack(channel, nack_enabled); |
nack_enabled_ = nack_enabled; |
} |
- |
- if (!found_send_codec) { |
+ if (!codec) { |
LOG(LS_WARNING) << "Received empty list of codecs."; |
return false; |
} |
@@ -1681,6 +1666,43 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( |
return true; |
} |
+const AudioCodec* WebRtcVoiceMediaChannel::GetPreferredCodec( |
the sun
2016/01/21 13:26:24
IIUC this function and GetRedSendCodec() do not us
stefan-webrtc
2016/01/21 15:09:09
Done.
|
+ const std::vector<AudioCodec>& codecs, |
+ webrtc::CodecInst* voe_codec, |
+ int* red_payload_type) const { |
+ // Set send codec (the first non-telephone-event/CN codec) |
+ for (const AudioCodec& codec : codecs) { |
+ *red_payload_type = -1; |
+ if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) { |
+ // Skip telephone-event/CN codec, which will be handled later. |
+ continue; |
+ } |
+ |
+ // We'll use the first codec in the list to actually send audio data. |
+ // Be sure to use the payload type requested by the remote side. |
+ // "red", for RED audio, is a special case where the actual codec to be |
+ // used is specified in params. |
+ const AudioCodec* found_codec = &codec; |
+ if (IsCodec(*found_codec, kRedCodecName)) { |
+ // Parse out the RED parameters. If we fail, just ignore RED; |
+ // we don't support all possible params/usage scenarios. |
+ *red_payload_type = codec.id; |
+ found_codec = GetRedSendCodec(*found_codec, codecs); |
+ if (!found_codec) { |
+ continue; |
+ } |
+ } |
+ // Ignore codecs we don't know about. The negotiation step should prevent |
+ // this, but double-check to be sure. |
+ if (!WebRtcVoiceEngine::ToCodecInst(*found_codec, voe_codec)) { |
+ LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec); |
+ continue; |
+ } |
+ return found_codec; |
+ } |
+ return nullptr; |
+} |
+ |
bool WebRtcVoiceMediaChannel::SetSendCodecs( |
const std::vector<AudioCodec>& codecs) { |
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
@@ -1710,6 +1732,25 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( |
SetNack(ch.second->channel(), nack_enabled_); |
} |
+ // Check if the transport cc feedback has changed on the preferred send codec, |
+ // and in that case reconfigure all receive streams. |
+ webrtc::CodecInst voe_codec; |
+ int red_payload_type; |
+ const AudioCodec* send_codec = |
+ GetPreferredCodec(send_codecs_, &voe_codec, &red_payload_type); |
+ if (send_codec) { |
+ bool transport_cc = HasTransportCc(*send_codec); |
+ if (transport_cc_enabled_ != transport_cc) { |
+ LOG(LS_INFO) << "Recreate all the receive streams because the send " |
+ "codec has changed."; |
+ transport_cc_enabled_ = transport_cc; |
+ for (auto& kv : recv_streams_) { |
+ RTC_DCHECK(kv.second != nullptr); |
+ kv.second->RecreateAudioReceiveStream(transport_cc_enabled_); |
+ } |
+ } |
+ } |
+ |
return true; |
} |
@@ -2016,10 +2057,13 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
<< " is associated with channel #" << send_channel << "."; |
} |
- recv_streams_.insert(std::make_pair(ssrc, new WebRtcAudioReceiveStream( |
- channel, ssrc, receiver_reports_ssrc_, |
- options_.combined_audio_video_bwe.value_or(false), sp.sync_label, |
- recv_rtp_extensions_, call_))); |
+ transport_cc_enabled_ = |
+ !send_codecs_.empty() ? HasTransportCc(send_codecs_[0]) : false; |
+ |
+ recv_streams_.insert(std::make_pair( |
+ ssrc, new WebRtcAudioReceiveStream(channel, ssrc, receiver_reports_ssrc_, |
+ transport_cc_enabled_, sp.sync_label, |
+ recv_rtp_extensions_, call_))); |
SetNack(channel, nack_enabled_); |
SetPlayout(channel, playout_); |
@@ -2477,8 +2521,9 @@ int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { |
return -1; |
} |
-bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, |
- const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { |
+const AudioCodec* WebRtcVoiceMediaChannel::GetRedSendCodec( |
+ const AudioCodec& red_codec, |
+ const std::vector<AudioCodec>& all_codecs) const { |
// Get the RED encodings from the parameter with no name. This may |
// change based on what is discussed on the Jingle list. |
// The encoding parameter is of the form "a/b"; we only support where |
@@ -2496,7 +2541,7 @@ bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, |
red_pts[0] != red_pts[1] || |
!rtc::FromString(red_pts[0], &red_pt)) { |
LOG(LS_WARNING) << "RED params " << red_params << " not supported."; |
- return false; |
+ return nullptr; |
} |
} else if (red_codec.params.empty()) { |
LOG(LS_WARNING) << "RED params not present, using defaults"; |
@@ -2508,17 +2553,11 @@ bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, |
// Try to find red_pt in |codecs|. |
for (const AudioCodec& codec : all_codecs) { |
if (codec.id == red_pt) { |
- // If we find the right codec, that will be the codec we pass to |
- // SetSendCodec, with the desired payload type. |
- if (WebRtcVoiceEngine::ToCodecInst(codec, send_codec)) { |
- return true; |
- } else { |
- break; |
- } |
+ return &codec; |
} |
} |
LOG(LS_WARNING) << "RED params " << red_params << " are invalid."; |
- return false; |
+ return nullptr; |
} |
bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { |