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:
Niels Möller
2018-11-16 09:50:42 +01:00
committed by Commit Bot
parent 25a3a97f59
commit 349ade3a4b
11 changed files with 436 additions and 582 deletions

View File

@ -26,8 +26,6 @@ rtc_static_library("audio") {
"audio_transport_impl.h",
"channel_receive.cc",
"channel_receive.h",
"channel_receive_proxy.cc",
"channel_receive_proxy.h",
"channel_send.cc",
"channel_send.h",
"channel_send_proxy.cc",

View File

@ -21,7 +21,6 @@
#include "audio/audio_send_stream.h"
#include "audio/audio_state.h"
#include "audio/channel_receive.h"
#include "audio/channel_receive_proxy.h"
#include "audio/conversion.h"
#include "call/rtp_config.h"
#include "call/rtp_stream_receiver_controller_interface.h"
@ -68,7 +67,7 @@ std::string AudioReceiveStream::Config::ToString() const {
namespace internal {
namespace {
std::unique_ptr<voe::ChannelReceiveProxy> CreateChannelAndProxy(
std::unique_ptr<voe::ChannelReceiveInterface> CreateChannelReceive(
webrtc::AudioState* audio_state,
ProcessThread* module_process_thread,
const webrtc::AudioReceiveStream::Config& config,
@ -76,13 +75,12 @@ std::unique_ptr<voe::ChannelReceiveProxy> CreateChannelAndProxy(
RTC_DCHECK(audio_state);
internal::AudioState* internal_audio_state =
static_cast<internal::AudioState*>(audio_state);
return absl::make_unique<voe::ChannelReceiveProxy>(
absl::make_unique<voe::ChannelReceive>(
return voe::CreateChannelReceive(
module_process_thread, internal_audio_state->audio_device_module(),
config.media_transport, config.rtcp_send_transport, event_log,
config.rtp.remote_ssrc, config.jitter_buffer_max_packets,
config.jitter_buffer_fast_accelerate, config.decoder_factory,
config.codec_pair_id, config.frame_decryptor, config.crypto_options));
config.codec_pair_id, config.frame_decryptor, config.crypto_options);
}
} // namespace
@ -98,7 +96,7 @@ AudioReceiveStream::AudioReceiveStream(
config,
audio_state,
event_log,
CreateChannelAndProxy(audio_state.get(),
CreateChannelReceive(audio_state.get(),
module_process_thread,
config,
event_log)) {}
@ -109,13 +107,13 @@ AudioReceiveStream::AudioReceiveStream(
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log,
std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy)
: audio_state_(audio_state), channel_proxy_(std::move(channel_proxy)) {
std::unique_ptr<voe::ChannelReceiveInterface> channel_receive)
: audio_state_(audio_state), channel_receive_(std::move(channel_receive)) {
RTC_LOG(LS_INFO) << "AudioReceiveStream: " << config.rtp.remote_ssrc;
RTC_DCHECK(config.decoder_factory);
RTC_DCHECK(config.rtcp_send_transport);
RTC_DCHECK(audio_state_);
RTC_DCHECK(channel_proxy_);
RTC_DCHECK(channel_receive_);
module_process_thread_checker_.DetachFromThread();
@ -123,11 +121,11 @@ AudioReceiveStream::AudioReceiveStream(
RTC_DCHECK(receiver_controller);
RTC_DCHECK(packet_router);
// Configure bandwidth estimation.
channel_proxy_->RegisterReceiverCongestionControlObjects(packet_router);
channel_receive_->RegisterReceiverCongestionControlObjects(packet_router);
// Register with transport.
rtp_stream_receiver_ = receiver_controller->CreateReceiver(
config.rtp.remote_ssrc, channel_proxy_.get());
config.rtp.remote_ssrc, channel_receive_.get());
}
ConfigureStream(this, config, true);
}
@ -136,9 +134,9 @@ AudioReceiveStream::~AudioReceiveStream() {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
RTC_LOG(LS_INFO) << "~AudioReceiveStream: " << config_.rtp.remote_ssrc;
Stop();
channel_proxy_->DisassociateSendChannel();
channel_receive_->SetAssociatedSendChannel(nullptr);
if (!config_.media_transport) {
channel_proxy_->ResetReceiverCongestionControlObjects();
channel_receive_->ResetReceiverCongestionControlObjects();
}
}
@ -153,7 +151,7 @@ void AudioReceiveStream::Start() {
if (playing_) {
return;
}
channel_proxy_->StartPlayout();
channel_receive_->StartPlayout();
playing_ = true;
audio_state()->AddReceivingStream(this);
}
@ -163,7 +161,7 @@ void AudioReceiveStream::Stop() {
if (!playing_) {
return;
}
channel_proxy_->StopPlayout();
channel_receive_->StopPlayout();
playing_ = false;
audio_state()->RemoveReceivingStream(this);
}
@ -174,11 +172,11 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
stats.remote_ssrc = config_.rtp.remote_ssrc;
webrtc::CallReceiveStatistics call_stats =
channel_proxy_->GetRTCPStatistics();
channel_receive_->GetRTCPStatistics();
// TODO(solenberg): Don't return here if we can't get the codec - return the
// stats we *can* get.
webrtc::CodecInst codec_inst = {0};
if (!channel_proxy_->GetRecCodec(&codec_inst)) {
if (!channel_receive_->GetRecCodec(&codec_inst)) {
return stats;
}
@ -195,13 +193,13 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
if (codec_inst.plfreq / 1000 > 0) {
stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
}
stats.delay_estimate_ms = channel_proxy_->GetDelayEstimate();
stats.audio_level = channel_proxy_->GetSpeechOutputLevelFullRange();
stats.total_output_energy = channel_proxy_->GetTotalOutputEnergy();
stats.total_output_duration = channel_proxy_->GetTotalOutputDuration();
stats.delay_estimate_ms = channel_receive_->GetDelayEstimate();
stats.audio_level = channel_receive_->GetSpeechOutputLevelFullRange();
stats.total_output_energy = channel_receive_->GetTotalOutputEnergy();
stats.total_output_duration = channel_receive_->GetTotalOutputDuration();
// Get jitter buffer and total delay (alg + jitter + playout) stats.
auto ns = channel_proxy_->GetNetworkStatistics();
auto ns = channel_receive_->GetNetworkStatistics();
stats.jitter_buffer_ms = ns.currentBufferSize;
stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
stats.total_samples_received = ns.totalSamplesReceived;
@ -217,7 +215,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
auto ds = channel_proxy_->GetDecodingCallStatistics();
auto ds = channel_receive_->GetDecodingCallStatistics();
stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
stats.decoding_calls_to_neteq = ds.calls_to_neteq;
stats.decoding_normal = ds.decoded_normal;
@ -231,23 +229,23 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
void AudioReceiveStream::SetSink(AudioSinkInterface* sink) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
channel_proxy_->SetSink(sink);
channel_receive_->SetSink(sink);
}
void AudioReceiveStream::SetGain(float gain) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
channel_proxy_->SetChannelOutputVolumeScaling(gain);
channel_receive_->SetChannelOutputVolumeScaling(gain);
}
std::vector<RtpSource> AudioReceiveStream::GetSources() const {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
return channel_proxy_->GetSources();
return channel_receive_->GetSources();
}
AudioMixer::Source::AudioFrameInfo AudioReceiveStream::GetAudioFrameWithInfo(
int sample_rate_hz,
AudioFrame* audio_frame) {
return channel_proxy_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
return channel_receive_->GetAudioFrameWithInfo(sample_rate_hz, audio_frame);
}
int AudioReceiveStream::Ssrc() const {
@ -255,7 +253,7 @@ int AudioReceiveStream::Ssrc() const {
}
int AudioReceiveStream::PreferredSampleRate() const {
return channel_proxy_->PreferredSampleRate();
return channel_receive_->PreferredSampleRate();
}
int AudioReceiveStream::id() const {
@ -265,32 +263,29 @@ int AudioReceiveStream::id() const {
absl::optional<Syncable::Info> AudioReceiveStream::GetInfo() const {
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)
return absl::nullopt;
info->current_delay_ms = channel_proxy_->GetDelayEstimate();
info->current_delay_ms = channel_receive_->GetDelayEstimate();
return info;
}
uint32_t AudioReceiveStream::GetPlayoutTimestamp() const {
// Called on video capture thread.
return channel_proxy_->GetPlayoutTimestamp();
return channel_receive_->GetPlayoutTimestamp();
}
void AudioReceiveStream::SetMinimumPlayoutDelay(int delay_ms) {
RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
return channel_proxy_->SetMinimumPlayoutDelay(delay_ms);
return channel_receive_->SetMinimumPlayoutDelay(delay_ms);
}
void AudioReceiveStream::AssociateSendStream(AudioSendStream* send_stream) {
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
if (send_stream) {
channel_proxy_->AssociateSendChannel(send_stream->GetChannelProxy());
} else {
channel_proxy_->DisassociateSendChannel();
}
channel_receive_->SetAssociatedSendChannel(
send_stream ? send_stream->GetChannel() : nullptr);
associated_send_stream_ = send_stream;
}
@ -303,7 +298,7 @@ bool AudioReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
// calls on the worker thread. We should move towards always using a network
// thread. Then this check can be enabled.
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
return channel_proxy_->ReceivedRTCPPacket(packet, length);
return channel_receive_->ReceivedRTCPPacket(packet, length);
}
void AudioReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) {
@ -311,7 +306,7 @@ void AudioReceiveStream::OnRtpPacket(const RtpPacketReceived& packet) {
// calls on the worker thread. We should move towards always using a network
// thread. Then this check can be enabled.
// RTC_DCHECK(!thread_checker_.CalledOnValidThread());
channel_proxy_->OnRtpPacket(packet);
channel_receive_->OnRtpPacket(packet);
}
const webrtc::AudioReceiveStream::Config& AudioReceiveStream::config() const {
@ -337,7 +332,7 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
RTC_LOG(LS_INFO) << "AudioReceiveStream::ConfigureStream: "
<< new_config.ToString();
RTC_DCHECK(stream);
const auto& channel_proxy = stream->channel_proxy_;
const auto& channel_receive = stream->channel_receive_;
const auto& old_config = stream->config_;
// Configuration parameters which cannot be changed.
@ -351,7 +346,7 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
old_config.decoder_factory == new_config.decoder_factory);
if (first_time || old_config.rtp.local_ssrc != new_config.rtp.local_ssrc) {
channel_proxy->SetLocalSSRC(new_config.rtp.local_ssrc);
channel_receive->SetLocalSSRC(new_config.rtp.local_ssrc);
}
if (!first_time) {
@ -363,11 +358,11 @@ void AudioReceiveStream::ConfigureStream(AudioReceiveStream* stream,
// using the actual packet size for the configured codec.
if (first_time || old_config.rtp.nack.rtp_history_ms !=
new_config.rtp.nack.rtp_history_ms) {
channel_proxy->SetNACKStatus(new_config.rtp.nack.rtp_history_ms != 0,
channel_receive->SetNACKStatus(new_config.rtp.nack.rtp_history_ms != 0,
new_config.rtp.nack.rtp_history_ms / 20);
}
if (first_time || old_config.decoder_map != new_config.decoder_map) {
channel_proxy->SetReceiveCodecs(new_config.decoder_map);
channel_receive->SetReceiveCodecs(new_config.decoder_map);
}
stream->config_ = new_config;

View File

@ -31,7 +31,7 @@ class RtpStreamReceiverControllerInterface;
class RtpStreamReceiverInterface;
namespace voe {
class ChannelReceiveProxy;
class ChannelReceiveInterface;
} // namespace voe
namespace internal {
@ -47,13 +47,14 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log);
// For unit tests, which need to supply a mock channel proxy.
AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller,
// For unit tests, which need to supply a mock channel receive.
AudioReceiveStream(
RtpStreamReceiverControllerInterface* receiver_controller,
PacketRouter* packet_router,
const webrtc::AudioReceiveStream::Config& config,
const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
webrtc::RtcEventLog* event_log,
std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy);
std::unique_ptr<voe::ChannelReceiveInterface> channel_receive);
~AudioReceiveStream() override;
// webrtc::AudioReceiveStream implementation.
@ -100,7 +101,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
rtc::ThreadChecker module_process_thread_checker_;
webrtc::AudioReceiveStream::Config config_;
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
std::unique_ptr<voe::ChannelReceiveProxy> channel_proxy_;
std::unique_ptr<voe::ChannelReceiveInterface> channel_receive_;
AudioSendStream* associated_send_stream_ = nullptr;
bool playing_ RTC_GUARDED_BY(worker_thread_checker_) = false;

View File

@ -83,16 +83,16 @@ struct ConfigHelper {
new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
audio_state_ = AudioState::Create(config);
channel_proxy_ = new testing::StrictMock<MockChannelReceiveProxy>();
EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
EXPECT_CALL(*channel_proxy_,
channel_receive_ = new testing::StrictMock<MockChannelReceive>();
EXPECT_CALL(*channel_receive_, SetLocalSSRC(kLocalSsrc)).Times(1);
EXPECT_CALL(*channel_receive_, SetNACKStatus(true, 15)).Times(1);
EXPECT_CALL(*channel_receive_,
RegisterReceiverCongestionControlObjects(&packet_router_))
.Times(1);
EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects())
EXPECT_CALL(*channel_receive_, ResetReceiverCongestionControlObjects())
.Times(1);
EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
EXPECT_CALL(*channel_receive_, SetAssociatedSendChannel(nullptr)).Times(1);
EXPECT_CALL(*channel_receive_, SetReceiveCodecs(_))
.WillRepeatedly(Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
EXPECT_THAT(codecs, testing::IsEmpty());
}));
@ -114,33 +114,33 @@ struct ConfigHelper {
new internal::AudioReceiveStream(
&rtp_stream_receiver_controller_, &packet_router_, stream_config_,
audio_state_, &event_log_,
std::unique_ptr<voe::ChannelReceiveProxy>(channel_proxy_)));
std::unique_ptr<voe::ChannelReceiveInterface>(channel_receive_)));
}
AudioReceiveStream::Config& config() { return stream_config_; }
rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
MockChannelReceiveProxy* channel_proxy() { return channel_proxy_; }
MockChannelReceive* channel_receive() { return channel_receive_; }
void SetupMockForGetStats() {
using testing::DoAll;
using testing::SetArgPointee;
ASSERT_TRUE(channel_proxy_);
EXPECT_CALL(*channel_proxy_, GetRTCPStatistics())
ASSERT_TRUE(channel_receive_);
EXPECT_CALL(*channel_receive_, GetRTCPStatistics())
.WillOnce(Return(kCallStats));
EXPECT_CALL(*channel_proxy_, GetDelayEstimate())
EXPECT_CALL(*channel_receive_, GetDelayEstimate())
.WillOnce(Return(kJitterBufferDelay + kPlayoutBufferDelay));
EXPECT_CALL(*channel_proxy_, GetSpeechOutputLevelFullRange())
EXPECT_CALL(*channel_receive_, GetSpeechOutputLevelFullRange())
.WillOnce(Return(kSpeechOutputLevel));
EXPECT_CALL(*channel_proxy_, GetTotalOutputEnergy())
EXPECT_CALL(*channel_receive_, GetTotalOutputEnergy())
.WillOnce(Return(kTotalOutputEnergy));
EXPECT_CALL(*channel_proxy_, GetTotalOutputDuration())
EXPECT_CALL(*channel_receive_, GetTotalOutputDuration())
.WillOnce(Return(kTotalOutputDuration));
EXPECT_CALL(*channel_proxy_, GetNetworkStatistics())
EXPECT_CALL(*channel_receive_, GetNetworkStatistics())
.WillOnce(Return(kNetworkStats));
EXPECT_CALL(*channel_proxy_, GetDecodingCallStatistics())
EXPECT_CALL(*channel_receive_, GetDecodingCallStatistics())
.WillOnce(Return(kAudioDecodeStats));
EXPECT_CALL(*channel_proxy_, GetRecCodec(_))
EXPECT_CALL(*channel_receive_, GetRecCodec(_))
.WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true)));
}
@ -150,7 +150,7 @@ struct ConfigHelper {
rtc::scoped_refptr<AudioState> audio_state_;
rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
AudioReceiveStream::Config stream_config_;
testing::StrictMock<MockChannelReceiveProxy>* channel_proxy_ = nullptr;
testing::StrictMock<MockChannelReceive>* channel_receive_ = nullptr;
RtpStreamReceiverController rtp_stream_receiver_controller_;
MockTransport rtcp_send_transport_;
};
@ -239,7 +239,7 @@ TEST(AudioReceiveStreamTest, ReceiveRtpPacket) {
ASSERT_TRUE(parsed_packet.Parse(&rtp_packet[0], rtp_packet.size()));
parsed_packet.set_arrival_time_ms((packet_time_us + 500) / 1000);
EXPECT_CALL(*helper.channel_proxy(),
EXPECT_CALL(*helper.channel_receive(),
OnRtpPacket(testing::Ref(parsed_packet)));
recv_stream->OnRtpPacket(parsed_packet);
@ -250,7 +250,7 @@ TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) {
helper.config().rtp.transport_cc = true;
auto recv_stream = helper.CreateAudioReceiveStream();
std::vector<uint8_t> rtcp_packet = CreateRtcpSenderReport();
EXPECT_CALL(*helper.channel_proxy(),
EXPECT_CALL(*helper.channel_receive(),
ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size()))
.WillOnce(Return(true));
EXPECT_TRUE(recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size()));
@ -312,7 +312,7 @@ TEST(AudioReceiveStreamTest, GetStats) {
TEST(AudioReceiveStreamTest, SetGain) {
ConfigHelper helper;
auto recv_stream = helper.CreateAudioReceiveStream();
EXPECT_CALL(*helper.channel_proxy(),
EXPECT_CALL(*helper.channel_receive(),
SetChannelOutputVolumeScaling(FloatEq(0.765f)));
recv_stream->SetGain(0.765f);
}
@ -323,10 +323,10 @@ TEST(AudioReceiveStreamTest, StreamsShouldBeAddedToMixerOnceOnStart) {
auto recv_stream1 = helper1.CreateAudioReceiveStream();
auto recv_stream2 = helper2.CreateAudioReceiveStream();
EXPECT_CALL(*helper1.channel_proxy(), StartPlayout()).Times(1);
EXPECT_CALL(*helper2.channel_proxy(), StartPlayout()).Times(1);
EXPECT_CALL(*helper1.channel_proxy(), StopPlayout()).Times(1);
EXPECT_CALL(*helper2.channel_proxy(), StopPlayout()).Times(1);
EXPECT_CALL(*helper1.channel_receive(), StartPlayout()).Times(1);
EXPECT_CALL(*helper2.channel_receive(), StartPlayout()).Times(1);
EXPECT_CALL(*helper1.channel_receive(), StopPlayout()).Times(1);
EXPECT_CALL(*helper2.channel_receive(), StopPlayout()).Times(1);
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream1.get()))
.WillOnce(Return(true));
EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream2.get()))
@ -367,10 +367,10 @@ TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) {
kTransportSequenceNumberId + 1));
new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1));
MockChannelReceiveProxy& channel_proxy = *helper.channel_proxy();
EXPECT_CALL(channel_proxy, SetLocalSSRC(kLocalSsrc + 1)).Times(1);
EXPECT_CALL(channel_proxy, SetNACKStatus(true, 15 + 1)).Times(1);
EXPECT_CALL(channel_proxy, SetReceiveCodecs(new_config.decoder_map));
MockChannelReceive& channel_receive = *helper.channel_receive();
EXPECT_CALL(channel_receive, SetLocalSSRC(kLocalSsrc + 1)).Times(1);
EXPECT_CALL(channel_receive, SetNACKStatus(true, 15 + 1)).Times(1);
EXPECT_CALL(channel_receive, SetReceiveCodecs(new_config.decoder_map));
recv_stream->Reconfigure(new_config);
}

View File

@ -553,9 +553,9 @@ RtpState AudioSendStream::GetRtpState() const {
return rtp_rtcp_module_->GetRtpState();
}
const voe::ChannelSendProxy& AudioSendStream::GetChannelProxy() const {
const voe::ChannelSend* AudioSendStream::GetChannel() const {
RTC_DCHECK(channel_proxy_.get());
return *channel_proxy_.get();
return channel_proxy_->GetChannel();
}
internal::AudioState* AudioSendStream::audio_state() {

View File

@ -31,6 +31,7 @@ class RtcpRttStats;
class RtpTransportControllerSendInterface;
namespace voe {
class ChannelSend;
class ChannelSendProxy;
} // namespace voe
@ -93,7 +94,7 @@ class AudioSendStream final : public webrtc::AudioSendStream,
void SetTransportOverhead(int transport_overhead_per_packet);
RtpState GetRtpState() const;
const voe::ChannelSendProxy& GetChannelProxy() const;
const voe::ChannelSend* GetChannel() const;
private:
class TimedTransport;

View File

@ -18,14 +18,19 @@
#include <vector>
#include "absl/memory/memory.h"
#include "audio/audio_level.h"
#include "audio/channel_send.h"
#include "audio/utility/audio_frame_operations.h"
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
#include "logging/rtc_event_log/rtc_event_log.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
#include "modules/audio_coding/include/audio_coding_module.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/pacing/packet_router.h"
#include "modules/rtp_rtcp/include/receive_statistics.h"
#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/source/contributing_sources.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/utility/include/process_thread.h"
@ -34,10 +39,16 @@
#include "rtc_base/format_macros.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "rtc_base/race_checker.h"
#include "rtc_base/thread_checker.h"
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/metrics.h"
// TODO(solenberg, nisse): This file contains a few NOLINT marks, to silence
// warnings about non-const reference arguments.
// These need cleanup, in a separate cl.
namespace webrtc {
namespace voe {
@ -83,7 +94,219 @@ WebRtcRTPHeader CreateWebrtcRTPHeaderForMediaTransportFrame(
return webrtc_header;
}
} // namespace
// Helper class to simplify locking scheme for members that are accessed from
// multiple threads.
// Example: a member can be set on thread T1 and read by an internal audio
// thread T2. Accessing the member via this class ensures that we are
// safe and also avoid TSan v2 warnings.
class ChannelReceiveState {
public:
struct State {
bool playing = false;
};
ChannelReceiveState() {}
virtual ~ChannelReceiveState() {}
void Reset() {
rtc::CritScope lock(&lock_);
state_ = State();
}
State Get() const {
rtc::CritScope lock(&lock_);
return state_;
}
void SetPlaying(bool enable) {
rtc::CritScope lock(&lock_);
state_.playing = enable;
}
private:
rtc::CriticalSection lock_;
State state_;
};
class ChannelReceive : public ChannelReceiveInterface,
public MediaTransportAudioSinkInterface {
public:
// Used for receive streams.
ChannelReceive(ProcessThread* module_process_thread,
AudioDeviceModule* audio_device_module,
MediaTransportInterface* media_transport,
Transport* rtcp_send_transport,
RtcEventLog* rtc_event_log,
uint32_t remote_ssrc,
size_t jitter_buffer_max_packets,
bool jitter_buffer_fast_playout,
rtc::scoped_refptr<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(
const uint8_t* payloadData,
@ -142,6 +365,7 @@ void ChannelReceive::OnData(uint64_t channel_id,
AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo(
int sample_rate_hz,
AudioFrame* audio_frame) {
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
audio_frame->sample_rate_hz_ = sample_rate_hz;
unsigned int ssrc;
@ -248,6 +472,7 @@ AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo(
}
int ChannelReceive::PreferredSampleRate() const {
RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
// Return the bigger of playout and receive frequency in the ACM.
return std::max(audio_coding_->ReceiveFrequency(),
audio_coding_->PlayoutFrequency());
@ -284,6 +509,9 @@ ChannelReceive::ChannelReceive(
media_transport_(media_transport),
frame_decryptor_(frame_decryptor),
crypto_options_(crypto_options) {
// TODO(nisse): Use _moduleProcessThreadPtr instead?
module_process_thread_checker_.DetachFromThread();
RTC_DCHECK(module_process_thread);
RTC_DCHECK(audio_device_module);
AudioCodingModule::Config acm_config;
@ -368,11 +596,13 @@ void ChannelReceive::Terminate() {
}
void ChannelReceive::SetSink(AudioSinkInterface* sink) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
rtc::CritScope cs(&_callbackCritSect);
audio_sink_ = sink;
}
void ChannelReceive::StartPlayout() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (channel_state_.Get().playing) {
return;
}
@ -381,6 +611,7 @@ void ChannelReceive::StartPlayout() {
}
void ChannelReceive::StopPlayout() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (!channel_state_.Get().playing) {
return;
}
@ -389,11 +620,13 @@ void ChannelReceive::StopPlayout() {
_outputAudioLevel.Clear();
}
bool ChannelReceive::GetRecCodec(CodecInst* codec) {
bool ChannelReceive::GetRecCodec(CodecInst* codec) const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return (audio_coding_->ReceiveCodec(codec) == 0);
}
std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
int64_t now_ms = rtc::TimeMillis();
std::vector<RtpSource> sources;
{
@ -411,6 +644,7 @@ std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
void ChannelReceive::SetReceiveCodecs(
const std::map<int, SdpAudioFormat>& codecs) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
for (const auto& kv : codecs) {
RTC_DCHECK_GE(kv.second.clockrate_hz, 1000);
payload_type_frequencies_[kv.first] = kv.second.clockrate_hz;
@ -418,7 +652,7 @@ void ChannelReceive::SetReceiveCodecs(
audio_coding_->SetReceiveCodecs(codecs);
}
// TODO(nisse): Move receive logic up to AudioReceiveStream.
// May be called on either worker thread or network thread.
void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) {
int64_t now_ms = rtc::TimeMillis();
uint8_t audio_level;
@ -509,6 +743,7 @@ bool ChannelReceive::ReceivePacket(const uint8_t* packet,
&webrtc_rtp_header);
}
// May be called on either worker thread or network thread.
// TODO(nisse): Drop always-true return value.
bool ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
// Store playout timestamp for the received RTCP packet
@ -547,23 +782,28 @@ bool ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
}
int ChannelReceive::GetSpeechOutputLevelFullRange() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return _outputAudioLevel.LevelFullRange();
}
double ChannelReceive::GetTotalOutputEnergy() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return _outputAudioLevel.TotalEnergy();
}
double ChannelReceive::GetTotalOutputDuration() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
return _outputAudioLevel.TotalDuration();
}
void ChannelReceive::SetChannelOutputVolumeScaling(float scaling) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
rtc::CritScope cs(&volume_settings_critsect_);
_outputGain = scaling;
}
void ChannelReceive::SetLocalSSRC(unsigned int ssrc) {
void ChannelReceive::SetLocalSSRC(uint32_t ssrc) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
_rtpRtcpModule->SetSSRC(ssrc);
}
@ -575,6 +815,7 @@ int ChannelReceive::GetRemoteSSRC(unsigned int& ssrc) {
void ChannelReceive::RegisterReceiverCongestionControlObjects(
PacketRouter* packet_router) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(packet_router);
RTC_DCHECK(!packet_router_);
constexpr bool remb_candidate = false;
@ -583,12 +824,14 @@ void ChannelReceive::RegisterReceiverCongestionControlObjects(
}
void ChannelReceive::ResetReceiverCongestionControlObjects() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
RTC_DCHECK(packet_router_);
packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get());
packet_router_ = nullptr;
}
CallReceiveStatistics ChannelReceive::GetRTCPStatistics() {
CallReceiveStatistics ChannelReceive::GetRTCPStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// --- RtcpStatistics
CallReceiveStatistics stats;
@ -630,11 +873,12 @@ CallReceiveStatistics ChannelReceive::GetRTCPStatistics() {
return stats;
}
void ChannelReceive::SetNACKStatus(bool enable, int maxNumberOfPackets) {
void ChannelReceive::SetNACKStatus(bool enable, int max_packets) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
// None of these functions can fail.
rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets);
if (enable)
audio_coding_->EnableNack(maxNumberOfPackets);
audio_coding_->EnableNack(max_packets);
else
audio_coding_->DisableNack();
}
@ -645,12 +889,14 @@ int ChannelReceive::ResendPackets(const uint16_t* sequence_numbers,
return _rtpRtcpModule->SendNACK(sequence_numbers, length);
}
void ChannelReceive::SetAssociatedSendChannel(ChannelSend* channel) {
void ChannelReceive::SetAssociatedSendChannel(const ChannelSend* channel) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
rtc::CritScope lock(&assoc_send_channel_lock_);
associated_send_channel_ = channel;
}
NetworkStatistics ChannelReceive::GetNetworkStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
NetworkStatistics stats;
int error = audio_coding_->GetNetworkStatistics(&stats);
RTC_DCHECK_EQ(0, error);
@ -658,29 +904,37 @@ NetworkStatistics ChannelReceive::GetNetworkStatistics() const {
}
AudioDecodingCallStats ChannelReceive::GetDecodingCallStatistics() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
AudioDecodingCallStats stats;
audio_coding_->GetDecodingCallStatistics(&stats);
return stats;
}
uint32_t ChannelReceive::GetDelayEstimate() const {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
module_process_thread_checker_.CalledOnValidThread());
rtc::CritScope lock(&video_sync_lock_);
return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
}
void ChannelReceive::SetMinimumPlayoutDelay(int delayMs) {
if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
(delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
void ChannelReceive::SetMinimumPlayoutDelay(int delay_ms) {
RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
// Limit to range accepted by both VoE and ACM, so we're at least getting as
// close as possible, instead of failing.
delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
(delay_ms > kVoiceEngineMaxMinPlayoutDelayMs)) {
RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay";
return;
}
if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
if (audio_coding_->SetMinimumPlayoutDelay(delay_ms) != 0) {
RTC_DLOG(LS_ERROR)
<< "SetMinimumPlayoutDelay() failed to set min playout delay";
}
}
uint32_t ChannelReceive::GetPlayoutTimestamp() {
uint32_t ChannelReceive::GetPlayoutTimestamp() const {
RTC_DCHECK_RUNS_SERIALIZED(&video_capture_thread_race_checker_);
{
rtc::CritScope lock(&video_sync_lock_);
return playout_timestamp_rtp_;
@ -688,6 +942,7 @@ uint32_t ChannelReceive::GetPlayoutTimestamp() {
}
absl::optional<Syncable::Info> ChannelReceive::GetSyncInfo() const {
RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
Syncable::Info info;
if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs,
&info.capture_time_ntp_frac, nullptr, nullptr,
@ -780,5 +1035,27 @@ int64_t ChannelReceive::GetRTT() const {
return rtt;
}
} // namespace
std::unique_ptr<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 webrtc

View File

@ -17,24 +17,18 @@
#include "absl/types/optional.h"
#include "api/audio/audio_mixer.h"
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/call/audio_sink.h"
#include "api/call/transport.h"
#include "api/crypto/cryptooptions.h"
#include "api/media_transport_interface.h"
#include "api/rtpreceiverinterface.h"
#include "audio/audio_level.h"
#include "call/rtp_packet_sink_interface.h"
#include "call/syncable.h"
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/include/audio_coding_module.h"
#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/source/contributing_sources.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/thread_checker.h"
// TODO(solenberg, nisse): This file contains a few NOLINT marks, to silence
// warnings about use of unsigned short, and non-const reference arguments.
// warnings about use of unsigned short.
// These need cleanup, in a separate cl.
namespace rtc {
@ -70,44 +64,69 @@ namespace voe {
class ChannelSend;
// Helper class to simplify locking scheme for members that are accessed from
// multiple threads.
// Example: a member can be set on thread T1 and read by an internal audio
// thread T2. Accessing the member via this class ensures that we are
// safe and also avoid TSan v2 warnings.
class ChannelReceiveState {
// Interface class needed for AudioReceiveStream tests that use a
// MockChannelReceive.
class ChannelReceiveInterface : public RtpPacketSinkInterface {
public:
struct State {
bool playing = false;
virtual ~ChannelReceiveInterface() = default;
virtual void SetSink(AudioSinkInterface* sink) = 0;
virtual void SetReceiveCodecs(
const std::map<int, SdpAudioFormat>& codecs) = 0;
virtual void StartPlayout() = 0;
virtual void StopPlayout() = 0;
virtual bool GetRecCodec(CodecInst* codec) const = 0;
virtual bool ReceivedRTCPPacket(const uint8_t* data, size_t length) = 0;
virtual void SetChannelOutputVolumeScaling(float scaling) = 0;
virtual int GetSpeechOutputLevelFullRange() const = 0;
// See description of "totalAudioEnergy" in the WebRTC stats spec:
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
virtual double GetTotalOutputEnergy() const = 0;
virtual double GetTotalOutputDuration() const = 0;
// Stats.
virtual NetworkStatistics GetNetworkStatistics() const = 0;
virtual AudioDecodingCallStats GetDecodingCallStatistics() const = 0;
// Audio+Video Sync.
virtual uint32_t GetDelayEstimate() const = 0;
virtual void SetMinimumPlayoutDelay(int delay_ms) = 0;
virtual uint32_t GetPlayoutTimestamp() const = 0;
// Produces the transport-related timestamps; current_delay_ms is left unset.
virtual absl::optional<Syncable::Info> GetSyncInfo() const = 0;
// RTP+RTCP
virtual void SetLocalSSRC(uint32_t ssrc) = 0;
virtual void RegisterReceiverCongestionControlObjects(
PacketRouter* packet_router) = 0;
virtual void ResetReceiverCongestionControlObjects() = 0;
virtual CallReceiveStatistics GetRTCPStatistics() const = 0;
virtual void SetNACKStatus(bool enable, int max_packets) = 0;
virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
int sample_rate_hz,
AudioFrame* audio_frame) = 0;
virtual int PreferredSampleRate() const = 0;
// Associate to a send channel.
// Used for obtaining RTT for a receive-only channel.
virtual void SetAssociatedSendChannel(const ChannelSend* channel) = 0;
virtual std::vector<RtpSource> GetSources() const = 0;
};
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 MediaTransportAudioSinkInterface {
public:
// Used for receive streams.
ChannelReceive(ProcessThread* module_process_thread,
std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
ProcessThread* module_process_thread,
AudioDeviceModule* audio_device_module,
MediaTransportInterface* media_transport,
Transport* rtcp_send_transport,
@ -119,155 +138,6 @@ class ChannelReceive : public MediaTransportAudioSinkInterface {
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:
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
double GetTotalOutputEnergy() const;
double GetTotalOutputDuration() const;
// Stats.
NetworkStatistics GetNetworkStatistics() const;
AudioDecodingCallStats GetDecodingCallStatistics() const;
// Audio+Video Sync.
uint32_t GetDelayEstimate() const;
void SetMinimumPlayoutDelay(int delayMs);
uint32_t GetPlayoutTimestamp();
// Produces the transport-related timestamps; current_delay_ms is left unset.
absl::optional<Syncable::Info> GetSyncInfo() const;
// RTP+RTCP
void SetLocalSSRC(unsigned int ssrc);
void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router);
void ResetReceiverCongestionControlObjects();
CallReceiveStatistics GetRTCPStatistics();
void SetNACKStatus(bool enable, int maxNumberOfPackets);
// 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<RtpSource> GetSources() const;
private:
void Init();
void Terminate();
int GetRemoteSSRC(unsigned int& ssrc); // NOLINT
bool ReceivePacket(const uint8_t* packet,
size_t packet_length,
const RTPHeader& header);
int ResendPackets(const uint16_t* sequence_numbers, int length);
void UpdatePlayoutTimestamp(bool rtcp);
int GetRtpTimestampRateHz() const;
int64_t GetRTT() const;
// MediaTransportAudioSinkInterface override;
void OnData(uint64_t channel_id,
MediaTransportEncodedAudioFrame frame) override;
int32_t OnReceivedPayloadData(const uint8_t* payloadData,
size_t payloadSize,
const WebRtcRTPHeader* rtpHeader);
rtc::CriticalSection _callbackCritSect;
rtc::CriticalSection volume_settings_critsect_;
ChannelReceiveState channel_state_;
RtcEventLog* const event_log_;
// Indexed by payload type.
std::map<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_;
};
} // namespace voe
} // namespace webrtc

View File

@ -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

View File

@ -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_

View File

@ -17,7 +17,7 @@
#include <vector>
#include "api/test/mock_frame_encryptor.h"
#include "audio/channel_receive_proxy.h"
#include "audio/channel_receive.h"
#include "audio/channel_send_proxy.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "test/gmock.h"
@ -25,7 +25,7 @@
namespace webrtc {
namespace test {
class MockChannelReceiveProxy : public voe::ChannelReceiveProxy {
class MockChannelReceive : public voe::ChannelReceiveInterface {
public:
MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets));
@ -47,10 +47,10 @@ class MockChannelReceiveProxy : public voe::ChannelReceiveProxy {
AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
AudioFrame* audio_frame));
MOCK_CONST_METHOD0(PreferredSampleRate, int());
MOCK_METHOD1(AssociateSendChannel,
void(const voe::ChannelSendProxy& send_channel_proxy));
MOCK_METHOD0(DisassociateSendChannel, void());
MOCK_METHOD1(SetAssociatedSendChannel,
void(const voe::ChannelSend* send_channel));
MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
MOCK_CONST_METHOD0(GetSyncInfo, absl::optional<Syncable::Info>());
MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
MOCK_METHOD1(SetReceiveCodecs,