diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc index 9aa2fc004c..d08bfeaa1e 100644 --- a/webrtc/audio/audio_send_stream.cc +++ b/webrtc/audio/audio_send_stream.cc @@ -127,6 +127,11 @@ bool AudioSendStream::SendTelephoneEvent(int payload_type, int event, channel_proxy_->SendTelephoneEventOutband(event, duration_ms); } +void AudioSendStream::SetMuted(bool muted) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + channel_proxy_->SetInputMute(muted); +} + webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const { RTC_DCHECK(thread_checker_.CalledOnValidThread()); webrtc::AudioSendStream::Stats stats; diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h index 61dd7f24b4..264f9b3a69 100644 --- a/webrtc/audio/audio_send_stream.h +++ b/webrtc/audio/audio_send_stream.h @@ -39,6 +39,7 @@ class AudioSendStream final : public webrtc::AudioSendStream { void Stop() override; bool SendTelephoneEvent(int payload_type, int event, int duration_ms) override; + void SetMuted(bool muted) override; webrtc::AudioSendStream::Stats GetStats() const override; void SignalNetworkState(NetworkState state); diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc index 44392ea1c0..b9535543e2 100644 --- a/webrtc/audio/audio_send_stream_unittest.cc +++ b/webrtc/audio/audio_send_stream_unittest.cc @@ -110,6 +110,7 @@ struct ConfigHelper { AudioSendStream::Config& config() { return stream_config_; } rtc::scoped_refptr audio_state() { return audio_state_; } + MockVoEChannelProxy* channel_proxy() { return channel_proxy_; } CongestionController* congestion_controller() { return &congestion_controller_; } @@ -200,6 +201,14 @@ TEST(AudioSendStreamTest, SendTelephoneEvent) { kTelephoneEventCode, kTelephoneEventDuration)); } +TEST(AudioSendStreamTest, SetMuted) { + ConfigHelper helper; + internal::AudioSendStream send_stream(helper.config(), helper.audio_state(), + helper.congestion_controller()); + EXPECT_CALL(*helper.channel_proxy(), SetInputMute(true)); + send_stream.SetMuted(true); +} + TEST(AudioSendStreamTest, GetStats) { ConfigHelper helper; internal::AudioSendStream send_stream(helper.config(), helper.audio_state(), diff --git a/webrtc/audio_send_stream.h b/webrtc/audio_send_stream.h index ffb5f9c4d5..1c6803ca99 100644 --- a/webrtc/audio_send_stream.h +++ b/webrtc/audio_send_stream.h @@ -100,6 +100,9 @@ class AudioSendStream { // TODO(solenberg): Make payload_type a config property instead. virtual bool SendTelephoneEvent(int payload_type, int event, int duration_ms) = 0; + + virtual void SetMuted(bool muted) = 0; + virtual Stats GetStats() const = 0; protected: diff --git a/webrtc/media/engine/fakewebrtccall.cc b/webrtc/media/engine/fakewebrtccall.cc index edb2fa46c1..fd020d43bd 100644 --- a/webrtc/media/engine/fakewebrtccall.cc +++ b/webrtc/media/engine/fakewebrtccall.cc @@ -47,6 +47,10 @@ bool FakeAudioSendStream::SendTelephoneEvent(int payload_type, int event, return true; } +void FakeAudioSendStream::SetMuted(bool muted) { + muted_ = muted; +} + webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const { return stats_; } diff --git a/webrtc/media/engine/fakewebrtccall.h b/webrtc/media/engine/fakewebrtccall.h index 2d1cb7415b..4a0e41cb59 100644 --- a/webrtc/media/engine/fakewebrtccall.h +++ b/webrtc/media/engine/fakewebrtccall.h @@ -46,6 +46,7 @@ class FakeAudioSendStream final : public webrtc::AudioSendStream { void SetStats(const webrtc::AudioSendStream::Stats& stats); TelephoneEvent GetLatestTelephoneEvent() const; bool IsSending() const { return sending_; } + bool muted() const { return muted_; } private: // webrtc::AudioSendStream implementation. @@ -54,12 +55,14 @@ class FakeAudioSendStream final : public webrtc::AudioSendStream { bool SendTelephoneEvent(int payload_type, int event, int duration_ms) override; + void SetMuted(bool muted) override; webrtc::AudioSendStream::Stats GetStats() const override; TelephoneEvent latest_telephone_event_; webrtc::AudioSendStream::Config config_; webrtc::AudioSendStream::Stats stats_; bool sending_ = false; + bool muted_ = false; }; class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream { diff --git a/webrtc/media/engine/webrtcvoe.h b/webrtc/media/engine/webrtcvoe.h index 238b4ce781..cbb68632c9 100644 --- a/webrtc/media/engine/webrtcvoe.h +++ b/webrtc/media/engine/webrtcvoe.h @@ -23,7 +23,6 @@ #include "webrtc/voice_engine/include/voe_codec.h" #include "webrtc/voice_engine/include/voe_errors.h" #include "webrtc/voice_engine/include/voe_hardware.h" -#include "webrtc/voice_engine/include/voe_network.h" #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" #include "webrtc/voice_engine/include/voe_volume_control.h" diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index b2eda0ee13..c1084c303b 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -1145,6 +1145,18 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream UpdateSendState(); } + void SetMuted(bool muted) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + RTC_DCHECK(stream_); + stream_->SetMuted(muted); + muted_ = muted; + } + + bool muted() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + return muted_; + } + webrtc::AudioSendStream::Stats GetStats() const { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); RTC_DCHECK(stream_); @@ -1250,6 +1262,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream // goes away. AudioSource* source_ = nullptr; bool send_ = false; + bool muted_ = false; webrtc::RtpParameters rtp_parameters_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); @@ -2361,29 +2374,21 @@ void WebRtcVoiceMediaChannel::OnNetworkRouteChanged( bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - int channel = GetSendChannelId(ssrc); - if (channel == -1) { + const auto it = send_streams_.find(ssrc); + if (it == send_streams_.end()) { LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; return false; } - if (engine()->voe()->volume()->SetInputMute(channel, muted) == -1) { - LOG_RTCERR2(SetInputMute, channel, muted); - return false; - } + it->second->SetMuted(muted); + + // TODO(solenberg): // We set the AGC to mute state only when all the channels are muted. // This implementation is not ideal, instead we should signal the AGC when // the mic channel is muted/unmuted. We can't do it today because there // is no good way to know which stream is mapping to the mic channel. bool all_muted = muted; - for (const auto& ch : send_streams_) { - if (!all_muted) { - break; - } - if (engine()->voe()->volume()->GetInputMute(ch.second->channel(), - all_muted)) { - LOG_RTCERR1(GetInputMute, ch.second->channel()); - return false; - } + for (const auto& kv : send_streams_) { + all_muted = all_muted && kv.second->muted(); } webrtc::AudioProcessing* ap = engine()->voe()->base()->audio_processing(); diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index 98495af88d..7c25367164 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -2135,6 +2135,17 @@ TEST_F(WebRtcVoiceEngineTestFake, SendStateWithAndWithoutSource) { EXPECT_FALSE(GetSendStream(kSsrc1).IsSending()); } +// Test that a channel is muted/unmuted. +TEST_F(WebRtcVoiceEngineTestFake, SendStateMuteUnmute) { + EXPECT_TRUE(SetupSendStream()); + EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); + EXPECT_FALSE(GetSendStream(kSsrc1).muted()); + EXPECT_TRUE(channel_->SetAudioSend(kSsrc1, true, nullptr, nullptr)); + EXPECT_FALSE(GetSendStream(kSsrc1).muted()); + EXPECT_TRUE(channel_->SetAudioSend(kSsrc1, false, nullptr, nullptr)); + EXPECT_TRUE(GetSendStream(kSsrc1).muted()); +} + // Test that SetSendParameters() does not alter a stream's send state. TEST_F(WebRtcVoiceEngineTestFake, SendStateWhenStreamsAreRecreated) { EXPECT_TRUE(SetupSendStream()); diff --git a/webrtc/test/mock_voe_channel_proxy.h b/webrtc/test/mock_voe_channel_proxy.h index 8b14545bc3..da215d6a73 100644 --- a/webrtc/test/mock_voe_channel_proxy.h +++ b/webrtc/test/mock_voe_channel_proxy.h @@ -45,6 +45,8 @@ class MockVoEChannelProxy : public voe::ChannelProxy { MOCK_CONST_METHOD0(GetDelayEstimate, uint32_t()); MOCK_METHOD1(SetSendTelephoneEventPayloadType, bool(int payload_type)); MOCK_METHOD2(SendTelephoneEventOutband, bool(int event, int duration_ms)); + MOCK_METHOD1(SetInputMute, void(bool muted)); + MOCK_METHOD1(RegisterExternalTransport, void(Transport* transport)); MOCK_METHOD0(DeRegisterExternalTransport, void()); MOCK_METHOD3(ReceivedRTPPacket, bool(const uint8_t* packet, diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc index e148649aa3..46288e9c6d 100644 --- a/webrtc/voice_engine/channel_proxy.cc +++ b/webrtc/voice_engine/channel_proxy.cc @@ -163,6 +163,12 @@ void ChannelProxy::SetSink(std::unique_ptr sink) { channel()->SetSink(std::move(sink)); } +void ChannelProxy::SetInputMute(bool muted) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + int error = channel()->SetInputMute(muted); + RTC_DCHECK_EQ(0, error); +} + void ChannelProxy::RegisterExternalTransport(Transport* transport) { RTC_DCHECK(thread_checker_.CalledOnValidThread()); int error = channel()->RegisterExternalTransport(transport); diff --git a/webrtc/voice_engine/channel_proxy.h b/webrtc/voice_engine/channel_proxy.h index 69d4f110bb..93b8a58355 100644 --- a/webrtc/voice_engine/channel_proxy.h +++ b/webrtc/voice_engine/channel_proxy.h @@ -73,6 +73,7 @@ class ChannelProxy { virtual bool SetSendTelephoneEventPayloadType(int payload_type); virtual bool SendTelephoneEventOutband(int event, int duration_ms); virtual void SetSink(std::unique_ptr sink); + virtual void SetInputMute(bool muted); virtual void RegisterExternalTransport(Transport* transport); virtual void DeRegisterExternalTransport();