From 349ade3a4b927bf1060d26d0f8152aa243e7714c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= Date: Fri, 16 Nov 2018 09:50:42 +0100 Subject: [PATCH] Delete class ChannelReceiveProxy. Replaced by an interface ChannelReceiveInterface, implemented by ChannelReceive and the corresponding mock class. Moved thread checkers to ChannelReceive. That class is moved to the anonymous namespace in the .cc file, and exposed only via a function CreateChannelReceive. Bug: webrtc:9801 Change-Id: Iecacbb1858885bf86da9484f2422e53323dbe87a Reviewed-on: https://webrtc-review.googlesource.com/c/110610 Commit-Queue: Niels Moller Reviewed-by: Fredrik Solenberg Reviewed-by: Karl Wiberg Cr-Commit-Position: refs/heads/master@{#25665} --- audio/BUILD.gn | 2 - audio/audio_receive_stream.cc | 97 ++++---- audio/audio_receive_stream.h | 19 +- audio/audio_receive_stream_unittest.cc | 60 ++--- audio/audio_send_stream.cc | 4 +- audio/audio_send_stream.h | 3 +- audio/channel_receive.cc | 305 +++++++++++++++++++++++-- audio/channel_receive.h | 230 ++++--------------- audio/channel_receive_proxy.cc | 179 --------------- audio/channel_receive_proxy.h | 109 --------- audio/mock_voe_channel_proxy.h | 10 +- 11 files changed, 436 insertions(+), 582 deletions(-) delete mode 100644 audio/channel_receive_proxy.cc delete mode 100644 audio/channel_receive_proxy.h diff --git a/audio/BUILD.gn b/audio/BUILD.gn index 4b2ec6110a..b6369e08b8 100644 --- a/audio/BUILD.gn +++ b/audio/BUILD.gn @@ -26,8 +26,6 @@ rtc_static_library("audio") { "audio_transport_impl.h", "channel_receive.cc", "channel_receive.h", - "channel_receive_proxy.cc", - "channel_receive_proxy.h", "channel_send.cc", "channel_send.h", "channel_send_proxy.cc", diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index 4f2e29c75e..48484915de 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -21,7 +21,6 @@ #include "audio/audio_send_stream.h" #include "audio/audio_state.h" #include "audio/channel_receive.h" -#include "audio/channel_receive_proxy.h" #include "audio/conversion.h" #include "call/rtp_config.h" #include "call/rtp_stream_receiver_controller_interface.h" @@ -68,7 +67,7 @@ std::string AudioReceiveStream::Config::ToString() const { namespace internal { namespace { -std::unique_ptr CreateChannelAndProxy( +std::unique_ptr CreateChannelReceive( webrtc::AudioState* audio_state, ProcessThread* module_process_thread, const webrtc::AudioReceiveStream::Config& config, @@ -76,13 +75,12 @@ std::unique_ptr CreateChannelAndProxy( RTC_DCHECK(audio_state); internal::AudioState* internal_audio_state = static_cast(audio_state); - return absl::make_unique( - absl::make_unique( - module_process_thread, internal_audio_state->audio_device_module(), - config.media_transport, config.rtcp_send_transport, event_log, - config.rtp.remote_ssrc, config.jitter_buffer_max_packets, - config.jitter_buffer_fast_accelerate, config.decoder_factory, - config.codec_pair_id, config.frame_decryptor, config.crypto_options)); + return voe::CreateChannelReceive( + module_process_thread, internal_audio_state->audio_device_module(), + config.media_transport, config.rtcp_send_transport, event_log, + config.rtp.remote_ssrc, config.jitter_buffer_max_packets, + config.jitter_buffer_fast_accelerate, config.decoder_factory, + config.codec_pair_id, config.frame_decryptor, config.crypto_options); } } // namespace @@ -98,10 +96,10 @@ AudioReceiveStream::AudioReceiveStream( config, audio_state, event_log, - CreateChannelAndProxy(audio_state.get(), - module_process_thread, - config, - event_log)) {} + CreateChannelReceive(audio_state.get(), + module_process_thread, + config, + event_log)) {} AudioReceiveStream::AudioReceiveStream( RtpStreamReceiverControllerInterface* receiver_controller, @@ -109,13 +107,13 @@ AudioReceiveStream::AudioReceiveStream( const webrtc::AudioReceiveStream::Config& config, const rtc::scoped_refptr& audio_state, webrtc::RtcEventLog* event_log, - std::unique_ptr channel_proxy) - : audio_state_(audio_state), channel_proxy_(std::move(channel_proxy)) { + std::unique_ptr channel_receive) + : audio_state_(audio_state), channel_receive_(std::move(channel_receive)) { RTC_LOG(LS_INFO) << "AudioReceiveStream: " << config.rtp.remote_ssrc; RTC_DCHECK(config.decoder_factory); RTC_DCHECK(config.rtcp_send_transport); RTC_DCHECK(audio_state_); - RTC_DCHECK(channel_proxy_); + RTC_DCHECK(channel_receive_); module_process_thread_checker_.DetachFromThread(); @@ -123,11 +121,11 @@ AudioReceiveStream::AudioReceiveStream( RTC_DCHECK(receiver_controller); RTC_DCHECK(packet_router); // Configure bandwidth estimation. - channel_proxy_->RegisterReceiverCongestionControlObjects(packet_router); + channel_receive_->RegisterReceiverCongestionControlObjects(packet_router); // Register with transport. rtp_stream_receiver_ = receiver_controller->CreateReceiver( - config.rtp.remote_ssrc, channel_proxy_.get()); + config.rtp.remote_ssrc, channel_receive_.get()); } ConfigureStream(this, config, true); } @@ -136,9 +134,9 @@ AudioReceiveStream::~AudioReceiveStream() { RTC_DCHECK_RUN_ON(&worker_thread_checker_); RTC_LOG(LS_INFO) << "~AudioReceiveStream: " << config_.rtp.remote_ssrc; Stop(); - channel_proxy_->DisassociateSendChannel(); + channel_receive_->SetAssociatedSendChannel(nullptr); if (!config_.media_transport) { - channel_proxy_->ResetReceiverCongestionControlObjects(); + channel_receive_->ResetReceiverCongestionControlObjects(); } } @@ -153,7 +151,7 @@ void AudioReceiveStream::Start() { if (playing_) { return; } - channel_proxy_->StartPlayout(); + channel_receive_->StartPlayout(); playing_ = true; audio_state()->AddReceivingStream(this); } @@ -163,7 +161,7 @@ void AudioReceiveStream::Stop() { if (!playing_) { return; } - channel_proxy_->StopPlayout(); + channel_receive_->StopPlayout(); playing_ = false; audio_state()->RemoveReceivingStream(this); } @@ -174,11 +172,11 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { stats.remote_ssrc = config_.rtp.remote_ssrc; webrtc::CallReceiveStatistics call_stats = - channel_proxy_->GetRTCPStatistics(); + channel_receive_->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 (!channel_proxy_->GetRecCodec(&codec_inst)) { + if (!channel_receive_->GetRecCodec(&codec_inst)) { return stats; } @@ -195,13 +193,13 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { if (codec_inst.plfreq / 1000 > 0) { stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000); } - stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate(); - stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange(); - stats.total_output_energy = channel_proxy_->GetTotalOutputEnergy(); - stats.total_output_duration = channel_proxy_->GetTotalOutputDuration(); + stats.delay_estimate_ms = channel_receive_->GetDelayEstimate(); + stats.audio_level = channel_receive_->GetSpeechOutputLevelFullRange(); + stats.total_output_energy = channel_receive_->GetTotalOutputEnergy(); + stats.total_output_duration = channel_receive_->GetTotalOutputDuration(); // Get jitter buffer and total delay (alg + jitter + playout) stats. - auto ns = channel_proxy_->GetNetworkStatistics(); + auto ns = channel_receive_->GetNetworkStatistics(); stats.jitter_buffer_ms = ns.currentBufferSize; stats.jitter_buffer_preferred_ms = ns.preferredBufferSize; stats.total_samples_received = ns.totalSamplesReceived; @@ -217,7 +215,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate); stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate); - auto ds = channel_proxy_->GetDecodingCallStatistics(); + auto ds = channel_receive_->GetDecodingCallStatistics(); stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator; stats.decoding_calls_to_neteq = ds.calls_to_neteq; stats.decoding_normal = ds.decoded_normal; @@ -231,23 +229,23 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { void AudioReceiveStream::SetSink(AudioSinkInterface* sink) { RTC_DCHECK_RUN_ON(&worker_thread_checker_); - channel_proxy_->SetSink(sink); + channel_receive_->SetSink(sink); } void AudioReceiveStream::SetGain(float gain) { RTC_DCHECK_RUN_ON(&worker_thread_checker_); - channel_proxy_->SetChannelOutputVolumeScaling(gain); + channel_receive_->SetChannelOutputVolumeScaling(gain); } std::vector AudioReceiveStream::GetSources() const { RTC_DCHECK_RUN_ON(&worker_thread_checker_); - return channel_proxy_->GetSources(); + return channel_receive_->GetSources(); } AudioMixer::Source::AudioFrameInfo AudioReceiveStream::GetAudioFrameWithInfo( int sample_rate_hz, AudioFrame* audio_frame) { - return channel_proxy_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame); + return channel_receive_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame); } int AudioReceiveStream::Ssrc() const { @@ -255,7 +253,7 @@ int AudioReceiveStream::Ssrc() const { } int AudioReceiveStream::PreferredSampleRate() const { - return channel_proxy_->PreferredSampleRate(); + return channel_receive_->PreferredSampleRate(); } int AudioReceiveStream::id() const { @@ -265,32 +263,29 @@ int AudioReceiveStream::id() const { absl::optional AudioReceiveStream::GetInfo() const { RTC_DCHECK_RUN_ON(&module_process_thread_checker_); - absl::optional info = channel_proxy_->GetSyncInfo(); + absl::optional info = channel_receive_->GetSyncInfo(); if (!info) return absl::nullopt; - info->current_delay_ms = channel_proxy_->GetDelayEstimate(); + info->current_delay_ms = channel_receive_->GetDelayEstimate(); return info; } uint32_t AudioReceiveStream::GetPlayoutTimestamp() const { // Called on video capture thread. - return channel_proxy_->GetPlayoutTimestamp(); + return channel_receive_->GetPlayoutTimestamp(); } void AudioReceiveStream::SetMinimumPlayoutDelay(int delay_ms) { RTC_DCHECK_RUN_ON(&module_process_thread_checker_); - return channel_proxy_->SetMinimumPlayoutDelay(delay_ms); + return channel_receive_->SetMinimumPlayoutDelay(delay_ms); } void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) { RTC_DCHECK_RUN_ON(&worker_thread_checker_); - if (send_stream) { - channel_proxy_->AssociateSendChannel(send_stream->GetChannelProxy()); - } else { - channel_proxy_->DisassociateSendChannel(); - } + channel_receive_->SetAssociatedSendChannel( + send_stream ? send_stream->GetChannel() : nullptr); associated_send_stream_ = send_stream; } @@ -303,7 +298,7 @@ bool AudioReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) { // calls on the worker thread. We should move towards always using a network // thread. Then this check can be enabled. // RTC_DCHECK(!thread_checker_.CalledOnValidThread()); - return channel_proxy_->ReceivedRTCPPacket(packet, length); + return channel_receive_->ReceivedRTCPPacket(packet, length); } void AudioReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) { @@ -311,7 +306,7 @@ void AudioReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) { // calls on the worker thread. We should move towards always using a network // thread. Then this check can be enabled. // RTC_DCHECK(!thread_checker_.CalledOnValidThread()); - channel_proxy_->OnRtpPacket(packet); + channel_receive_->OnRtpPacket(packet); } const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const { @@ -337,7 +332,7 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream, RTC_LOG(LS_INFO) << "AudioReceiveStream::ConfigureStream: " << new_config.ToString(); RTC_DCHECK(stream); - const auto& channel_proxy = stream->channel_proxy_; + const auto& channel_receive = stream->channel_receive_; const auto& old_config = stream->config_; // Configuration parameters which cannot be changed. @@ -351,7 +346,7 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream, old_config.decoder_factory == new_config.decoder_factory); if (first_time || old_config.rtp.local_ssrc != new_config.rtp.local_ssrc) { - channel_proxy->SetLocalSSRC(new_config.rtp.local_ssrc); + channel_receive->SetLocalSSRC(new_config.rtp.local_ssrc); } if (!first_time) { @@ -363,11 +358,11 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream, // using the actual packet size for the configured codec. if (first_time || old_config.rtp.nack.rtp_history_ms != new_config.rtp.nack.rtp_history_ms) { - channel_proxy->SetNACKStatus(new_config.rtp.nack.rtp_history_ms != 0, - new_config.rtp.nack.rtp_history_ms / 20); + channel_receive->SetNACKStatus(new_config.rtp.nack.rtp_history_ms != 0, + new_config.rtp.nack.rtp_history_ms / 20); } if (first_time || old_config.decoder_map != new_config.decoder_map) { - channel_proxy->SetReceiveCodecs(new_config.decoder_map); + channel_receive->SetReceiveCodecs(new_config.decoder_map); } stream->config_ = new_config; diff --git a/audio/audio_receive_stream.h b/audio/audio_receive_stream.h index dde0da4918..5b41f1ad01 100644 --- a/audio/audio_receive_stream.h +++ b/audio/audio_receive_stream.h @@ -31,7 +31,7 @@ class RtpStreamReceiverControllerInterface; class RtpStreamReceiverInterface; namespace voe { -class ChannelReceiveProxy; +class ChannelReceiveInterface; } // namespace voe namespace internal { @@ -47,13 +47,14 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream, const webrtc::AudioReceiveStream::Config& config, const rtc::scoped_refptr& audio_state, webrtc::RtcEventLog* event_log); - // For unit tests, which need to supply a mock channel proxy. - AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller, - PacketRouter* packet_router, - const webrtc::AudioReceiveStream::Config& config, - const rtc::scoped_refptr& audio_state, - webrtc::RtcEventLog* event_log, - std::unique_ptr channel_proxy); + // For unit tests, which need to supply a mock channel receive. + AudioReceiveStream( + RtpStreamReceiverControllerInterface* receiver_controller, + PacketRouter* packet_router, + const webrtc::AudioReceiveStream::Config& config, + const rtc::scoped_refptr& audio_state, + webrtc::RtcEventLog* event_log, + std::unique_ptr channel_receive); ~AudioReceiveStream() override; // webrtc::AudioReceiveStream implementation. @@ -100,7 +101,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream, rtc::ThreadChecker module_process_thread_checker_; webrtc::AudioReceiveStream::Config config_; rtc::scoped_refptr audio_state_; - std::unique_ptr channel_proxy_; + std::unique_ptr channel_receive_; AudioSendStream* associated_send_stream_ = nullptr; bool playing_ RTC_GUARDED_BY(worker_thread_checker_) = false; diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc index a5c7e2031a..7422810856 100644 --- a/audio/audio_receive_stream_unittest.cc +++ b/audio/audio_receive_stream_unittest.cc @@ -83,16 +83,16 @@ struct ConfigHelper { new rtc::RefCountedObject>(); audio_state_ = AudioState::Create(config); - channel_proxy_ = new testing::StrictMock(); - EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1); - EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1); - EXPECT_CALL(*channel_proxy_, + channel_receive_ = new testing::StrictMock(); + EXPECT_CALL(*channel_receive_, SetLocalSSRC(kLocalSsrc)).Times(1); + EXPECT_CALL(*channel_receive_, SetNACKStatus(true, 15)).Times(1); + EXPECT_CALL(*channel_receive_, RegisterReceiverCongestionControlObjects(&packet_router_)) .Times(1); - EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects()) + EXPECT_CALL(*channel_receive_, ResetReceiverCongestionControlObjects()) .Times(1); - EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1); - EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_)) + EXPECT_CALL(*channel_receive_, SetAssociatedSendChannel(nullptr)).Times(1); + EXPECT_CALL(*channel_receive_, SetReceiveCodecs(_)) .WillRepeatedly(Invoke([](const std::map& codecs) { EXPECT_THAT(codecs, testing::IsEmpty()); })); @@ -114,33 +114,33 @@ struct ConfigHelper { new internal::AudioReceiveStream( &rtp_stream_receiver_controller_, &packet_router_, stream_config_, audio_state_, &event_log_, - std::unique_ptr(channel_proxy_))); + std::unique_ptr(channel_receive_))); } AudioReceiveStream::Config& config() { return stream_config_; } rtc::scoped_refptr audio_mixer() { return audio_mixer_; } - MockChannelReceiveProxy* channel_proxy() { return channel_proxy_; } + MockChannelReceive* channel_receive() { return channel_receive_; } void SetupMockForGetStats() { using testing::DoAll; using testing::SetArgPointee; - ASSERT_TRUE(channel_proxy_); - EXPECT_CALL(*channel_proxy_, GetRTCPStatistics()) + ASSERT_TRUE(channel_receive_); + EXPECT_CALL(*channel_receive_, GetRTCPStatistics()) .WillOnce(Return(kCallStats)); - EXPECT_CALL(*channel_proxy_, GetDelayEstimate()) + EXPECT_CALL(*channel_receive_, GetDelayEstimate()) .WillOnce(Return(kJitterBufferDelay + kPlayoutBufferDelay)); - EXPECT_CALL(*channel_proxy_, GetSpeechOutputLevelFullRange()) + EXPECT_CALL(*channel_receive_, GetSpeechOutputLevelFullRange()) .WillOnce(Return(kSpeechOutputLevel)); - EXPECT_CALL(*channel_proxy_, GetTotalOutputEnergy()) + EXPECT_CALL(*channel_receive_, GetTotalOutputEnergy()) .WillOnce(Return(kTotalOutputEnergy)); - EXPECT_CALL(*channel_proxy_, GetTotalOutputDuration()) + EXPECT_CALL(*channel_receive_, GetTotalOutputDuration()) .WillOnce(Return(kTotalOutputDuration)); - EXPECT_CALL(*channel_proxy_, GetNetworkStatistics()) + EXPECT_CALL(*channel_receive_, GetNetworkStatistics()) .WillOnce(Return(kNetworkStats)); - EXPECT_CALL(*channel_proxy_, GetDecodingCallStatistics()) + EXPECT_CALL(*channel_receive_, GetDecodingCallStatistics()) .WillOnce(Return(kAudioDecodeStats)); - EXPECT_CALL(*channel_proxy_, GetRecCodec(_)) + EXPECT_CALL(*channel_receive_, GetRecCodec(_)) .WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true))); } @@ -150,7 +150,7 @@ struct ConfigHelper { rtc::scoped_refptr audio_state_; rtc::scoped_refptr audio_mixer_; AudioReceiveStream::Config stream_config_; - testing::StrictMock* channel_proxy_ = nullptr; + testing::StrictMock* channel_receive_ = nullptr; RtpStreamReceiverController rtp_stream_receiver_controller_; MockTransport rtcp_send_transport_; }; @@ -239,7 +239,7 @@ TEST(AudioReceiveStreamTest, ReceiveRtpPacket) { ASSERT_TRUE(parsed_packet.Parse(&rtp_packet[0], rtp_packet.size())); parsed_packet.set_arrival_time_ms((packet_time_us + 500) / 1000); - EXPECT_CALL(*helper.channel_proxy(), + EXPECT_CALL(*helper.channel_receive(), OnRtpPacket(testing::Ref(parsed_packet))); recv_stream->OnRtpPacket(parsed_packet); @@ -250,7 +250,7 @@ TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) { helper.config().rtp.transport_cc = true; auto recv_stream = helper.CreateAudioReceiveStream(); std::vector rtcp_packet = CreateRtcpSenderReport(); - EXPECT_CALL(*helper.channel_proxy(), + EXPECT_CALL(*helper.channel_receive(), ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size())) .WillOnce(Return(true)); EXPECT_TRUE(recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size())); @@ -312,7 +312,7 @@ TEST(AudioReceiveStreamTest, GetStats) { TEST(AudioReceiveStreamTest, SetGain) { ConfigHelper helper; auto recv_stream = helper.CreateAudioReceiveStream(); - EXPECT_CALL(*helper.channel_proxy(), + EXPECT_CALL(*helper.channel_receive(), SetChannelOutputVolumeScaling(FloatEq(0.765f))); recv_stream->SetGain(0.765f); } @@ -323,10 +323,10 @@ TEST(AudioReceiveStreamTest, StreamsShouldBeAddedToMixerOnceOnStart) { auto recv_stream1 = helper1.CreateAudioReceiveStream(); auto recv_stream2 = helper2.CreateAudioReceiveStream(); - EXPECT_CALL(*helper1.channel_proxy(), StartPlayout()).Times(1); - EXPECT_CALL(*helper2.channel_proxy(), StartPlayout()).Times(1); - EXPECT_CALL(*helper1.channel_proxy(), StopPlayout()).Times(1); - EXPECT_CALL(*helper2.channel_proxy(), StopPlayout()).Times(1); + EXPECT_CALL(*helper1.channel_receive(), StartPlayout()).Times(1); + EXPECT_CALL(*helper2.channel_receive(), StartPlayout()).Times(1); + EXPECT_CALL(*helper1.channel_receive(), StopPlayout()).Times(1); + EXPECT_CALL(*helper2.channel_receive(), StopPlayout()).Times(1); EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream1.get())) .WillOnce(Return(true)); EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream2.get())) @@ -367,10 +367,10 @@ TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) { kTransportSequenceNumberId + 1)); new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1)); - MockChannelReceiveProxy& channel_proxy = *helper.channel_proxy(); - EXPECT_CALL(channel_proxy, SetLocalSSRC(kLocalSsrc + 1)).Times(1); - EXPECT_CALL(channel_proxy, SetNACKStatus(true, 15 + 1)).Times(1); - EXPECT_CALL(channel_proxy, SetReceiveCodecs(new_config.decoder_map)); + MockChannelReceive& channel_receive = *helper.channel_receive(); + EXPECT_CALL(channel_receive, SetLocalSSRC(kLocalSsrc + 1)).Times(1); + EXPECT_CALL(channel_receive, SetNACKStatus(true, 15 + 1)).Times(1); + EXPECT_CALL(channel_receive, SetReceiveCodecs(new_config.decoder_map)); recv_stream->Reconfigure(new_config); } diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 7824653434..00c66a28ba 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -553,9 +553,9 @@ RtpState AudioSendStream::GetRtpState() const { return rtp_rtcp_module_->GetRtpState(); } -const voe::ChannelSendProxy& AudioSendStream::GetChannelProxy() const { +const voe::ChannelSend* AudioSendStream::GetChannel() const { RTC_DCHECK(channel_proxy_.get()); - return *channel_proxy_.get(); + return channel_proxy_->GetChannel(); } internal::AudioState* AudioSendStream::audio_state() { diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h index c86a9dcef7..5f7ea1498d 100644 --- a/audio/audio_send_stream.h +++ b/audio/audio_send_stream.h @@ -31,6 +31,7 @@ class RtcpRttStats; class RtpTransportControllerSendInterface; namespace voe { +class ChannelSend; class ChannelSendProxy; } // namespace voe @@ -93,7 +94,7 @@ class AudioSendStream final : public webrtc::AudioSendStream, void SetTransportOverhead(int transport_overhead_per_packet); RtpState GetRtpState() const; - const voe::ChannelSendProxy& GetChannelProxy() const; + const voe::ChannelSend* GetChannel() const; private: class TimedTransport; diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc index 1d6f0899e3..9c100fba75 100644 --- a/audio/channel_receive.cc +++ b/audio/channel_receive.cc @@ -18,14 +18,19 @@ #include #include "absl/memory/memory.h" +#include "audio/audio_level.h" #include "audio/channel_send.h" #include "audio/utility/audio_frame_operations.h" #include "logging/rtc_event_log/events/rtc_event_audio_playout.h" #include "logging/rtc_event_log/rtc_event_log.h" #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h" +#include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_device/include/audio_device.h" #include "modules/pacing/packet_router.h" #include "modules/rtp_rtcp/include/receive_statistics.h" +#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h" +#include "modules/rtp_rtcp/include/rtp_rtcp.h" +#include "modules/rtp_rtcp/source/contributing_sources.h" #include "modules/rtp_rtcp/source/rtp_header_extensions.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "modules/utility/include/process_thread.h" @@ -34,10 +39,16 @@ #include "rtc_base/format_macros.h" #include "rtc_base/location.h" #include "rtc_base/logging.h" +#include "rtc_base/numerics/safe_minmax.h" +#include "rtc_base/race_checker.h" #include "rtc_base/thread_checker.h" #include "rtc_base/timeutils.h" #include "system_wrappers/include/metrics.h" +// TODO(solenberg, nisse): This file contains a few NOLINT marks, to silence +// warnings about non-const reference arguments. +// These need cleanup, in a separate cl. + namespace webrtc { namespace voe { @@ -83,7 +94,219 @@ WebRtcRTPHeader CreateWebrtcRTPHeaderForMediaTransportFrame( return webrtc_header; } -} // namespace +// Helper class to simplify locking scheme for members that are accessed from +// multiple threads. +// Example: a member can be set on thread T1 and read by an internal audio +// thread T2. Accessing the member via this class ensures that we are +// safe and also avoid TSan v2 warnings. +class ChannelReceiveState { + public: + struct State { + bool playing = false; + }; + + ChannelReceiveState() {} + virtual ~ChannelReceiveState() {} + + void Reset() { + rtc::CritScope lock(&lock_); + state_ = State(); + } + + State Get() const { + rtc::CritScope lock(&lock_); + return state_; + } + + void SetPlaying(bool enable) { + rtc::CritScope lock(&lock_); + state_.playing = enable; + } + + private: + rtc::CriticalSection lock_; + State state_; +}; + +class ChannelReceive : public ChannelReceiveInterface, + public MediaTransportAudioSinkInterface { + public: + // Used for receive streams. + ChannelReceive(ProcessThread* module_process_thread, + AudioDeviceModule* audio_device_module, + MediaTransportInterface* media_transport, + Transport* rtcp_send_transport, + RtcEventLog* rtc_event_log, + uint32_t remote_ssrc, + size_t jitter_buffer_max_packets, + bool jitter_buffer_fast_playout, + rtc::scoped_refptr decoder_factory, + absl::optional codec_pair_id, + rtc::scoped_refptr frame_decryptor, + const webrtc::CryptoOptions& crypto_options); + ~ChannelReceive() override; + + void SetSink(AudioSinkInterface* sink) override; + + void SetReceiveCodecs(const std::map& codecs) override; + + // API methods + + void StartPlayout() override; + void StopPlayout() override; + + // Codecs + bool GetRecCodec(CodecInst* codec) const override; + + bool ReceivedRTCPPacket(const uint8_t* data, size_t length) override; + + // RtpPacketSinkInterface. + void OnRtpPacket(const RtpPacketReceived& packet) override; + + // Muting, Volume and Level. + void SetChannelOutputVolumeScaling(float scaling) override; + int GetSpeechOutputLevelFullRange() const override; + // See description of "totalAudioEnergy" in the WebRTC stats spec: + // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy + double GetTotalOutputEnergy() const override; + double GetTotalOutputDuration() const override; + + // Stats. + NetworkStatistics GetNetworkStatistics() const override; + AudioDecodingCallStats GetDecodingCallStatistics() const override; + + // Audio+Video Sync. + uint32_t GetDelayEstimate() const override; + void SetMinimumPlayoutDelay(int delayMs) override; + uint32_t GetPlayoutTimestamp() const override; + + // Produces the transport-related timestamps; current_delay_ms is left unset. + absl::optional GetSyncInfo() const override; + + // RTP+RTCP + void SetLocalSSRC(unsigned int ssrc) override; + + void RegisterReceiverCongestionControlObjects( + PacketRouter* packet_router) override; + void ResetReceiverCongestionControlObjects() override; + + CallReceiveStatistics GetRTCPStatistics() const override; + void SetNACKStatus(bool enable, int maxNumberOfPackets) override; + + AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo( + int sample_rate_hz, + AudioFrame* audio_frame) override; + + int PreferredSampleRate() const override; + + // Associate to a send channel. + // Used for obtaining RTT for a receive-only channel. + void SetAssociatedSendChannel(const ChannelSend* channel) override; + + std::vector GetSources() const override; + + private: + void Init(); + void Terminate(); + + int GetRemoteSSRC(unsigned int& ssrc); // NOLINT + + bool ReceivePacket(const uint8_t* packet, + size_t packet_length, + const RTPHeader& header); + int ResendPackets(const uint16_t* sequence_numbers, int length); + void UpdatePlayoutTimestamp(bool rtcp); + + int GetRtpTimestampRateHz() const; + int64_t GetRTT() const; + + // MediaTransportAudioSinkInterface override; + void OnData(uint64_t channel_id, + MediaTransportEncodedAudioFrame frame) override; + + int32_t OnReceivedPayloadData(const uint8_t* payloadData, + size_t payloadSize, + const WebRtcRTPHeader* rtpHeader); + + // Thread checkers document and lock usage of some methods to specific threads + // we know about. The goal is to eventually split up voe::ChannelReceive into + // parts with single-threaded semantics, and thereby reduce the need for + // locks. + rtc::ThreadChecker worker_thread_checker_; + rtc::ThreadChecker module_process_thread_checker_; + // Methods accessed from audio and video threads are checked for sequential- + // only access. We don't necessarily own and control these threads, so thread + // checkers cannot be used. E.g. Chromium may transfer "ownership" from one + // audio thread to another, but access is still sequential. + rtc::RaceChecker audio_thread_race_checker_; + rtc::RaceChecker video_capture_thread_race_checker_; + rtc::CriticalSection _callbackCritSect; + rtc::CriticalSection volume_settings_critsect_; + + ChannelReceiveState channel_state_; + + RtcEventLog* const event_log_; + + // Indexed by payload type. + std::map payload_type_frequencies_; + + std::unique_ptr rtp_receive_statistics_; + std::unique_ptr _rtpRtcpModule; + const uint32_t remote_ssrc_; + + // Info for GetSources and GetSyncInfo is updated on network or worker thread, + // queried on the worker thread. + rtc::CriticalSection rtp_sources_lock_; + ContributingSources contributing_sources_ RTC_GUARDED_BY(&rtp_sources_lock_); + absl::optional last_received_rtp_timestamp_ + RTC_GUARDED_BY(&rtp_sources_lock_); + absl::optional last_received_rtp_system_time_ms_ + RTC_GUARDED_BY(&rtp_sources_lock_); + absl::optional last_received_rtp_audio_level_ + RTC_GUARDED_BY(&rtp_sources_lock_); + + std::unique_ptr audio_coding_; + AudioSinkInterface* audio_sink_ = nullptr; + AudioLevel _outputAudioLevel; + + RemoteNtpTimeEstimator ntp_estimator_ RTC_GUARDED_BY(ts_stats_lock_); + + // Timestamp of the audio pulled from NetEq. + absl::optional jitter_buffer_playout_timestamp_; + + rtc::CriticalSection video_sync_lock_; + uint32_t playout_timestamp_rtp_ RTC_GUARDED_BY(video_sync_lock_); + uint32_t playout_delay_ms_ RTC_GUARDED_BY(video_sync_lock_); + + rtc::CriticalSection ts_stats_lock_; + + std::unique_ptr rtp_ts_wraparound_handler_; + // The rtp timestamp of the first played out audio frame. + int64_t capture_start_rtp_time_stamp_; + // The capture ntp time (in local timebase) of the first played out audio + // frame. + int64_t capture_start_ntp_time_ms_ RTC_GUARDED_BY(ts_stats_lock_); + + // uses + ProcessThread* _moduleProcessThreadPtr; + AudioDeviceModule* _audioDeviceModulePtr; + float _outputGain RTC_GUARDED_BY(volume_settings_critsect_); + + // An associated send channel. + rtc::CriticalSection assoc_send_channel_lock_; + const ChannelSend* associated_send_channel_ + RTC_GUARDED_BY(assoc_send_channel_lock_); + + PacketRouter* packet_router_ = nullptr; + + rtc::ThreadChecker construction_thread_; + + MediaTransportInterface* const media_transport_; + + // E2EE Audio Frame Decryption + rtc::scoped_refptr frame_decryptor_; + webrtc::CryptoOptions crypto_options_; +}; int32_t ChannelReceive::OnReceivedPayloadData( const uint8_t* payloadData, @@ -142,6 +365,7 @@ void ChannelReceive::OnData(uint64_t channel_id, AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo( int sample_rate_hz, AudioFrame* audio_frame) { + RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_); audio_frame->sample_rate_hz_ = sample_rate_hz; unsigned int ssrc; @@ -248,6 +472,7 @@ AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo( } int ChannelReceive::PreferredSampleRate() const { + RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_); // Return the bigger of playout and receive frequency in the ACM. return std::max(audio_coding_->ReceiveFrequency(), audio_coding_->PlayoutFrequency()); @@ -284,6 +509,9 @@ ChannelReceive::ChannelReceive( media_transport_(media_transport), frame_decryptor_(frame_decryptor), crypto_options_(crypto_options) { + // TODO(nisse): Use _moduleProcessThreadPtr instead? + module_process_thread_checker_.DetachFromThread(); + RTC_DCHECK(module_process_thread); RTC_DCHECK(audio_device_module); AudioCodingModule::Config acm_config; @@ -368,11 +596,13 @@ void ChannelReceive::Terminate() { } void ChannelReceive::SetSink(AudioSinkInterface* sink) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); rtc::CritScope cs(&_callbackCritSect); audio_sink_ = sink; } void ChannelReceive::StartPlayout() { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); if (channel_state_.Get().playing) { return; } @@ -381,6 +611,7 @@ void ChannelReceive::StartPlayout() { } void ChannelReceive::StopPlayout() { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); if (!channel_state_.Get().playing) { return; } @@ -389,11 +620,13 @@ void ChannelReceive::StopPlayout() { _outputAudioLevel.Clear(); } -bool ChannelReceive::GetRecCodec(CodecInst* codec) { +bool ChannelReceive::GetRecCodec(CodecInst* codec) const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); return (audio_coding_->ReceiveCodec(codec) == 0); } std::vector ChannelReceive::GetSources() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); int64_t now_ms = rtc::TimeMillis(); std::vector sources; { @@ -411,6 +644,7 @@ std::vector ChannelReceive::GetSources() const { void ChannelReceive::SetReceiveCodecs( const std::map& codecs) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); for (const auto& kv : codecs) { RTC_DCHECK_GE(kv.second.clockrate_hz, 1000); payload_type_frequencies_[kv.first] = kv.second.clockrate_hz; @@ -418,7 +652,7 @@ void ChannelReceive::SetReceiveCodecs( audio_coding_->SetReceiveCodecs(codecs); } -// TODO(nisse): Move receive logic up to AudioReceiveStream. +// May be called on either worker thread or network thread. void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) { int64_t now_ms = rtc::TimeMillis(); uint8_t audio_level; @@ -509,6 +743,7 @@ bool ChannelReceive::ReceivePacket(const uint8_t* packet, &webrtc_rtp_header); } +// May be called on either worker thread or network thread. // TODO(nisse): Drop always-true return value. bool ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) { // Store playout timestamp for the received RTCP packet @@ -547,23 +782,28 @@ bool ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) { } int ChannelReceive::GetSpeechOutputLevelFullRange() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); return _outputAudioLevel.LevelFullRange(); } double ChannelReceive::GetTotalOutputEnergy() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); return _outputAudioLevel.TotalEnergy(); } double ChannelReceive::GetTotalOutputDuration() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); return _outputAudioLevel.TotalDuration(); } void ChannelReceive::SetChannelOutputVolumeScaling(float scaling) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); rtc::CritScope cs(&volume_settings_critsect_); _outputGain = scaling; } -void ChannelReceive::SetLocalSSRC(unsigned int ssrc) { +void ChannelReceive::SetLocalSSRC(uint32_t ssrc) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); _rtpRtcpModule->SetSSRC(ssrc); } @@ -575,6 +815,7 @@ int ChannelReceive::GetRemoteSSRC(unsigned int& ssrc) { void ChannelReceive::RegisterReceiverCongestionControlObjects( PacketRouter* packet_router) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); RTC_DCHECK(packet_router); RTC_DCHECK(!packet_router_); constexpr bool remb_candidate = false; @@ -583,12 +824,14 @@ void ChannelReceive::RegisterReceiverCongestionControlObjects( } void ChannelReceive::ResetReceiverCongestionControlObjects() { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); RTC_DCHECK(packet_router_); packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get()); packet_router_ = nullptr; } -CallReceiveStatistics ChannelReceive::GetRTCPStatistics() { +CallReceiveStatistics ChannelReceive::GetRTCPStatistics() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); // --- RtcpStatistics CallReceiveStatistics stats; @@ -630,11 +873,12 @@ CallReceiveStatistics ChannelReceive::GetRTCPStatistics() { return stats; } -void ChannelReceive::SetNACKStatus(bool enable, int maxNumberOfPackets) { +void ChannelReceive::SetNACKStatus(bool enable, int max_packets) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); // None of these functions can fail. - rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets); + rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets); if (enable) - audio_coding_->EnableNack(maxNumberOfPackets); + audio_coding_->EnableNack(max_packets); else audio_coding_->DisableNack(); } @@ -645,12 +889,14 @@ int ChannelReceive::ResendPackets(const uint16_t* sequence_numbers, return _rtpRtcpModule->SendNACK(sequence_numbers, length); } -void ChannelReceive::SetAssociatedSendChannel(ChannelSend* channel) { +void ChannelReceive::SetAssociatedSendChannel(const ChannelSend* channel) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); rtc::CritScope lock(&assoc_send_channel_lock_); associated_send_channel_ = channel; } NetworkStatistics ChannelReceive::GetNetworkStatistics() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); NetworkStatistics stats; int error = audio_coding_->GetNetworkStatistics(&stats); RTC_DCHECK_EQ(0, error); @@ -658,29 +904,37 @@ NetworkStatistics ChannelReceive::GetNetworkStatistics() const { } AudioDecodingCallStats ChannelReceive::GetDecodingCallStatistics() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); AudioDecodingCallStats stats; audio_coding_->GetDecodingCallStatistics(&stats); return stats; } uint32_t ChannelReceive::GetDelayEstimate() const { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() || + module_process_thread_checker_.CalledOnValidThread()); rtc::CritScope lock(&video_sync_lock_); return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_; } -void ChannelReceive::SetMinimumPlayoutDelay(int delayMs) { - if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) || - (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) { +void ChannelReceive::SetMinimumPlayoutDelay(int delay_ms) { + RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); + // Limit to range accepted by both VoE and ACM, so we're at least getting as + // close as possible, instead of failing. + delay_ms = rtc::SafeClamp(delay_ms, 0, 10000); + if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) || + (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs)) { RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay"; return; } - if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) { + if (audio_coding_->SetMinimumPlayoutDelay(delay_ms) != 0) { RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() failed to set min playout delay"; } } -uint32_t ChannelReceive::GetPlayoutTimestamp() { +uint32_t ChannelReceive::GetPlayoutTimestamp() const { + RTC_DCHECK_RUNS_SERIALIZED(&video_capture_thread_race_checker_); { rtc::CritScope lock(&video_sync_lock_); return playout_timestamp_rtp_; @@ -688,6 +942,7 @@ uint32_t ChannelReceive::GetPlayoutTimestamp() { } absl::optional ChannelReceive::GetSyncInfo() const { + RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); Syncable::Info info; if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs, &info.capture_time_ntp_frac, nullptr, nullptr, @@ -780,5 +1035,27 @@ int64_t ChannelReceive::GetRTT() const { return rtt; } +} // namespace + +std::unique_ptr CreateChannelReceive( + ProcessThread* module_process_thread, + AudioDeviceModule* audio_device_module, + MediaTransportInterface* media_transport, + Transport* rtcp_send_transport, + RtcEventLog* rtc_event_log, + uint32_t remote_ssrc, + size_t jitter_buffer_max_packets, + bool jitter_buffer_fast_playout, + rtc::scoped_refptr decoder_factory, + absl::optional codec_pair_id, + rtc::scoped_refptr frame_decryptor, + const webrtc::CryptoOptions& crypto_options) { + return absl::make_unique( + module_process_thread, audio_device_module, media_transport, + rtcp_send_transport, rtc_event_log, remote_ssrc, + jitter_buffer_max_packets, jitter_buffer_fast_playout, decoder_factory, + codec_pair_id, frame_decryptor, crypto_options); +} + } // namespace voe } // namespace webrtc diff --git a/audio/channel_receive.h b/audio/channel_receive.h index de2ae2aef0..fbfd7f038b 100644 --- a/audio/channel_receive.h +++ b/audio/channel_receive.h @@ -17,24 +17,18 @@ #include "absl/types/optional.h" #include "api/audio/audio_mixer.h" +#include "api/audio_codecs/audio_decoder_factory.h" #include "api/call/audio_sink.h" #include "api/call/transport.h" #include "api/crypto/cryptooptions.h" #include "api/media_transport_interface.h" #include "api/rtpreceiverinterface.h" -#include "audio/audio_level.h" +#include "call/rtp_packet_sink_interface.h" #include "call/syncable.h" #include "common_types.h" // NOLINT(build/include) -#include "modules/audio_coding/include/audio_coding_module.h" -#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h" -#include "modules/rtp_rtcp/include/rtp_header_parser.h" -#include "modules/rtp_rtcp/include/rtp_rtcp.h" -#include "modules/rtp_rtcp/source/contributing_sources.h" -#include "rtc_base/criticalsection.h" -#include "rtc_base/thread_checker.h" // TODO(solenberg, nisse): This file contains a few NOLINT marks, to silence -// warnings about use of unsigned short, and non-const reference arguments. +// warnings about use of unsigned short. // These need cleanup, in a separate cl. namespace rtc { @@ -70,205 +64,81 @@ namespace voe { class ChannelSend; -// Helper class to simplify locking scheme for members that are accessed from -// multiple threads. -// Example: a member can be set on thread T1 and read by an internal audio -// thread T2. Accessing the member via this class ensures that we are -// safe and also avoid TSan v2 warnings. -class ChannelReceiveState { +// Interface class needed for AudioReceiveStream tests that use a +// MockChannelReceive. + +class ChannelReceiveInterface : public RtpPacketSinkInterface { public: - struct State { - bool playing = false; - }; + virtual ~ChannelReceiveInterface() = default; - ChannelReceiveState() {} - virtual ~ChannelReceiveState() {} + virtual void SetSink(AudioSinkInterface* sink) = 0; - void Reset() { - rtc::CritScope lock(&lock_); - state_ = State(); - } + virtual void SetReceiveCodecs( + const std::map& codecs) = 0; - State Get() const { - rtc::CritScope lock(&lock_); - return state_; - } + virtual void StartPlayout() = 0; + virtual void StopPlayout() = 0; - void SetPlaying(bool enable) { - rtc::CritScope lock(&lock_); - state_.playing = enable; - } + virtual bool GetRecCodec(CodecInst* codec) const = 0; - private: - rtc::CriticalSection lock_; - State state_; -}; + virtual bool ReceivedRTCPPacket(const uint8_t* data, size_t length) = 0; -class ChannelReceive : public MediaTransportAudioSinkInterface { - public: - // Used for receive streams. - ChannelReceive(ProcessThread* module_process_thread, - AudioDeviceModule* audio_device_module, - MediaTransportInterface* media_transport, - Transport* rtcp_send_transport, - RtcEventLog* rtc_event_log, - uint32_t remote_ssrc, - size_t jitter_buffer_max_packets, - bool jitter_buffer_fast_playout, - rtc::scoped_refptr decoder_factory, - absl::optional codec_pair_id, - rtc::scoped_refptr frame_decryptor, - const webrtc::CryptoOptions& crypto_options); - virtual ~ChannelReceive(); - - void SetSink(AudioSinkInterface* sink); - - void SetReceiveCodecs(const std::map& codecs); - - // API methods - - void StartPlayout(); - void StopPlayout(); - - // Codecs - bool GetRecCodec(CodecInst* codec); - - // TODO(nisse, solenberg): Delete when VoENetwork is deleted. - bool ReceivedRTCPPacket(const uint8_t* data, size_t length); - void OnRtpPacket(const RtpPacketReceived& packet); - - // Muting, Volume and Level. - void SetChannelOutputVolumeScaling(float scaling); - int GetSpeechOutputLevelFullRange() const; + virtual void SetChannelOutputVolumeScaling(float scaling) = 0; + virtual int GetSpeechOutputLevelFullRange() const = 0; // See description of "totalAudioEnergy" in the WebRTC stats spec: // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy - double GetTotalOutputEnergy() const; - double GetTotalOutputDuration() const; + virtual double GetTotalOutputEnergy() const = 0; + virtual double GetTotalOutputDuration() const = 0; // Stats. - NetworkStatistics GetNetworkStatistics() const; - AudioDecodingCallStats GetDecodingCallStatistics() const; + virtual NetworkStatistics GetNetworkStatistics() const = 0; + virtual AudioDecodingCallStats GetDecodingCallStatistics() const = 0; // Audio+Video Sync. - uint32_t GetDelayEstimate() const; - void SetMinimumPlayoutDelay(int delayMs); - uint32_t GetPlayoutTimestamp(); + virtual uint32_t GetDelayEstimate() const = 0; + virtual void SetMinimumPlayoutDelay(int delay_ms) = 0; + virtual uint32_t GetPlayoutTimestamp() const = 0; // Produces the transport-related timestamps; current_delay_ms is left unset. - absl::optional GetSyncInfo() const; + virtual absl::optional GetSyncInfo() const = 0; // RTP+RTCP - void SetLocalSSRC(unsigned int ssrc); + virtual void SetLocalSSRC(uint32_t ssrc) = 0; - void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router); - void ResetReceiverCongestionControlObjects(); + virtual void RegisterReceiverCongestionControlObjects( + PacketRouter* packet_router) = 0; + virtual void ResetReceiverCongestionControlObjects() = 0; - CallReceiveStatistics GetRTCPStatistics(); - void SetNACKStatus(bool enable, int maxNumberOfPackets); + virtual CallReceiveStatistics GetRTCPStatistics() const = 0; + virtual void SetNACKStatus(bool enable, int max_packets) = 0; - // From AudioMixer::Source. - AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo( + virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo( int sample_rate_hz, - AudioFrame* audio_frame); + AudioFrame* audio_frame) = 0; - int PreferredSampleRate() const; + virtual int PreferredSampleRate() const = 0; // Associate to a send channel. // Used for obtaining RTT for a receive-only channel. - void SetAssociatedSendChannel(ChannelSend* channel); + virtual void SetAssociatedSendChannel(const ChannelSend* channel) = 0; - std::vector GetSources() const; - - private: - void Init(); - void Terminate(); - - int GetRemoteSSRC(unsigned int& ssrc); // NOLINT - - bool ReceivePacket(const uint8_t* packet, - size_t packet_length, - const RTPHeader& header); - int ResendPackets(const uint16_t* sequence_numbers, int length); - void UpdatePlayoutTimestamp(bool rtcp); - - int GetRtpTimestampRateHz() const; - int64_t GetRTT() const; - - // MediaTransportAudioSinkInterface override; - void OnData(uint64_t channel_id, - MediaTransportEncodedAudioFrame frame) override; - - int32_t OnReceivedPayloadData(const uint8_t* payloadData, - size_t payloadSize, - const WebRtcRTPHeader* rtpHeader); - rtc::CriticalSection _callbackCritSect; - rtc::CriticalSection volume_settings_critsect_; - - ChannelReceiveState channel_state_; - - RtcEventLog* const event_log_; - - // Indexed by payload type. - std::map payload_type_frequencies_; - - std::unique_ptr rtp_receive_statistics_; - std::unique_ptr _rtpRtcpModule; - const uint32_t remote_ssrc_; - - // Info for GetSources and GetSyncInfo is updated on network or worker thread, - // queried on the worker thread. - rtc::CriticalSection rtp_sources_lock_; - ContributingSources contributing_sources_ RTC_GUARDED_BY(&rtp_sources_lock_); - absl::optional last_received_rtp_timestamp_ - RTC_GUARDED_BY(&rtp_sources_lock_); - absl::optional last_received_rtp_system_time_ms_ - RTC_GUARDED_BY(&rtp_sources_lock_); - absl::optional last_received_rtp_audio_level_ - RTC_GUARDED_BY(&rtp_sources_lock_); - - std::unique_ptr audio_coding_; - AudioSinkInterface* audio_sink_ = nullptr; - AudioLevel _outputAudioLevel; - - RemoteNtpTimeEstimator ntp_estimator_ RTC_GUARDED_BY(ts_stats_lock_); - - // Timestamp of the audio pulled from NetEq. - absl::optional jitter_buffer_playout_timestamp_; - - rtc::CriticalSection video_sync_lock_; - uint32_t playout_timestamp_rtp_ RTC_GUARDED_BY(video_sync_lock_); - uint32_t playout_delay_ms_ RTC_GUARDED_BY(video_sync_lock_); - - rtc::CriticalSection ts_stats_lock_; - - std::unique_ptr rtp_ts_wraparound_handler_; - // The rtp timestamp of the first played out audio frame. - int64_t capture_start_rtp_time_stamp_; - // The capture ntp time (in local timebase) of the first played out audio - // frame. - int64_t capture_start_ntp_time_ms_ RTC_GUARDED_BY(ts_stats_lock_); - - // uses - ProcessThread* _moduleProcessThreadPtr; - AudioDeviceModule* _audioDeviceModulePtr; - float _outputGain RTC_GUARDED_BY(volume_settings_critsect_); - - // An associated send channel. - rtc::CriticalSection assoc_send_channel_lock_; - ChannelSend* associated_send_channel_ - RTC_GUARDED_BY(assoc_send_channel_lock_); - - PacketRouter* packet_router_ = nullptr; - - rtc::ThreadChecker construction_thread_; - - MediaTransportInterface* const media_transport_; - - // E2EE Audio Frame Decryption - rtc::scoped_refptr frame_decryptor_; - webrtc::CryptoOptions crypto_options_; + virtual std::vector GetSources() const = 0; }; +std::unique_ptr CreateChannelReceive( + ProcessThread* module_process_thread, + AudioDeviceModule* audio_device_module, + MediaTransportInterface* media_transport, + Transport* rtcp_send_transport, + RtcEventLog* rtc_event_log, + uint32_t remote_ssrc, + size_t jitter_buffer_max_packets, + bool jitter_buffer_fast_playout, + rtc::scoped_refptr decoder_factory, + absl::optional codec_pair_id, + rtc::scoped_refptr frame_decryptor, + const webrtc::CryptoOptions& crypto_options); + } // namespace voe } // namespace webrtc diff --git a/audio/channel_receive_proxy.cc b/audio/channel_receive_proxy.cc deleted file mode 100644 index 36beaf12e3..0000000000 --- a/audio/channel_receive_proxy.cc +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "audio/channel_receive_proxy.h" - -#include - -#include "api/call/audio_sink.h" -#include "audio/channel_send_proxy.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/numerics/safe_minmax.h" - -namespace webrtc { -namespace voe { -ChannelReceiveProxy::ChannelReceiveProxy() {} - -ChannelReceiveProxy::ChannelReceiveProxy( - std::unique_ptr channel) - : channel_(std::move(channel)) { - RTC_DCHECK(channel_); - module_process_thread_checker_.DetachFromThread(); -} - -ChannelReceiveProxy::~ChannelReceiveProxy() {} - -void ChannelReceiveProxy::SetLocalSSRC(uint32_t ssrc) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetLocalSSRC(ssrc); -} - -void ChannelReceiveProxy::SetNACKStatus(bool enable, int max_packets) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetNACKStatus(enable, max_packets); -} - -CallReceiveStatistics ChannelReceiveProxy::GetRTCPStatistics() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetRTCPStatistics(); -} - -bool ChannelReceiveProxy::ReceivedRTCPPacket(const uint8_t* packet, - size_t length) { - // May be called on either worker thread or network thread. - return channel_->ReceivedRTCPPacket(packet, length) == 0; -} - -void ChannelReceiveProxy::RegisterReceiverCongestionControlObjects( - PacketRouter* packet_router) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->RegisterReceiverCongestionControlObjects(packet_router); -} - -void ChannelReceiveProxy::ResetReceiverCongestionControlObjects() { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->ResetReceiverCongestionControlObjects(); -} - -NetworkStatistics ChannelReceiveProxy::GetNetworkStatistics() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetNetworkStatistics(); -} - -AudioDecodingCallStats ChannelReceiveProxy::GetDecodingCallStatistics() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetDecodingCallStatistics(); -} - -int ChannelReceiveProxy::GetSpeechOutputLevelFullRange() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetSpeechOutputLevelFullRange(); -} - -double ChannelReceiveProxy::GetTotalOutputEnergy() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetTotalOutputEnergy(); -} - -double ChannelReceiveProxy::GetTotalOutputDuration() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetTotalOutputDuration(); -} - -uint32_t ChannelReceiveProxy::GetDelayEstimate() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() || - module_process_thread_checker_.CalledOnValidThread()); - return channel_->GetDelayEstimate(); -} - -void ChannelReceiveProxy::SetReceiveCodecs( - const std::map& codecs) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetReceiveCodecs(codecs); -} - -void ChannelReceiveProxy::SetSink(AudioSinkInterface* sink) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetSink(sink); -} - -void ChannelReceiveProxy::OnRtpPacket(const RtpPacketReceived& packet) { - // May be called on either worker thread or network thread. - channel_->OnRtpPacket(packet); -} - -void ChannelReceiveProxy::SetChannelOutputVolumeScaling(float scaling) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetChannelOutputVolumeScaling(scaling); -} - -AudioMixer::Source::AudioFrameInfo ChannelReceiveProxy::GetAudioFrameWithInfo( - int sample_rate_hz, - AudioFrame* audio_frame) { - RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_); - return channel_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame); -} - -int ChannelReceiveProxy::PreferredSampleRate() const { - RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_); - return channel_->PreferredSampleRate(); -} - -void ChannelReceiveProxy::AssociateSendChannel( - const ChannelSendProxy& send_channel_proxy) { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetAssociatedSendChannel(send_channel_proxy.GetChannel()); -} - -void ChannelReceiveProxy::DisassociateSendChannel() { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->SetAssociatedSendChannel(nullptr); -} - -absl::optional ChannelReceiveProxy::GetSyncInfo() const { - RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); - return channel_->GetSyncInfo(); -} - -uint32_t ChannelReceiveProxy::GetPlayoutTimestamp() const { - RTC_DCHECK_RUNS_SERIALIZED(&video_capture_thread_race_checker_); - return channel_->GetPlayoutTimestamp(); -} - -void ChannelReceiveProxy::SetMinimumPlayoutDelay(int delay_ms) { - RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); - // Limit to range accepted by both VoE and ACM, so we're at least getting as - // close as possible, instead of failing. - delay_ms = rtc::SafeClamp(delay_ms, 0, 10000); - channel_->SetMinimumPlayoutDelay(delay_ms); -} - -bool ChannelReceiveProxy::GetRecCodec(CodecInst* codec_inst) const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetRecCodec(codec_inst); -} - -std::vector ChannelReceiveProxy::GetSources() const { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return channel_->GetSources(); -} - -void ChannelReceiveProxy::StartPlayout() { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->StartPlayout(); -} - -void ChannelReceiveProxy::StopPlayout() { - RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - channel_->StopPlayout(); -} -} // namespace voe -} // namespace webrtc diff --git a/audio/channel_receive_proxy.h b/audio/channel_receive_proxy.h deleted file mode 100644 index 8ebacc300d..0000000000 --- a/audio/channel_receive_proxy.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef AUDIO_CHANNEL_RECEIVE_PROXY_H_ -#define AUDIO_CHANNEL_RECEIVE_PROXY_H_ - -#include -#include -#include - -#include "api/audio/audio_mixer.h" -#include "api/rtpreceiverinterface.h" -#include "audio/channel_receive.h" -#include "call/rtp_packet_sink_interface.h" -#include "rtc_base/constructormagic.h" -#include "rtc_base/race_checker.h" -#include "rtc_base/thread_checker.h" - -namespace webrtc { - -class AudioSinkInterface; -class PacketRouter; -class RtpPacketReceived; -class Transport; - -namespace voe { - -class ChannelSendProxy; - -// This class provides the "view" of a voe::Channel that we need to implement -// webrtc::AudioReceiveStream. It serves two purposes: -// 1. Allow mocking just the interfaces used, instead of the entire -// voe::Channel class. -// 2. Provide a refined interface for the stream classes, including assumptions -// on return values and input adaptation. -class ChannelReceiveProxy : public RtpPacketSinkInterface { - public: - ChannelReceiveProxy(); - explicit ChannelReceiveProxy(std::unique_ptr channel); - virtual ~ChannelReceiveProxy(); - - // Shared with ChannelSendProxy - virtual void SetLocalSSRC(uint32_t ssrc); - virtual void SetNACKStatus(bool enable, int max_packets); - virtual CallReceiveStatistics GetRTCPStatistics() const; - virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length); - - virtual void RegisterReceiverCongestionControlObjects( - PacketRouter* packet_router); - virtual void ResetReceiverCongestionControlObjects(); - virtual NetworkStatistics GetNetworkStatistics() const; - virtual AudioDecodingCallStats GetDecodingCallStatistics() const; - virtual int GetSpeechOutputLevelFullRange() const; - // See description of "totalAudioEnergy" in the WebRTC stats spec: - // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy - virtual double GetTotalOutputEnergy() const; - virtual double GetTotalOutputDuration() const; - virtual uint32_t GetDelayEstimate() const; - virtual void SetReceiveCodecs(const std::map& codecs); - virtual void SetSink(AudioSinkInterface* sink); - - // Implements RtpPacketSinkInterface - void OnRtpPacket(const RtpPacketReceived& packet) override; - - virtual void SetChannelOutputVolumeScaling(float scaling); - virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo( - int sample_rate_hz, - AudioFrame* audio_frame); - virtual int PreferredSampleRate() const; - virtual void AssociateSendChannel(const ChannelSendProxy& send_channel_proxy); - virtual void DisassociateSendChannel(); - - // Produces the transport-related timestamps; current_delay_ms is left unset. - absl::optional GetSyncInfo() const; - virtual uint32_t GetPlayoutTimestamp() const; - virtual void SetMinimumPlayoutDelay(int delay_ms); - virtual bool GetRecCodec(CodecInst* codec_inst) const; - virtual std::vector GetSources() const; - virtual void StartPlayout(); - virtual void StopPlayout(); - - private: - // Thread checkers document and lock usage of some methods on voe::Channel to - // specific threads we know about. The goal is to eventually split up - // voe::Channel into parts with single-threaded semantics, and thereby reduce - // the need for locks. - rtc::ThreadChecker worker_thread_checker_; - rtc::ThreadChecker module_process_thread_checker_; - // Methods accessed from audio and video threads are checked for sequential- - // only access. We don't necessarily own and control these threads, so thread - // checkers cannot be used. E.g. Chromium may transfer "ownership" from one - // audio thread to another, but access is still sequential. - rtc::RaceChecker audio_thread_race_checker_; - rtc::RaceChecker video_capture_thread_race_checker_; - std::unique_ptr channel_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ChannelReceiveProxy); -}; -} // namespace voe -} // namespace webrtc - -#endif // AUDIO_CHANNEL_RECEIVE_PROXY_H_ diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h index 962152f2e6..0571c8daba 100644 --- a/audio/mock_voe_channel_proxy.h +++ b/audio/mock_voe_channel_proxy.h @@ -17,7 +17,7 @@ #include #include "api/test/mock_frame_encryptor.h" -#include "audio/channel_receive_proxy.h" +#include "audio/channel_receive.h" #include "audio/channel_send_proxy.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "test/gmock.h" @@ -25,7 +25,7 @@ namespace webrtc { namespace test { -class MockChannelReceiveProxy : public voe::ChannelReceiveProxy { +class MockChannelReceive : public voe::ChannelReceiveInterface { public: MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc)); MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets)); @@ -47,10 +47,10 @@ class MockChannelReceiveProxy : public voe::ChannelReceiveProxy { AudioMixer::Source::AudioFrameInfo(int sample_rate_hz, AudioFrame* audio_frame)); MOCK_CONST_METHOD0(PreferredSampleRate, int()); - MOCK_METHOD1(AssociateSendChannel, - void(const voe::ChannelSendProxy& send_channel_proxy)); - MOCK_METHOD0(DisassociateSendChannel, void()); + MOCK_METHOD1(SetAssociatedSendChannel, + void(const voe::ChannelSend* send_channel)); MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t()); + MOCK_CONST_METHOD0(GetSyncInfo, absl::optional()); MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms)); MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst)); MOCK_METHOD1(SetReceiveCodecs,