From 217fb66e16627be23b8769edded8a23f6406ddab Mon Sep 17 00:00:00 2001 From: solenberg Date: Fri, 17 Jun 2016 08:30:54 -0700 Subject: [PATCH] Add AudioReceiveStream::SetGain() method and use that in WVoMC::SetOutputVolume(). Removes the need to use VoEVolume::SetChannelOutputVolumeScaling(). BUG=webrtc:4690 Review-Url: https://codereview.webrtc.org/2062193002 Cr-Commit-Position: refs/heads/master@{#13194} --- webrtc/audio/audio_receive_stream.cc | 5 +++++ webrtc/audio/audio_receive_stream.h | 1 + webrtc/audio/audio_receive_stream_unittest.cc | 21 +++++++++++++----- webrtc/audio_receive_stream.h | 4 ++++ webrtc/media/engine/fakewebrtccall.cc | 6 ++++- webrtc/media/engine/fakewebrtccall.h | 5 ++++- webrtc/media/engine/fakewebrtcvoiceengine.h | 13 ++--------- webrtc/media/engine/webrtcvoiceengine.cc | 22 +++++++++---------- .../engine/webrtcvoiceengine_unittest.cc | 16 +++++--------- webrtc/test/mock_voe_channel_proxy.h | 4 +++- webrtc/voice_engine/channel_proxy.cc | 9 +++++++- webrtc/voice_engine/channel_proxy.h | 4 +++- 12 files changed, 67 insertions(+), 43 deletions(-) diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc index 15e4f6107a..c933f78ea2 100644 --- a/webrtc/audio/audio_receive_stream.cc +++ b/webrtc/audio/audio_receive_stream.cc @@ -210,6 +210,11 @@ void AudioReceiveStream::SetSink(std::unique_ptr sink) { channel_proxy_->SetSink(std::move(sink)); } +void AudioReceiveStream::SetGain(float gain) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + channel_proxy_->SetChannelOutputVolumeScaling(gain); +} + const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const { RTC_DCHECK(thread_checker_.CalledOnValidThread()); return config_; diff --git a/webrtc/audio/audio_receive_stream.h b/webrtc/audio/audio_receive_stream.h index d99956c2dd..284f98e42d 100644 --- a/webrtc/audio/audio_receive_stream.h +++ b/webrtc/audio/audio_receive_stream.h @@ -41,6 +41,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream { void Stop() override; webrtc::AudioReceiveStream::Stats GetStats() const override; void SetSink(std::unique_ptr sink) override; + void SetGain(float gain) override; void SignalNetworkState(NetworkState state); bool DeliverRtcp(const uint8_t* packet, size_t length); diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc index 2e789f92c2..8e26dd9083 100644 --- a/webrtc/audio/audio_receive_stream_unittest.cc +++ b/webrtc/audio/audio_receive_stream_unittest.cc @@ -30,6 +30,7 @@ namespace test { namespace { using testing::_; +using testing::FloatEq; using testing::Return; using testing::ReturnRef; @@ -92,12 +93,12 @@ struct ConfigHelper { EXPECT_CALL(*channel_proxy_, SetReceiveAudioLevelIndicationStatus(true, kAudioLevelId)) .Times(1); - EXPECT_CALL(*channel_proxy_, EnableReceiveTransportSequenceNumber( - kTransportSequenceNumberId)) - .Times(1); EXPECT_CALL(*channel_proxy_, - RegisterReceiverCongestionControlObjects(&packet_router_)) - .Times(1); + EnableReceiveTransportSequenceNumber(kTransportSequenceNumberId)) + .Times(1); + EXPECT_CALL(*channel_proxy_, + RegisterReceiverCongestionControlObjects(&packet_router_)) + .Times(1); EXPECT_CALL(congestion_controller_, packet_router()) .WillOnce(Return(&packet_router_)); EXPECT_CALL(*channel_proxy_, ResetCongestionControlObjects()) @@ -303,7 +304,6 @@ TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) { EXPECT_TRUE(recv_stream.DeliverRtcp(&rtcp_packet[0], rtcp_packet.size())); } - TEST(AudioReceiveStreamTest, GetStats) { ConfigHelper helper; internal::AudioReceiveStream recv_stream( @@ -345,5 +345,14 @@ TEST(AudioReceiveStreamTest, GetStats) { EXPECT_EQ(kCallStats.capture_start_ntp_time_ms_, stats.capture_start_ntp_time_ms); } + +TEST(AudioReceiveStreamTest, SetGain) { + ConfigHelper helper; + internal::AudioReceiveStream recv_stream( + helper.congestion_controller(), helper.config(), helper.audio_state()); + EXPECT_CALL(*helper.channel_proxy(), + SetChannelOutputVolumeScaling(FloatEq(0.765f))); + recv_stream.SetGain(0.765f); +} } // namespace test } // namespace webrtc diff --git a/webrtc/audio_receive_stream.h b/webrtc/audio_receive_stream.h index 16ed769263..e0e9536a58 100644 --- a/webrtc/audio_receive_stream.h +++ b/webrtc/audio_receive_stream.h @@ -127,6 +127,10 @@ class AudioReceiveStream { // of feeding to the AEC. virtual void SetSink(std::unique_ptr sink) = 0; + // Sets playback gain of the stream, applied when mixing, and thus after it + // is potentially forwarded to any attached AudioSinkInterface implementation. + virtual void SetGain(float gain) = 0; + protected: virtual ~AudioReceiveStream() {} }; diff --git a/webrtc/media/engine/fakewebrtccall.cc b/webrtc/media/engine/fakewebrtccall.cc index fd020d43bd..914a403f41 100644 --- a/webrtc/media/engine/fakewebrtccall.cc +++ b/webrtc/media/engine/fakewebrtccall.cc @@ -57,7 +57,7 @@ webrtc::AudioSendStream::Stats FakeAudioSendStream::GetStats() const { FakeAudioReceiveStream::FakeAudioReceiveStream( const webrtc::AudioReceiveStream::Config& config) - : config_(config), received_packets_(0) { + : config_(config) { RTC_DCHECK(config.voe_channel_id != -1); } @@ -93,6 +93,10 @@ void FakeAudioReceiveStream::SetSink( sink_ = std::move(sink); } +void FakeAudioReceiveStream::SetGain(float gain) { + gain_ = gain; +} + FakeVideoSendStream::FakeVideoSendStream( const webrtc::VideoSendStream::Config& config, const webrtc::VideoEncoderConfig& encoder_config) diff --git a/webrtc/media/engine/fakewebrtccall.h b/webrtc/media/engine/fakewebrtccall.h index 4a0e41cb59..f703b157d8 100644 --- a/webrtc/media/engine/fakewebrtccall.h +++ b/webrtc/media/engine/fakewebrtccall.h @@ -75,6 +75,7 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream { int received_packets() const { return received_packets_; } bool VerifyLastPacket(const uint8_t* data, size_t length) const; const webrtc::AudioSinkInterface* sink() const { return sink_.get(); } + float gain() const { return gain_; } bool DeliverRtp(const uint8_t* packet, size_t length, const webrtc::PacketTime& packet_time); @@ -86,11 +87,13 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream { webrtc::AudioReceiveStream::Stats GetStats() const override; void SetSink(std::unique_ptr sink) override; + void SetGain(float gain) override; webrtc::AudioReceiveStream::Config config_; webrtc::AudioReceiveStream::Stats stats_; - int received_packets_; + int received_packets_ = 0; std::unique_ptr sink_; + float gain_ = 1.0f; rtc::Buffer last_packet_; }; diff --git a/webrtc/media/engine/fakewebrtcvoiceengine.h b/webrtc/media/engine/fakewebrtcvoiceengine.h index 8d15f5249e..4e3ced6c35 100644 --- a/webrtc/media/engine/fakewebrtcvoiceengine.h +++ b/webrtc/media/engine/fakewebrtcvoiceengine.h @@ -129,7 +129,6 @@ class FakeWebRtcVoiceEngine memset(&send_codec, 0, sizeof(send_codec)); } bool playout = false; - float volume_scale = 1.0f; bool vad = false; bool codec_fec = false; int max_encoding_bandwidth = 0; @@ -441,16 +440,8 @@ class FakeWebRtcVoiceEngine WEBRTC_STUB(GetSpeechOutputLevel, (int, unsigned int&)); WEBRTC_STUB(GetSpeechInputLevelFullRange, (unsigned int&)); WEBRTC_STUB(GetSpeechOutputLevelFullRange, (int, unsigned int&)); - WEBRTC_FUNC(SetChannelOutputVolumeScaling, (int channel, float scale)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->volume_scale= scale; - return 0; - } - WEBRTC_FUNC(GetChannelOutputVolumeScaling, (int channel, float& scale)) { - WEBRTC_CHECK_CHANNEL(channel); - scale = channels_[channel]->volume_scale; - return 0; - } + WEBRTC_STUB(SetChannelOutputVolumeScaling, (int channel, float scale)); + WEBRTC_STUB(GetChannelOutputVolumeScaling, (int channel, float& scale)); WEBRTC_STUB(SetOutputVolumePan, (int channel, float left, float right)); WEBRTC_STUB(GetOutputVolumePan, (int channel, float& left, float& right)); diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index eb9b4bb356..2ddf67dd3a 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -1341,6 +1341,11 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { stream_->SetSink(std::move(sink)); } + void SetOutputVolume(double volume) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + stream_->SetGain(volume); + } + private: void RecreateAudioReceiveStream( uint32_t local_ssrc, @@ -2270,19 +2275,14 @@ bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) { } ssrc = static_cast(default_recv_ssrc_); } - int ch_id = GetReceiveChannelId(ssrc); - if (ch_id < 0) { - LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc; + const auto it = recv_streams_.find(ssrc); + if (it == recv_streams_.end()) { + LOG(LS_WARNING) << "SetOutputVolume: no recv stream" << ssrc; return false; } - - if (-1 == engine()->voe()->volume()->SetChannelOutputVolumeScaling(ch_id, - volume)) { - LOG_RTCERR2(SetChannelOutputVolumeScaling, ch_id, volume); - return false; - } - LOG(LS_INFO) << "SetOutputVolume to " << volume - << " for channel " << ch_id << " and ssrc " << ssrc; + it->second->SetOutputVolume(volume); + LOG(LS_INFO) << "SetOutputVolume() to " << volume + << " for recv stream with ssrc " << ssrc; return true; } diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index 167ec89267..2db70d1521 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -3130,24 +3130,20 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOutputVolume) { cricket::StreamParams stream; stream.ssrcs.push_back(kSsrc2); EXPECT_TRUE(channel_->AddRecvStream(stream)); - int channel_id = voe_.GetLastChannel(); + EXPECT_DOUBLE_EQ(1, GetRecvStream(kSsrc2).gain()); EXPECT_TRUE(channel_->SetOutputVolume(kSsrc2, 3)); - float scale = 0; - EXPECT_EQ(0, voe_.GetChannelOutputVolumeScaling(channel_id, scale)); - EXPECT_DOUBLE_EQ(3, scale); + EXPECT_DOUBLE_EQ(3, GetRecvStream(kSsrc2).gain()); } TEST_F(WebRtcVoiceEngineTestFake, SetOutputVolumeDefaultRecvStream) { EXPECT_TRUE(SetupChannel()); EXPECT_TRUE(channel_->SetOutputVolume(0, 2)); DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame)); - int channel_id = voe_.GetLastChannel(); - float scale = 0; - EXPECT_EQ(0, voe_.GetChannelOutputVolumeScaling(channel_id, scale)); - EXPECT_DOUBLE_EQ(2, scale); + EXPECT_DOUBLE_EQ(2, GetRecvStream(1).gain()); EXPECT_TRUE(channel_->SetOutputVolume(0, 3)); - EXPECT_EQ(0, voe_.GetChannelOutputVolumeScaling(channel_id, scale)); - EXPECT_DOUBLE_EQ(3, scale); + EXPECT_DOUBLE_EQ(3, GetRecvStream(1).gain()); + EXPECT_TRUE(channel_->SetOutputVolume(1, 4)); + EXPECT_DOUBLE_EQ(4, GetRecvStream(1).gain()); } TEST_F(WebRtcVoiceEngineTestFake, SetsSyncGroupFromSyncLabel) { diff --git a/webrtc/test/mock_voe_channel_proxy.h b/webrtc/test/mock_voe_channel_proxy.h index da215d6a73..dc2a961b3c 100644 --- a/webrtc/test/mock_voe_channel_proxy.h +++ b/webrtc/test/mock_voe_channel_proxy.h @@ -46,7 +46,8 @@ class MockVoEChannelProxy : public voe::ChannelProxy { MOCK_METHOD1(SetSendTelephoneEventPayloadType, bool(int payload_type)); MOCK_METHOD2(SendTelephoneEventOutband, bool(int event, int duration_ms)); MOCK_METHOD1(SetInputMute, void(bool muted)); - + // TODO(solenberg): Talk the compiler into accepting this mock method: + // MOCK_METHOD1(SetSink, void(std::unique_ptr sink)); MOCK_METHOD1(RegisterExternalTransport, void(Transport* transport)); MOCK_METHOD0(DeRegisterExternalTransport, void()); MOCK_METHOD3(ReceivedRTPPacket, bool(const uint8_t* packet, @@ -55,6 +56,7 @@ class MockVoEChannelProxy : public voe::ChannelProxy { MOCK_METHOD2(ReceivedRTCPPacket, bool(const uint8_t* packet, size_t length)); MOCK_CONST_METHOD0(GetAudioDecoderFactory, const rtc::scoped_refptr&()); + MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling)); }; } // namespace test } // namespace webrtc diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc index 46288e9c6d..f60728aadc 100644 --- a/webrtc/voice_engine/channel_proxy.cc +++ b/webrtc/voice_engine/channel_proxy.cc @@ -193,10 +193,17 @@ bool ChannelProxy::ReceivedRTCPPacket(const uint8_t* packet, size_t length) { } const rtc::scoped_refptr& -ChannelProxy::GetAudioDecoderFactory() const { + ChannelProxy::GetAudioDecoderFactory() const { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); return channel()->GetAudioDecoderFactory(); } +void ChannelProxy::SetChannelOutputVolumeScaling(float scaling) { + RTC_DCHECK(thread_checker_.CalledOnValidThread()); + int error = channel()->SetChannelOutputVolumeScaling(scaling); + RTC_DCHECK_EQ(0, error); +} + 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 93b8a58355..39eed67d5d 100644 --- a/webrtc/voice_engine/channel_proxy.h +++ b/webrtc/voice_engine/channel_proxy.h @@ -83,7 +83,9 @@ class ChannelProxy { virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length); virtual const rtc::scoped_refptr& - GetAudioDecoderFactory() const; + GetAudioDecoderFactory() const; + + virtual void SetChannelOutputVolumeScaling(float scaling); private: Channel* channel() const;