Delete class ChannelReceiveProxy.
Replaced by an interface ChannelReceiveInterface, implemented by ChannelReceive and the corresponding mock class. Moved thread checkers to ChannelReceive. That class is moved to the anonymous namespace in the .cc file, and exposed only via a function CreateChannelReceive. Bug: webrtc:9801 Change-Id: Iecacbb1858885bf86da9484f2422e53323dbe87a Reviewed-on: https://webrtc-review.googlesource.com/c/110610 Commit-Queue: Niels Moller <nisse@webrtc.org> Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25665}
This commit is contained in:
@ -26,8 +26,6 @@ rtc_static_library("audio") {
|
|||||||
"audio_transport_impl.h",
|
"audio_transport_impl.h",
|
||||||
"channel_receive.cc",
|
"channel_receive.cc",
|
||||||
"channel_receive.h",
|
"channel_receive.h",
|
||||||
"channel_receive_proxy.cc",
|
|
||||||
"channel_receive_proxy.h",
|
|
||||||
"channel_send.cc",
|
"channel_send.cc",
|
||||||
"channel_send.h",
|
"channel_send.h",
|
||||||
"channel_send_proxy.cc",
|
"channel_send_proxy.cc",
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
#include "audio/audio_send_stream.h"
|
#include "audio/audio_send_stream.h"
|
||||||
#include "audio/audio_state.h"
|
#include "audio/audio_state.h"
|
||||||
#include "audio/channel_receive.h"
|
#include "audio/channel_receive.h"
|
||||||
#include "audio/channel_receive_proxy.h"
|
|
||||||
#include "audio/conversion.h"
|
#include "audio/conversion.h"
|
||||||
#include "call/rtp_config.h"
|
#include "call/rtp_config.h"
|
||||||
#include "call/rtp_stream_receiver_controller_interface.h"
|
#include "call/rtp_stream_receiver_controller_interface.h"
|
||||||
@ -68,7 +67,7 @@ std::string AudioReceiveStream::Config::ToString() const {
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
namespace {
|
namespace {
|
||||||
std::unique_ptr<voe::ChannelReceiveProxy> CreateChannelAndProxy(
|
std::unique_ptr<voe::ChannelReceiveInterface> CreateChannelReceive(
|
||||||
webrtc::AudioState* audio_state,
|
webrtc::AudioState* audio_state,
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
const webrtc::AudioReceiveStream::Config& config,
|
const webrtc::AudioReceiveStream::Config& config,
|
||||||
@ -76,13 +75,12 @@ std::unique_ptr<voe::ChannelReceiveProxy> CreateChannelAndProxy(
|
|||||||
RTC_DCHECK(audio_state);
|
RTC_DCHECK(audio_state);
|
||||||
internal::AudioState* internal_audio_state =
|
internal::AudioState* internal_audio_state =
|
||||||
static_cast<internal::AudioState*>(audio_state);
|
static_cast<internal::AudioState*>(audio_state);
|
||||||
return absl::make_unique<voe::ChannelReceiveProxy>(
|
return voe::CreateChannelReceive(
|
||||||
absl::make_unique<voe::ChannelReceive>(
|
module_process_thread, internal_audio_state->audio_device_module(),
|
||||||
module_process_thread, internal_audio_state->audio_device_module(),
|
config.media_transport, config.rtcp_send_transport, event_log,
|
||||||
config.media_transport, config.rtcp_send_transport, event_log,
|
config.rtp.remote_ssrc, config.jitter_buffer_max_packets,
|
||||||
config.rtp.remote_ssrc, config.jitter_buffer_max_packets,
|
config.jitter_buffer_fast_accelerate, config.decoder_factory,
|
||||||
config.jitter_buffer_fast_accelerate, config.decoder_factory,
|
config.codec_pair_id, config.frame_decryptor, config.crypto_options);
|
||||||
config.codec_pair_id, config.frame_decryptor, config.crypto_options));
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -98,10 +96,10 @@ AudioReceiveStream::AudioReceiveStream(
|
|||||||
config,
|
config,
|
||||||
audio_state,
|
audio_state,
|
||||||
event_log,
|
event_log,
|
||||||
CreateChannelAndProxy(audio_state.get(),
|
CreateChannelReceive(audio_state.get(),
|
||||||
module_process_thread,
|
module_process_thread,
|
||||||
config,
|
config,
|
||||||
event_log)) {}
|
event_log)) {}
|
||||||
|
|
||||||
AudioReceiveStream::AudioReceiveStream(
|
AudioReceiveStream::AudioReceiveStream(
|
||||||
RtpStreamReceiverControllerInterface* receiver_controller,
|
RtpStreamReceiverControllerInterface* receiver_controller,
|
||||||
@ -109,13 +107,13 @@ AudioReceiveStream::AudioReceiveStream(
|
|||||||
const webrtc::AudioReceiveStream::Config& config,
|
const webrtc::AudioReceiveStream::Config& config,
|
||||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
|
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
|
||||||
webrtc::RtcEventLog* event_log,
|
webrtc::RtcEventLog* event_log,
|
||||||
std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy)
|
std::unique_ptr<voe::ChannelReceiveInterface> channel_receive)
|
||||||
: audio_state_(audio_state), channel_proxy_(std::move(channel_proxy)) {
|
: audio_state_(audio_state), channel_receive_(std::move(channel_receive)) {
|
||||||
RTC_LOG(LS_INFO) << "AudioReceiveStream: " << config.rtp.remote_ssrc;
|
RTC_LOG(LS_INFO) << "AudioReceiveStream: " << config.rtp.remote_ssrc;
|
||||||
RTC_DCHECK(config.decoder_factory);
|
RTC_DCHECK(config.decoder_factory);
|
||||||
RTC_DCHECK(config.rtcp_send_transport);
|
RTC_DCHECK(config.rtcp_send_transport);
|
||||||
RTC_DCHECK(audio_state_);
|
RTC_DCHECK(audio_state_);
|
||||||
RTC_DCHECK(channel_proxy_);
|
RTC_DCHECK(channel_receive_);
|
||||||
|
|
||||||
module_process_thread_checker_.DetachFromThread();
|
module_process_thread_checker_.DetachFromThread();
|
||||||
|
|
||||||
@ -123,11 +121,11 @@ AudioReceiveStream::AudioReceiveStream(
|
|||||||
RTC_DCHECK(receiver_controller);
|
RTC_DCHECK(receiver_controller);
|
||||||
RTC_DCHECK(packet_router);
|
RTC_DCHECK(packet_router);
|
||||||
// Configure bandwidth estimation.
|
// Configure bandwidth estimation.
|
||||||
channel_proxy_->RegisterReceiverCongestionControlObjects(packet_router);
|
channel_receive_->RegisterReceiverCongestionControlObjects(packet_router);
|
||||||
|
|
||||||
// Register with transport.
|
// Register with transport.
|
||||||
rtp_stream_receiver_ = receiver_controller->CreateReceiver(
|
rtp_stream_receiver_ = receiver_controller->CreateReceiver(
|
||||||
config.rtp.remote_ssrc, channel_proxy_.get());
|
config.rtp.remote_ssrc, channel_receive_.get());
|
||||||
}
|
}
|
||||||
ConfigureStream(this, config, true);
|
ConfigureStream(this, config, true);
|
||||||
}
|
}
|
||||||
@ -136,9 +134,9 @@ AudioReceiveStream::~AudioReceiveStream() {
|
|||||||
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
||||||
RTC_LOG(LS_INFO) << "~AudioReceiveStream: " << config_.rtp.remote_ssrc;
|
RTC_LOG(LS_INFO) << "~AudioReceiveStream: " << config_.rtp.remote_ssrc;
|
||||||
Stop();
|
Stop();
|
||||||
channel_proxy_->DisassociateSendChannel();
|
channel_receive_->SetAssociatedSendChannel(nullptr);
|
||||||
if (!config_.media_transport) {
|
if (!config_.media_transport) {
|
||||||
channel_proxy_->ResetReceiverCongestionControlObjects();
|
channel_receive_->ResetReceiverCongestionControlObjects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +151,7 @@ void AudioReceiveStream::Start() {
|
|||||||
if (playing_) {
|
if (playing_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
channel_proxy_->StartPlayout();
|
channel_receive_->StartPlayout();
|
||||||
playing_ = true;
|
playing_ = true;
|
||||||
audio_state()->AddReceivingStream(this);
|
audio_state()->AddReceivingStream(this);
|
||||||
}
|
}
|
||||||
@ -163,7 +161,7 @@ void AudioReceiveStream::Stop() {
|
|||||||
if (!playing_) {
|
if (!playing_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
channel_proxy_->StopPlayout();
|
channel_receive_->StopPlayout();
|
||||||
playing_ = false;
|
playing_ = false;
|
||||||
audio_state()->RemoveReceivingStream(this);
|
audio_state()->RemoveReceivingStream(this);
|
||||||
}
|
}
|
||||||
@ -174,11 +172,11 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
|||||||
stats.remote_ssrc = config_.rtp.remote_ssrc;
|
stats.remote_ssrc = config_.rtp.remote_ssrc;
|
||||||
|
|
||||||
webrtc::CallReceiveStatistics call_stats =
|
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
|
// TODO(solenberg): Don't return here if we can't get the codec - return the
|
||||||
// stats we *can* get.
|
// stats we *can* get.
|
||||||
webrtc::CodecInst codec_inst = {0};
|
webrtc::CodecInst codec_inst = {0};
|
||||||
if (!channel_proxy_->GetRecCodec(&codec_inst)) {
|
if (!channel_receive_->GetRecCodec(&codec_inst)) {
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,13 +193,13 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
|||||||
if (codec_inst.plfreq / 1000 > 0) {
|
if (codec_inst.plfreq / 1000 > 0) {
|
||||||
stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
|
stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
|
||||||
}
|
}
|
||||||
stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate();
|
stats.delay_estimate_ms = channel_receive_->GetDelayEstimate();
|
||||||
stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange();
|
stats.audio_level = channel_receive_->GetSpeechOutputLevelFullRange();
|
||||||
stats.total_output_energy = channel_proxy_->GetTotalOutputEnergy();
|
stats.total_output_energy = channel_receive_->GetTotalOutputEnergy();
|
||||||
stats.total_output_duration = channel_proxy_->GetTotalOutputDuration();
|
stats.total_output_duration = channel_receive_->GetTotalOutputDuration();
|
||||||
|
|
||||||
// Get jitter buffer and total delay (alg + jitter + playout) stats.
|
// 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_ms = ns.currentBufferSize;
|
||||||
stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
|
stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
|
||||||
stats.total_samples_received = ns.totalSamplesReceived;
|
stats.total_samples_received = ns.totalSamplesReceived;
|
||||||
@ -217,7 +215,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
|||||||
stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
|
stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
|
||||||
stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
|
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_silence_generator = ds.calls_to_silence_generator;
|
||||||
stats.decoding_calls_to_neteq = ds.calls_to_neteq;
|
stats.decoding_calls_to_neteq = ds.calls_to_neteq;
|
||||||
stats.decoding_normal = ds.decoded_normal;
|
stats.decoding_normal = ds.decoded_normal;
|
||||||
@ -231,23 +229,23 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
|||||||
|
|
||||||
void AudioReceiveStream::SetSink(AudioSinkInterface* sink) {
|
void AudioReceiveStream::SetSink(AudioSinkInterface* sink) {
|
||||||
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
||||||
channel_proxy_->SetSink(sink);
|
channel_receive_->SetSink(sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioReceiveStream::SetGain(float gain) {
|
void AudioReceiveStream::SetGain(float gain) {
|
||||||
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
||||||
channel_proxy_->SetChannelOutputVolumeScaling(gain);
|
channel_receive_->SetChannelOutputVolumeScaling(gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RtpSource> AudioReceiveStream::GetSources() const {
|
std::vector<RtpSource> AudioReceiveStream::GetSources() const {
|
||||||
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
||||||
return channel_proxy_->GetSources();
|
return channel_receive_->GetSources();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioMixer::Source::AudioFrameInfo AudioReceiveStream::GetAudioFrameWithInfo(
|
AudioMixer::Source::AudioFrameInfo AudioReceiveStream::GetAudioFrameWithInfo(
|
||||||
int sample_rate_hz,
|
int sample_rate_hz,
|
||||||
AudioFrame* audio_frame) {
|
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 {
|
int AudioReceiveStream::Ssrc() const {
|
||||||
@ -255,7 +253,7 @@ int AudioReceiveStream::Ssrc() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int AudioReceiveStream::PreferredSampleRate() const {
|
int AudioReceiveStream::PreferredSampleRate() const {
|
||||||
return channel_proxy_->PreferredSampleRate();
|
return channel_receive_->PreferredSampleRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioReceiveStream::id() const {
|
int AudioReceiveStream::id() const {
|
||||||
@ -265,32 +263,29 @@ int AudioReceiveStream::id() const {
|
|||||||
|
|
||||||
absl::optional<Syncable::Info> AudioReceiveStream::GetInfo() const {
|
absl::optional<Syncable::Info> AudioReceiveStream::GetInfo() const {
|
||||||
RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
|
RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
|
||||||
absl::optional<Syncable::Info> info = channel_proxy_->GetSyncInfo();
|
absl::optional<Syncable::Info> info = channel_receive_->GetSyncInfo();
|
||||||
|
|
||||||
if (!info)
|
if (!info)
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
|
|
||||||
info->current_delay_ms = channel_proxy_->GetDelayEstimate();
|
info->current_delay_ms = channel_receive_->GetDelayEstimate();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AudioReceiveStream::GetPlayoutTimestamp() const {
|
uint32_t AudioReceiveStream::GetPlayoutTimestamp() const {
|
||||||
// Called on video capture thread.
|
// Called on video capture thread.
|
||||||
return channel_proxy_->GetPlayoutTimestamp();
|
return channel_receive_->GetPlayoutTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioReceiveStream::SetMinimumPlayoutDelay(int delay_ms) {
|
void AudioReceiveStream::SetMinimumPlayoutDelay(int delay_ms) {
|
||||||
RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
|
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) {
|
void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) {
|
||||||
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
||||||
if (send_stream) {
|
channel_receive_->SetAssociatedSendChannel(
|
||||||
channel_proxy_->AssociateSendChannel(send_stream->GetChannelProxy());
|
send_stream ? send_stream->GetChannel() : nullptr);
|
||||||
} else {
|
|
||||||
channel_proxy_->DisassociateSendChannel();
|
|
||||||
}
|
|
||||||
associated_send_stream_ = send_stream;
|
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
|
// calls on the worker thread. We should move towards always using a network
|
||||||
// thread. Then this check can be enabled.
|
// thread. Then this check can be enabled.
|
||||||
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
|
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
|
||||||
return channel_proxy_->ReceivedRTCPPacket(packet, length);
|
return channel_receive_->ReceivedRTCPPacket(packet, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) {
|
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
|
// calls on the worker thread. We should move towards always using a network
|
||||||
// thread. Then this check can be enabled.
|
// thread. Then this check can be enabled.
|
||||||
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
|
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
|
||||||
channel_proxy_->OnRtpPacket(packet);
|
channel_receive_->OnRtpPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
|
const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
|
||||||
@ -337,7 +332,7 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
|
|||||||
RTC_LOG(LS_INFO) << "AudioReceiveStream::ConfigureStream: "
|
RTC_LOG(LS_INFO) << "AudioReceiveStream::ConfigureStream: "
|
||||||
<< new_config.ToString();
|
<< new_config.ToString();
|
||||||
RTC_DCHECK(stream);
|
RTC_DCHECK(stream);
|
||||||
const auto& channel_proxy = stream->channel_proxy_;
|
const auto& channel_receive = stream->channel_receive_;
|
||||||
const auto& old_config = stream->config_;
|
const auto& old_config = stream->config_;
|
||||||
|
|
||||||
// Configuration parameters which cannot be changed.
|
// Configuration parameters which cannot be changed.
|
||||||
@ -351,7 +346,7 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
|
|||||||
old_config.decoder_factory == new_config.decoder_factory);
|
old_config.decoder_factory == new_config.decoder_factory);
|
||||||
|
|
||||||
if (first_time || old_config.rtp.local_ssrc != new_config.rtp.local_ssrc) {
|
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) {
|
if (!first_time) {
|
||||||
@ -363,11 +358,11 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
|
|||||||
// using the actual packet size for the configured codec.
|
// using the actual packet size for the configured codec.
|
||||||
if (first_time || old_config.rtp.nack.rtp_history_ms !=
|
if (first_time || old_config.rtp.nack.rtp_history_ms !=
|
||||||
new_config.rtp.nack.rtp_history_ms) {
|
new_config.rtp.nack.rtp_history_ms) {
|
||||||
channel_proxy->SetNACKStatus(new_config.rtp.nack.rtp_history_ms != 0,
|
channel_receive->SetNACKStatus(new_config.rtp.nack.rtp_history_ms != 0,
|
||||||
new_config.rtp.nack.rtp_history_ms / 20);
|
new_config.rtp.nack.rtp_history_ms / 20);
|
||||||
}
|
}
|
||||||
if (first_time || old_config.decoder_map != new_config.decoder_map) {
|
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;
|
stream->config_ = new_config;
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class RtpStreamReceiverControllerInterface;
|
|||||||
class RtpStreamReceiverInterface;
|
class RtpStreamReceiverInterface;
|
||||||
|
|
||||||
namespace voe {
|
namespace voe {
|
||||||
class ChannelReceiveProxy;
|
class ChannelReceiveInterface;
|
||||||
} // namespace voe
|
} // namespace voe
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -47,13 +47,14 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
|
|||||||
const webrtc::AudioReceiveStream::Config& config,
|
const webrtc::AudioReceiveStream::Config& config,
|
||||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
|
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
|
||||||
webrtc::RtcEventLog* event_log);
|
webrtc::RtcEventLog* event_log);
|
||||||
// For unit tests, which need to supply a mock channel proxy.
|
// For unit tests, which need to supply a mock channel receive.
|
||||||
AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller,
|
AudioReceiveStream(
|
||||||
PacketRouter* packet_router,
|
RtpStreamReceiverControllerInterface* receiver_controller,
|
||||||
const webrtc::AudioReceiveStream::Config& config,
|
PacketRouter* packet_router,
|
||||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
|
const webrtc::AudioReceiveStream::Config& config,
|
||||||
webrtc::RtcEventLog* event_log,
|
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
|
||||||
std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy);
|
webrtc::RtcEventLog* event_log,
|
||||||
|
std::unique_ptr<voe::ChannelReceiveInterface> channel_receive);
|
||||||
~AudioReceiveStream() override;
|
~AudioReceiveStream() override;
|
||||||
|
|
||||||
// webrtc::AudioReceiveStream implementation.
|
// webrtc::AudioReceiveStream implementation.
|
||||||
@ -100,7 +101,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
|
|||||||
rtc::ThreadChecker module_process_thread_checker_;
|
rtc::ThreadChecker module_process_thread_checker_;
|
||||||
webrtc::AudioReceiveStream::Config config_;
|
webrtc::AudioReceiveStream::Config config_;
|
||||||
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
|
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
|
||||||
std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy_;
|
std::unique_ptr<voe::ChannelReceiveInterface> channel_receive_;
|
||||||
AudioSendStream* associated_send_stream_ = nullptr;
|
AudioSendStream* associated_send_stream_ = nullptr;
|
||||||
|
|
||||||
bool playing_ RTC_GUARDED_BY(worker_thread_checker_) = false;
|
bool playing_ RTC_GUARDED_BY(worker_thread_checker_) = false;
|
||||||
|
|||||||
@ -83,16 +83,16 @@ struct ConfigHelper {
|
|||||||
new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
|
new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
|
||||||
audio_state_ = AudioState::Create(config);
|
audio_state_ = AudioState::Create(config);
|
||||||
|
|
||||||
channel_proxy_ = new testing::StrictMock<MockChannelReceiveProxy>();
|
channel_receive_ = new testing::StrictMock<MockChannelReceive>();
|
||||||
EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
|
EXPECT_CALL(*channel_receive_, SetLocalSSRC(kLocalSsrc)).Times(1);
|
||||||
EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
|
EXPECT_CALL(*channel_receive_, SetNACKStatus(true, 15)).Times(1);
|
||||||
EXPECT_CALL(*channel_proxy_,
|
EXPECT_CALL(*channel_receive_,
|
||||||
RegisterReceiverCongestionControlObjects(&packet_router_))
|
RegisterReceiverCongestionControlObjects(&packet_router_))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects())
|
EXPECT_CALL(*channel_receive_, ResetReceiverCongestionControlObjects())
|
||||||
.Times(1);
|
.Times(1);
|
||||||
EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
|
EXPECT_CALL(*channel_receive_, SetAssociatedSendChannel(nullptr)).Times(1);
|
||||||
EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
|
EXPECT_CALL(*channel_receive_, SetReceiveCodecs(_))
|
||||||
.WillRepeatedly(Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
|
.WillRepeatedly(Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
|
||||||
EXPECT_THAT(codecs, testing::IsEmpty());
|
EXPECT_THAT(codecs, testing::IsEmpty());
|
||||||
}));
|
}));
|
||||||
@ -114,33 +114,33 @@ struct ConfigHelper {
|
|||||||
new internal::AudioReceiveStream(
|
new internal::AudioReceiveStream(
|
||||||
&rtp_stream_receiver_controller_, &packet_router_, stream_config_,
|
&rtp_stream_receiver_controller_, &packet_router_, stream_config_,
|
||||||
audio_state_, &event_log_,
|
audio_state_, &event_log_,
|
||||||
std::unique_ptr<voe::ChannelReceiveProxy>(channel_proxy_)));
|
std::unique_ptr<voe::ChannelReceiveInterface>(channel_receive_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioReceiveStream::Config& config() { return stream_config_; }
|
AudioReceiveStream::Config& config() { return stream_config_; }
|
||||||
rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
|
rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
|
||||||
MockChannelReceiveProxy* channel_proxy() { return channel_proxy_; }
|
MockChannelReceive* channel_receive() { return channel_receive_; }
|
||||||
|
|
||||||
void SetupMockForGetStats() {
|
void SetupMockForGetStats() {
|
||||||
using testing::DoAll;
|
using testing::DoAll;
|
||||||
using testing::SetArgPointee;
|
using testing::SetArgPointee;
|
||||||
|
|
||||||
ASSERT_TRUE(channel_proxy_);
|
ASSERT_TRUE(channel_receive_);
|
||||||
EXPECT_CALL(*channel_proxy_, GetRTCPStatistics())
|
EXPECT_CALL(*channel_receive_, GetRTCPStatistics())
|
||||||
.WillOnce(Return(kCallStats));
|
.WillOnce(Return(kCallStats));
|
||||||
EXPECT_CALL(*channel_proxy_, GetDelayEstimate())
|
EXPECT_CALL(*channel_receive_, GetDelayEstimate())
|
||||||
.WillOnce(Return(kJitterBufferDelay + kPlayoutBufferDelay));
|
.WillOnce(Return(kJitterBufferDelay + kPlayoutBufferDelay));
|
||||||
EXPECT_CALL(*channel_proxy_, GetSpeechOutputLevelFullRange())
|
EXPECT_CALL(*channel_receive_, GetSpeechOutputLevelFullRange())
|
||||||
.WillOnce(Return(kSpeechOutputLevel));
|
.WillOnce(Return(kSpeechOutputLevel));
|
||||||
EXPECT_CALL(*channel_proxy_, GetTotalOutputEnergy())
|
EXPECT_CALL(*channel_receive_, GetTotalOutputEnergy())
|
||||||
.WillOnce(Return(kTotalOutputEnergy));
|
.WillOnce(Return(kTotalOutputEnergy));
|
||||||
EXPECT_CALL(*channel_proxy_, GetTotalOutputDuration())
|
EXPECT_CALL(*channel_receive_, GetTotalOutputDuration())
|
||||||
.WillOnce(Return(kTotalOutputDuration));
|
.WillOnce(Return(kTotalOutputDuration));
|
||||||
EXPECT_CALL(*channel_proxy_, GetNetworkStatistics())
|
EXPECT_CALL(*channel_receive_, GetNetworkStatistics())
|
||||||
.WillOnce(Return(kNetworkStats));
|
.WillOnce(Return(kNetworkStats));
|
||||||
EXPECT_CALL(*channel_proxy_, GetDecodingCallStatistics())
|
EXPECT_CALL(*channel_receive_, GetDecodingCallStatistics())
|
||||||
.WillOnce(Return(kAudioDecodeStats));
|
.WillOnce(Return(kAudioDecodeStats));
|
||||||
EXPECT_CALL(*channel_proxy_, GetRecCodec(_))
|
EXPECT_CALL(*channel_receive_, GetRecCodec(_))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true)));
|
.WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ struct ConfigHelper {
|
|||||||
rtc::scoped_refptr<AudioState> audio_state_;
|
rtc::scoped_refptr<AudioState> audio_state_;
|
||||||
rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
|
rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
|
||||||
AudioReceiveStream::Config stream_config_;
|
AudioReceiveStream::Config stream_config_;
|
||||||
testing::StrictMock<MockChannelReceiveProxy>* channel_proxy_ = nullptr;
|
testing::StrictMock<MockChannelReceive>* channel_receive_ = nullptr;
|
||||||
RtpStreamReceiverController rtp_stream_receiver_controller_;
|
RtpStreamReceiverController rtp_stream_receiver_controller_;
|
||||||
MockTransport rtcp_send_transport_;
|
MockTransport rtcp_send_transport_;
|
||||||
};
|
};
|
||||||
@ -239,7 +239,7 @@ TEST(AudioReceiveStreamTest, ReceiveRtpPacket) {
|
|||||||
ASSERT_TRUE(parsed_packet.Parse(&rtp_packet[0], rtp_packet.size()));
|
ASSERT_TRUE(parsed_packet.Parse(&rtp_packet[0], rtp_packet.size()));
|
||||||
parsed_packet.set_arrival_time_ms((packet_time_us + 500) / 1000);
|
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)));
|
OnRtpPacket(testing::Ref(parsed_packet)));
|
||||||
|
|
||||||
recv_stream->OnRtpPacket(parsed_packet);
|
recv_stream->OnRtpPacket(parsed_packet);
|
||||||
@ -250,7 +250,7 @@ TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) {
|
|||||||
helper.config().rtp.transport_cc = true;
|
helper.config().rtp.transport_cc = true;
|
||||||
auto recv_stream = helper.CreateAudioReceiveStream();
|
auto recv_stream = helper.CreateAudioReceiveStream();
|
||||||
std::vector<uint8_t> rtcp_packet = CreateRtcpSenderReport();
|
std::vector<uint8_t> rtcp_packet = CreateRtcpSenderReport();
|
||||||
EXPECT_CALL(*helper.channel_proxy(),
|
EXPECT_CALL(*helper.channel_receive(),
|
||||||
ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size()))
|
ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size()))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_TRUE(recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size()));
|
EXPECT_TRUE(recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size()));
|
||||||
@ -312,7 +312,7 @@ TEST(AudioReceiveStreamTest, GetStats) {
|
|||||||
TEST(AudioReceiveStreamTest, SetGain) {
|
TEST(AudioReceiveStreamTest, SetGain) {
|
||||||
ConfigHelper helper;
|
ConfigHelper helper;
|
||||||
auto recv_stream = helper.CreateAudioReceiveStream();
|
auto recv_stream = helper.CreateAudioReceiveStream();
|
||||||
EXPECT_CALL(*helper.channel_proxy(),
|
EXPECT_CALL(*helper.channel_receive(),
|
||||||
SetChannelOutputVolumeScaling(FloatEq(0.765f)));
|
SetChannelOutputVolumeScaling(FloatEq(0.765f)));
|
||||||
recv_stream->SetGain(0.765f);
|
recv_stream->SetGain(0.765f);
|
||||||
}
|
}
|
||||||
@ -323,10 +323,10 @@ TEST(AudioReceiveStreamTest, StreamsShouldBeAddedToMixerOnceOnStart) {
|
|||||||
auto recv_stream1 = helper1.CreateAudioReceiveStream();
|
auto recv_stream1 = helper1.CreateAudioReceiveStream();
|
||||||
auto recv_stream2 = helper2.CreateAudioReceiveStream();
|
auto recv_stream2 = helper2.CreateAudioReceiveStream();
|
||||||
|
|
||||||
EXPECT_CALL(*helper1.channel_proxy(), StartPlayout()).Times(1);
|
EXPECT_CALL(*helper1.channel_receive(), StartPlayout()).Times(1);
|
||||||
EXPECT_CALL(*helper2.channel_proxy(), StartPlayout()).Times(1);
|
EXPECT_CALL(*helper2.channel_receive(), StartPlayout()).Times(1);
|
||||||
EXPECT_CALL(*helper1.channel_proxy(), StopPlayout()).Times(1);
|
EXPECT_CALL(*helper1.channel_receive(), StopPlayout()).Times(1);
|
||||||
EXPECT_CALL(*helper2.channel_proxy(), StopPlayout()).Times(1);
|
EXPECT_CALL(*helper2.channel_receive(), StopPlayout()).Times(1);
|
||||||
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream1.get()))
|
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream1.get()))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream2.get()))
|
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream2.get()))
|
||||||
@ -367,10 +367,10 @@ TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) {
|
|||||||
kTransportSequenceNumberId + 1));
|
kTransportSequenceNumberId + 1));
|
||||||
new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1));
|
new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1));
|
||||||
|
|
||||||
MockChannelReceiveProxy& channel_proxy = *helper.channel_proxy();
|
MockChannelReceive& channel_receive = *helper.channel_receive();
|
||||||
EXPECT_CALL(channel_proxy, SetLocalSSRC(kLocalSsrc + 1)).Times(1);
|
EXPECT_CALL(channel_receive, SetLocalSSRC(kLocalSsrc + 1)).Times(1);
|
||||||
EXPECT_CALL(channel_proxy, SetNACKStatus(true, 15 + 1)).Times(1);
|
EXPECT_CALL(channel_receive, SetNACKStatus(true, 15 + 1)).Times(1);
|
||||||
EXPECT_CALL(channel_proxy, SetReceiveCodecs(new_config.decoder_map));
|
EXPECT_CALL(channel_receive, SetReceiveCodecs(new_config.decoder_map));
|
||||||
|
|
||||||
recv_stream->Reconfigure(new_config);
|
recv_stream->Reconfigure(new_config);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -553,9 +553,9 @@ RtpState AudioSendStream::GetRtpState() const {
|
|||||||
return rtp_rtcp_module_->GetRtpState();
|
return rtp_rtcp_module_->GetRtpState();
|
||||||
}
|
}
|
||||||
|
|
||||||
const voe::ChannelSendProxy& AudioSendStream::GetChannelProxy() const {
|
const voe::ChannelSend* AudioSendStream::GetChannel() const {
|
||||||
RTC_DCHECK(channel_proxy_.get());
|
RTC_DCHECK(channel_proxy_.get());
|
||||||
return *channel_proxy_.get();
|
return channel_proxy_->GetChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal::AudioState* AudioSendStream::audio_state() {
|
internal::AudioState* AudioSendStream::audio_state() {
|
||||||
|
|||||||
@ -31,6 +31,7 @@ class RtcpRttStats;
|
|||||||
class RtpTransportControllerSendInterface;
|
class RtpTransportControllerSendInterface;
|
||||||
|
|
||||||
namespace voe {
|
namespace voe {
|
||||||
|
class ChannelSend;
|
||||||
class ChannelSendProxy;
|
class ChannelSendProxy;
|
||||||
} // namespace voe
|
} // namespace voe
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ class AudioSendStream final : public webrtc::AudioSendStream,
|
|||||||
void SetTransportOverhead(int transport_overhead_per_packet);
|
void SetTransportOverhead(int transport_overhead_per_packet);
|
||||||
|
|
||||||
RtpState GetRtpState() const;
|
RtpState GetRtpState() const;
|
||||||
const voe::ChannelSendProxy& GetChannelProxy() const;
|
const voe::ChannelSend* GetChannel() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class TimedTransport;
|
class TimedTransport;
|
||||||
|
|||||||
@ -18,14 +18,19 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
|
#include "audio/audio_level.h"
|
||||||
#include "audio/channel_send.h"
|
#include "audio/channel_send.h"
|
||||||
#include "audio/utility/audio_frame_operations.h"
|
#include "audio/utility/audio_frame_operations.h"
|
||||||
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
|
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
|
||||||
#include "logging/rtc_event_log/rtc_event_log.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/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/audio_device/include/audio_device.h"
|
||||||
#include "modules/pacing/packet_router.h"
|
#include "modules/pacing/packet_router.h"
|
||||||
#include "modules/rtp_rtcp/include/receive_statistics.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_header_extensions.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||||
#include "modules/utility/include/process_thread.h"
|
#include "modules/utility/include/process_thread.h"
|
||||||
@ -34,10 +39,16 @@
|
|||||||
#include "rtc_base/format_macros.h"
|
#include "rtc_base/format_macros.h"
|
||||||
#include "rtc_base/location.h"
|
#include "rtc_base/location.h"
|
||||||
#include "rtc_base/logging.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/thread_checker.h"
|
||||||
#include "rtc_base/timeutils.h"
|
#include "rtc_base/timeutils.h"
|
||||||
#include "system_wrappers/include/metrics.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 webrtc {
|
||||||
namespace voe {
|
namespace voe {
|
||||||
|
|
||||||
@ -83,7 +94,219 @@ WebRtcRTPHeader CreateWebrtcRTPHeaderForMediaTransportFrame(
|
|||||||
return webrtc_header;
|
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<AudioDecoderFactory> decoder_factory,
|
||||||
|
absl::optional<AudioCodecPairId> codec_pair_id,
|
||||||
|
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
|
||||||
|
const webrtc::CryptoOptions& crypto_options);
|
||||||
|
~ChannelReceive() override;
|
||||||
|
|
||||||
|
void SetSink(AudioSinkInterface* sink) override;
|
||||||
|
|
||||||
|
void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& 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<Syncable::Info> 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<RtpSource> 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<uint8_t, int> payload_type_frequencies_;
|
||||||
|
|
||||||
|
std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
|
||||||
|
std::unique_ptr<RtpRtcp> _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<uint32_t> last_received_rtp_timestamp_
|
||||||
|
RTC_GUARDED_BY(&rtp_sources_lock_);
|
||||||
|
absl::optional<int64_t> last_received_rtp_system_time_ms_
|
||||||
|
RTC_GUARDED_BY(&rtp_sources_lock_);
|
||||||
|
absl::optional<uint8_t> last_received_rtp_audio_level_
|
||||||
|
RTC_GUARDED_BY(&rtp_sources_lock_);
|
||||||
|
|
||||||
|
std::unique_ptr<AudioCodingModule> 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<uint32_t> 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<rtc::TimestampWrapAroundHandler> 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<FrameDecryptorInterface> frame_decryptor_;
|
||||||
|
webrtc::CryptoOptions crypto_options_;
|
||||||
|
};
|
||||||
|
|
||||||
int32_t ChannelReceive::OnReceivedPayloadData(
|
int32_t ChannelReceive::OnReceivedPayloadData(
|
||||||
const uint8_t* payloadData,
|
const uint8_t* payloadData,
|
||||||
@ -142,6 +365,7 @@ void ChannelReceive::OnData(uint64_t channel_id,
|
|||||||
AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo(
|
AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo(
|
||||||
int sample_rate_hz,
|
int sample_rate_hz,
|
||||||
AudioFrame* audio_frame) {
|
AudioFrame* audio_frame) {
|
||||||
|
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
|
||||||
audio_frame->sample_rate_hz_ = sample_rate_hz;
|
audio_frame->sample_rate_hz_ = sample_rate_hz;
|
||||||
|
|
||||||
unsigned int ssrc;
|
unsigned int ssrc;
|
||||||
@ -248,6 +472,7 @@ AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ChannelReceive::PreferredSampleRate() const {
|
int ChannelReceive::PreferredSampleRate() const {
|
||||||
|
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
|
||||||
// Return the bigger of playout and receive frequency in the ACM.
|
// Return the bigger of playout and receive frequency in the ACM.
|
||||||
return std::max(audio_coding_->ReceiveFrequency(),
|
return std::max(audio_coding_->ReceiveFrequency(),
|
||||||
audio_coding_->PlayoutFrequency());
|
audio_coding_->PlayoutFrequency());
|
||||||
@ -284,6 +509,9 @@ ChannelReceive::ChannelReceive(
|
|||||||
media_transport_(media_transport),
|
media_transport_(media_transport),
|
||||||
frame_decryptor_(frame_decryptor),
|
frame_decryptor_(frame_decryptor),
|
||||||
crypto_options_(crypto_options) {
|
crypto_options_(crypto_options) {
|
||||||
|
// TODO(nisse): Use _moduleProcessThreadPtr instead?
|
||||||
|
module_process_thread_checker_.DetachFromThread();
|
||||||
|
|
||||||
RTC_DCHECK(module_process_thread);
|
RTC_DCHECK(module_process_thread);
|
||||||
RTC_DCHECK(audio_device_module);
|
RTC_DCHECK(audio_device_module);
|
||||||
AudioCodingModule::Config acm_config;
|
AudioCodingModule::Config acm_config;
|
||||||
@ -368,11 +596,13 @@ void ChannelReceive::Terminate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::SetSink(AudioSinkInterface* sink) {
|
void ChannelReceive::SetSink(AudioSinkInterface* sink) {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
rtc::CritScope cs(&_callbackCritSect);
|
rtc::CritScope cs(&_callbackCritSect);
|
||||||
audio_sink_ = sink;
|
audio_sink_ = sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::StartPlayout() {
|
void ChannelReceive::StartPlayout() {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
if (channel_state_.Get().playing) {
|
if (channel_state_.Get().playing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -381,6 +611,7 @@ void ChannelReceive::StartPlayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::StopPlayout() {
|
void ChannelReceive::StopPlayout() {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
if (!channel_state_.Get().playing) {
|
if (!channel_state_.Get().playing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -389,11 +620,13 @@ void ChannelReceive::StopPlayout() {
|
|||||||
_outputAudioLevel.Clear();
|
_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);
|
return (audio_coding_->ReceiveCodec(codec) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
|
std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
int64_t now_ms = rtc::TimeMillis();
|
int64_t now_ms = rtc::TimeMillis();
|
||||||
std::vector<RtpSource> sources;
|
std::vector<RtpSource> sources;
|
||||||
{
|
{
|
||||||
@ -411,6 +644,7 @@ std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
|
|||||||
|
|
||||||
void ChannelReceive::SetReceiveCodecs(
|
void ChannelReceive::SetReceiveCodecs(
|
||||||
const std::map<int, SdpAudioFormat>& codecs) {
|
const std::map<int, SdpAudioFormat>& codecs) {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
for (const auto& kv : codecs) {
|
for (const auto& kv : codecs) {
|
||||||
RTC_DCHECK_GE(kv.second.clockrate_hz, 1000);
|
RTC_DCHECK_GE(kv.second.clockrate_hz, 1000);
|
||||||
payload_type_frequencies_[kv.first] = kv.second.clockrate_hz;
|
payload_type_frequencies_[kv.first] = kv.second.clockrate_hz;
|
||||||
@ -418,7 +652,7 @@ void ChannelReceive::SetReceiveCodecs(
|
|||||||
audio_coding_->SetReceiveCodecs(codecs);
|
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) {
|
void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) {
|
||||||
int64_t now_ms = rtc::TimeMillis();
|
int64_t now_ms = rtc::TimeMillis();
|
||||||
uint8_t audio_level;
|
uint8_t audio_level;
|
||||||
@ -509,6 +743,7 @@ bool ChannelReceive::ReceivePacket(const uint8_t* packet,
|
|||||||
&webrtc_rtp_header);
|
&webrtc_rtp_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// May be called on either worker thread or network thread.
|
||||||
// TODO(nisse): Drop always-true return value.
|
// TODO(nisse): Drop always-true return value.
|
||||||
bool ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
|
bool ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
|
||||||
// Store playout timestamp for the received RTCP packet
|
// 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 {
|
int ChannelReceive::GetSpeechOutputLevelFullRange() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
return _outputAudioLevel.LevelFullRange();
|
return _outputAudioLevel.LevelFullRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
double ChannelReceive::GetTotalOutputEnergy() const {
|
double ChannelReceive::GetTotalOutputEnergy() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
return _outputAudioLevel.TotalEnergy();
|
return _outputAudioLevel.TotalEnergy();
|
||||||
}
|
}
|
||||||
|
|
||||||
double ChannelReceive::GetTotalOutputDuration() const {
|
double ChannelReceive::GetTotalOutputDuration() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
return _outputAudioLevel.TotalDuration();
|
return _outputAudioLevel.TotalDuration();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::SetChannelOutputVolumeScaling(float scaling) {
|
void ChannelReceive::SetChannelOutputVolumeScaling(float scaling) {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
rtc::CritScope cs(&volume_settings_critsect_);
|
rtc::CritScope cs(&volume_settings_critsect_);
|
||||||
_outputGain = scaling;
|
_outputGain = scaling;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::SetLocalSSRC(unsigned int ssrc) {
|
void ChannelReceive::SetLocalSSRC(uint32_t ssrc) {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
_rtpRtcpModule->SetSSRC(ssrc);
|
_rtpRtcpModule->SetSSRC(ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,6 +815,7 @@ int ChannelReceive::GetRemoteSSRC(unsigned int& ssrc) {
|
|||||||
|
|
||||||
void ChannelReceive::RegisterReceiverCongestionControlObjects(
|
void ChannelReceive::RegisterReceiverCongestionControlObjects(
|
||||||
PacketRouter* packet_router) {
|
PacketRouter* packet_router) {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
RTC_DCHECK(packet_router);
|
RTC_DCHECK(packet_router);
|
||||||
RTC_DCHECK(!packet_router_);
|
RTC_DCHECK(!packet_router_);
|
||||||
constexpr bool remb_candidate = false;
|
constexpr bool remb_candidate = false;
|
||||||
@ -583,12 +824,14 @@ void ChannelReceive::RegisterReceiverCongestionControlObjects(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::ResetReceiverCongestionControlObjects() {
|
void ChannelReceive::ResetReceiverCongestionControlObjects() {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
RTC_DCHECK(packet_router_);
|
RTC_DCHECK(packet_router_);
|
||||||
packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get());
|
packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get());
|
||||||
packet_router_ = nullptr;
|
packet_router_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallReceiveStatistics ChannelReceive::GetRTCPStatistics() {
|
CallReceiveStatistics ChannelReceive::GetRTCPStatistics() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
// --- RtcpStatistics
|
// --- RtcpStatistics
|
||||||
CallReceiveStatistics stats;
|
CallReceiveStatistics stats;
|
||||||
|
|
||||||
@ -630,11 +873,12 @@ CallReceiveStatistics ChannelReceive::GetRTCPStatistics() {
|
|||||||
return stats;
|
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.
|
// None of these functions can fail.
|
||||||
rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
|
rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets);
|
||||||
if (enable)
|
if (enable)
|
||||||
audio_coding_->EnableNack(maxNumberOfPackets);
|
audio_coding_->EnableNack(max_packets);
|
||||||
else
|
else
|
||||||
audio_coding_->DisableNack();
|
audio_coding_->DisableNack();
|
||||||
}
|
}
|
||||||
@ -645,12 +889,14 @@ int ChannelReceive::ResendPackets(const uint16_t* sequence_numbers,
|
|||||||
return _rtpRtcpModule->SendNACK(sequence_numbers, length);
|
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_);
|
rtc::CritScope lock(&assoc_send_channel_lock_);
|
||||||
associated_send_channel_ = channel;
|
associated_send_channel_ = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkStatistics ChannelReceive::GetNetworkStatistics() const {
|
NetworkStatistics ChannelReceive::GetNetworkStatistics() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
NetworkStatistics stats;
|
NetworkStatistics stats;
|
||||||
int error = audio_coding_->GetNetworkStatistics(&stats);
|
int error = audio_coding_->GetNetworkStatistics(&stats);
|
||||||
RTC_DCHECK_EQ(0, error);
|
RTC_DCHECK_EQ(0, error);
|
||||||
@ -658,29 +904,37 @@ NetworkStatistics ChannelReceive::GetNetworkStatistics() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioDecodingCallStats ChannelReceive::GetDecodingCallStatistics() const {
|
AudioDecodingCallStats ChannelReceive::GetDecodingCallStatistics() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||||
AudioDecodingCallStats stats;
|
AudioDecodingCallStats stats;
|
||||||
audio_coding_->GetDecodingCallStatistics(&stats);
|
audio_coding_->GetDecodingCallStatistics(&stats);
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ChannelReceive::GetDelayEstimate() const {
|
uint32_t ChannelReceive::GetDelayEstimate() const {
|
||||||
|
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
|
||||||
|
module_process_thread_checker_.CalledOnValidThread());
|
||||||
rtc::CritScope lock(&video_sync_lock_);
|
rtc::CritScope lock(&video_sync_lock_);
|
||||||
return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
|
return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelReceive::SetMinimumPlayoutDelay(int delayMs) {
|
void ChannelReceive::SetMinimumPlayoutDelay(int delay_ms) {
|
||||||
if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
|
RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
|
||||||
(delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
|
// 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";
|
RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
|
if (audio_coding_->SetMinimumPlayoutDelay(delay_ms) != 0) {
|
||||||
RTC_DLOG(LS_ERROR)
|
RTC_DLOG(LS_ERROR)
|
||||||
<< "SetMinimumPlayoutDelay() failed to set min playout delay";
|
<< "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_);
|
rtc::CritScope lock(&video_sync_lock_);
|
||||||
return playout_timestamp_rtp_;
|
return playout_timestamp_rtp_;
|
||||||
@ -688,6 +942,7 @@ uint32_t ChannelReceive::GetPlayoutTimestamp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<Syncable::Info> ChannelReceive::GetSyncInfo() const {
|
absl::optional<Syncable::Info> ChannelReceive::GetSyncInfo() const {
|
||||||
|
RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
|
||||||
Syncable::Info info;
|
Syncable::Info info;
|
||||||
if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs,
|
if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs,
|
||||||
&info.capture_time_ntp_frac, nullptr, nullptr,
|
&info.capture_time_ntp_frac, nullptr, nullptr,
|
||||||
@ -780,5 +1035,27 @@ int64_t ChannelReceive::GetRTT() const {
|
|||||||
return rtt;
|
return rtt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<ChannelReceiveInterface> 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<AudioDecoderFactory> decoder_factory,
|
||||||
|
absl::optional<AudioCodecPairId> codec_pair_id,
|
||||||
|
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
|
||||||
|
const webrtc::CryptoOptions& crypto_options) {
|
||||||
|
return absl::make_unique<ChannelReceive>(
|
||||||
|
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 voe
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -17,24 +17,18 @@
|
|||||||
|
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/audio/audio_mixer.h"
|
#include "api/audio/audio_mixer.h"
|
||||||
|
#include "api/audio_codecs/audio_decoder_factory.h"
|
||||||
#include "api/call/audio_sink.h"
|
#include "api/call/audio_sink.h"
|
||||||
#include "api/call/transport.h"
|
#include "api/call/transport.h"
|
||||||
#include "api/crypto/cryptooptions.h"
|
#include "api/crypto/cryptooptions.h"
|
||||||
#include "api/media_transport_interface.h"
|
#include "api/media_transport_interface.h"
|
||||||
#include "api/rtpreceiverinterface.h"
|
#include "api/rtpreceiverinterface.h"
|
||||||
#include "audio/audio_level.h"
|
#include "call/rtp_packet_sink_interface.h"
|
||||||
#include "call/syncable.h"
|
#include "call/syncable.h"
|
||||||
#include "common_types.h" // NOLINT(build/include)
|
#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
|
// 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.
|
// These need cleanup, in a separate cl.
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
@ -70,205 +64,81 @@ namespace voe {
|
|||||||
|
|
||||||
class ChannelSend;
|
class ChannelSend;
|
||||||
|
|
||||||
// Helper class to simplify locking scheme for members that are accessed from
|
// Interface class needed for AudioReceiveStream tests that use a
|
||||||
// multiple threads.
|
// MockChannelReceive.
|
||||||
// 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
|
class ChannelReceiveInterface : public RtpPacketSinkInterface {
|
||||||
// safe and also avoid TSan v2 warnings.
|
|
||||||
class ChannelReceiveState {
|
|
||||||
public:
|
public:
|
||||||
struct State {
|
virtual ~ChannelReceiveInterface() = default;
|
||||||
bool playing = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
ChannelReceiveState() {}
|
virtual void SetSink(AudioSinkInterface* sink) = 0;
|
||||||
virtual ~ChannelReceiveState() {}
|
|
||||||
|
|
||||||
void Reset() {
|
virtual void SetReceiveCodecs(
|
||||||
rtc::CritScope lock(&lock_);
|
const std::map<int, SdpAudioFormat>& codecs) = 0;
|
||||||
state_ = State();
|
|
||||||
}
|
|
||||||
|
|
||||||
State Get() const {
|
virtual void StartPlayout() = 0;
|
||||||
rtc::CritScope lock(&lock_);
|
virtual void StopPlayout() = 0;
|
||||||
return state_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPlaying(bool enable) {
|
virtual bool GetRecCodec(CodecInst* codec) const = 0;
|
||||||
rtc::CritScope lock(&lock_);
|
|
||||||
state_.playing = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
virtual bool ReceivedRTCPPacket(const uint8_t* data, size_t length) = 0;
|
||||||
rtc::CriticalSection lock_;
|
|
||||||
State state_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChannelReceive : public MediaTransportAudioSinkInterface {
|
virtual void SetChannelOutputVolumeScaling(float scaling) = 0;
|
||||||
public:
|
virtual int GetSpeechOutputLevelFullRange() const = 0;
|
||||||
// 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<AudioDecoderFactory> decoder_factory,
|
|
||||||
absl::optional<AudioCodecPairId> codec_pair_id,
|
|
||||||
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
|
|
||||||
const webrtc::CryptoOptions& crypto_options);
|
|
||||||
virtual ~ChannelReceive();
|
|
||||||
|
|
||||||
void SetSink(AudioSinkInterface* sink);
|
|
||||||
|
|
||||||
void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& 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;
|
|
||||||
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
||||||
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
||||||
double GetTotalOutputEnergy() const;
|
virtual double GetTotalOutputEnergy() const = 0;
|
||||||
double GetTotalOutputDuration() const;
|
virtual double GetTotalOutputDuration() const = 0;
|
||||||
|
|
||||||
// Stats.
|
// Stats.
|
||||||
NetworkStatistics GetNetworkStatistics() const;
|
virtual NetworkStatistics GetNetworkStatistics() const = 0;
|
||||||
AudioDecodingCallStats GetDecodingCallStatistics() const;
|
virtual AudioDecodingCallStats GetDecodingCallStatistics() const = 0;
|
||||||
|
|
||||||
// Audio+Video Sync.
|
// Audio+Video Sync.
|
||||||
uint32_t GetDelayEstimate() const;
|
virtual uint32_t GetDelayEstimate() const = 0;
|
||||||
void SetMinimumPlayoutDelay(int delayMs);
|
virtual void SetMinimumPlayoutDelay(int delay_ms) = 0;
|
||||||
uint32_t GetPlayoutTimestamp();
|
virtual uint32_t GetPlayoutTimestamp() const = 0;
|
||||||
|
|
||||||
// Produces the transport-related timestamps; current_delay_ms is left unset.
|
// Produces the transport-related timestamps; current_delay_ms is left unset.
|
||||||
absl::optional<Syncable::Info> GetSyncInfo() const;
|
virtual absl::optional<Syncable::Info> GetSyncInfo() const = 0;
|
||||||
|
|
||||||
// RTP+RTCP
|
// RTP+RTCP
|
||||||
void SetLocalSSRC(unsigned int ssrc);
|
virtual void SetLocalSSRC(uint32_t ssrc) = 0;
|
||||||
|
|
||||||
void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router);
|
virtual void RegisterReceiverCongestionControlObjects(
|
||||||
void ResetReceiverCongestionControlObjects();
|
PacketRouter* packet_router) = 0;
|
||||||
|
virtual void ResetReceiverCongestionControlObjects() = 0;
|
||||||
|
|
||||||
CallReceiveStatistics GetRTCPStatistics();
|
virtual CallReceiveStatistics GetRTCPStatistics() const = 0;
|
||||||
void SetNACKStatus(bool enable, int maxNumberOfPackets);
|
virtual void SetNACKStatus(bool enable, int max_packets) = 0;
|
||||||
|
|
||||||
// From AudioMixer::Source.
|
virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
|
||||||
AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
|
|
||||||
int sample_rate_hz,
|
int sample_rate_hz,
|
||||||
AudioFrame* audio_frame);
|
AudioFrame* audio_frame) = 0;
|
||||||
|
|
||||||
int PreferredSampleRate() const;
|
virtual int PreferredSampleRate() const = 0;
|
||||||
|
|
||||||
// Associate to a send channel.
|
// Associate to a send channel.
|
||||||
// Used for obtaining RTT for a receive-only channel.
|
// Used for obtaining RTT for a receive-only channel.
|
||||||
void SetAssociatedSendChannel(ChannelSend* channel);
|
virtual void SetAssociatedSendChannel(const ChannelSend* channel) = 0;
|
||||||
|
|
||||||
std::vector<RtpSource> GetSources() const;
|
virtual std::vector<RtpSource> GetSources() const = 0;
|
||||||
|
|
||||||
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<uint8_t, int> payload_type_frequencies_;
|
|
||||||
|
|
||||||
std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
|
|
||||||
std::unique_ptr<RtpRtcp> _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<uint32_t> last_received_rtp_timestamp_
|
|
||||||
RTC_GUARDED_BY(&rtp_sources_lock_);
|
|
||||||
absl::optional<int64_t> last_received_rtp_system_time_ms_
|
|
||||||
RTC_GUARDED_BY(&rtp_sources_lock_);
|
|
||||||
absl::optional<uint8_t> last_received_rtp_audio_level_
|
|
||||||
RTC_GUARDED_BY(&rtp_sources_lock_);
|
|
||||||
|
|
||||||
std::unique_ptr<AudioCodingModule> 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<uint32_t> 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<rtc::TimestampWrapAroundHandler> 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<FrameDecryptorInterface> frame_decryptor_;
|
|
||||||
webrtc::CryptoOptions crypto_options_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<ChannelReceiveInterface> 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<AudioDecoderFactory> decoder_factory,
|
||||||
|
absl::optional<AudioCodecPairId> codec_pair_id,
|
||||||
|
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
|
||||||
|
const webrtc::CryptoOptions& crypto_options);
|
||||||
|
|
||||||
} // namespace voe
|
} // namespace voe
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
|
|||||||
@ -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 <utility>
|
|
||||||
|
|
||||||
#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<ChannelReceive> 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<int, SdpAudioFormat>& 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<Syncable::Info> 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<RtpSource> 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
|
|
||||||
@ -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 <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#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<ChannelReceive> 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<int, SdpAudioFormat>& 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<Syncable::Info> GetSyncInfo() const;
|
|
||||||
virtual uint32_t GetPlayoutTimestamp() const;
|
|
||||||
virtual void SetMinimumPlayoutDelay(int delay_ms);
|
|
||||||
virtual bool GetRecCodec(CodecInst* codec_inst) const;
|
|
||||||
virtual std::vector<webrtc::RtpSource> 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<ChannelReceive> channel_;
|
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(ChannelReceiveProxy);
|
|
||||||
};
|
|
||||||
} // namespace voe
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // AUDIO_CHANNEL_RECEIVE_PROXY_H_
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "api/test/mock_frame_encryptor.h"
|
#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 "audio/channel_send_proxy.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||||
#include "test/gmock.h"
|
#include "test/gmock.h"
|
||||||
@ -25,7 +25,7 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
class MockChannelReceiveProxy : public voe::ChannelReceiveProxy {
|
class MockChannelReceive : public voe::ChannelReceiveInterface {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
|
MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
|
||||||
MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets));
|
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,
|
AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
|
||||||
AudioFrame* audio_frame));
|
AudioFrame* audio_frame));
|
||||||
MOCK_CONST_METHOD0(PreferredSampleRate, int());
|
MOCK_CONST_METHOD0(PreferredSampleRate, int());
|
||||||
MOCK_METHOD1(AssociateSendChannel,
|
MOCK_METHOD1(SetAssociatedSendChannel,
|
||||||
void(const voe::ChannelSendProxy& send_channel_proxy));
|
void(const voe::ChannelSend* send_channel));
|
||||||
MOCK_METHOD0(DisassociateSendChannel, void());
|
|
||||||
MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
|
MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
|
||||||
|
MOCK_CONST_METHOD0(GetSyncInfo, absl::optional<Syncable::Info>());
|
||||||
MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
|
MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
|
||||||
MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
|
MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
|
||||||
MOCK_METHOD1(SetReceiveCodecs,
|
MOCK_METHOD1(SetReceiveCodecs,
|
||||||
|
|||||||
Reference in New Issue
Block a user