On WVoMC::SetSendParameters(), figure out send codec settings ONCE, not for each send stream.

This CL is a first step to moving codec configuration into AudioSendStream.

BUG=webrtc:4690
TBR=ossu@webrtc.org

Review URL: https://codereview.webrtc.org/1765873002

Cr-Commit-Position: refs/heads/master@{#11911}
This commit is contained in:
solenberg 2016-03-08 06:35:16 -08:00 committed by Commit bot
parent 2e43cc9d57
commit 72e29d2cbb
2 changed files with 260 additions and 221 deletions

View File

@ -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,182 +1519,9 @@ bool WebRtcVoiceMediaChannel::SetRecvCodecs(
return result;
}
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);
// 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);
// 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);
}
// 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)) {
LOG(LS_WARNING) << "Failed to set packet size for codec "
<< send_codec.plname;
return false;
}
}
}
}
if (nack_enabled_ != nack_enabled) {
SetNack(channel, nack_enabled);
nack_enabled_ = nack_enabled;
}
if (!codec) {
LOG(LS_WARNING) << "Received empty list of codecs.";
return false;
}
// Set the codec immediately, since SetVADStatus() depends on whether
// the current codec is mono or stereo.
if (!SetSendCodec(channel, send_codec))
return false;
// FEC should be enabled after SetSendCodec.
if (enable_codec_fec) {
LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
<< channel;
if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
// Enable codec internal FEC. Treat any failure as fatal internal error.
LOG_RTCERR2(SetFECStatus, channel, true);
return false;
}
}
if (IsCodec(send_codec, 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")
<< " Opus DTX on channel "
<< channel;
if (engine()->voe()->codec()->SetOpusDtx(channel, enable_opus_dtx)) {
LOG_RTCERR2(SetOpusDtx, channel, 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) {
LOG(LS_INFO) << "Attempt to set maximum playback rate to "
<< 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);
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).
webrtc::PayloadFrequencies cn_freq;
switch (codec.clockrate) {
case 8000:
cn_freq = webrtc::kFreq8000Hz;
break;
case 16000:
cn_freq = webrtc::kFreq16000Hz;
break;
case 32000:
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);
return false;
}
}
}
}
return true;
}
// 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(
const std::vector<AudioCodec>& codecs) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
@ -1709,38 +1538,233 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
}
}
// Scan through the list to figure out the codec to use for sending, along
// 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_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_spec.codec_inst, ptime_ms)) {
LOG(LS_WARNING) << "Failed to set packet size for codec "
<< 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.
send_codecs_ = codecs;
for (const auto& ch : send_streams_) {
if (!SetSendCodecs(ch.second->channel(), codecs)) {
if (!SetSendCodecs(ch.second->channel())) {
return false;
}
}
// Set nack status on receive channels and update |nack_enabled_|.
for (const auto& ch : recv_streams_) {
SetNack(ch.second->channel(), 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);
}
}
// 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_);
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_spec_.codec_inst)) {
return false;
}
// FEC should be enabled after SetSendCodec.
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) {
// Enable codec internal FEC. Treat any failure as fatal internal error.
LOG_RTCERR2(SetFECStatus, channel, true);
return false;
}
}
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 "
<< (send_codec_spec_.enable_opus_dtx ? "enable" : "disable")
<< " Opus DTX on channel "
<< channel;
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 (send_codec_spec_.opus_max_playback_rate > 0) {
LOG(LS_INFO) << "Attempt to set maximum playback rate to "
<< send_codec_spec_.opus_max_playback_rate
<< " Hz on channel "
<< channel;
if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
channel, send_codec_spec_.opus_max_playback_rate) == -1) {
LOG_RTCERR2(SetOpusMaxPlaybackRate, channel,
send_codec_spec_.opus_max_playback_rate);
return false;
}
}
}
if (send_bitrate_setting_) {
SetSendBitrateInternal(send_bitrate_bps_);
}
// 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 (send_codec_spec_.cng_plfreq) {
case 16000:
cn_freq = webrtc::kFreq16000Hz;
break;
case 32000:
cn_freq = webrtc::kFreq32000Hz;
break;
default:
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.
}
}
// 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) {

View File

@ -211,10 +211,13 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
int GetSendChannelId(uint32_t ssrc) const;
private:
bool SetSendCodecs(const std::vector<AudioCodec>& codecs);
bool SetOptions(const AudioOptions& options);
bool SetMaxSendBandwidth(int bps);
bool SetRecvCodecs(const std::vector<AudioCodec>& codecs);
bool SetSendCodecs(const std::vector<AudioCodec>& codecs);
bool SetSendCodecs(int channel);
void SetNack(int channel, bool nack_enabled);
bool SetSendCodec(int channel, const webrtc::CodecInst& send_codec);
bool SetMaxSendBandwidth(int bps);
bool SetLocalRenderer(uint32_t ssrc, AudioRenderer* renderer);
bool MuteStream(uint32_t ssrc, bool mute);
@ -222,8 +225,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
int GetLastEngineError() { return engine()->GetLastEngineError(); }
int GetOutputLevel(int channel);
bool SetPlayout(int channel, bool playout);
void SetNack(int channel, bool nack_enabled);
bool SetSendCodec(int channel, const webrtc::CodecInst& send_codec);
bool ChangePlayout(bool playout);
bool ChangeSend(SendFlags send);
bool ChangeSend(int channel, SendFlags send);
@ -232,22 +233,21 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
bool IsDefaultRecvStream(uint32_t ssrc) {
return default_recv_ssrc_ == static_cast<int64_t>(ssrc);
}
bool SetSendCodecs(int channel, const std::vector<AudioCodec>& codecs);
bool SetSendBitrateInternal(int bps);
bool HasSendCodec() const {
return send_codec_spec_.codec_inst.pltype != -1;
}
rtc::ThreadChecker worker_thread_checker_;
WebRtcVoiceEngine* const engine_ = nullptr;
std::vector<AudioCodec> recv_codecs_;
std::vector<AudioCodec> send_codecs_;
std::unique_ptr<webrtc::CodecInst> send_codec_;
bool send_bitrate_setting_ = false;
int send_bitrate_bps_ = 0;
AudioOptions options_;
rtc::Optional<int> dtmf_payload_type_;
bool desired_playout_ = false;
bool nack_enabled_ = false;
bool transport_cc_enabled_ = false;
bool recv_transport_cc_enabled_ = false;
bool playout_ = false;
SendFlags desired_send_ = SEND_NOTHING;
SendFlags send_ = SEND_NOTHING;
@ -272,6 +272,23 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
std::map<uint32_t, WebRtcAudioReceiveStream*> recv_streams_;
std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
struct SendCodecSpec {
SendCodecSpec() {
webrtc::CodecInst empty_inst = {0};
codec_inst = empty_inst;
codec_inst.pltype = -1;
}
bool nack_enabled = false;
bool transport_cc_enabled = false;
bool enable_codec_fec = false;
bool enable_opus_dtx = false;
int opus_max_playback_rate = 0;
int red_payload_type = -1;
int cng_payload_type = -1;
int cng_plfreq = -1;
webrtc::CodecInst codec_inst;
} send_codec_spec_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel);
};
} // namespace cricket