diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc index 17da10f357..5cca45e2c1 100644 --- a/webrtc/audio/audio_receive_stream.cc +++ b/webrtc/audio/audio_receive_stream.cc @@ -25,11 +25,6 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" #include "webrtc/voice_engine/channel_proxy.h" #include "webrtc/voice_engine/include/voe_base.h" -#include "webrtc/voice_engine/include/voe_codec.h" -#include "webrtc/voice_engine/include/voe_neteq_stats.h" -#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" -#include "webrtc/voice_engine/include/voe_video_sync.h" -#include "webrtc/voice_engine/include/voe_volume_control.h" #include "webrtc/voice_engine/voice_engine_impl.h" namespace webrtc { @@ -177,11 +172,12 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { RTC_DCHECK_RUN_ON(&worker_thread_checker_); webrtc::AudioReceiveStream::Stats stats; stats.remote_ssrc = config_.rtp.remote_ssrc; - ScopedVoEInterface codec(voice_engine()); webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics(); + // TODO(solenberg): Don't return here if we can't get the codec - return the + // stats we *can* get. webrtc::CodecInst codec_inst = {0}; - if (codec->GetRecCodec(config_.voe_channel_id, codec_inst) == -1) { + if (!channel_proxy_->GetRecCodec(&codec_inst)) { return stats; } diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc index 8df66fe127..70e6ac131f 100644 --- a/webrtc/audio/audio_receive_stream_unittest.cc +++ b/webrtc/audio/audio_receive_stream_unittest.cc @@ -143,7 +143,7 @@ struct ConfigHelper { void SetupMockForGetStats() { using testing::DoAll; - using testing::SetArgReferee; + using testing::SetArgPointee; ASSERT_TRUE(channel_proxy_); EXPECT_CALL(*channel_proxy_, GetRTCPStatistics()) @@ -156,9 +156,8 @@ struct ConfigHelper { .WillOnce(Return(kNetworkStats)); EXPECT_CALL(*channel_proxy_, GetDecodingCallStatistics()) .WillOnce(Return(kAudioDecodeStats)); - - EXPECT_CALL(voice_engine_, GetRecCodec(kChannelId, _)) - .WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0))); + EXPECT_CALL(*channel_proxy_, GetRecCodec(_)) + .WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true))); } private: diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc index d8bc84858a..c43d0da573 100644 --- a/webrtc/audio/audio_send_stream.cc +++ b/webrtc/audio/audio_send_stream.cc @@ -23,9 +23,7 @@ #include "webrtc/modules/pacing/paced_sender.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/voice_engine/channel_proxy.h" -#include "webrtc/voice_engine/include/voe_audio_processing.h" -#include "webrtc/voice_engine/include/voe_codec.h" -#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" +#include "webrtc/voice_engine/include/voe_base.h" #include "webrtc/voice_engine/include/voe_volume_control.h" #include "webrtc/voice_engine/voice_engine_impl.h" @@ -155,9 +153,6 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { RTC_DCHECK(thread_checker_.CalledOnValidThread()); webrtc::AudioSendStream::Stats stats; stats.local_ssrc = config_.rtp.ssrc; - ScopedVoEInterface processing(voice_engine()); - ScopedVoEInterface codec(voice_engine()); - ScopedVoEInterface volume(voice_engine()); webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics(); stats.bytes_sent = call_stats.bytesSent; @@ -172,7 +167,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { stats.aec_quality_min = -1; webrtc::CodecInst codec_inst = {0}; - if (codec->GetSendCodec(config_.voe_channel_id, codec_inst) != -1) { + if (channel_proxy_->GetSendCodec(&codec_inst)) { RTC_DCHECK_NE(codec_inst.pltype, -1); stats.codec_name = codec_inst.plname; stats.codec_payload_type = rtc::Optional(codec_inst.pltype); @@ -196,6 +191,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { // Local speech level. { + ScopedVoEInterface volume(voice_engine()); unsigned int level = 0; int error = volume->GetSpeechInputLevelFullRange(level); RTC_DCHECK_EQ(0, error); @@ -274,14 +270,9 @@ VoiceEngine* AudioSendStream::voice_engine() const { // Apply current codec settings to a single voe::Channel used for sending. bool AudioSendStream::SetupSendCodec() { - ScopedVoEInterface base(voice_engine()); - ScopedVoEInterface codec(voice_engine()); - - const int channel = config_.voe_channel_id; - // Disable VAD and FEC unless we know the other side wants them. - codec->SetVADStatus(channel, false); - codec->SetFECStatus(channel, false); + channel_proxy_->SetVADStatus(false); + channel_proxy_->SetCodecFECStatus(false); // We disable audio network adaptor here. This will on one hand make sure that // audio network adaptor is disabled by default, and on the other allow audio @@ -298,36 +289,35 @@ bool AudioSendStream::SetupSendCodec() { // TODO(minyue): check if this check is really needed, or can we move it into // |codec->SetSendCodec|. webrtc::CodecInst current_codec = {0}; - if (codec->GetSendCodec(channel, current_codec) != 0 || + if (!channel_proxy_->GetSendCodec(¤t_codec) || (send_codec_spec.codec_inst != current_codec)) { - if (codec->SetSendCodec(channel, send_codec_spec.codec_inst) == -1) { - LOG(LS_WARNING) << "SetSendCodec() failed: " << base->LastError(); + if (!channel_proxy_->SetSendCodec(send_codec_spec.codec_inst)) { + LOG(LS_WARNING) << "SetSendCodec() failed."; return false; } } // Codec internal FEC. Treat any failure as fatal internal error. if (send_codec_spec.enable_codec_fec) { - if (codec->SetFECStatus(channel, true) != 0) { - LOG(LS_WARNING) << "SetFECStatus() failed: " << base->LastError(); + if (!channel_proxy_->SetCodecFECStatus(true)) { + LOG(LS_WARNING) << "SetCodecFECStatus() failed."; return false; } } // DTX and maxplaybackrate are only set if current codec is Opus. if (IsCodec(send_codec_spec.codec_inst, kOpusCodecName)) { - if (codec->SetOpusDtx(channel, send_codec_spec.enable_opus_dtx) != 0) { - LOG(LS_WARNING) << "SetOpusDtx() failed: " << base->LastError(); + if (!channel_proxy_->SetOpusDtx(send_codec_spec.enable_opus_dtx)) { + LOG(LS_WARNING) << "SetOpusDtx() failed."; 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) { - if (codec->SetOpusMaxPlaybackRate( - channel, send_codec_spec.opus_max_playback_rate) != 0) { - LOG(LS_WARNING) << "SetOpusMaxPlaybackRate() failed: " - << base->LastError(); + if (!channel_proxy_->SetOpusMaxPlaybackRate( + send_codec_spec.opus_max_playback_rate)) { + LOG(LS_WARNING) << "SetOpusMaxPlaybackRate() failed."; return false; } } @@ -361,10 +351,9 @@ bool AudioSendStream::SetupSendCodec() { RTC_NOTREACHED(); return false; } - if (codec->SetSendCNPayloadType(channel, send_codec_spec.cng_payload_type, - cn_freq) != 0) { - LOG(LS_WARNING) << "SetSendCNPayloadType() failed: " - << base->LastError(); + if (!channel_proxy_->SetSendCNPayloadType( + send_codec_spec.cng_payload_type, cn_freq)) { + LOG(LS_WARNING) << "SetSendCNPayloadType() failed."; // TODO(ajm): This failure condition will be removed from VoE. // Restore the return here when we update to a new enough webrtc. // @@ -382,8 +371,8 @@ bool AudioSendStream::SetupSendCodec() { send_codec_spec.codec_inst.channels == 1) { // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the // interaction between VAD and Opus FEC. - if (codec->SetVADStatus(channel, true) != 0) { - LOG(LS_WARNING) << "SetVADStatus() failed: " << base->LastError(); + if (!channel_proxy_->SetVADStatus(true)) { + LOG(LS_WARNING) << "SetVADStatus() failed."; return false; } } diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc index 4efd91b3e5..4b7415a738 100644 --- a/webrtc/audio/audio_send_stream_unittest.cc +++ b/webrtc/audio/audio_send_stream_unittest.cc @@ -154,16 +154,15 @@ struct ConfigHelper { } void SetupMockForSetupSendCodec() { - EXPECT_CALL(voice_engine_, SetVADStatus(kChannelId, false, _, _)) - .WillOnce(Return(0)); - EXPECT_CALL(voice_engine_, SetFECStatus(kChannelId, false)) - .WillOnce(Return(0)); + EXPECT_CALL(*channel_proxy_, SetVADStatus(false)) + .WillOnce(Return(true)); + EXPECT_CALL(*channel_proxy_, SetCodecFECStatus(false)) + .WillOnce(Return(true)); EXPECT_CALL(*channel_proxy_, DisableAudioNetworkAdaptor()); - // Let |GetSendCodec| return -1 for the first time to indicate that no send - // codec has been set. - EXPECT_CALL(voice_engine_, GetSendCodec(kChannelId, _)) - .WillOnce(Return(-1)); - EXPECT_CALL(voice_engine_, SetSendCodec(kChannelId, _)).WillOnce(Return(0)); + // Let |GetSendCodec| return false for the first time to indicate that no + // send codec has been set. + EXPECT_CALL(*channel_proxy_, GetSendCodec(_)).WillOnce(Return(false)); + EXPECT_CALL(*channel_proxy_, SetSendCodec(_)).WillOnce(Return(true)); } RtcpRttStats* rtcp_rtt_stats() { return &rtcp_rtt_stats_; } @@ -180,6 +179,7 @@ struct ConfigHelper { void SetupMockForGetStats() { using testing::DoAll; + using testing::SetArgPointee; using testing::SetArgReferee; std::vector report_blocks; @@ -195,9 +195,8 @@ struct ConfigHelper { .WillRepeatedly(Return(kCallStats)); EXPECT_CALL(*channel_proxy_, GetRemoteRTCPReportBlocks()) .WillRepeatedly(Return(report_blocks)); - - EXPECT_CALL(voice_engine_, GetSendCodec(kChannelId, _)) - .WillRepeatedly(DoAll(SetArgReferee<1>(kIsacCodec), Return(0))); + EXPECT_CALL(*channel_proxy_, GetSendCodec(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(kIsacCodec), Return(true))); EXPECT_CALL(voice_engine_, GetSpeechInputLevelFullRange(_)) .WillRepeatedly(DoAll(SetArgReferee<0>(kSpeechInputLevel), Return(0))); EXPECT_CALL(voice_engine_, audio_processing()) @@ -365,22 +364,22 @@ TEST(AudioSendStreamTest, SendCodecAppliesConfigParams) { stream_config.send_codec_spec.max_ptime_ms = 60; stream_config.audio_network_adaptor_config = rtc::Optional("abced"); - EXPECT_CALL(*helper.voice_engine(), SetFECStatus(kChannelId, true)) - .WillOnce(Return(0)); + EXPECT_CALL(*helper.channel_proxy(), SetCodecFECStatus(true)) + .WillOnce(Return(true)); EXPECT_CALL( - *helper.voice_engine(), - SetOpusDtx(kChannelId, stream_config.send_codec_spec.enable_opus_dtx)) - .WillOnce(Return(0)); + *helper.channel_proxy(), + SetOpusDtx(stream_config.send_codec_spec.enable_opus_dtx)) + .WillOnce(Return(true)); EXPECT_CALL( - *helper.voice_engine(), + *helper.channel_proxy(), SetOpusMaxPlaybackRate( - kChannelId, stream_config.send_codec_spec.opus_max_playback_rate)) - .WillOnce(Return(0)); - EXPECT_CALL(*helper.voice_engine(), + stream_config.send_codec_spec.opus_max_playback_rate)) + .WillOnce(Return(true)); + EXPECT_CALL(*helper.channel_proxy(), SetSendCNPayloadType( - kChannelId, stream_config.send_codec_spec.cng_payload_type, + stream_config.send_codec_spec.cng_payload_type, webrtc::kFreq16000Hz)) - .WillOnce(Return(0)); + .WillOnce(Return(true)); EXPECT_CALL( *helper.channel_proxy(), SetReceiverFrameLengthRange(stream_config.send_codec_spec.min_ptime_ms, @@ -403,8 +402,8 @@ TEST(AudioSendStreamTest, SendCodecCanApplyVad) { stream_config.send_codec_spec.codec_inst = kG722Codec; stream_config.send_codec_spec.cng_plfreq = 8000; stream_config.send_codec_spec.cng_payload_type = 105; - EXPECT_CALL(*helper.voice_engine(), SetVADStatus(kChannelId, true, _, _)) - .WillOnce(Return(0)); + EXPECT_CALL(*helper.channel_proxy(), SetVADStatus(true)) + .WillOnce(Return(true)); internal::AudioSendStream send_stream( stream_config, helper.audio_state(), helper.worker_queue(), helper.packet_router(), helper.congestion_controller(), diff --git a/webrtc/test/mock_voe_channel_proxy.h b/webrtc/test/mock_voe_channel_proxy.h index dc2c532b1a..39b2e9fd58 100644 --- a/webrtc/test/mock_voe_channel_proxy.h +++ b/webrtc/test/mock_voe_channel_proxy.h @@ -79,6 +79,15 @@ class MockVoEChannelProxy : public voe::ChannelProxy { int* playout_buffer_delay_ms)); MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t()); MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms)); + MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst)); + MOCK_CONST_METHOD1(GetSendCodec, bool(CodecInst* codec_inst)); + MOCK_METHOD1(SetVADStatus, bool(bool enable)); + MOCK_METHOD1(SetCodecFECStatus, bool(bool enable)); + MOCK_METHOD1(SetOpusDtx, bool(bool enable)); + MOCK_METHOD1(SetOpusMaxPlaybackRate, bool(int frequency_hz)); + MOCK_METHOD1(SetSendCodec, bool(const CodecInst& codec_inst)); + MOCK_METHOD2(SetSendCNPayloadType, + bool(int type, PayloadFrequencies frequency)); }; } // namespace test } // namespace webrtc diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc index b3c3a98507..e5e3804b71 100644 --- a/webrtc/voice_engine/channel_proxy.cc +++ b/webrtc/voice_engine/channel_proxy.cc @@ -297,6 +297,74 @@ void ChannelProxy::SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) { channel()->SetRtcpRttStats(rtcp_rtt_stats); } +bool ChannelProxy::GetRecCodec(CodecInst* codec_inst) const { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel()->GetRecCodec(*codec_inst) == 0; +} + +bool ChannelProxy::GetSendCodec(CodecInst* codec_inst) const { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel()->GetSendCodec(*codec_inst) == 0; +} + +bool ChannelProxy::SetVADStatus(bool enable) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel()->SetVADStatus(enable, VADNormal, false) == 0; +} + +bool ChannelProxy::SetCodecFECStatus(bool enable) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel()->SetCodecFECStatus(enable) == 0; +} + +bool ChannelProxy::SetOpusDtx(bool enable) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel()->SetOpusDtx(enable) == 0; +} + +bool ChannelProxy::SetOpusMaxPlaybackRate(int frequency_hz) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + return channel()->SetOpusMaxPlaybackRate(frequency_hz) == 0; +} + +bool ChannelProxy::SetSendCodec(const CodecInst& codec_inst) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + // Validation code copied from VoECodecImpl::SetSendCodec(). + if ((STR_CASE_CMP(codec_inst.plname, "L16") == 0) && + (codec_inst.pacsize >= 960)) { + return false; + } + if (!STR_CASE_CMP(codec_inst.plname, "CN") || + !STR_CASE_CMP(codec_inst.plname, "TELEPHONE-EVENT") || + !STR_CASE_CMP(codec_inst.plname, "RED")) { + return false; + } + if ((codec_inst.channels != 1) && (codec_inst.channels != 2)) { + return false; + } + if (!AudioCodingModule::IsCodecValid(codec_inst)) { + return false; + } + return channel()->SetSendCodec(codec_inst) == 0; +} + +bool ChannelProxy::SetSendCNPayloadType(int type, + PayloadFrequencies frequency) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + // Validation code copied from VoECodecImpl::SetSendCNPayloadType(). + if (type < 96 || type > 127) { + // Only allow dynamic range: 96 to 127 + return false; + } + if ((frequency != kFreq16000Hz) && (frequency != kFreq32000Hz)) { + // It is not possible to modify the payload type for CN/8000. + // We only allow modification of the CN payload type for CN/16000 + // and CN/32000. + return false; + } + return channel()->SetSendCNPayloadType(type, frequency) == 0; +} + Channel* ChannelProxy::channel() const { RTC_DCHECK(channel_owner_.channel()); return channel_owner_.channel(); diff --git a/webrtc/voice_engine/channel_proxy.h b/webrtc/voice_engine/channel_proxy.h index 7d18a74d57..20aba6fd95 100644 --- a/webrtc/voice_engine/channel_proxy.h +++ b/webrtc/voice_engine/channel_proxy.h @@ -107,8 +107,15 @@ class ChannelProxy { int* playout_buffer_delay_ms) const; virtual uint32_t GetPlayoutTimestamp() const; virtual void SetMinimumPlayoutDelay(int delay_ms); - virtual void SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats); + virtual bool GetRecCodec(CodecInst* codec_inst) const; + virtual bool GetSendCodec(CodecInst* codec_inst) const; + virtual bool SetVADStatus(bool enable); + virtual bool SetCodecFECStatus(bool enable); + virtual bool SetOpusDtx(bool enable); + virtual bool SetOpusMaxPlaybackRate(int frequency_hz); + virtual bool SetSendCodec(const CodecInst& codec_inst); + virtual bool SetSendCNPayloadType(int type, PayloadFrequencies frequency); private: Channel* channel() const;