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,