From 530ead49744204cb758c4345ab9d07c49f269b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= Date: Thu, 4 Oct 2018 14:28:39 +0200 Subject: [PATCH] Split voe::Channel into ChannelSend and ChannelReceive Bug: webrtc:9801 Change-Id: Ia15af1e53c8d384ad6e5fbddcb25311fce4befae Reviewed-on: https://webrtc-review.googlesource.com/c/103640 Reviewed-by: Fredrik Solenberg Reviewed-by: Karl Wiberg Commit-Queue: Niels Moller Cr-Commit-Position: refs/heads/master@{#24992} --- audio/BUILD.gn | 6 +- audio/audio_receive_stream.cc | 5 +- audio/audio_receive_stream_unittest.cc | 4 +- audio/audio_send_stream.cc | 15 +- audio/audio_send_stream_unittest.cc | 3 +- audio/channel_receive.cc | 711 +++++++++++++++++++++++++ audio/channel_receive.h | 271 ++++++++++ audio/channel_receive_proxy.cc | 7 +- audio/channel_receive_proxy.h | 8 +- audio/{channel.cc => channel_send.cc} | 675 +++-------------------- audio/{channel.h => channel_send.h} | 168 +----- audio/channel_send_proxy.cc | 8 +- audio/channel_send_proxy.h | 10 +- audio/mock_voe_channel_proxy.h | 4 +- 14 files changed, 1124 insertions(+), 771 deletions(-) create mode 100644 audio/channel_receive.cc create mode 100644 audio/channel_receive.h rename audio/{channel.cc => channel_send.cc} (56%) rename audio/{channel.h => channel_send.h} (59%) diff --git a/audio/BUILD.gn b/audio/BUILD.gn index e42a726ccd..91cece93cb 100644 --- a/audio/BUILD.gn +++ b/audio/BUILD.gn @@ -24,10 +24,12 @@ rtc_static_library("audio") { "audio_state.h", "audio_transport_impl.cc", "audio_transport_impl.h", - "channel.cc", - "channel.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", "channel_send_proxy.h", "conversion.h", diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index e6c9b96c5a..b9faea5bf8 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -71,7 +71,7 @@ std::unique_ptr CreateChannelAndProxy( internal::AudioState* internal_audio_state = static_cast(audio_state); return absl::make_unique( - absl::make_unique( + absl::make_unique( module_process_thread, internal_audio_state->audio_device_module(), nullptr /* RtcpRttStats */, event_log, config.rtp.remote_ssrc, config.jitter_buffer_max_packets, @@ -166,7 +166,8 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const { webrtc::AudioReceiveStream::Stats stats; stats.remote_ssrc = config_.rtp.remote_ssrc; - webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics(); + webrtc::CallReceiveStatistics call_stats = + channel_proxy_->GetRTCPStatistics(); // TODO(solenberg): Don't return here if we can't get the codec - return the // stats we *can* get. webrtc::CodecInst codec_inst = {0}; diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc index 59963da846..c5c53e5825 100644 --- a/audio/audio_receive_stream_unittest.cc +++ b/audio/audio_receive_stream_unittest.cc @@ -59,8 +59,8 @@ const unsigned int kSpeechOutputLevel = 99; const double kTotalOutputEnergy = 0.25; const double kTotalOutputDuration = 0.5; -const CallStatistics kCallStats = {345, 678, 901, 234, -12, - 3456, 7890, 567, 890, 123}; +const CallReceiveStatistics kCallStats = {345, 678, 901, 234, + -12, 567, 890, 123}; const CodecInst kCodecInst = {123, "codec_name_recv", 96000, -187, 0, -103}; const NetworkStatistics kNetworkStats = { 123, 456, false, 789012, 3456, 123, 456, 0, {}, 789, 12, diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 8de7a71b9f..06be261f85 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -47,19 +47,13 @@ void CallEncoder(const std::unique_ptr& channel_proxy, } std::unique_ptr CreateChannelAndProxy( - webrtc::AudioState* audio_state, rtc::TaskQueue* worker_queue, ProcessThread* module_process_thread, RtcpRttStats* rtcp_rtt_stats, RtcEventLog* event_log) { - RTC_DCHECK(audio_state); - internal::AudioState* internal_audio_state = - static_cast(audio_state); return absl::make_unique( - absl::make_unique( - worker_queue, module_process_thread, - internal_audio_state->audio_device_module(), rtcp_rtt_stats, - event_log)); + absl::make_unique(worker_queue, module_process_thread, + rtcp_rtt_stats, event_log)); } } // namespace @@ -106,8 +100,7 @@ AudioSendStream::AudioSendStream( rtcp_rtt_stats, suspended_rtp_state, overall_call_lifetime, - CreateChannelAndProxy(audio_state.get(), - worker_queue, + CreateChannelAndProxy(worker_queue, module_process_thread, rtcp_rtt_stats, event_log)) {} @@ -352,7 +345,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats( webrtc::AudioSendStream::Stats stats; stats.local_ssrc = config_.rtp.ssrc; - webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics(); + webrtc::CallSendStatistics call_stats = channel_proxy_->GetRTCPStatistics(); stats.bytes_sent = call_stats.bytesSent; stats.packets_sent = call_stats.packetsSent; // RTT isn't known until a RTCP report is received. Until then, VoiceEngine diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc index 0fa2393325..0ed1ac18f6 100644 --- a/audio/audio_send_stream_unittest.cc +++ b/audio/audio_send_stream_unittest.cc @@ -56,8 +56,7 @@ const double kEchoReturnLoss = -65; const double kEchoReturnLossEnhancement = 101; const double kResidualEchoLikelihood = -1.0f; const double kResidualEchoLikelihoodMax = 23.0f; -const CallStatistics kCallStats = {1345, 1678, 1901, 1234, 112, - 13456, 17890, 1567, -1890, -1123}; +const CallSendStatistics kCallStats = {112, 13456, 17890}; const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354}; const int kTelephoneEventPayloadType = 123; const int kTelephoneEventPayloadFrequency = 65432; diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc new file mode 100644 index 0000000000..784e4a7747 --- /dev/null +++ b/audio/channel_receive.cc @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2012 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.h" + +#include +#include +#include +#include +#include +#include + +#include "absl/memory/memory.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_device/include/audio_device.h" +#include "modules/pacing/packet_router.h" +#include "modules/rtp_rtcp/include/receive_statistics.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "modules/utility/include/process_thread.h" +#include "rtc_base/checks.h" +#include "rtc_base/criticalsection.h" +#include "rtc_base/format_macros.h" +#include "rtc_base/location.h" +#include "rtc_base/logging.h" +#include "rtc_base/thread_checker.h" +#include "rtc_base/timeutils.h" +#include "system_wrappers/include/metrics.h" + +namespace webrtc { +namespace voe { + +namespace { + +constexpr double kAudioSampleDurationSeconds = 0.01; +constexpr int64_t kMaxRetransmissionWindowMs = 1000; +constexpr int64_t kMinRetransmissionWindowMs = 30; + +// Video Sync. +constexpr int kVoiceEngineMinMinPlayoutDelayMs = 0; +constexpr int kVoiceEngineMaxMinPlayoutDelayMs = 10000; + +} // namespace + +bool ChannelReceive::SendRtp(const uint8_t* data, + size_t len, + const PacketOptions& options) { + RTC_NOTREACHED(); + return false; +} + +bool ChannelReceive::SendRtcp(const uint8_t* data, size_t len) { + rtc::CritScope cs(&_callbackCritSect); + if (_transportPtr == NULL) { + RTC_DLOG(LS_ERROR) + << "ChannelReceive::SendRtcp() failed to send RTCP packet due to" + << " invalid transport object"; + return false; + } + + int n = _transportPtr->SendRtcp(data, len); + if (n < 0) { + RTC_DLOG(LS_ERROR) << "ChannelReceive::SendRtcp() transmission failed"; + return false; + } + return true; +} + +int32_t ChannelReceive::OnReceivedPayloadData( + const uint8_t* payloadData, + size_t payloadSize, + const WebRtcRTPHeader* rtpHeader) { + if (!channel_state_.Get().playing) { + // Avoid inserting into NetEQ when we are not playing. Count the + // packet as discarded. + return 0; + } + + // Push the incoming payload (parsed and ready for decoding) into the ACM + if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) != + 0) { + RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to " + "push data to the ACM"; + return -1; + } + + int64_t round_trip_time = 0; + _rtpRtcpModule->RTT(remote_ssrc_, &round_trip_time, NULL, NULL, NULL); + + std::vector nack_list = audio_coding_->GetNackList(round_trip_time); + if (!nack_list.empty()) { + // Can't use nack_list.data() since it's not supported by all + // compilers. + ResendPackets(&(nack_list[0]), static_cast(nack_list.size())); + } + return 0; +} + +AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo( + int sample_rate_hz, + AudioFrame* audio_frame) { + audio_frame->sample_rate_hz_ = sample_rate_hz; + + unsigned int ssrc; + RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0); + event_log_->Log(absl::make_unique(ssrc)); + // Get 10ms raw PCM data from the ACM (mixer limits output frequency) + bool muted; + if (audio_coding_->PlayoutData10Ms(audio_frame->sample_rate_hz_, audio_frame, + &muted) == -1) { + RTC_DLOG(LS_ERROR) + << "ChannelReceive::GetAudioFrame() PlayoutData10Ms() failed!"; + // In all likelihood, the audio in this frame is garbage. We return an + // error so that the audio mixer module doesn't add it to the mix. As + // a result, it won't be played out and the actions skipped here are + // irrelevant. + return AudioMixer::Source::AudioFrameInfo::kError; + } + + if (muted) { + // TODO(henrik.lundin): We should be able to do better than this. But we + // will have to go through all the cases below where the audio samples may + // be used, and handle the muted case in some way. + AudioFrameOperations::Mute(audio_frame); + } + + { + // Pass the audio buffers to an optional sink callback, before applying + // scaling/panning, as that applies to the mix operation. + // External recipients of the audio (e.g. via AudioTrack), will do their + // own mixing/dynamic processing. + rtc::CritScope cs(&_callbackCritSect); + if (audio_sink_) { + AudioSinkInterface::Data data( + audio_frame->data(), audio_frame->samples_per_channel_, + audio_frame->sample_rate_hz_, audio_frame->num_channels_, + audio_frame->timestamp_); + audio_sink_->OnData(data); + } + } + + float output_gain = 1.0f; + { + rtc::CritScope cs(&volume_settings_critsect_); + output_gain = _outputGain; + } + + // Output volume scaling + if (output_gain < 0.99f || output_gain > 1.01f) { + // TODO(solenberg): Combine with mute state - this can cause clicks! + AudioFrameOperations::ScaleWithSat(output_gain, audio_frame); + } + + // Measure audio level (0-9) + // TODO(henrik.lundin) Use the |muted| information here too. + // TODO(deadbeef): Use RmsLevel for |_outputAudioLevel| (see + // https://crbug.com/webrtc/7517). + _outputAudioLevel.ComputeLevel(*audio_frame, kAudioSampleDurationSeconds); + + if (capture_start_rtp_time_stamp_ < 0 && audio_frame->timestamp_ != 0) { + // The first frame with a valid rtp timestamp. + capture_start_rtp_time_stamp_ = audio_frame->timestamp_; + } + + if (capture_start_rtp_time_stamp_ >= 0) { + // audio_frame.timestamp_ should be valid from now on. + + // Compute elapsed time. + int64_t unwrap_timestamp = + rtp_ts_wraparound_handler_->Unwrap(audio_frame->timestamp_); + audio_frame->elapsed_time_ms_ = + (unwrap_timestamp - capture_start_rtp_time_stamp_) / + (GetRtpTimestampRateHz() / 1000); + + { + rtc::CritScope lock(&ts_stats_lock_); + // Compute ntp time. + audio_frame->ntp_time_ms_ = + ntp_estimator_.Estimate(audio_frame->timestamp_); + // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received. + if (audio_frame->ntp_time_ms_ > 0) { + // Compute |capture_start_ntp_time_ms_| so that + // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_| + capture_start_ntp_time_ms_ = + audio_frame->ntp_time_ms_ - audio_frame->elapsed_time_ms_; + } + } + } + + { + RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.TargetJitterBufferDelayMs", + audio_coding_->TargetDelayMs()); + const int jitter_buffer_delay = audio_coding_->FilteredCurrentDelayMs(); + rtc::CritScope lock(&video_sync_lock_); + RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverDelayEstimateMs", + jitter_buffer_delay + playout_delay_ms_); + RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverJitterBufferDelayMs", + jitter_buffer_delay); + RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverDeviceDelayMs", + playout_delay_ms_); + } + + return muted ? AudioMixer::Source::AudioFrameInfo::kMuted + : AudioMixer::Source::AudioFrameInfo::kNormal; +} + +int ChannelReceive::PreferredSampleRate() const { + // Return the bigger of playout and receive frequency in the ACM. + return std::max(audio_coding_->ReceiveFrequency(), + audio_coding_->PlayoutFrequency()); +} + +ChannelReceive::ChannelReceive( + ProcessThread* module_process_thread, + AudioDeviceModule* audio_device_module, + RtcpRttStats* rtcp_rtt_stats, + 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) + : event_log_(rtc_event_log), + rtp_receive_statistics_( + ReceiveStatistics::Create(Clock::GetRealTimeClock())), + remote_ssrc_(remote_ssrc), + _outputAudioLevel(), + ntp_estimator_(Clock::GetRealTimeClock()), + playout_timestamp_rtp_(0), + playout_delay_ms_(0), + rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()), + capture_start_rtp_time_stamp_(-1), + capture_start_ntp_time_ms_(-1), + _moduleProcessThreadPtr(module_process_thread), + _audioDeviceModulePtr(audio_device_module), + _transportPtr(NULL), + _outputGain(1.0f), + associated_send_channel_(nullptr) { + RTC_DCHECK(module_process_thread); + RTC_DCHECK(audio_device_module); + AudioCodingModule::Config acm_config; + acm_config.decoder_factory = decoder_factory; + acm_config.neteq_config.codec_pair_id = codec_pair_id; + acm_config.neteq_config.max_packets_in_buffer = jitter_buffer_max_packets; + acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout; + acm_config.neteq_config.enable_muted_state = true; + audio_coding_.reset(AudioCodingModule::Create(acm_config)); + + _outputAudioLevel.Clear(); + + rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true); + RtpRtcp::Configuration configuration; + configuration.audio = true; + configuration.outgoing_transport = this; + configuration.receive_statistics = rtp_receive_statistics_.get(); + + configuration.event_log = event_log_; + configuration.rtt_stats = rtcp_rtt_stats; + + _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); + _rtpRtcpModule->SetSendingMediaStatus(false); + _rtpRtcpModule->SetRemoteSSRC(remote_ssrc_); + Init(); +} + +ChannelReceive::~ChannelReceive() { + Terminate(); + RTC_DCHECK(!channel_state_.Get().playing); +} + +void ChannelReceive::Init() { + channel_state_.Reset(); + + // --- Add modules to process thread (for periodic schedulation) + _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get(), RTC_FROM_HERE); + + // --- ACM initialization + int error = audio_coding_->InitializeReceiver(); + RTC_DCHECK_EQ(0, error); + + // --- RTP/RTCP module initialization + + // Ensure that RTCP is enabled by default for the created channel. + // Note that, the module will keep generating RTCP until it is explicitly + // disabled by the user. + // After StopListen (when no sockets exists), RTCP packets will no longer + // be transmitted since the Transport object will then be invalid. + // RTCP is enabled by default. + _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound); +} + +void ChannelReceive::Terminate() { + RTC_DCHECK(construction_thread_.CalledOnValidThread()); + // Must be called on the same thread as Init(). + rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL); + + StopPlayout(); + + // The order to safely shutdown modules in a channel is: + // 1. De-register callbacks in modules + // 2. De-register modules in process thread + // 3. Destroy modules + int error = audio_coding_->RegisterTransportCallback(NULL); + RTC_DCHECK_EQ(0, error); + + // De-register modules in process thread + if (_moduleProcessThreadPtr) + _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()); + + // End of modules shutdown +} + +void ChannelReceive::SetSink(AudioSinkInterface* sink) { + rtc::CritScope cs(&_callbackCritSect); + audio_sink_ = sink; +} + +int32_t ChannelReceive::StartPlayout() { + if (channel_state_.Get().playing) { + return 0; + } + + channel_state_.SetPlaying(true); + + return 0; +} + +int32_t ChannelReceive::StopPlayout() { + if (!channel_state_.Get().playing) { + return 0; + } + + channel_state_.SetPlaying(false); + _outputAudioLevel.Clear(); + + return 0; +} + +int32_t ChannelReceive::GetRecCodec(CodecInst& codec) { + return (audio_coding_->ReceiveCodec(&codec)); +} + +std::vector ChannelReceive::GetSources() const { + int64_t now_ms = rtc::TimeMillis(); + std::vector sources; + { + rtc::CritScope cs(&rtp_sources_lock_); + sources = contributing_sources_.GetSources(now_ms); + if (last_received_rtp_system_time_ms_ >= + now_ms - ContributingSources::kHistoryMs) { + sources.emplace_back(*last_received_rtp_system_time_ms_, remote_ssrc_, + RtpSourceType::SSRC); + sources.back().set_audio_level(last_received_rtp_audio_level_); + } + } + return sources; +} + +void ChannelReceive::SetReceiveCodecs( + const std::map& codecs) { + for (const auto& kv : codecs) { + RTC_DCHECK_GE(kv.second.clockrate_hz, 1000); + payload_type_frequencies_[kv.first] = kv.second.clockrate_hz; + } + audio_coding_->SetReceiveCodecs(codecs); +} + +void ChannelReceive::RegisterTransport(Transport* transport) { + rtc::CritScope cs(&_callbackCritSect); + _transportPtr = transport; +} + +// TODO(nisse): Move receive logic up to AudioReceiveStream. +void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) { + int64_t now_ms = rtc::TimeMillis(); + uint8_t audio_level; + bool voice_activity; + bool has_audio_level = + packet.GetExtension<::webrtc::AudioLevel>(&voice_activity, &audio_level); + + { + rtc::CritScope cs(&rtp_sources_lock_); + last_received_rtp_timestamp_ = packet.Timestamp(); + last_received_rtp_system_time_ms_ = now_ms; + if (has_audio_level) + last_received_rtp_audio_level_ = audio_level; + std::vector csrcs = packet.Csrcs(); + contributing_sources_.Update(now_ms, csrcs); + } + + // Store playout timestamp for the received RTP packet + UpdatePlayoutTimestamp(false); + + const auto& it = payload_type_frequencies_.find(packet.PayloadType()); + if (it == payload_type_frequencies_.end()) + return; + // TODO(nisse): Set payload_type_frequency earlier, when packet is parsed. + RtpPacketReceived packet_copy(packet); + packet_copy.set_payload_type_frequency(it->second); + + rtp_receive_statistics_->OnRtpPacket(packet_copy); + + RTPHeader header; + packet_copy.GetHeader(&header); + + ReceivePacket(packet_copy.data(), packet_copy.size(), header); +} + +bool ChannelReceive::ReceivePacket(const uint8_t* packet, + size_t packet_length, + const RTPHeader& header) { + const uint8_t* payload = packet + header.headerLength; + assert(packet_length >= header.headerLength); + size_t payload_length = packet_length - header.headerLength; + WebRtcRTPHeader webrtc_rtp_header = {}; + webrtc_rtp_header.header = header; + + const size_t payload_data_length = payload_length - header.paddingLength; + if (payload_data_length == 0) { + webrtc_rtp_header.frameType = kEmptyFrame; + return OnReceivedPayloadData(nullptr, 0, &webrtc_rtp_header); + } + return OnReceivedPayloadData(payload, payload_data_length, + &webrtc_rtp_header); +} + +int32_t ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) { + // Store playout timestamp for the received RTCP packet + UpdatePlayoutTimestamp(true); + + // Deliver RTCP packet to RTP/RTCP module for parsing + _rtpRtcpModule->IncomingRtcpPacket(data, length); + + int64_t rtt = GetRTT(); + if (rtt == 0) { + // Waiting for valid RTT. + return 0; + } + + int64_t nack_window_ms = rtt; + if (nack_window_ms < kMinRetransmissionWindowMs) { + nack_window_ms = kMinRetransmissionWindowMs; + } else if (nack_window_ms > kMaxRetransmissionWindowMs) { + nack_window_ms = kMaxRetransmissionWindowMs; + } + + uint32_t ntp_secs = 0; + uint32_t ntp_frac = 0; + uint32_t rtp_timestamp = 0; + if (0 != _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL, + &rtp_timestamp)) { + // Waiting for RTCP. + return 0; + } + + { + rtc::CritScope lock(&ts_stats_lock_); + ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp); + } + return 0; +} + +int ChannelReceive::GetSpeechOutputLevelFullRange() const { + return _outputAudioLevel.LevelFullRange(); +} + +double ChannelReceive::GetTotalOutputEnergy() const { + return _outputAudioLevel.TotalEnergy(); +} + +double ChannelReceive::GetTotalOutputDuration() const { + return _outputAudioLevel.TotalDuration(); +} + +void ChannelReceive::SetChannelOutputVolumeScaling(float scaling) { + rtc::CritScope cs(&volume_settings_critsect_); + _outputGain = scaling; +} + +int ChannelReceive::SetLocalSSRC(unsigned int ssrc) { + _rtpRtcpModule->SetSSRC(ssrc); + return 0; +} + +// TODO(nisse): Pass ssrc in return value instead. +int ChannelReceive::GetRemoteSSRC(unsigned int& ssrc) { + ssrc = remote_ssrc_; + return 0; +} + +void ChannelReceive::RegisterReceiverCongestionControlObjects( + PacketRouter* packet_router) { + RTC_DCHECK(packet_router); + RTC_DCHECK(!packet_router_); + constexpr bool remb_candidate = false; + packet_router->AddReceiveRtpModule(_rtpRtcpModule.get(), remb_candidate); + packet_router_ = packet_router; +} + +void ChannelReceive::ResetReceiverCongestionControlObjects() { + RTC_DCHECK(packet_router_); + packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get()); + packet_router_ = nullptr; +} + +int ChannelReceive::GetRTPStatistics(CallReceiveStatistics& stats) { + // --- RtcpStatistics + + // The jitter statistics is updated for each received RTP packet and is + // based on received packets. + RtcpStatistics statistics; + StreamStatistician* statistician = + rtp_receive_statistics_->GetStatistician(remote_ssrc_); + if (statistician) { + statistician->GetStatistics(&statistics, + _rtpRtcpModule->RTCP() == RtcpMode::kOff); + } + + stats.fractionLost = statistics.fraction_lost; + stats.cumulativeLost = statistics.packets_lost; + stats.extendedMax = statistics.extended_highest_sequence_number; + stats.jitterSamples = statistics.jitter; + + // --- RTT + stats.rttMs = GetRTT(); + + // --- Data counters + + size_t bytesReceived(0); + uint32_t packetsReceived(0); + + if (statistician) { + statistician->GetDataCounters(&bytesReceived, &packetsReceived); + } + + stats.bytesReceived = bytesReceived; + stats.packetsReceived = packetsReceived; + + // --- Timestamps + { + rtc::CritScope lock(&ts_stats_lock_); + stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_; + } + return 0; +} + +void ChannelReceive::SetNACKStatus(bool enable, int maxNumberOfPackets) { + // None of these functions can fail. + rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets); + if (enable) + audio_coding_->EnableNack(maxNumberOfPackets); + else + audio_coding_->DisableNack(); +} + +// Called when we are missing one or more packets. +int ChannelReceive::ResendPackets(const uint16_t* sequence_numbers, + int length) { + return _rtpRtcpModule->SendNACK(sequence_numbers, length); +} + +void ChannelReceive::SetAssociatedSendChannel(ChannelSend* channel) { + rtc::CritScope lock(&assoc_send_channel_lock_); + associated_send_channel_ = channel; +} + +int ChannelReceive::GetNetworkStatistics(NetworkStatistics& stats) { + return audio_coding_->GetNetworkStatistics(&stats); +} + +void ChannelReceive::GetDecodingCallStatistics( + AudioDecodingCallStats* stats) const { + audio_coding_->GetDecodingCallStatistics(stats); +} + +uint32_t ChannelReceive::GetDelayEstimate() const { + rtc::CritScope lock(&video_sync_lock_); + return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_; +} + +int ChannelReceive::SetMinimumPlayoutDelay(int delayMs) { + if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) || + (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) { + RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay"; + return -1; + } + if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) { + RTC_DLOG(LS_ERROR) + << "SetMinimumPlayoutDelay() failed to set min playout delay"; + return -1; + } + return 0; +} + +int ChannelReceive::GetPlayoutTimestamp(unsigned int& timestamp) { + uint32_t playout_timestamp_rtp = 0; + { + rtc::CritScope lock(&video_sync_lock_); + playout_timestamp_rtp = playout_timestamp_rtp_; + } + if (playout_timestamp_rtp == 0) { + RTC_DLOG(LS_ERROR) << "GetPlayoutTimestamp() failed to retrieve timestamp"; + return -1; + } + timestamp = playout_timestamp_rtp; + return 0; +} + +absl::optional ChannelReceive::GetSyncInfo() const { + Syncable::Info info; + if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs, + &info.capture_time_ntp_frac, nullptr, nullptr, + &info.capture_time_source_clock) != 0) { + return absl::nullopt; + } + { + rtc::CritScope cs(&rtp_sources_lock_); + if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_ms_) { + return absl::nullopt; + } + info.latest_received_capture_timestamp = *last_received_rtp_timestamp_; + info.latest_receive_time_ms = *last_received_rtp_system_time_ms_; + } + return info; +} + +void ChannelReceive::UpdatePlayoutTimestamp(bool rtcp) { + jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp(); + + if (!jitter_buffer_playout_timestamp_) { + // This can happen if this channel has not received any RTP packets. In + // this case, NetEq is not capable of computing a playout timestamp. + return; + } + + uint16_t delay_ms = 0; + if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) { + RTC_DLOG(LS_WARNING) + << "ChannelReceive::UpdatePlayoutTimestamp() failed to read" + << " playout delay from the ADM"; + return; + } + + RTC_DCHECK(jitter_buffer_playout_timestamp_); + uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_; + + // Remove the playout delay. + playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000)); + + { + rtc::CritScope lock(&video_sync_lock_); + if (!rtcp) { + playout_timestamp_rtp_ = playout_timestamp; + } + playout_delay_ms_ = delay_ms; + } +} + +int ChannelReceive::GetRtpTimestampRateHz() const { + const auto format = audio_coding_->ReceiveFormat(); + // Default to the playout frequency if we've not gotten any packets yet. + // TODO(ossu): Zero clockrate can only happen if we've added an external + // decoder for a format we don't support internally. Remove once that way of + // adding decoders is gone! + return (format && format->clockrate_hz != 0) + ? format->clockrate_hz + : audio_coding_->PlayoutFrequency(); +} + +int64_t ChannelReceive::GetRTT() const { + RtcpMode method = _rtpRtcpModule->RTCP(); + if (method == RtcpMode::kOff) { + return 0; + } + std::vector report_blocks; + _rtpRtcpModule->RemoteRTCPStat(&report_blocks); + + // TODO(nisse): Could we check the return value from the ->RTT() call below, + // instead of checking if we have any report blocks? + if (report_blocks.empty()) { + rtc::CritScope lock(&assoc_send_channel_lock_); + // Tries to get RTT from an associated channel. + if (!associated_send_channel_) { + return 0; + } + return associated_send_channel_->GetRTT(); + } + + int64_t rtt = 0; + int64_t avg_rtt = 0; + int64_t max_rtt = 0; + int64_t min_rtt = 0; + if (_rtpRtcpModule->RTT(remote_ssrc_, &rtt, &avg_rtt, &min_rtt, &max_rtt) != + 0) { + return 0; + } + return rtt; +} + +} // namespace voe +} // namespace webrtc diff --git a/audio/channel_receive.h b/audio/channel_receive.h new file mode 100644 index 0000000000..20198c47fd --- /dev/null +++ b/audio/channel_receive.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2012 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_H_ +#define AUDIO_CHANNEL_RECEIVE_H_ + +#include +#include +#include + +#include "absl/types/optional.h" +#include "api/audio/audio_mixer.h" +#include "api/call/audio_sink.h" +#include "api/call/transport.h" +#include "api/rtpreceiverinterface.h" +#include "audio/audio_level.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. +// These need cleanup, in a separate cl. + +namespace rtc { +class TimestampWrapAroundHandler; +} + +namespace webrtc { + +class AudioDeviceModule; +class PacketRouter; +class ProcessThread; +class RateLimiter; +class ReceiveStatistics; +class RtcEventLog; +class RtpPacketReceived; +class RtpRtcp; + +struct CallReceiveStatistics { + unsigned short fractionLost; // NOLINT + unsigned int cumulativeLost; + unsigned int extendedMax; + unsigned int jitterSamples; + int64_t rttMs; + size_t bytesReceived; + int packetsReceived; + // The capture ntp time (in local timebase) of the first played out audio + // frame. + int64_t capture_start_ntp_time_ms_; +}; + +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 { + 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 RtpData, public Transport { + public: + // Used for receive streams. + ChannelReceive(ProcessThread* module_process_thread, + AudioDeviceModule* audio_device_module, + RtcpRttStats* rtcp_rtt_stats, + 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); + virtual ~ChannelReceive(); + + void SetSink(AudioSinkInterface* sink); + + void SetReceiveCodecs(const std::map& codecs); + + // API methods + + // VoEBase + int32_t StartPlayout(); + int32_t StopPlayout(); + + // Codecs + int32_t GetRecCodec(CodecInst& codec); // NOLINT + + // Network + void RegisterTransport(Transport* transport); + // TODO(nisse, solenberg): Delete when VoENetwork is deleted. + int32_t ReceivedRTCPPacket(const uint8_t* data, size_t length); + void OnRtpPacket(const RtpPacketReceived& packet); + + // Muting, Volume and Level. + void SetChannelOutputVolumeScaling(float scaling); + int GetSpeechOutputLevelFullRange() const; + // See description of "totalAudioEnergy" in the WebRTC stats spec: + // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy + double GetTotalOutputEnergy() const; + double GetTotalOutputDuration() const; + + // Stats. + int GetNetworkStatistics(NetworkStatistics& stats); // NOLINT + void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const; + + // Audio+Video Sync. + uint32_t GetDelayEstimate() const; + int SetMinimumPlayoutDelay(int delayMs); + int GetPlayoutTimestamp(unsigned int& timestamp); // NOLINT + + // Produces the transport-related timestamps; current_delay_ms is left unset. + absl::optional GetSyncInfo() const; + + // RTP+RTCP + int SetLocalSSRC(unsigned int ssrc); + + void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router); + void ResetReceiverCongestionControlObjects(); + + int GetRTPStatistics(CallReceiveStatistics& stats); // NOLINT + void SetNACKStatus(bool enable, int maxNumberOfPackets); + + // From RtpData in the RTP/RTCP module + int32_t OnReceivedPayloadData(const uint8_t* payloadData, + size_t payloadSize, + const WebRtcRTPHeader* rtpHeader) override; + + // From Transport (called by the RTP/RTCP module) + bool SendRtp(const uint8_t* data, + size_t len, + const PacketOptions& packet_options) override; + bool SendRtcp(const uint8_t* data, size_t len) override; + + // From AudioMixer::Source. + AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo( + int sample_rate_hz, + AudioFrame* audio_frame); + + int PreferredSampleRate() const; + + // Associate to a send channel. + // Used for obtaining RTT for a receive-only channel. + void SetAssociatedSendChannel(ChannelSend* channel); + + 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; + + 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; + Transport* _transportPtr; // WebRtc socket or external transport + 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_; +}; + +} // namespace voe +} // namespace webrtc + +#endif // AUDIO_CHANNEL_RECEIVE_H_ diff --git a/audio/channel_receive_proxy.cc b/audio/channel_receive_proxy.cc index c57bae063e..b68ab061dd 100644 --- a/audio/channel_receive_proxy.cc +++ b/audio/channel_receive_proxy.cc @@ -23,7 +23,8 @@ namespace webrtc { namespace voe { ChannelReceiveProxy::ChannelReceiveProxy() {} -ChannelReceiveProxy::ChannelReceiveProxy(std::unique_ptr channel) +ChannelReceiveProxy::ChannelReceiveProxy( + std::unique_ptr channel) : channel_(std::move(channel)) { RTC_DCHECK(channel_); module_process_thread_checker_.DetachFromThread(); @@ -42,9 +43,9 @@ void ChannelReceiveProxy::SetNACKStatus(bool enable, int max_packets) { channel_->SetNACKStatus(enable, max_packets); } -CallStatistics ChannelReceiveProxy::GetRTCPStatistics() const { +CallReceiveStatistics ChannelReceiveProxy::GetRTCPStatistics() const { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - CallStatistics stats = {0}; + CallReceiveStatistics stats = {0}; int error = channel_->GetRTPStatistics(stats); RTC_DCHECK_EQ(0, error); return stats; diff --git a/audio/channel_receive_proxy.h b/audio/channel_receive_proxy.h index 9426968bd6..2e65e7979e 100644 --- a/audio/channel_receive_proxy.h +++ b/audio/channel_receive_proxy.h @@ -17,7 +17,7 @@ #include "api/audio/audio_mixer.h" #include "api/rtpreceiverinterface.h" -#include "audio/channel.h" +#include "audio/channel_receive.h" #include "call/rtp_packet_sink_interface.h" #include "rtc_base/constructormagic.h" #include "rtc_base/race_checker.h" @@ -43,13 +43,13 @@ class ChannelSendProxy; class ChannelReceiveProxy : public RtpPacketSinkInterface { public: ChannelReceiveProxy(); - explicit ChannelReceiveProxy(std::unique_ptr channel); + 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 CallStatistics GetRTCPStatistics() const; + virtual CallReceiveStatistics GetRTCPStatistics() const; virtual void RegisterTransport(Transport* transport); virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length); @@ -100,7 +100,7 @@ class ChannelReceiveProxy : public RtpPacketSinkInterface { // 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_; + std::unique_ptr channel_; RTC_DISALLOW_COPY_AND_ASSIGN(ChannelReceiveProxy); }; diff --git a/audio/channel.cc b/audio/channel_send.cc similarity index 56% rename from audio/channel.cc rename to audio/channel_send.cc index 0614db98f7..0c9328f474 100644 --- a/audio/channel.cc +++ b/audio/channel_send.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "audio/channel.h" +#include "audio/channel_send.h" #include #include @@ -24,12 +24,7 @@ #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/codecs/audio_format_conversion.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_processing/include/audio_processing.h" #include "modules/pacing/packet_router.h" -#include "modules/rtp_rtcp/include/receive_statistics.h" -#include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "modules/utility/include/process_thread.h" #include "rtc_base/checks.h" #include "rtc_base/criticalsection.h" @@ -48,14 +43,9 @@ namespace voe { namespace { -constexpr double kAudioSampleDurationSeconds = 0.01; constexpr int64_t kMaxRetransmissionWindowMs = 1000; constexpr int64_t kMinRetransmissionWindowMs = 30; -// Video Sync. -constexpr int kVoiceEngineMinMinPlayoutDelayMs = 0; -constexpr int kVoiceEngineMaxMinPlayoutDelayMs = 10000; - } // namespace const int kTelephoneEventAttenuationdB = 10; @@ -165,7 +155,7 @@ class RtpPacketSenderProxy : public RtpPacketSender { class VoERtcpObserver : public RtcpBandwidthObserver { public: - explicit VoERtcpObserver(Channel* owner) + explicit VoERtcpObserver(ChannelSend* owner) : owner_(owner), bandwidth_observer_(nullptr) {} virtual ~VoERtcpObserver() {} @@ -230,17 +220,17 @@ class VoERtcpObserver : public RtcpBandwidthObserver { } private: - Channel* owner_; + ChannelSend* owner_; // Maps remote side ssrc to extended highest sequence number received. std::map extended_max_sequence_number_; rtc::CriticalSection crit_; RtcpBandwidthObserver* bandwidth_observer_ RTC_GUARDED_BY(crit_); }; -class Channel::ProcessAndEncodeAudioTask : public rtc::QueuedTask { +class ChannelSend::ProcessAndEncodeAudioTask : public rtc::QueuedTask { public: ProcessAndEncodeAudioTask(std::unique_ptr audio_frame, - Channel* channel) + ChannelSend* channel) : audio_frame_(std::move(audio_frame)), channel_(channel) { RTC_DCHECK(channel_); } @@ -253,15 +243,15 @@ class Channel::ProcessAndEncodeAudioTask : public rtc::QueuedTask { } std::unique_ptr audio_frame_; - Channel* const channel_; + ChannelSend* const channel_; }; -int32_t Channel::SendData(FrameType frameType, - uint8_t payloadType, - uint32_t timeStamp, - const uint8_t* payloadData, - size_t payloadSize, - const RTPFragmentationHeader* fragmentation) { +int32_t ChannelSend::SendData(FrameType frameType, + uint8_t payloadType, + uint32_t timeStamp, + const uint8_t* payloadData, + size_t payloadSize, + const RTPFragmentationHeader* fragmentation) { RTC_DCHECK_RUN_ON(encoder_queue_); if (_includeAudioLevelIndication) { // Store current audio level in the RTP/RTCP module. @@ -280,268 +270,87 @@ int32_t Channel::SendData(FrameType frameType, // undefined for voice for now. -1, payloadData, payloadSize, fragmentation, nullptr, nullptr)) { RTC_DLOG(LS_ERROR) - << "Channel::SendData() failed to send data to RTP/RTCP module"; + << "ChannelSend::SendData() failed to send data to RTP/RTCP module"; return -1; } return 0; } -bool Channel::SendRtp(const uint8_t* data, - size_t len, - const PacketOptions& options) { +bool ChannelSend::SendRtp(const uint8_t* data, + size_t len, + const PacketOptions& options) { rtc::CritScope cs(&_callbackCritSect); if (_transportPtr == NULL) { RTC_DLOG(LS_ERROR) - << "Channel::SendPacket() failed to send RTP packet due to" + << "ChannelSend::SendPacket() failed to send RTP packet due to" << " invalid transport object"; return false; } if (!_transportPtr->SendRtp(data, len, options)) { - RTC_DLOG(LS_ERROR) << "Channel::SendPacket() RTP transmission failed"; + RTC_DLOG(LS_ERROR) << "ChannelSend::SendPacket() RTP transmission failed"; return false; } return true; } -bool Channel::SendRtcp(const uint8_t* data, size_t len) { +bool ChannelSend::SendRtcp(const uint8_t* data, size_t len) { rtc::CritScope cs(&_callbackCritSect); if (_transportPtr == NULL) { RTC_DLOG(LS_ERROR) - << "Channel::SendRtcp() failed to send RTCP packet due to" + << "ChannelSend::SendRtcp() failed to send RTCP packet due to" << " invalid transport object"; return false; } int n = _transportPtr->SendRtcp(data, len); if (n < 0) { - RTC_DLOG(LS_ERROR) << "Channel::SendRtcp() transmission failed"; + RTC_DLOG(LS_ERROR) << "ChannelSend::SendRtcp() transmission failed"; return false; } return true; } -int32_t Channel::OnReceivedPayloadData(const uint8_t* payloadData, - size_t payloadSize, - const WebRtcRTPHeader* rtpHeader) { - if (!channel_state_.Get().playing) { - // Avoid inserting into NetEQ when we are not playing. Count the - // packet as discarded. - return 0; - } - - // Push the incoming payload (parsed and ready for decoding) into the ACM - if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) != - 0) { - RTC_DLOG(LS_ERROR) - << "Channel::OnReceivedPayloadData() unable to push data to the ACM"; - return -1; - } - - int64_t round_trip_time = 0; - _rtpRtcpModule->RTT(remote_ssrc_, &round_trip_time, NULL, NULL, NULL); - - std::vector nack_list = audio_coding_->GetNackList(round_trip_time); - if (!nack_list.empty()) { - // Can't use nack_list.data() since it's not supported by all - // compilers. - ResendPackets(&(nack_list[0]), static_cast(nack_list.size())); - } - return 0; -} - -AudioMixer::Source::AudioFrameInfo Channel::GetAudioFrameWithInfo( - int sample_rate_hz, - AudioFrame* audio_frame) { - audio_frame->sample_rate_hz_ = sample_rate_hz; - - unsigned int ssrc; - RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0); - event_log_->Log(absl::make_unique(ssrc)); - // Get 10ms raw PCM data from the ACM (mixer limits output frequency) - bool muted; - if (audio_coding_->PlayoutData10Ms(audio_frame->sample_rate_hz_, audio_frame, - &muted) == -1) { - RTC_DLOG(LS_ERROR) << "Channel::GetAudioFrame() PlayoutData10Ms() failed!"; - // In all likelihood, the audio in this frame is garbage. We return an - // error so that the audio mixer module doesn't add it to the mix. As - // a result, it won't be played out and the actions skipped here are - // irrelevant. - return AudioMixer::Source::AudioFrameInfo::kError; - } - - if (muted) { - // TODO(henrik.lundin): We should be able to do better than this. But we - // will have to go through all the cases below where the audio samples may - // be used, and handle the muted case in some way. - AudioFrameOperations::Mute(audio_frame); - } - - { - // Pass the audio buffers to an optional sink callback, before applying - // scaling/panning, as that applies to the mix operation. - // External recipients of the audio (e.g. via AudioTrack), will do their - // own mixing/dynamic processing. - rtc::CritScope cs(&_callbackCritSect); - if (audio_sink_) { - AudioSinkInterface::Data data( - audio_frame->data(), audio_frame->samples_per_channel_, - audio_frame->sample_rate_hz_, audio_frame->num_channels_, - audio_frame->timestamp_); - audio_sink_->OnData(data); - } - } - - float output_gain = 1.0f; - { - rtc::CritScope cs(&volume_settings_critsect_); - output_gain = _outputGain; - } - - // Output volume scaling - if (output_gain < 0.99f || output_gain > 1.01f) { - // TODO(solenberg): Combine with mute state - this can cause clicks! - AudioFrameOperations::ScaleWithSat(output_gain, audio_frame); - } - - // Measure audio level (0-9) - // TODO(henrik.lundin) Use the |muted| information here too. - // TODO(deadbeef): Use RmsLevel for |_outputAudioLevel| (see - // https://crbug.com/webrtc/7517). - _outputAudioLevel.ComputeLevel(*audio_frame, kAudioSampleDurationSeconds); - - if (capture_start_rtp_time_stamp_ < 0 && audio_frame->timestamp_ != 0) { - // The first frame with a valid rtp timestamp. - capture_start_rtp_time_stamp_ = audio_frame->timestamp_; - } - - if (capture_start_rtp_time_stamp_ >= 0) { - // audio_frame.timestamp_ should be valid from now on. - - // Compute elapsed time. - int64_t unwrap_timestamp = - rtp_ts_wraparound_handler_->Unwrap(audio_frame->timestamp_); - audio_frame->elapsed_time_ms_ = - (unwrap_timestamp - capture_start_rtp_time_stamp_) / - (GetRtpTimestampRateHz() / 1000); - - { - rtc::CritScope lock(&ts_stats_lock_); - // Compute ntp time. - audio_frame->ntp_time_ms_ = - ntp_estimator_.Estimate(audio_frame->timestamp_); - // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received. - if (audio_frame->ntp_time_ms_ > 0) { - // Compute |capture_start_ntp_time_ms_| so that - // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_| - capture_start_ntp_time_ms_ = - audio_frame->ntp_time_ms_ - audio_frame->elapsed_time_ms_; - } - } - } - - { - RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.TargetJitterBufferDelayMs", - audio_coding_->TargetDelayMs()); - const int jitter_buffer_delay = audio_coding_->FilteredCurrentDelayMs(); - rtc::CritScope lock(&video_sync_lock_); - RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverDelayEstimateMs", - jitter_buffer_delay + playout_delay_ms_); - RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverJitterBufferDelayMs", - jitter_buffer_delay); - RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverDeviceDelayMs", - playout_delay_ms_); - } - - return muted ? AudioMixer::Source::AudioFrameInfo::kMuted - : AudioMixer::Source::AudioFrameInfo::kNormal; -} - -int Channel::PreferredSampleRate() const { +int ChannelSend::PreferredSampleRate() const { // Return the bigger of playout and receive frequency in the ACM. return std::max(audio_coding_->ReceiveFrequency(), audio_coding_->PlayoutFrequency()); } -Channel::Channel(rtc::TaskQueue* encoder_queue, - ProcessThread* module_process_thread, - AudioDeviceModule* audio_device_module, - RtcpRttStats* rtcp_rtt_stats, - RtcEventLog* rtc_event_log) - : Channel(module_process_thread, - audio_device_module, - rtcp_rtt_stats, - rtc_event_log, - 0, - 0, - false, - rtc::scoped_refptr(), - absl::nullopt) { - RTC_DCHECK(encoder_queue); - encoder_queue_ = encoder_queue; -} - -Channel::Channel(ProcessThread* module_process_thread, - AudioDeviceModule* audio_device_module, - RtcpRttStats* rtcp_rtt_stats, - 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) +ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue, + ProcessThread* module_process_thread, + RtcpRttStats* rtcp_rtt_stats, + RtcEventLog* rtc_event_log) : event_log_(rtc_event_log), - rtp_receive_statistics_( - ReceiveStatistics::Create(Clock::GetRealTimeClock())), - remote_ssrc_(remote_ssrc), - _outputAudioLevel(), _timeStamp(0), // This is just an offset, RTP module will add it's own // random offset - ntp_estimator_(Clock::GetRealTimeClock()), - playout_timestamp_rtp_(0), - playout_delay_ms_(0), send_sequence_number_(0), - rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()), - capture_start_rtp_time_stamp_(-1), - capture_start_ntp_time_ms_(-1), _moduleProcessThreadPtr(module_process_thread), - _audioDeviceModulePtr(audio_device_module), _transportPtr(NULL), input_mute_(false), previous_frame_muted_(false), - _outputGain(1.0f), _includeAudioLevelIndication(false), transport_overhead_per_packet_(0), rtp_overhead_per_packet_(0), rtcp_observer_(new VoERtcpObserver(this)), - associated_send_channel_(nullptr), feedback_observer_proxy_(new TransportFeedbackProxy()), seq_num_allocator_proxy_(new TransportSequenceNumberProxy()), rtp_packet_sender_proxy_(new RtpPacketSenderProxy()), retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(), kMaxRetransmissionWindowMs)), use_twcc_plr_for_ana_( - webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled") { + webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"), + encoder_queue_(encoder_queue) { RTC_DCHECK(module_process_thread); - RTC_DCHECK(audio_device_module); - AudioCodingModule::Config acm_config; - acm_config.decoder_factory = decoder_factory; - acm_config.neteq_config.codec_pair_id = codec_pair_id; - acm_config.neteq_config.max_packets_in_buffer = jitter_buffer_max_packets; - acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout; - acm_config.neteq_config.enable_muted_state = true; - audio_coding_.reset(AudioCodingModule::Create(acm_config)); + RTC_DCHECK(encoder_queue); + audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config())); - _outputAudioLevel.Clear(); - - rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true); RtpRtcp::Configuration configuration; configuration.audio = true; configuration.outgoing_transport = this; configuration.overhead_observer = this; - configuration.receive_statistics = rtp_receive_statistics_.get(); configuration.bandwidth_callback = rtcp_observer_.get(); configuration.paced_sender = rtp_packet_sender_proxy_.get(); @@ -556,17 +365,15 @@ Channel::Channel(ProcessThread* module_process_thread, _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); _rtpRtcpModule->SetSendingMediaStatus(false); - _rtpRtcpModule->SetRemoteSSRC(remote_ssrc_); Init(); } -Channel::~Channel() { +ChannelSend::~ChannelSend() { Terminate(); RTC_DCHECK(!channel_state_.Get().sending); - RTC_DCHECK(!channel_state_.Get().playing); } -void Channel::Init() { +void ChannelSend::Init() { channel_state_.Reset(); // --- Add modules to process thread (for periodic schedulation) @@ -591,13 +398,11 @@ void Channel::Init() { RTC_DCHECK_EQ(0, error); } -void Channel::Terminate() { +void ChannelSend::Terminate() { RTC_DCHECK(construction_thread_.CalledOnValidThread()); // Must be called on the same thread as Init(). - rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL); StopSend(); - StopPlayout(); // The order to safely shutdown modules in a channel is: // 1. De-register callbacks in modules @@ -613,33 +418,7 @@ void Channel::Terminate() { // End of modules shutdown } -void Channel::SetSink(AudioSinkInterface* sink) { - rtc::CritScope cs(&_callbackCritSect); - audio_sink_ = sink; -} - -int32_t Channel::StartPlayout() { - if (channel_state_.Get().playing) { - return 0; - } - - channel_state_.SetPlaying(true); - - return 0; -} - -int32_t Channel::StopPlayout() { - if (!channel_state_.Get().playing) { - return 0; - } - - channel_state_.SetPlaying(false); - _outputAudioLevel.Clear(); - - return 0; -} - -int32_t Channel::StartSend() { +int32_t ChannelSend::StartSend() { if (channel_state_.Get().sending) { return 0; } @@ -666,7 +445,7 @@ int32_t Channel::StartSend() { return 0; } -void Channel::StopSend() { +void ChannelSend::StopSend() { if (!channel_state_.Get().sending) { return; } @@ -706,8 +485,8 @@ void Channel::StopSend() { _rtpRtcpModule->SetSendingMediaStatus(false); } -bool Channel::SetEncoder(int payload_type, - std::unique_ptr encoder) { +bool ChannelSend::SetEncoder(int payload_type, + std::unique_ptr encoder) { RTC_DCHECK_GE(payload_type, 0); RTC_DCHECK_LE(payload_type, 127); // TODO(ossu): Make CodecInsts up, for now: one for the RTP/RTCP module and @@ -742,16 +521,12 @@ bool Channel::SetEncoder(int payload_type, return true; } -void Channel::ModifyEncoder( +void ChannelSend::ModifyEncoder( rtc::FunctionView*)> modifier) { audio_coding_->ModifyEncoder(modifier); } -int32_t Channel::GetRecCodec(CodecInst& codec) { - return (audio_coding_->ReceiveCodec(&codec)); -} - -void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) { +void ChannelSend::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) { audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { if (*encoder) { (*encoder)->OnReceivedUplinkBandwidth(bitrate_bps, probing_interval_ms); @@ -760,7 +535,7 @@ void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) { retransmission_rate_limiter_->SetMaxRate(bitrate_bps); } -void Channel::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) { +void ChannelSend::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) { if (!use_twcc_plr_for_ana_) return; audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { @@ -770,7 +545,7 @@ void Channel::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) { }); } -void Channel::OnRecoverableUplinkPacketLossRate( +void ChannelSend::OnRecoverableUplinkPacketLossRate( float recoverable_packet_loss_rate) { audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { if (*encoder) { @@ -780,23 +555,7 @@ void Channel::OnRecoverableUplinkPacketLossRate( }); } -std::vector Channel::GetSources() const { - int64_t now_ms = rtc::TimeMillis(); - std::vector sources; - { - rtc::CritScope cs(&rtp_sources_lock_); - sources = contributing_sources_.GetSources(now_ms); - if (last_received_rtp_system_time_ms_ >= - now_ms - ContributingSources::kHistoryMs) { - sources.emplace_back(*last_received_rtp_system_time_ms_, remote_ssrc_, - RtpSourceType::SSRC); - sources.back().set_audio_level(last_received_rtp_audio_level_); - } - } - return sources; -} - -void Channel::OnUplinkPacketLossRate(float packet_loss_rate) { +void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) { if (use_twcc_plr_for_ana_) return; audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { @@ -806,15 +565,7 @@ void Channel::OnUplinkPacketLossRate(float packet_loss_rate) { }); } -void Channel::SetReceiveCodecs(const std::map& codecs) { - for (const auto& kv : codecs) { - RTC_DCHECK_GE(kv.second.clockrate_hz, 1000); - payload_type_frequencies_[kv.first] = kv.second.clockrate_hz; - } - audio_coding_->SetReceiveCodecs(codecs); -} - -bool Channel::EnableAudioNetworkAdaptor(const std::string& config_string) { +bool ChannelSend::EnableAudioNetworkAdaptor(const std::string& config_string) { bool success = false; audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { if (*encoder) { @@ -825,15 +576,15 @@ bool Channel::EnableAudioNetworkAdaptor(const std::string& config_string) { return success; } -void Channel::DisableAudioNetworkAdaptor() { +void ChannelSend::DisableAudioNetworkAdaptor() { audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { if (*encoder) (*encoder)->DisableAudioNetworkAdaptor(); }); } -void Channel::SetReceiverFrameLengthRange(int min_frame_length_ms, - int max_frame_length_ms) { +void ChannelSend::SetReceiverFrameLengthRange(int min_frame_length_ms, + int max_frame_length_ms) { audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { if (*encoder) { (*encoder)->SetReceiverFrameLengthRange(min_frame_length_ms, @@ -842,73 +593,16 @@ void Channel::SetReceiverFrameLengthRange(int min_frame_length_ms, }); } -void Channel::RegisterTransport(Transport* transport) { +void ChannelSend::RegisterTransport(Transport* transport) { rtc::CritScope cs(&_callbackCritSect); _transportPtr = transport; } -// TODO(nisse): Move receive logic up to AudioReceiveStream. -void Channel::OnRtpPacket(const RtpPacketReceived& packet) { - int64_t now_ms = rtc::TimeMillis(); - uint8_t audio_level; - bool voice_activity; - bool has_audio_level = - packet.GetExtension<::webrtc::AudioLevel>(&voice_activity, &audio_level); - - { - rtc::CritScope cs(&rtp_sources_lock_); - last_received_rtp_timestamp_ = packet.Timestamp(); - last_received_rtp_system_time_ms_ = now_ms; - if (has_audio_level) - last_received_rtp_audio_level_ = audio_level; - std::vector csrcs = packet.Csrcs(); - contributing_sources_.Update(now_ms, csrcs); - } - - // Store playout timestamp for the received RTP packet - UpdatePlayoutTimestamp(false); - - const auto& it = payload_type_frequencies_.find(packet.PayloadType()); - if (it == payload_type_frequencies_.end()) - return; - // TODO(nisse): Set payload_type_frequency earlier, when packet is parsed. - RtpPacketReceived packet_copy(packet); - packet_copy.set_payload_type_frequency(it->second); - - rtp_receive_statistics_->OnRtpPacket(packet_copy); - - RTPHeader header; - packet_copy.GetHeader(&header); - - ReceivePacket(packet_copy.data(), packet_copy.size(), header); -} - -bool Channel::ReceivePacket(const uint8_t* packet, - size_t packet_length, - const RTPHeader& header) { - const uint8_t* payload = packet + header.headerLength; - assert(packet_length >= header.headerLength); - size_t payload_length = packet_length - header.headerLength; - WebRtcRTPHeader webrtc_rtp_header = {}; - webrtc_rtp_header.header = header; - - const size_t payload_data_length = payload_length - header.paddingLength; - if (payload_data_length == 0) { - webrtc_rtp_header.frameType = kEmptyFrame; - return OnReceivedPayloadData(nullptr, 0, &webrtc_rtp_header); - } - return OnReceivedPayloadData(payload, payload_data_length, - &webrtc_rtp_header); -} - -int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) { - // Store playout timestamp for the received RTCP packet - UpdatePlayoutTimestamp(true); - +int32_t ChannelSend::ReceivedRTCPPacket(const uint8_t* data, size_t length) { // Deliver RTCP packet to RTP/RTCP module for parsing _rtpRtcpModule->IncomingRtcpPacket(data, length); - int64_t rtt = GetRTT(true); + int64_t rtt = GetRTT(); if (rtt == 0) { // Waiting for valid RTT. return 0; @@ -928,50 +622,20 @@ int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) { (*encoder)->OnReceivedRtt(rtt); }); - uint32_t ntp_secs = 0; - uint32_t ntp_frac = 0; - uint32_t rtp_timestamp = 0; - if (0 != _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL, - &rtp_timestamp)) { - // Waiting for RTCP. - return 0; - } - - { - rtc::CritScope lock(&ts_stats_lock_); - ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp); - } return 0; } -int Channel::GetSpeechOutputLevelFullRange() const { - return _outputAudioLevel.LevelFullRange(); -} - -double Channel::GetTotalOutputEnergy() const { - return _outputAudioLevel.TotalEnergy(); -} - -double Channel::GetTotalOutputDuration() const { - return _outputAudioLevel.TotalDuration(); -} - -void Channel::SetInputMute(bool enable) { +void ChannelSend::SetInputMute(bool enable) { rtc::CritScope cs(&volume_settings_critsect_); input_mute_ = enable; } -bool Channel::InputMute() const { +bool ChannelSend::InputMute() const { rtc::CritScope cs(&volume_settings_critsect_); return input_mute_; } -void Channel::SetChannelOutputVolumeScaling(float scaling) { - rtc::CritScope cs(&volume_settings_critsect_); - _outputGain = scaling; -} - -int Channel::SendTelephoneEventOutband(int event, int duration_ms) { +int ChannelSend::SendTelephoneEventOutband(int event, int duration_ms) { RTC_DCHECK_LE(0, event); RTC_DCHECK_GE(255, event); RTC_DCHECK_LE(0, duration_ms); @@ -987,8 +651,8 @@ int Channel::SendTelephoneEventOutband(int event, int duration_ms) { return 0; } -int Channel::SetSendTelephoneEventPayloadType(int payload_type, - int payload_frequency) { +int ChannelSend::SetSendTelephoneEventPayloadType(int payload_type, + int payload_frequency) { RTC_DCHECK_LE(0, payload_type); RTC_DCHECK_GE(127, payload_type); CodecInst codec = {0}; @@ -1007,7 +671,7 @@ int Channel::SetSendTelephoneEventPayloadType(int payload_type, return 0; } -int Channel::SetLocalSSRC(unsigned int ssrc) { +int ChannelSend::SetLocalSSRC(unsigned int ssrc) { if (channel_state_.Get().sending) { RTC_DLOG(LS_ERROR) << "SetLocalSSRC() already sending"; return -1; @@ -1016,30 +680,25 @@ int Channel::SetLocalSSRC(unsigned int ssrc) { return 0; } -void Channel::SetMid(const std::string& mid, int extension_id) { +void ChannelSend::SetMid(const std::string& mid, int extension_id) { int ret = SetSendRtpHeaderExtension(true, kRtpExtensionMid, extension_id); RTC_DCHECK_EQ(0, ret); _rtpRtcpModule->SetMid(mid); } -// TODO(nisse): Pass ssrc in return value instead. -int Channel::GetRemoteSSRC(unsigned int& ssrc) { - ssrc = remote_ssrc_; - return 0; -} - -int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) { +int ChannelSend::SetSendAudioLevelIndicationStatus(bool enable, + unsigned char id) { _includeAudioLevelIndication = enable; return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id); } -void Channel::EnableSendTransportSequenceNumber(int id) { +void ChannelSend::EnableSendTransportSequenceNumber(int id) { int ret = SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id); RTC_DCHECK_EQ(0, ret); } -void Channel::RegisterSenderCongestionControlObjects( +void ChannelSend::RegisterSenderCongestionControlObjects( RtpTransportControllerSendInterface* transport, RtcpBandwidthObserver* bandwidth_observer) { RtpPacketSender* rtp_packet_sender = transport->packet_sender(); @@ -1062,16 +721,7 @@ void Channel::RegisterSenderCongestionControlObjects( packet_router_ = packet_router; } -void Channel::RegisterReceiverCongestionControlObjects( - PacketRouter* packet_router) { - RTC_DCHECK(packet_router); - RTC_DCHECK(!packet_router_); - constexpr bool remb_candidate = false; - packet_router->AddReceiveRtpModule(_rtpRtcpModule.get(), remb_candidate); - packet_router_ = packet_router; -} - -void Channel::ResetSenderCongestionControlObjects() { +void ChannelSend::ResetSenderCongestionControlObjects() { RTC_DCHECK(packet_router_); _rtpRtcpModule->SetStorePacketsStatus(false, 600); rtcp_observer_->SetBandwidthObserver(nullptr); @@ -1082,17 +732,11 @@ void Channel::ResetSenderCongestionControlObjects() { rtp_packet_sender_proxy_->SetPacketSender(nullptr); } -void Channel::ResetReceiverCongestionControlObjects() { - RTC_DCHECK(packet_router_); - packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get()); - packet_router_ = nullptr; -} - -void Channel::SetRTCPStatus(bool enable) { +void ChannelSend::SetRTCPStatus(bool enable) { _rtpRtcpModule->SetRTCPStatus(enable ? RtcpMode::kCompound : RtcpMode::kOff); } -int Channel::SetRTCP_CNAME(const char cName[256]) { +int ChannelSend::SetRTCP_CNAME(const char cName[256]) { if (_rtpRtcpModule->SetCNAME(cName) != 0) { RTC_DLOG(LS_ERROR) << "SetRTCP_CNAME() failed to set RTCP CNAME"; return -1; @@ -1100,7 +744,7 @@ int Channel::SetRTCP_CNAME(const char cName[256]) { return 0; } -int Channel::GetRemoteRTCPReportBlocks( +int ChannelSend::GetRemoteRTCPReportBlocks( std::vector* report_blocks) { if (report_blocks == NULL) { RTC_DLOG(LS_ERROR) << "GetRemoteRTCPReportBlock()s invalid report_blocks."; @@ -1135,37 +779,16 @@ int Channel::GetRemoteRTCPReportBlocks( return 0; } -int Channel::GetRTPStatistics(CallStatistics& stats) { +int ChannelSend::GetRTPStatistics(CallSendStatistics& stats) { // --- RtcpStatistics - // The jitter statistics is updated for each received RTP packet and is - // based on received packets. - RtcpStatistics statistics; - StreamStatistician* statistician = - rtp_receive_statistics_->GetStatistician(remote_ssrc_); - if (statistician) { - statistician->GetStatistics(&statistics, - _rtpRtcpModule->RTCP() == RtcpMode::kOff); - } - - stats.fractionLost = statistics.fraction_lost; - stats.cumulativeLost = statistics.packets_lost; - stats.extendedMax = statistics.extended_highest_sequence_number; - stats.jitterSamples = statistics.jitter; - // --- RTT - stats.rttMs = GetRTT(true); + stats.rttMs = GetRTT(); // --- Data counters size_t bytesSent(0); uint32_t packetsSent(0); - size_t bytesReceived(0); - uint32_t packetsReceived(0); - - if (statistician) { - statistician->GetDataCounters(&bytesReceived, &packetsReceived); - } if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) { RTC_DLOG(LS_WARNING) @@ -1175,20 +798,12 @@ int Channel::GetRTPStatistics(CallStatistics& stats) { stats.bytesSent = bytesSent; stats.packetsSent = packetsSent; - stats.bytesReceived = bytesReceived; - stats.packetsReceived = packetsReceived; - // --- Timestamps - { - rtc::CritScope lock(&ts_stats_lock_); - stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_; - } return 0; } -void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) { +void ChannelSend::SetNACKStatus(bool enable, int maxNumberOfPackets) { // None of these functions can fail. - rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets); if (enable) audio_coding_->EnableNack(maxNumberOfPackets); else @@ -1196,11 +811,12 @@ void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) { } // Called when we are missing one or more packets. -int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) { +int ChannelSend::ResendPackets(const uint16_t* sequence_numbers, int length) { return _rtpRtcpModule->SendNACK(sequence_numbers, length); } -void Channel::ProcessAndEncodeAudio(std::unique_ptr audio_frame) { +void ChannelSend::ProcessAndEncodeAudio( + std::unique_ptr audio_frame) { // Avoid posting any new tasks if sending was already stopped in StopSend(). rtc::CritScope cs(&encoder_queue_lock_); if (!encoder_queue_is_active_) { @@ -1213,7 +829,7 @@ void Channel::ProcessAndEncodeAudio(std::unique_ptr audio_frame) { new ProcessAndEncodeAudioTask(std::move(audio_frame), this))); } -void Channel::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) { +void ChannelSend::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) { RTC_DCHECK_RUN_ON(encoder_queue_); RTC_DCHECK_GT(audio_input->samples_per_channel_, 0); RTC_DCHECK_LE(audio_input->num_channels_, 2); @@ -1255,13 +871,7 @@ void Channel::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) { _timeStamp += static_cast(audio_input->samples_per_channel_); } -void Channel::SetAssociatedSendChannel(Channel* channel) { - RTC_DCHECK_NE(this, channel); - rtc::CritScope lock(&assoc_send_channel_lock_); - associated_send_channel_ = channel; -} - -void Channel::UpdateOverheadForEncoder() { +void ChannelSend::UpdateOverheadForEncoder() { size_t overhead_per_packet = transport_overhead_per_packet_ + rtp_overhead_per_packet_; audio_coding_->ModifyEncoder([&](std::unique_ptr* encoder) { @@ -1271,120 +881,30 @@ void Channel::UpdateOverheadForEncoder() { }); } -void Channel::SetTransportOverhead(size_t transport_overhead_per_packet) { +void ChannelSend::SetTransportOverhead(size_t transport_overhead_per_packet) { rtc::CritScope cs(&overhead_per_packet_lock_); transport_overhead_per_packet_ = transport_overhead_per_packet; UpdateOverheadForEncoder(); } // TODO(solenberg): Make AudioSendStream an OverheadObserver instead. -void Channel::OnOverheadChanged(size_t overhead_bytes_per_packet) { +void ChannelSend::OnOverheadChanged(size_t overhead_bytes_per_packet) { rtc::CritScope cs(&overhead_per_packet_lock_); rtp_overhead_per_packet_ = overhead_bytes_per_packet; UpdateOverheadForEncoder(); } -int Channel::GetNetworkStatistics(NetworkStatistics& stats) { - return audio_coding_->GetNetworkStatistics(&stats); -} - -void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const { - audio_coding_->GetDecodingCallStatistics(stats); -} - -ANAStats Channel::GetANAStatistics() const { +ANAStats ChannelSend::GetANAStatistics() const { return audio_coding_->GetANAStats(); } -uint32_t Channel::GetDelayEstimate() const { - rtc::CritScope lock(&video_sync_lock_); - return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_; -} - -int Channel::SetMinimumPlayoutDelay(int delayMs) { - if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) || - (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) { - RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay"; - return -1; - } - if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) { - RTC_DLOG(LS_ERROR) - << "SetMinimumPlayoutDelay() failed to set min playout delay"; - return -1; - } - return 0; -} - -int Channel::GetPlayoutTimestamp(unsigned int& timestamp) { - uint32_t playout_timestamp_rtp = 0; - { - rtc::CritScope lock(&video_sync_lock_); - playout_timestamp_rtp = playout_timestamp_rtp_; - } - if (playout_timestamp_rtp == 0) { - RTC_DLOG(LS_ERROR) << "GetPlayoutTimestamp() failed to retrieve timestamp"; - return -1; - } - timestamp = playout_timestamp_rtp; - return 0; -} - -RtpRtcp* Channel::GetRtpRtcp() const { +RtpRtcp* ChannelSend::GetRtpRtcp() const { return _rtpRtcpModule.get(); } -absl::optional Channel::GetSyncInfo() const { - Syncable::Info info; - if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs, - &info.capture_time_ntp_frac, nullptr, nullptr, - &info.capture_time_source_clock) != 0) { - return absl::nullopt; - } - { - rtc::CritScope cs(&rtp_sources_lock_); - if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_ms_) { - return absl::nullopt; - } - info.latest_received_capture_timestamp = *last_received_rtp_timestamp_; - info.latest_receive_time_ms = *last_received_rtp_system_time_ms_; - } - return info; -} - -void Channel::UpdatePlayoutTimestamp(bool rtcp) { - jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp(); - - if (!jitter_buffer_playout_timestamp_) { - // This can happen if this channel has not received any RTP packets. In - // this case, NetEq is not capable of computing a playout timestamp. - return; - } - - uint16_t delay_ms = 0; - if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) { - RTC_DLOG(LS_WARNING) << "Channel::UpdatePlayoutTimestamp() failed to read" - << " playout delay from the ADM"; - return; - } - - RTC_DCHECK(jitter_buffer_playout_timestamp_); - uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_; - - // Remove the playout delay. - playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000)); - - { - rtc::CritScope lock(&video_sync_lock_); - if (!rtcp) { - playout_timestamp_rtp_ = playout_timestamp; - } - playout_delay_ms_ = delay_ms; - } -} - -int Channel::SetSendRtpHeaderExtension(bool enable, - RTPExtensionType type, - unsigned char id) { +int ChannelSend::SetSendRtpHeaderExtension(bool enable, + RTPExtensionType type, + unsigned char id) { int error = 0; _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type); if (enable) { @@ -1393,7 +913,7 @@ int Channel::SetSendRtpHeaderExtension(bool enable, return error; } -int Channel::GetRtpTimestampRateHz() const { +int ChannelSend::GetRtpTimestampRateHz() const { const auto format = audio_coding_->ReceiveFormat(); // Default to the playout frequency if we've not gotten any packets yet. // TODO(ossu): Zero clockrate can only happen if we've added an external @@ -1404,7 +924,7 @@ int Channel::GetRtpTimestampRateHz() const { : audio_coding_->PlayoutFrequency(); } -int64_t Channel::GetRTT(bool allow_associate_channel) const { +int64_t ChannelSend::GetRTT() const { RtcpMode method = _rtpRtcpModule->RTCP(); if (method == RtcpMode::kOff) { return 0; @@ -1412,39 +932,18 @@ int64_t Channel::GetRTT(bool allow_associate_channel) const { std::vector report_blocks; _rtpRtcpModule->RemoteRTCPStat(&report_blocks); - int64_t rtt = 0; if (report_blocks.empty()) { - if (allow_associate_channel) { - rtc::CritScope lock(&assoc_send_channel_lock_); - // Tries to get RTT from an associated channel. This is important for - // receive-only channels. - if (associated_send_channel_) { - // To prevent infinite recursion and deadlock, calling GetRTT of - // associate channel should always use "false" for argument: - // |allow_associate_channel|. - rtt = associated_send_channel_->GetRTT(false); - } - } - return rtt; + return 0; } - std::vector::const_iterator it = report_blocks.begin(); - for (; it != report_blocks.end(); ++it) { - if (it->sender_ssrc == remote_ssrc_) - break; - } - - // If we have not received packets with SSRC matching the report blocks, use - // the SSRC of the first report block for calculating the RTT. This is very - // important for send-only channels where we don't know the SSRC of the other - // end. - uint32_t ssrc = - (it == report_blocks.end()) ? report_blocks[0].sender_ssrc : remote_ssrc_; - + int64_t rtt = 0; int64_t avg_rtt = 0; int64_t max_rtt = 0; int64_t min_rtt = 0; - if (_rtpRtcpModule->RTT(ssrc, &rtt, &avg_rtt, &min_rtt, &max_rtt) != 0) { + // We don't know in advance the remote ssrc used by the other end's receiver + // reports, so use the SSRC of the first report block for calculating the RTT. + if (_rtpRtcpModule->RTT(report_blocks[0].sender_ssrc, &rtt, &avg_rtt, + &min_rtt, &max_rtt) != 0) { return 0; } return rtt; diff --git a/audio/channel.h b/audio/channel_send.h similarity index 59% rename from audio/channel.h rename to audio/channel_send.h index b9694aa19f..4569201038 100644 --- a/audio/channel.h +++ b/audio/channel_send.h @@ -8,31 +8,22 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef AUDIO_CHANNEL_H_ -#define AUDIO_CHANNEL_H_ +#ifndef AUDIO_CHANNEL_SEND_H_ +#define AUDIO_CHANNEL_SEND_H_ #include #include #include #include -#include "absl/types/optional.h" -#include "api/audio/audio_mixer.h" +#include "api/audio/audio_frame.h" #include "api/audio_codecs/audio_encoder.h" -#include "api/call/audio_sink.h" #include "api/call/transport.h" -#include "api/rtpreceiverinterface.h" -#include "audio/audio_level.h" -#include "call/syncable.h" #include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_processing/rms_level.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/event.h" #include "rtc_base/task_queue.h" #include "rtc_base/thread_checker.h" @@ -46,32 +37,19 @@ class TimestampWrapAroundHandler; namespace webrtc { -class AudioDeviceModule; class PacketRouter; class ProcessThread; class RateLimiter; -class ReceiveStatistics; -class RemoteNtpTimeEstimator; class RtcEventLog; -class RtpPacketReceived; class RtpRtcp; class RtpTransportControllerSendInterface; struct SenderInfo; -struct CallStatistics { - unsigned short fractionLost; // NOLINT - unsigned int cumulativeLost; - unsigned int extendedMax; - unsigned int jitterSamples; +struct CallSendStatistics { int64_t rttMs; size_t bytesSent; int packetsSent; - size_t bytesReceived; - int packetsReceived; - // The capture ntp time (in local timebase) of the first played out audio - // frame. - int64_t capture_start_ntp_time_ms_; }; // See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details. @@ -98,15 +76,14 @@ class VoERtcpObserver; // 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 ChannelState { +class ChannelSendState { public: struct State { - bool playing = false; bool sending = false; }; - ChannelState() {} - virtual ~ChannelState() {} + ChannelSendState() {} + virtual ~ChannelSendState() {} void Reset() { rtc::CritScope lock(&lock_); @@ -118,11 +95,6 @@ class ChannelState { return state_; } - void SetPlaying(bool enable) { - rtc::CritScope lock(&lock_); - state_.playing = enable; - } - void SetSending(bool enable) { rtc::CritScope lock(&lock_); state_.sending = enable; @@ -133,38 +105,22 @@ class ChannelState { State state_; }; -class Channel - : public RtpData, - public Transport, +class ChannelSend + : public Transport, public AudioPacketizationCallback, // receive encoded packets from the // ACM public OverheadObserver { public: + // TODO(nisse): Make OnUplinkPacketLossRate public, and delete friend + // declaration. friend class VoERtcpObserver; - enum { KNumSocketThreads = 1 }; - enum { KNumberOfSocketBuffers = 8 }; - // Used for send streams. - Channel(rtc::TaskQueue* encoder_queue, - ProcessThread* module_process_thread, - AudioDeviceModule* audio_device_module, - RtcpRttStats* rtcp_rtt_stats, - RtcEventLog* rtc_event_log); - // Used for receive streams. - Channel(ProcessThread* module_process_thread, - AudioDeviceModule* audio_device_module, - RtcpRttStats* rtcp_rtt_stats, - 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); - virtual ~Channel(); + ChannelSend(rtc::TaskQueue* encoder_queue, + ProcessThread* module_process_thread, + RtcpRttStats* rtcp_rtt_stats, + RtcEventLog* rtc_event_log); - void SetSink(AudioSinkInterface* sink); - - void SetReceiveCodecs(const std::map& codecs); + virtual ~ChannelSend(); // Send using this encoder, with this payload type. bool SetEncoder(int payload_type, std::unique_ptr encoder); @@ -174,16 +130,15 @@ class Channel // API methods // VoEBase - int32_t StartPlayout(); - int32_t StopPlayout(); int32_t StartSend(); void StopSend(); // Codecs - int32_t GetRecCodec(CodecInst& codec); // NOLINT void SetBitRate(int bitrate_bps, int64_t probing_interval_ms); bool EnableAudioNetworkAdaptor(const std::string& config_string); void DisableAudioNetworkAdaptor(); + + // TODO(nisse): Modifies decoder, but not used? void SetReceiverFrameLengthRange(int min_frame_length_ms, int max_frame_length_ms); @@ -191,32 +146,16 @@ class Channel void RegisterTransport(Transport* transport); // TODO(nisse, solenberg): Delete when VoENetwork is deleted. int32_t ReceivedRTCPPacket(const uint8_t* data, size_t length); - void OnRtpPacket(const RtpPacketReceived& packet); // Muting, Volume and Level. void SetInputMute(bool enable); - void SetChannelOutputVolumeScaling(float scaling); - int GetSpeechOutputLevelFullRange() const; - // See description of "totalAudioEnergy" in the WebRTC stats spec: - // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy - double GetTotalOutputEnergy() const; - double GetTotalOutputDuration() const; // Stats. - int GetNetworkStatistics(NetworkStatistics& stats); // NOLINT - void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const; ANAStats GetANAStatistics() const; - // Audio+Video Sync. - uint32_t GetDelayEstimate() const; - int SetMinimumPlayoutDelay(int delayMs); - int GetPlayoutTimestamp(unsigned int& timestamp); // NOLINT - // Used by AudioSendStream. RtpRtcp* GetRtpRtcp() const; - // Produces the transport-related timestamps; current_delay_ms is left unset. - absl::optional GetSyncInfo() const; // DTMF. int SendTelephoneEventOutband(int event, int duration_ms); int SetSendTelephoneEventPayloadType(int payload_type, int payload_frequency); @@ -231,13 +170,11 @@ class Channel void RegisterSenderCongestionControlObjects( RtpTransportControllerSendInterface* transport, RtcpBandwidthObserver* bandwidth_observer); - void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router); void ResetSenderCongestionControlObjects(); - void ResetReceiverCongestionControlObjects(); void SetRTCPStatus(bool enable); int SetRTCP_CNAME(const char cName[256]); int GetRemoteRTCPReportBlocks(std::vector* report_blocks); - int GetRTPStatistics(CallStatistics& stats); // NOLINT + int GetRTPStatistics(CallSendStatistics& stats); // NOLINT void SetNACKStatus(bool enable, int maxNumberOfPackets); // From AudioPacketizationCallback in the ACM @@ -248,25 +185,14 @@ class Channel size_t payloadSize, const RTPFragmentationHeader* fragmentation) override; - // From RtpData in the RTP/RTCP module - int32_t OnReceivedPayloadData(const uint8_t* payloadData, - size_t payloadSize, - const WebRtcRTPHeader* rtpHeader) override; - // From Transport (called by the RTP/RTCP module) bool SendRtp(const uint8_t* data, size_t len, const PacketOptions& packet_options) override; bool SendRtcp(const uint8_t* data, size_t len) override; - // From AudioMixer::Source. - AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo( - int sample_rate_hz, - AudioFrame* audio_frame); - int PreferredSampleRate() const; - bool Playing() const { return channel_state_.Get().playing; } bool Sending() const { return channel_state_.Get().sending; } RtpRtcp* RtpRtcpModulePtr() const { return _rtpRtcpModule.get(); } @@ -281,10 +207,6 @@ class Channel // packet. void ProcessAndEncodeAudio(std::unique_ptr audio_frame); - // Associate to a send channel. - // Used for obtaining RTT for a receive-only channel. - void SetAssociatedSendChannel(Channel* channel); - void SetTransportOverhead(size_t transport_overhead_per_packet); // From OverheadObserver in the RTP/RTCP module @@ -298,7 +220,7 @@ class Channel void OnRecoverableUplinkPacketLossRate(float recoverable_packet_loss_rate); - std::vector GetSources() const; + int64_t GetRTT() const; private: class ProcessAndEncodeAudioTask; @@ -306,15 +228,10 @@ class Channel void Init(); void Terminate(); - int GetRemoteSSRC(unsigned int& ssrc); // NOLINT void OnUplinkPacketLossRate(float packet_loss_rate); bool InputMute() const; - 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 SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, @@ -324,7 +241,6 @@ class Channel RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_); int GetRtpTimestampRateHz() const; - int64_t GetRTT(bool allow_associate_channel) const; // Called on the encoder task queue when a new input audio frame is ready // for encoding. @@ -333,60 +249,23 @@ class Channel rtc::CriticalSection _callbackCritSect; rtc::CriticalSection volume_settings_critsect_; - ChannelState channel_state_; + ChannelSendState 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; uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_); - 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_); uint16_t send_sequence_number_; - 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; Transport* _transportPtr; // WebRtc socket or external transport RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_); bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_); bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_); - float _outputGain RTC_GUARDED_BY(volume_settings_critsect_); // VoeRTP_RTCP // TODO(henrika): can today be accessed on the main thread and on the // task queue; hence potential race. @@ -397,9 +276,6 @@ class Channel rtc::CriticalSection overhead_per_packet_lock_; // RtcpBandwidthObserver std::unique_ptr rtcp_observer_; - // An associated send channel. - rtc::CriticalSection assoc_send_channel_lock_; - Channel* associated_send_channel_ RTC_GUARDED_BY(assoc_send_channel_lock_); PacketRouter* packet_router_ = nullptr; std::unique_ptr feedback_observer_proxy_; @@ -419,4 +295,4 @@ class Channel } // namespace voe } // namespace webrtc -#endif // AUDIO_CHANNEL_H_ +#endif // AUDIO_CHANNEL_SEND_H_ diff --git a/audio/channel_send_proxy.cc b/audio/channel_send_proxy.cc index 43aac58039..a4d8b690d4 100644 --- a/audio/channel_send_proxy.cc +++ b/audio/channel_send_proxy.cc @@ -22,7 +22,7 @@ namespace webrtc { namespace voe { ChannelSendProxy::ChannelSendProxy() {} -ChannelSendProxy::ChannelSendProxy(std::unique_ptr channel) +ChannelSendProxy::ChannelSendProxy(std::unique_ptr channel) : channel_(std::move(channel)) { RTC_DCHECK(channel_); module_process_thread_checker_.DetachFromThread(); @@ -41,9 +41,9 @@ void ChannelSendProxy::SetNACKStatus(bool enable, int max_packets) { channel_->SetNACKStatus(enable, max_packets); } -CallStatistics ChannelSendProxy::GetRTCPStatistics() const { +CallSendStatistics ChannelSendProxy::GetRTCPStatistics() const { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - CallStatistics stats = {0}; + CallSendStatistics stats = {0}; int error = channel_->GetRTPStatistics(stats); RTC_DCHECK_EQ(0, error); return stats; @@ -193,7 +193,7 @@ void ChannelSendProxy::StopSend() { channel_->StopSend(); } -Channel* ChannelSendProxy::GetChannel() const { +ChannelSend* ChannelSendProxy::GetChannel() const { return channel_.get(); } diff --git a/audio/channel_send_proxy.h b/audio/channel_send_proxy.h index 88ce610f25..754f9f61fd 100644 --- a/audio/channel_send_proxy.h +++ b/audio/channel_send_proxy.h @@ -16,7 +16,7 @@ #include #include "api/audio_codecs/audio_encoder.h" -#include "audio/channel.h" +#include "audio/channel_send.h" #include "rtc_base/constructormagic.h" #include "rtc_base/race_checker.h" #include "rtc_base/thread_checker.h" @@ -39,13 +39,13 @@ namespace voe { class ChannelSendProxy { public: ChannelSendProxy(); - explicit ChannelSendProxy(std::unique_ptr channel); + explicit ChannelSendProxy(std::unique_ptr channel); virtual ~ChannelSendProxy(); // Shared with ChannelReceiveProxy virtual void SetLocalSSRC(uint32_t ssrc); virtual void SetNACKStatus(bool enable, int max_packets); - virtual CallStatistics GetRTCPStatistics() const; + virtual CallSendStatistics GetRTCPStatistics() const; virtual void RegisterTransport(Transport* transport); virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length); @@ -82,7 +82,7 @@ class ChannelSendProxy { virtual void StopSend(); // Needed by ChannelReceiveProxy::AssociateSendChannel. - virtual Channel* GetChannel() const; + virtual ChannelSend* GetChannel() const; private: // Thread checkers document and lock usage of some methods on voe::Channel to @@ -97,7 +97,7 @@ class ChannelSendProxy { // 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_; + std::unique_ptr channel_; RTC_DISALLOW_COPY_AND_ASSIGN(ChannelSendProxy); }; diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h index 9d122c6704..0ae3cdcfa1 100644 --- a/audio/mock_voe_channel_proxy.h +++ b/audio/mock_voe_channel_proxy.h @@ -31,7 +31,7 @@ class MockChannelReceiveProxy : public voe::ChannelReceiveProxy { MOCK_METHOD1(RegisterReceiverCongestionControlObjects, void(PacketRouter* packet_router)); MOCK_METHOD0(ResetReceiverCongestionControlObjects, void()); - MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics()); + MOCK_CONST_METHOD0(GetRTCPStatistics, CallReceiveStatistics()); MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics()); MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats()); MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int()); @@ -82,7 +82,7 @@ class MockChannelSendProxy : public voe::ChannelSendProxy { void(RtpTransportControllerSendInterface* transport, RtcpBandwidthObserver* bandwidth_observer)); MOCK_METHOD0(ResetSenderCongestionControlObjects, void()); - MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics()); + MOCK_CONST_METHOD0(GetRTCPStatistics, CallSendStatistics()); MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector()); MOCK_CONST_METHOD0(GetANAStatistics, ANAStats()); MOCK_METHOD2(SetSendTelephoneEventPayloadType,