Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Unified Diff: webrtc/media/engine/webrtcvoiceengine.cc

Issue 1765873002: On WVoMC::SetSendParameters(), figure out send codec settings ONCE, not for each send stream. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/media/engine/webrtcvoiceengine.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/media/engine/webrtcvoiceengine.cc
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index c50ff1159c6dcc4ae64d9043fc858a8dadff88d2..4116f42568b3201254cef20d511d8925acf52580 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -380,9 +380,9 @@ class WebRtcVoiceCodecs final {
static const AudioCodec* GetPreferredCodec(
const std::vector<AudioCodec>& codecs,
- webrtc::CodecInst* voe_codec,
+ webrtc::CodecInst* out,
int* red_payload_type) {
- RTC_DCHECK(voe_codec);
+ RTC_DCHECK(out);
RTC_DCHECK(red_payload_type);
// Select the preferred send codec (the first non-telephone-event/CN codec).
for (const AudioCodec& codec : codecs) {
@@ -408,10 +408,12 @@ class WebRtcVoiceCodecs final {
}
// Ignore codecs we don't know about. The negotiation step should prevent
// this, but double-check to be sure.
- if (!ToCodecInst(*found_codec, voe_codec)) {
+ webrtc::CodecInst voe_codec = {0};
+ if (!ToCodecInst(*found_codec, &voe_codec)) {
LOG(LS_WARNING) << "Unknown codec " << ToString(*found_codec);
continue;
}
+ *out = voe_codec;
return found_codec;
}
return nullptr;
@@ -566,7 +568,7 @@ bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
bool WebRtcVoiceEngine::InitInternal() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
- // Temporarily turn logging level up for the Init call
+ // Temporarily turn logging level up for the Init call.
webrtc::Trace::set_level_filter(kElevatedTraceFilter);
LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
if (voe_wrapper_->base()->Init(adm_) == -1) {
@@ -603,7 +605,7 @@ bool WebRtcVoiceEngine::InitInternal() {
}
}
- // Print our codec list again for the call diagnostic log
+ // Print our codec list again for the call diagnostic log.
LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
for (const AudioCodec& codec : codecs_) {
LOG(LS_INFO) << ToString(codec);
@@ -1003,7 +1005,7 @@ void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
else if (level == webrtc::kTraceTerseInfo)
sev = rtc::LS_INFO;
- // Skip past boilerplate prefix text
+ // Skip past boilerplate prefix text.
if (length < 72) {
std::string msg(trace, length);
LOG(LS_ERROR) << "Malformed webrtc log message: ";
@@ -1489,7 +1491,7 @@ bool WebRtcVoiceMediaChannel::SetRecvCodecs(
bool result = true;
for (const AudioCodec& codec : new_codecs) {
- webrtc::CodecInst voe_codec;
+ webrtc::CodecInst voe_codec = {0};
if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
LOG(LS_INFO) << ToString(codec);
voe_codec.pltype = codec.id;
@@ -1517,75 +1519,164 @@ bool WebRtcVoiceMediaChannel::SetRecvCodecs(
return result;
}
+// Utility function called from SetSendParameters() to extract current send
+// codec settings from the given list of codecs (originally from SDP). Both send
+// and receive streams may be reconfigured based on the new settings.
bool WebRtcVoiceMediaChannel::SetSendCodecs(
- int channel, const std::vector<AudioCodec>& codecs) {
- // Disable VAD, FEC, and RED unless we know the other side wants them.
- engine()->voe()->codec()->SetVADStatus(channel, false);
- engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
- engine()->voe()->rtp()->SetREDStatus(channel, false);
- engine()->voe()->codec()->SetFECStatus(channel, false);
+ const std::vector<AudioCodec>& codecs) {
+ RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+ // TODO(solenberg): Validate input - that payload types don't overlap, are
+ // within range, filter out codecs we don't support,
+ // redundant codecs etc.
+
+ // Find the DTMF telephone event "codec" payload type.
+ dtmf_payload_type_ = rtc::Optional<int>();
+ for (const AudioCodec& codec : codecs) {
+ if (IsCodec(codec, kDtmfCodecName)) {
+ dtmf_payload_type_ = rtc::Optional<int>(codec.id);
+ break;
+ }
+ }
// Scan through the list to figure out the codec to use for sending, along
- // with the proper configuration for VAD.
- webrtc::CodecInst send_codec;
- memset(&send_codec, 0, sizeof(send_codec));
-
- bool nack_enabled = nack_enabled_;
- 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)
- const AudioCodec* codec = WebRtcVoiceCodecs::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,
- red_payload_type) == -1) {
- LOG_RTCERR3(SetREDStatus, channel, true, red_payload_type);
- return false;
- }
- } else {
- nack_enabled = HasNack(*codec);
+ // with the proper configuration for VAD, CNG, RED, NACK and Opus-specific
+ // parameters.
+ {
+ SendCodecSpec send_codec_spec;
+ send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled;
+
+ // Find send codec (the first non-telephone-event/CN codec).
+ const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec(
+ codecs, &send_codec_spec.codec_inst, &send_codec_spec.red_payload_type);
+ if (!codec) {
+ LOG(LS_WARNING) << "Received empty list of codecs.";
+ return false;
+ }
+
+ send_codec_spec.transport_cc_enabled = HasTransportCc(*codec);
+
+ // This condition is apparently here because Opus does not support RED and
+ // FEC simultaneously. However, DTX and max playback rate shouldn't have
+ // such limitations.
+ // TODO(solenberg): Refactor this logic once we create AudioEncoders here.
+ if (send_codec_spec.red_payload_type == -1) {
+ send_codec_spec.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,
- &opus_max_playback_rate, &enable_opus_dtx);
+ GetOpusConfig(*codec, &send_codec_spec.codec_inst,
+ &send_codec_spec.enable_codec_fec,
+ &send_codec_spec.opus_max_playback_rate,
+ &send_codec_spec.enable_opus_dtx);
}
// Set packet size if the AudioCodec param kCodecParamPTime is set.
int ptime_ms = 0;
if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
- if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(&send_codec, ptime_ms)) {
+ if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(
+ &send_codec_spec.codec_inst, ptime_ms)) {
LOG(LS_WARNING) << "Failed to set packet size for codec "
- << send_codec.plname;
+ << send_codec_spec.codec_inst.plname;
return false;
}
}
}
+
+ // Loop through the codecs list again to find the CN codec.
+ // TODO(solenberg): Break out into a separate function?
+ 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 = {0};
+ if (!WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
+ LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
+ continue;
+ }
+
+ if (IsCodec(codec, kCnCodecName)) {
+ // Turn voice activity detection/comfort noise on if supported.
+ // Set the wideband CN payload type appropriately.
+ // (narrowband always uses the static payload type 13).
+ int cng_plfreq = -1;
+ switch (codec.clockrate) {
+ case 8000:
+ case 16000:
+ case 32000:
+ cng_plfreq = codec.clockrate;
+ break;
+ default:
+ LOG(LS_WARNING) << "CN frequency " << codec.clockrate
+ << " not supported.";
+ continue;
+ }
+ send_codec_spec.cng_payload_type = codec.id;
+ send_codec_spec.cng_plfreq = cng_plfreq;
+ break;
+ }
+ }
+
+ // Latch in the new state.
+ send_codec_spec_ = std::move(send_codec_spec);
+ }
+
+ // Cache the codecs in order to configure the channel created later.
+ for (const auto& ch : send_streams_) {
+ if (!SetSendCodecs(ch.second->channel())) {
+ return false;
+ }
}
- if (nack_enabled_ != nack_enabled) {
- SetNack(channel, nack_enabled);
- nack_enabled_ = nack_enabled;
+ // Set nack status on receive channels.
+ if (!send_streams_.empty()) {
+ for (const auto& kv : recv_streams_) {
+ SetNack(kv.second->channel(), send_codec_spec_.nack_enabled);
+ }
}
- if (!codec) {
- LOG(LS_WARNING) << "Received empty list of codecs.";
- return false;
+
+ // Check if the transport cc feedback has changed on the preferred send codec,
+ // and in that case reconfigure all receive streams.
+ if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled) {
+ LOG(LS_INFO) << "Recreate all the receive streams because the send "
+ "codec has changed.";
+ recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled;
+ for (auto& kv : recv_streams_) {
+ kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_);
+ }
}
+ return true;
+}
+
+// Apply current codec settings to a single voe::Channel used for sending.
+bool WebRtcVoiceMediaChannel::SetSendCodecs(int channel) {
+ // Disable VAD, FEC, and RED unless we know the other side wants them.
+ engine()->voe()->codec()->SetVADStatus(channel, false);
+ engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
+ engine()->voe()->rtp()->SetREDStatus(channel, false);
+ engine()->voe()->codec()->SetFECStatus(channel, false);
+
+ if (send_codec_spec_.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,
+ send_codec_spec_.red_payload_type) == -1) {
+ LOG_RTCERR3(SetREDStatus, channel, true,
+ send_codec_spec_.red_payload_type);
+ return false;
+ }
+ }
+
+ SetNack(channel, send_codec_spec_.nack_enabled);
+
// Set the codec immediately, since SetVADStatus() depends on whether
// the current codec is mono or stereo.
- if (!SetSendCodec(channel, send_codec))
+ if (!SetSendCodec(channel, send_codec_spec_.codec_inst)) {
return false;
+ }
// FEC should be enabled after SetSendCodec.
- if (enable_codec_fec) {
+ if (send_codec_spec_.enable_codec_fec) {
LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
<< channel;
if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
@@ -1595,61 +1686,47 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
}
}
- if (IsCodec(send_codec, kOpusCodecName)) {
+ if (IsCodec(send_codec_spec_.codec_inst, kOpusCodecName)) {
// DTX and maxplaybackrate should be set after SetSendCodec. Because current
// send codec has to be Opus.
// Set Opus internal DTX.
LOG(LS_INFO) << "Attempt to "
- << (enable_opus_dtx ? "enable" : "disable")
+ << (send_codec_spec_.enable_opus_dtx ? "enable" : "disable")
<< " Opus DTX on channel "
<< channel;
- if (engine()->voe()->codec()->SetOpusDtx(channel, enable_opus_dtx)) {
- LOG_RTCERR2(SetOpusDtx, channel, enable_opus_dtx);
+ if (engine()->voe()->codec()->SetOpusDtx(channel,
+ send_codec_spec_.enable_opus_dtx)) {
+ LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec_.enable_opus_dtx);
return false;
}
// If opus_max_playback_rate <= 0, the default maximum playback rate
// (48 kHz) will be used.
- if (opus_max_playback_rate > 0) {
+ if (send_codec_spec_.opus_max_playback_rate > 0) {
LOG(LS_INFO) << "Attempt to set maximum playback rate to "
- << opus_max_playback_rate
+ << send_codec_spec_.opus_max_playback_rate
<< " Hz on channel "
<< channel;
if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
- channel, opus_max_playback_rate) == -1) {
- LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, opus_max_playback_rate);
+ channel, send_codec_spec_.opus_max_playback_rate) == -1) {
+ LOG_RTCERR2(SetOpusMaxPlaybackRate, channel,
+ send_codec_spec_.opus_max_playback_rate);
return false;
}
}
}
- // Always update the |send_codec_| to the currently set send codec.
- send_codec_.reset(new webrtc::CodecInst(send_codec));
-
if (send_bitrate_setting_) {
SetSendBitrateInternal(send_bitrate_bps_);
}
- // Loop through the codecs list again to config the 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, kCnCodecName)) {
- // Turn voice activity detection/comfort noise on if supported.
- // Set the wideband CN payload type appropriately.
- // (narrowband always uses the static payload type 13).
+ // Set the CN payloadtype and the VAD status.
+ if (send_codec_spec_.cng_payload_type != -1) {
+ // The CN payload type for 8000 Hz clockrate is fixed at 13.
+ if (send_codec_spec_.cng_plfreq != 8000) {
webrtc::PayloadFrequencies cn_freq;
- switch (codec.clockrate) {
- case 8000:
- cn_freq = webrtc::kFreq8000Hz;
- break;
+ switch (send_codec_spec_.cng_plfreq) {
case 16000:
cn_freq = webrtc::kFreq16000Hz;
break;
@@ -1657,90 +1734,37 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
cn_freq = webrtc::kFreq32000Hz;
break;
default:
- LOG(LS_WARNING) << "CN frequency " << codec.clockrate
- << " not supported.";
- continue;
- }
- // Set the CN payloadtype and the VAD status.
- // The CN payload type for 8000 Hz clockrate is fixed at 13.
- if (cn_freq != webrtc::kFreq8000Hz) {
- if (engine()->voe()->codec()->SetSendCNPayloadType(
- channel, codec.id, cn_freq) == -1) {
- LOG_RTCERR3(SetSendCNPayloadType, channel, codec.id, cn_freq);
- // TODO(ajm): This failure condition will be removed from VoE.
- // Restore the return here when we update to a new enough webrtc.
- //
- // Not returning false because the SetSendCNPayloadType will fail if
- // the channel is already sending.
- // This can happen if the remote description is applied twice, for
- // example in the case of ROAP on top of JSEP, where both side will
- // send the offer.
- }
- }
- // Only turn on VAD if we have a CN payload type that matches the
- // clockrate for the codec we are going to use.
- if (codec.clockrate == send_codec.plfreq && send_codec.channels != 2) {
- // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the
- // interaction between VAD and Opus FEC.
- LOG(LS_INFO) << "Enabling VAD";
- if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
- LOG_RTCERR2(SetVADStatus, channel, true);
+ RTC_NOTREACHED();
return false;
- }
+ }
+ if (engine()->voe()->codec()->SetSendCNPayloadType(
+ channel, send_codec_spec_.cng_payload_type, cn_freq) == -1) {
+ LOG_RTCERR3(SetSendCNPayloadType, channel,
+ send_codec_spec_.cng_payload_type, cn_freq);
+ // TODO(ajm): This failure condition will be removed from VoE.
+ // Restore the return here when we update to a new enough webrtc.
+ //
+ // Not returning false because the SetSendCNPayloadType will fail if
+ // the channel is already sending.
+ // This can happen if the remote description is applied twice, for
+ // example in the case of ROAP on top of JSEP, where both side will
+ // send the offer.
}
}
- }
- return true;
-}
-
-bool WebRtcVoiceMediaChannel::SetSendCodecs(
- const std::vector<AudioCodec>& codecs) {
- RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
- // TODO(solenberg): Validate input - that payload types don't overlap, are
- // within range, filter out codecs we don't support,
- // redundant codecs etc.
-
- // Find the DTMF telephone event "codec" payload type.
- dtmf_payload_type_ = rtc::Optional<int>();
- for (const AudioCodec& codec : codecs) {
- if (IsCodec(codec, kDtmfCodecName)) {
- dtmf_payload_type_ = rtc::Optional<int>(codec.id);
- break;
- }
- }
-
- // Cache the codecs in order to configure the channel created later.
- send_codecs_ = codecs;
- for (const auto& ch : send_streams_) {
- if (!SetSendCodecs(ch.second->channel(), codecs)) {
- return false;
- }
- }
- // Set nack status on receive channels and update |nack_enabled_|.
- for (const auto& ch : recv_streams_) {
- 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 = WebRtcVoiceCodecs::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_);
+ // Only turn on VAD if we have a CN payload type that matches the
+ // clockrate for the codec we are going to use.
+ if (send_codec_spec_.cng_plfreq == send_codec_spec_.codec_inst.plfreq &&
+ send_codec_spec_.codec_inst.channels == 1) {
+ // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the
+ // interaction between VAD and Opus FEC.
+ LOG(LS_INFO) << "Enabling VAD";
+ if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
+ LOG_RTCERR2(SetVADStatus, channel, true);
+ return false;
}
}
}
-
return true;
}
@@ -1759,7 +1783,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodec(
LOG(LS_INFO) << "Send channel " << channel << " selected voice codec "
<< ToString(send_codec) << ", bitrate=" << send_codec.rate;
- webrtc::CodecInst current_codec;
+ webrtc::CodecInst current_codec = {0};
if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 &&
(send_codec == current_codec)) {
// Codec is already configured, we can return without setting it again.
@@ -1929,7 +1953,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
// Set the current codecs to be used for the new channel. We need to do this
// after adding the channel to send_channels_, because of how max bitrate is
// currently being configured by SetSendCodec().
- if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) {
+ if (HasSendCodec() && !SetSendCodecs(channel)) {
RemoveSendStream(ssrc);
return false;
}
@@ -2026,7 +2050,7 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
// Only enable those configured for this channel.
for (const auto& codec : recv_codecs_) {
- webrtc::CodecInst voe_codec;
+ webrtc::CodecInst voe_codec = {0};
if (WebRtcVoiceEngine::ToCodecInst(codec, &voe_codec)) {
voe_codec.pltype = codec.id;
if (engine()->voe()->codec()->SetRecPayloadType(
@@ -2047,15 +2071,13 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
<< " is associated with channel #" << send_channel << ".";
}
- 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_)));
+ recv_transport_cc_enabled_,
+ sp.sync_label, recv_rtp_extensions_,
+ call_)));
- SetNack(channel, nack_enabled_);
+ SetNack(channel, send_codec_spec_.nack_enabled);
SetPlayout(channel, playout_);
return true;
@@ -2359,7 +2381,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
send_bitrate_setting_ = true;
send_bitrate_bps_ = bps;
- if (!send_codec_) {
+ if (!HasSendCodec()) {
LOG(LS_INFO) << "The send codec has not been set up yet. "
<< "The send bitrate setting will be applied later.";
return true;
@@ -2371,7 +2393,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
if (bps <= 0)
return true;
- webrtc::CodecInst codec = *send_codec_;
+ webrtc::CodecInst codec = send_codec_spec_.codec_inst;
bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec);
if (is_multi_rate) {
« no previous file with comments | « webrtc/media/engine/webrtcvoiceengine.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698