diff --git a/talk/media/webrtc/fakewebrtcvoiceengine.h b/talk/media/webrtc/fakewebrtcvoiceengine.h index bb529e2c8..960bad310 100644 --- a/talk/media/webrtc/fakewebrtcvoiceengine.h +++ b/talk/media/webrtc/fakewebrtcvoiceengine.h @@ -192,6 +192,7 @@ class FakeWebRtcVoiceEngine vad(false), codec_fec(false), max_encoding_bandwidth(0), + opus_dtx(false), red(false), nack(false), media_processor_registered(false), @@ -222,6 +223,7 @@ class FakeWebRtcVoiceEngine bool vad; bool codec_fec; int max_encoding_bandwidth; + bool opus_dtx; bool red; bool nack; bool media_processor_registered; @@ -664,6 +666,16 @@ class FakeWebRtcVoiceEngine return 0; } + WEBRTC_FUNC(SetOpusDtx, (int channel, bool enable_dtx)) { + WEBRTC_CHECK_CHANNEL(channel); + if (_stricmp(channels_[channel]->send_codec.plname, "opus") != 0) { + // Return -1 if current send codec is not Opus. + return -1; + } + channels_[channel]->opus_dtx = enable_dtx; + return 0; + } + // webrtc::VoEDtmf WEBRTC_FUNC(SendTelephoneEvent, (int channel, int event_code, bool out_of_band = true, int length_ms = 160, int attenuation_db = 10)) { diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc index 2df3a713e..719cc35a5 100644 --- a/webrtc/voice_engine/channel.cc +++ b/webrtc/voice_engine/channel.cc @@ -1565,6 +1565,19 @@ int Channel::SetOpusMaxPlaybackRate(int frequency_hz) { return 0; } +int Channel::SetOpusDtx(bool enable_dtx) { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), + "Channel::SetOpusDtx(%d)", enable_dtx); + int ret = enable_dtx ? audio_coding_->EnableOpusDtx(true) + : audio_coding_->DisableOpusDtx(); + if (ret != 0) { + _engineStatisticsPtr->SetLastError( + VE_AUDIO_CODING_MODULE_ERROR, kTraceError, "SetOpusDtx() failed"); + return -1; + } + return 0; +} + int32_t Channel::RegisterExternalTransport(Transport& transport) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), diff --git a/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h index cd1469f27..e197af872 100644 --- a/webrtc/voice_engine/channel.h +++ b/webrtc/voice_engine/channel.h @@ -208,6 +208,7 @@ public: int32_t GetRecPayloadType(CodecInst& codec); int32_t SetSendCNPayloadType(int type, PayloadFrequencies frequency); int SetOpusMaxPlaybackRate(int frequency_hz); + int SetOpusDtx(bool enable_dtx); // VoENetwork int32_t RegisterExternalTransport(Transport& transport); diff --git a/webrtc/voice_engine/include/voe_codec.h b/webrtc/voice_engine/include/voe_codec.h index a61b49b2c..4b9f939ce 100644 --- a/webrtc/voice_engine/include/voe_codec.h +++ b/webrtc/voice_engine/include/voe_codec.h @@ -117,6 +117,10 @@ public: return -1; } + // If send codec is Opus on a specified |channel|, set its DTX. Returns 0 if + // success, and -1 if failed. + virtual int SetOpusDtx(int channel, bool enable_dtx) = 0; + // Don't use. To be removed. virtual int SetAMREncFormat(int channel, AmrMode mode) { return -1; } virtual int SetAMRDecFormat(int channel, AmrMode mode) { return -1; } diff --git a/webrtc/voice_engine/test/auto_test/standard/codec_test.cc b/webrtc/voice_engine/test/auto_test/standard/codec_test.cc index 3460f0a5c..bfc2a30c5 100644 --- a/webrtc/voice_engine/test/auto_test/standard/codec_test.cc +++ b/webrtc/voice_engine/test/auto_test/standard/codec_test.cc @@ -158,6 +158,30 @@ TEST_F(CodecTest, OpusMaxPlaybackRateCannotBeSetForNonOpus) { } } +TEST_F(CodecTest, OpusDtxCanBeSetForOpus) { + for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) { + voe_codec_->GetCodec(i, codec_instance_); + if (_stricmp("opus", codec_instance_.plname)) { + continue; + } + voe_codec_->SetSendCodec(channel_, codec_instance_); + EXPECT_EQ(0, voe_codec_->SetOpusDtx(channel_, false)); + EXPECT_EQ(0, voe_codec_->SetOpusDtx(channel_, true)); + } +} + +TEST_F(CodecTest, OpusDtxCannotBeSetForNonOpus) { + for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) { + voe_codec_->GetCodec(i, codec_instance_); + if (!_stricmp("opus", codec_instance_.plname)) { + continue; + } + voe_codec_->SetSendCodec(channel_, codec_instance_); + EXPECT_EQ(-1, voe_codec_->SetOpusDtx(channel_, false)); + EXPECT_EQ(-1, voe_codec_->SetOpusDtx(channel_, true)); + } +} + // TODO(xians, phoglund): Re-enable when issue 372 is resolved. TEST_F(CodecTest, DISABLED_ManualVerifySendCodecsForAllPacketSizes) { for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) { diff --git a/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc b/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc index f0c3471a6..419ba55d7 100644 --- a/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc +++ b/webrtc/voice_engine/test/cmd_test/voe_cmd_test.cc @@ -232,6 +232,7 @@ void RunTest(std::string out_path) { bool typing_detection = false; bool muted = false; bool opus_stereo = false; + bool opus_dtx = false; bool experimental_ns_enabled = false; bool debug_recording_started = false; @@ -447,6 +448,7 @@ void RunTest(std::string out_path) { printf("%i. Toggle Opus stereo (Opus must be selected again to apply " "the setting) \n", option_index++); printf("%i. Set Opus maximum playback rate \n", option_index++); + printf("%i. Toggle Opus DTX \n", option_index++); printf("%i. Set bit rate (only take effect on codecs that allow the " "change) \n", option_index++); printf("%i. Toggle debug recording \n", option_index++); @@ -773,6 +775,11 @@ void RunTest(std::string out_path) { ASSERT_EQ(1, scanf("%i", &max_playback_rate)); res = codec->SetOpusMaxPlaybackRate(chan, max_playback_rate); VALIDATE; + } else if (option_selection == option_index++) { + opus_dtx = !opus_dtx; + res = codec->SetOpusDtx(chan, opus_dtx); + VALIDATE; + printf("Opus DTX %s.\n", opus_dtx ? "enabled" : "disabled"); } else if (option_selection == option_index++) { res = codec->GetSendCodec(chan, cinst); VALIDATE; diff --git a/webrtc/voice_engine/voe_codec_impl.cc b/webrtc/voice_engine/voe_codec_impl.cc index aa54a1f58..2b0141fa8 100644 --- a/webrtc/voice_engine/voe_codec_impl.cc +++ b/webrtc/voice_engine/voe_codec_impl.cc @@ -436,6 +436,23 @@ int VoECodecImpl::SetOpusMaxPlaybackRate(int channel, int frequency_hz) { return channelPtr->SetOpusMaxPlaybackRate(frequency_hz); } +int VoECodecImpl::SetOpusDtx(int channel, bool enable_dtx) { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SetOpusDtx(channel=%d, enable_dtx=%d)", channel, enable_dtx); + if (!_shared->statistics().Initialized()) { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel); + voe::Channel* channelPtr = ch.channel(); + if (channelPtr == NULL) { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetOpusDtx failed to locate channel"); + return -1; + } + return channelPtr->SetOpusDtx(enable_dtx); +} + void VoECodecImpl::ACMToExternalCodecRepresentation(CodecInst& toInst, const CodecInst& fromInst) { diff --git a/webrtc/voice_engine/voe_codec_impl.h b/webrtc/voice_engine/voe_codec_impl.h index ab26adc80..dad808dbb 100644 --- a/webrtc/voice_engine/voe_codec_impl.h +++ b/webrtc/voice_engine/voe_codec_impl.h @@ -56,6 +56,8 @@ public: virtual int SetOpusMaxPlaybackRate(int channel, int frequency_hz); + virtual int SetOpusDtx(int channel, bool enable_dtx); + protected: VoECodecImpl(voe::SharedData* shared); virtual ~VoECodecImpl();