Adding "usedtx" as Opus codec parameter.
This is according to https://tools.ietf.org/html/draft-spittka-payload-rtp-opus-03 Specifically, usedtx: specifies if the decoder prefers the use of DTX. values are 1 and 0. If no value is specified, usedtx is assumed to be 0. BUG=1014 R=juberti@webrtc.org, tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/48499004 Cr-Commit-Position: refs/heads/master@{#8872}
This commit is contained in:
parent
bef8d2d020
commit
7100dcd317
@ -69,6 +69,7 @@ using cricket::kCodecParamSPropStereo;
|
||||
using cricket::kCodecParamStartBitrate;
|
||||
using cricket::kCodecParamStereo;
|
||||
using cricket::kCodecParamUseInbandFec;
|
||||
using cricket::kCodecParamUseDtx;
|
||||
using cricket::kCodecParamSctpProtocol;
|
||||
using cricket::kCodecParamSctpStreams;
|
||||
using cricket::kCodecParamMaxAverageBitrate;
|
||||
@ -1560,9 +1561,9 @@ void WriteFmtpParameters(const cricket::CodecParameterMap& parameters,
|
||||
bool IsFmtpParam(const std::string& name) {
|
||||
const char* kFmtpParams[] = {
|
||||
kCodecParamMinPTime, kCodecParamSPropStereo,
|
||||
kCodecParamStereo, kCodecParamUseInbandFec, kCodecParamStartBitrate,
|
||||
kCodecParamMaxBitrate, kCodecParamMinBitrate, kCodecParamMaxQuantization,
|
||||
kCodecParamSctpProtocol, kCodecParamSctpStreams,
|
||||
kCodecParamStereo, kCodecParamUseInbandFec, kCodecParamUseDtx,
|
||||
kCodecParamStartBitrate, kCodecParamMaxBitrate, kCodecParamMinBitrate,
|
||||
kCodecParamMaxQuantization, kCodecParamSctpProtocol, kCodecParamSctpStreams,
|
||||
kCodecParamMaxAverageBitrate, kCodecParamMaxPlaybackRate,
|
||||
kCodecParamAssociatedPayloadType
|
||||
};
|
||||
|
@ -62,6 +62,7 @@ const char kCodecParamMinPTime[] = "minptime";
|
||||
const char kCodecParamSPropStereo[] = "sprop-stereo";
|
||||
const char kCodecParamStereo[] = "stereo";
|
||||
const char kCodecParamUseInbandFec[] = "useinbandfec";
|
||||
const char kCodecParamUseDtx[] = "usedtx";
|
||||
const char kCodecParamMaxAverageBitrate[] = "maxaveragebitrate";
|
||||
const char kCodecParamMaxPlaybackRate[] = "maxplaybackrate";
|
||||
|
||||
@ -77,6 +78,7 @@ const int kOpusDefaultMinPTime = 3;
|
||||
const int kOpusDefaultSPropStereo = 0;
|
||||
const int kOpusDefaultStereo = 0;
|
||||
const int kOpusDefaultUseInbandFec = 0;
|
||||
const int kOpusDefaultUseDtx = 0;
|
||||
const int kOpusDefaultMaxPlaybackRate = 48000;
|
||||
|
||||
const int kPreferredMaxPTime = 60;
|
||||
|
@ -68,6 +68,7 @@ extern const char kCodecParamMinPTime[];
|
||||
extern const char kCodecParamSPropStereo[];
|
||||
extern const char kCodecParamStereo[];
|
||||
extern const char kCodecParamUseInbandFec[];
|
||||
extern const char kCodecParamUseDtx[];
|
||||
extern const char kCodecParamMaxAverageBitrate[];
|
||||
extern const char kCodecParamMaxPlaybackRate[];
|
||||
extern const char kCodecParamSctpProtocol[];
|
||||
@ -87,6 +88,7 @@ extern const int kOpusDefaultMinPTime;
|
||||
extern const int kOpusDefaultSPropStereo;
|
||||
extern const int kOpusDefaultStereo;
|
||||
extern const int kOpusDefaultUseInbandFec;
|
||||
extern const int kOpusDefaultUseDtx;
|
||||
extern const int kOpusDefaultMaxPlaybackRate;
|
||||
|
||||
// Prefered values in this code base. Note that they may differ from the default
|
||||
|
@ -314,6 +314,9 @@ class FakeWebRtcVoiceEngine
|
||||
bool GetVAD(int channel) {
|
||||
return channels_[channel]->vad;
|
||||
}
|
||||
bool GetOpusDtx(int channel) {
|
||||
return channels_[channel]->opus_dtx;
|
||||
}
|
||||
bool GetRED(int channel) {
|
||||
return channels_[channel]->red;
|
||||
}
|
||||
|
@ -79,7 +79,6 @@ static const CodecPref kCodecPrefs[] = {
|
||||
{ kIlbcCodecName, 8000, 1, 102, false, { 20, 30, 40, 60 } },
|
||||
{ kPcmuCodecName, 8000, 1, 0, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kPcmaCodecName, 8000, 1, 8, false, { 10, 20, 30, 40, 50, 60 } },
|
||||
{ kCnCodecName, 48000, 1, 107, false, { } },
|
||||
{ kCnCodecName, 32000, 1, 106, false, { } },
|
||||
{ kCnCodecName, 16000, 1, 105, false, { } },
|
||||
{ kCnCodecName, 8000, 1, 13, false, { } },
|
||||
@ -161,6 +160,7 @@ static std::string ToString(const AudioCodec& codec) {
|
||||
<< " (" << codec.id << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string ToString(const webrtc::CodecInst& codec) {
|
||||
std::stringstream ss;
|
||||
ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels
|
||||
@ -191,9 +191,17 @@ static int SeverityToFilter(int severity) {
|
||||
return filter;
|
||||
}
|
||||
|
||||
static bool IsCodec(const AudioCodec& codec, const char* ref_name) {
|
||||
return (_stricmp(codec.name.c_str(), ref_name) == 0);
|
||||
}
|
||||
|
||||
static bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) {
|
||||
return (_stricmp(codec.plname, ref_name) == 0);
|
||||
}
|
||||
|
||||
static bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) {
|
||||
if (_stricmp(kCodecPrefs[i].name, codec.plname) == 0 &&
|
||||
if (IsCodec(codec, kCodecPrefs[i].name) &&
|
||||
kCodecPrefs[i].clockrate == codec.plfreq) {
|
||||
return kCodecPrefs[i].is_multi_rate;
|
||||
}
|
||||
@ -201,18 +209,6 @@ static bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsTelephoneEventCodec(const std::string& name) {
|
||||
return _stricmp(name.c_str(), "telephone-event") == 0;
|
||||
}
|
||||
|
||||
static bool IsCNCodec(const std::string& name) {
|
||||
return _stricmp(name.c_str(), "CN") == 0;
|
||||
}
|
||||
|
||||
static bool IsRedCodec(const std::string& name) {
|
||||
return _stricmp(name.c_str(), "red") == 0;
|
||||
}
|
||||
|
||||
static bool FindCodec(const std::vector<AudioCodec>& codecs,
|
||||
const AudioCodec& codec,
|
||||
AudioCodec* found_codec) {
|
||||
@ -248,9 +244,9 @@ static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) {
|
||||
// TODO(Brave): Query supported packet sizes from ACM when the API is ready.
|
||||
static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
|
||||
for (const CodecPref& codec_pref : kCodecPrefs) {
|
||||
if ((_stricmp(codec_pref.name, codec->plname) == 0 &&
|
||||
if ((IsCodec(*codec, codec_pref.name) &&
|
||||
codec_pref.clockrate == codec->plfreq) ||
|
||||
_stricmp(codec_pref.name, kG722CodecName) == 0) {
|
||||
IsCodec(*codec, kG722CodecName)) {
|
||||
int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms);
|
||||
if (packet_size_ms) {
|
||||
// Convert unit from milli-seconds to samples.
|
||||
@ -262,6 +258,87 @@ static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if codec.params[feature] == "1", false otherwise.
|
||||
static bool IsCodecFeatureEnabled(const AudioCodec& codec,
|
||||
const char* feature) {
|
||||
int value;
|
||||
return codec.GetParam(feature, &value) && value == 1;
|
||||
}
|
||||
|
||||
// Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate
|
||||
// otherwise. If the value (either from params or codec.bitrate) <=0, use the
|
||||
// default configuration. If the value is beyond feasible bit rate of Opus,
|
||||
// clamp it. Returns the Opus bit rate for operation.
|
||||
static int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) {
|
||||
int bitrate = 0;
|
||||
bool use_param = true;
|
||||
if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) {
|
||||
bitrate = codec.bitrate;
|
||||
use_param = false;
|
||||
}
|
||||
if (bitrate <= 0) {
|
||||
if (max_playback_rate <= 8000) {
|
||||
bitrate = kOpusBitrateNb;
|
||||
} else if (max_playback_rate <= 16000) {
|
||||
bitrate = kOpusBitrateWb;
|
||||
} else {
|
||||
bitrate = kOpusBitrateFb;
|
||||
}
|
||||
|
||||
if (IsCodecFeatureEnabled(codec, kCodecParamStereo)) {
|
||||
bitrate *= 2;
|
||||
}
|
||||
} else if (bitrate < kOpusMinBitrate || bitrate > kOpusMaxBitrate) {
|
||||
bitrate = (bitrate < kOpusMinBitrate) ? kOpusMinBitrate : kOpusMaxBitrate;
|
||||
std::string rate_source =
|
||||
use_param ? "Codec parameter \"maxaveragebitrate\"" :
|
||||
"Supplied Opus bitrate";
|
||||
LOG(LS_WARNING) << rate_source
|
||||
<< " is invalid and is replaced by: "
|
||||
<< bitrate;
|
||||
}
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
// Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not
|
||||
// defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise.
|
||||
static int GetOpusMaxPlaybackRate(const AudioCodec& codec) {
|
||||
int value;
|
||||
if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) {
|
||||
return value;
|
||||
}
|
||||
return kOpusDefaultMaxPlaybackRate;
|
||||
}
|
||||
|
||||
static void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec,
|
||||
bool* enable_codec_fec, int* max_playback_rate,
|
||||
bool* enable_codec_dtx) {
|
||||
*enable_codec_fec = IsCodecFeatureEnabled(codec, kCodecParamUseInbandFec);
|
||||
*enable_codec_dtx = IsCodecFeatureEnabled(codec, kCodecParamUseDtx);
|
||||
*max_playback_rate = GetOpusMaxPlaybackRate(codec);
|
||||
|
||||
// If OPUS, change what we send according to the "stereo" codec
|
||||
// parameter, and not the "channels" parameter. We set
|
||||
// voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If
|
||||
// the bitrate is not specified, i.e. is <= zero, we set it to the
|
||||
// appropriate default value for mono or stereo Opus.
|
||||
|
||||
voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1;
|
||||
voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate);
|
||||
}
|
||||
|
||||
// Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
|
||||
// which says that G722 should be advertised as 8 kHz although it is a 16 kHz
|
||||
// codec.
|
||||
static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
|
||||
if (IsCodec(*voe_codec, kG722CodecName)) {
|
||||
// If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
|
||||
// has changed, and this special case is no longer needed.
|
||||
ASSERT(voe_codec->plfreq != new_plfreq);
|
||||
voe_codec->plfreq = new_plfreq;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the default set of options applied to the engine. Historically, these
|
||||
// were supplied as a combination of flags from the channel manager (ec, agc,
|
||||
// ns, and highpass) and the rest hardcoded in InitInternal.
|
||||
@ -283,100 +360,8 @@ static AudioOptions GetDefaultEngineOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
static bool IsOpus(const AudioCodec& codec) {
|
||||
return (_stricmp(codec.name.c_str(), kOpusCodecName) == 0);
|
||||
}
|
||||
|
||||
static bool IsIsac(const AudioCodec& codec) {
|
||||
return (_stricmp(codec.name.c_str(), kIsacCodecName) == 0);
|
||||
}
|
||||
|
||||
// True if params["stereo"] == "1"
|
||||
static bool IsOpusStereoEnabled(const AudioCodec& codec) {
|
||||
int value;
|
||||
return codec.GetParam(kCodecParamStereo, &value) && value == 1;
|
||||
}
|
||||
|
||||
// Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate
|
||||
// otherwise. If the value (either from params or codec.bitrate) <=0, use the
|
||||
// default configuration. If the value is beyond feasible bit rate of Opus,
|
||||
// clamp it. Returns the Opus bit rate for operation.
|
||||
static int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) {
|
||||
int bitrate = 0;
|
||||
bool use_param = true;
|
||||
if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) {
|
||||
bitrate = codec.bitrate;
|
||||
use_param = false;
|
||||
}
|
||||
if (bitrate <= 0) {
|
||||
if (max_playback_rate <= 8000) {
|
||||
bitrate = kOpusBitrateNb;
|
||||
}
|
||||
else if (max_playback_rate <= 16000) {
|
||||
bitrate = kOpusBitrateWb;
|
||||
}
|
||||
else {
|
||||
bitrate = kOpusBitrateFb;
|
||||
}
|
||||
|
||||
if (IsOpusStereoEnabled(codec)) {
|
||||
bitrate *= 2;
|
||||
}
|
||||
}
|
||||
else if (bitrate < kOpusMinBitrate || bitrate > kOpusMaxBitrate) {
|
||||
bitrate = (bitrate < kOpusMinBitrate) ? kOpusMinBitrate : kOpusMaxBitrate;
|
||||
std::string rate_source =
|
||||
use_param ? "Codec parameter \"maxaveragebitrate\"" :
|
||||
"Supplied Opus bitrate";
|
||||
LOG(LS_WARNING) << rate_source
|
||||
<< " is invalid and is replaced by: "
|
||||
<< bitrate;
|
||||
}
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
// Return true if params[kCodecParamUseInbandFec] == "1", false
|
||||
// otherwise.
|
||||
static bool IsOpusFecEnabled(const AudioCodec& codec) {
|
||||
int value;
|
||||
return codec.GetParam(kCodecParamUseInbandFec, &value) && value == 1;
|
||||
}
|
||||
|
||||
// Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not
|
||||
// defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise.
|
||||
static int GetOpusMaxPlaybackRate(const AudioCodec& codec) {
|
||||
int value;
|
||||
if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) {
|
||||
return value;
|
||||
}
|
||||
return kOpusDefaultMaxPlaybackRate;
|
||||
}
|
||||
|
||||
static void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec,
|
||||
bool* enable_codec_fec, int* max_playback_rate) {
|
||||
*enable_codec_fec = IsOpusFecEnabled(codec);
|
||||
*max_playback_rate = GetOpusMaxPlaybackRate(codec);
|
||||
|
||||
// If OPUS, change what we send according to the "stereo" codec
|
||||
// parameter, and not the "channels" parameter. We set
|
||||
// voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If
|
||||
// the bitrate is not specified, i.e. is <= zero, we set it to the
|
||||
// appropriate default value for mono or stereo Opus.
|
||||
|
||||
voe_codec->channels = IsOpusStereoEnabled(codec) ? 2 : 1;
|
||||
voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate);
|
||||
}
|
||||
|
||||
// Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
|
||||
// which says that G722 should be advertised as 8 kHz although it is a 16 kHz
|
||||
// codec.
|
||||
static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
|
||||
if (_stricmp(voe_codec->plname, kG722CodecName) == 0) {
|
||||
// If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
|
||||
// has changed, and this special case is no longer needed.
|
||||
ASSERT(voe_codec->plfreq != new_plfreq);
|
||||
voe_codec->plfreq = new_plfreq;
|
||||
}
|
||||
static std::string GetEnableString(bool enable) {
|
||||
return enable ? "enable" : "disable";
|
||||
}
|
||||
|
||||
class WebRtcSoundclipMedia : public SoundclipMedia {
|
||||
@ -535,13 +520,13 @@ void WebRtcVoiceEngine::ConstructCodecs() {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (GetVoeCodec(i, &voe_codec)) {
|
||||
// Skip uncompressed formats.
|
||||
if (_stricmp(voe_codec.plname, kL16CodecName) == 0) {
|
||||
if (IsCodec(voe_codec, kL16CodecName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const CodecPref* pref = NULL;
|
||||
for (size_t j = 0; j < ARRAY_SIZE(kCodecPrefs); ++j) {
|
||||
if (_stricmp(kCodecPrefs[j].name, voe_codec.plname) == 0 &&
|
||||
if (IsCodec(voe_codec, kCodecPrefs[j].name) &&
|
||||
kCodecPrefs[j].clockrate == voe_codec.plfreq &&
|
||||
kCodecPrefs[j].channels == voe_codec.channels) {
|
||||
pref = &kCodecPrefs[j];
|
||||
@ -556,11 +541,11 @@ void WebRtcVoiceEngine::ConstructCodecs() {
|
||||
voe_codec.rate, voe_codec.channels,
|
||||
ARRAY_SIZE(kCodecPrefs) - (pref - kCodecPrefs));
|
||||
LOG(LS_INFO) << ToString(codec);
|
||||
if (IsIsac(codec)) {
|
||||
if (IsCodec(codec, kIsacCodecName)) {
|
||||
// Indicate auto-bitrate in signaling.
|
||||
codec.bitrate = 0;
|
||||
}
|
||||
if (IsOpus(codec)) {
|
||||
if (IsCodec(codec, kOpusCodecName)) {
|
||||
// Only add fmtp parameters that differ from the spec.
|
||||
if (kPreferredMinPTime != kOpusDefaultMinPTime) {
|
||||
codec.params[kCodecParamMinPTime] =
|
||||
@ -1323,7 +1308,7 @@ bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
|
||||
MaybeFixupG722(&voe_codec, 16000);
|
||||
|
||||
// Apply codec-specific settings.
|
||||
if (IsIsac(codec)) {
|
||||
if (IsCodec(codec, kIsacCodecName)) {
|
||||
// If ISAC and an explicit bitrate is not specified,
|
||||
// enable auto bitrate adjustment.
|
||||
voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
|
||||
@ -2120,7 +2105,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
|
||||
bool nack_enabled = nack_enabled_;
|
||||
bool enable_codec_fec = false;
|
||||
|
||||
bool enable_opus_dtx = false;
|
||||
int opus_max_playback_rate = 0;
|
||||
|
||||
// Set send codec (the first non-telephone-event/CN codec)
|
||||
@ -2134,7 +2119,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsTelephoneEventCodec(it->name) || IsCNCodec(it->name)) {
|
||||
if (IsCodec(*it, kDtmfCodecName) || IsCodec(*it, kCnCodecName)) {
|
||||
// Skip telephone-event/CN codec, which will be handled later.
|
||||
continue;
|
||||
}
|
||||
@ -2143,7 +2128,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
// 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 (IsRedCodec(it->name)) {
|
||||
if (IsCodec(*it, kRedCodecName)) {
|
||||
// Parse out the RED parameters. If we fail, just ignore RED;
|
||||
// we don't support all possible params/usage scenarios.
|
||||
if (!GetRedSendCodec(*it, codecs, &send_codec)) {
|
||||
@ -2160,11 +2145,11 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
} else {
|
||||
send_codec = voe_codec;
|
||||
nack_enabled = IsNackEnabled(*it);
|
||||
// For Opus as the send codec, we are to enable inband FEC if requested
|
||||
// and set maximum playback rate.
|
||||
if (IsOpus(*it)) {
|
||||
// For Opus as the send codec, we are to determine inband FEC, maximum
|
||||
// playback rate, and opus internal dtx.
|
||||
if (IsCodec(*it, kOpusCodecName)) {
|
||||
GetOpusConfig(*it, &send_codec, &enable_codec_fec,
|
||||
&opus_max_playback_rate);
|
||||
&opus_max_playback_rate, &enable_opus_dtx);
|
||||
}
|
||||
|
||||
// Set packet size if the AudioCodec param kCodecParamPTime is set.
|
||||
@ -2207,17 +2192,32 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
}
|
||||
}
|
||||
|
||||
// maxplaybackrate should be set after SetSendCodec.
|
||||
// If opus_max_playback_rate <= 0, the default maximum playback rate of 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 "
|
||||
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 "
|
||||
<< GetEnableString(enable_opus_dtx)
|
||||
<< " Opus DTX on channel "
|
||||
<< channel;
|
||||
if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
|
||||
channel, opus_max_playback_rate) == -1) {
|
||||
LOG(LS_WARNING) << "Could not set maximum playback rate.";
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2241,13 +2241,13 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
|
||||
// Find the DTMF telephone event "codec" and tell VoiceEngine channels
|
||||
// about it.
|
||||
if (IsTelephoneEventCodec(it->name)) {
|
||||
if (IsCodec(*it, kDtmfCodecName)) {
|
||||
if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
|
||||
channel, it->id) == -1) {
|
||||
LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, it->id);
|
||||
return false;
|
||||
}
|
||||
} else if (IsCNCodec(it->name)) {
|
||||
} else if (IsCodec(*it, 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).
|
||||
@ -2285,7 +2285,9 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
}
|
||||
// Only turn on VAD if we have a CN payload type that matches the
|
||||
// clockrate for the codec we are going to use.
|
||||
if (it->clockrate == send_codec.plfreq) {
|
||||
if (it->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);
|
||||
@ -2303,8 +2305,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
|
||||
it != codecs.end(); ++it) {
|
||||
// Find the DTMF telephone event "codec".
|
||||
if (_stricmp(it->name.c_str(), "telephone-event") == 0 ||
|
||||
_stricmp(it->name.c_str(), "audio/telephone-event") == 0) {
|
||||
if (IsCodec(*it, kDtmfCodecName)) {
|
||||
dtmf_allowed_ = true;
|
||||
}
|
||||
}
|
||||
|
@ -1402,6 +1402,53 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateOnTwoStreams) {
|
||||
voe_.GetMaxEncodingBandwidth(channel_num));
|
||||
}
|
||||
|
||||
// Test that with usedtx=0, Opus DTX is off.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, DisableOpusDtxOnOpus) {
|
||||
EXPECT_TRUE(SetupEngine());
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
std::vector<cricket::AudioCodec> codecs;
|
||||
codecs.push_back(kOpusCodec);
|
||||
codecs[0].params["usedtx"] = "0";
|
||||
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
||||
EXPECT_FALSE(voe_.GetOpusDtx(channel_num));
|
||||
}
|
||||
|
||||
// Test that with usedtx=1, Opus DTX is on.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, EnableOpusDtxOnOpus) {
|
||||
EXPECT_TRUE(SetupEngine());
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
std::vector<cricket::AudioCodec> codecs;
|
||||
codecs.push_back(kOpusCodec);
|
||||
codecs[0].params["usedtx"] = "1";
|
||||
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
||||
EXPECT_TRUE(voe_.GetOpusDtx(channel_num));
|
||||
EXPECT_FALSE(voe_.GetVAD(channel_num)); // Opus DTX should not affect VAD.
|
||||
}
|
||||
|
||||
// Test that usedtx=1 works with stereo Opus.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, EnableOpusDtxOnOpusStereo) {
|
||||
EXPECT_TRUE(SetupEngine());
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
std::vector<cricket::AudioCodec> codecs;
|
||||
codecs.push_back(kOpusCodec);
|
||||
codecs[0].params["usedtx"] = "1";
|
||||
codecs[0].params["stereo"] = "1";
|
||||
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
||||
EXPECT_TRUE(voe_.GetOpusDtx(channel_num));
|
||||
EXPECT_FALSE(voe_.GetVAD(channel_num)); // Opus DTX should not affect VAD.
|
||||
}
|
||||
|
||||
// Test that usedtx=1 does not work with non Opus.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, CannotEnableOpusDtxOnNonOpus) {
|
||||
EXPECT_TRUE(SetupEngine());
|
||||
int channel_num = voe_.GetLastChannel();
|
||||
std::vector<cricket::AudioCodec> codecs;
|
||||
codecs.push_back(kIsacCodec);
|
||||
codecs[0].params["usedtx"] = "1";
|
||||
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
||||
EXPECT_FALSE(voe_.GetOpusDtx(channel_num));
|
||||
}
|
||||
|
||||
// Test that we can switch back and forth between Opus and ISAC with CN.
|
||||
TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsIsacOpusSwitching) {
|
||||
EXPECT_TRUE(SetupEngine());
|
||||
|
Loading…
Reference in New Issue
Block a user