Split voe::Channel into ChannelSend and ChannelReceive
Bug: webrtc:9801 Change-Id: Ia15af1e53c8d384ad6e5fbddcb25311fce4befae Reviewed-on: https://webrtc-review.googlesource.com/c/103640 Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Commit-Queue: Niels Moller <nisse@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24992}
This commit is contained in:
parent
c0f26d458d
commit
530ead4974
@ -24,10 +24,12 @@ rtc_static_library("audio") {
|
||||
"audio_state.h",
|
||||
"audio_transport_impl.cc",
|
||||
"audio_transport_impl.h",
|
||||
"channel.cc",
|
||||
"channel.h",
|
||||
"channel_receive.cc",
|
||||
"channel_receive.h",
|
||||
"channel_receive_proxy.cc",
|
||||
"channel_receive_proxy.h",
|
||||
"channel_send.cc",
|
||||
"channel_send.h",
|
||||
"channel_send_proxy.cc",
|
||||
"channel_send_proxy.h",
|
||||
"conversion.h",
|
||||
|
||||
@ -71,7 +71,7 @@ std::unique_ptr<voe::ChannelReceiveProxy> CreateChannelAndProxy(
|
||||
internal::AudioState* internal_audio_state =
|
||||
static_cast<internal::AudioState*>(audio_state);
|
||||
return absl::make_unique<voe::ChannelReceiveProxy>(
|
||||
absl::make_unique<voe::Channel>(
|
||||
absl::make_unique<voe::ChannelReceive>(
|
||||
module_process_thread, internal_audio_state->audio_device_module(),
|
||||
nullptr /* RtcpRttStats */, event_log, config.rtp.remote_ssrc,
|
||||
config.jitter_buffer_max_packets,
|
||||
@ -166,7 +166,8 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
||||
webrtc::AudioReceiveStream::Stats stats;
|
||||
stats.remote_ssrc = config_.rtp.remote_ssrc;
|
||||
|
||||
webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics();
|
||||
webrtc::CallReceiveStatistics call_stats =
|
||||
channel_proxy_->GetRTCPStatistics();
|
||||
// TODO(solenberg): Don't return here if we can't get the codec - return the
|
||||
// stats we *can* get.
|
||||
webrtc::CodecInst codec_inst = {0};
|
||||
|
||||
@ -59,8 +59,8 @@ const unsigned int kSpeechOutputLevel = 99;
|
||||
const double kTotalOutputEnergy = 0.25;
|
||||
const double kTotalOutputDuration = 0.5;
|
||||
|
||||
const CallStatistics kCallStats = {345, 678, 901, 234, -12,
|
||||
3456, 7890, 567, 890, 123};
|
||||
const CallReceiveStatistics kCallStats = {345, 678, 901, 234,
|
||||
-12, 567, 890, 123};
|
||||
const CodecInst kCodecInst = {123, "codec_name_recv", 96000, -187, 0, -103};
|
||||
const NetworkStatistics kNetworkStats = {
|
||||
123, 456, false, 789012, 3456, 123, 456, 0, {}, 789, 12,
|
||||
|
||||
@ -47,19 +47,13 @@ void CallEncoder(const std::unique_ptr<voe::ChannelSendProxy>& channel_proxy,
|
||||
}
|
||||
|
||||
std::unique_ptr<voe::ChannelSendProxy> CreateChannelAndProxy(
|
||||
webrtc::AudioState* audio_state,
|
||||
rtc::TaskQueue* worker_queue,
|
||||
ProcessThread* module_process_thread,
|
||||
RtcpRttStats* rtcp_rtt_stats,
|
||||
RtcEventLog* event_log) {
|
||||
RTC_DCHECK(audio_state);
|
||||
internal::AudioState* internal_audio_state =
|
||||
static_cast<internal::AudioState*>(audio_state);
|
||||
return absl::make_unique<voe::ChannelSendProxy>(
|
||||
absl::make_unique<voe::Channel>(
|
||||
worker_queue, module_process_thread,
|
||||
internal_audio_state->audio_device_module(), rtcp_rtt_stats,
|
||||
event_log));
|
||||
absl::make_unique<voe::ChannelSend>(worker_queue, module_process_thread,
|
||||
rtcp_rtt_stats, event_log));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -106,8 +100,7 @@ AudioSendStream::AudioSendStream(
|
||||
rtcp_rtt_stats,
|
||||
suspended_rtp_state,
|
||||
overall_call_lifetime,
|
||||
CreateChannelAndProxy(audio_state.get(),
|
||||
worker_queue,
|
||||
CreateChannelAndProxy(worker_queue,
|
||||
module_process_thread,
|
||||
rtcp_rtt_stats,
|
||||
event_log)) {}
|
||||
@ -352,7 +345,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
|
||||
webrtc::AudioSendStream::Stats stats;
|
||||
stats.local_ssrc = config_.rtp.ssrc;
|
||||
|
||||
webrtc::CallStatistics call_stats = channel_proxy_->GetRTCPStatistics();
|
||||
webrtc::CallSendStatistics call_stats = channel_proxy_->GetRTCPStatistics();
|
||||
stats.bytes_sent = call_stats.bytesSent;
|
||||
stats.packets_sent = call_stats.packetsSent;
|
||||
// RTT isn't known until a RTCP report is received. Until then, VoiceEngine
|
||||
|
||||
@ -56,8 +56,7 @@ const double kEchoReturnLoss = -65;
|
||||
const double kEchoReturnLossEnhancement = 101;
|
||||
const double kResidualEchoLikelihood = -1.0f;
|
||||
const double kResidualEchoLikelihoodMax = 23.0f;
|
||||
const CallStatistics kCallStats = {1345, 1678, 1901, 1234, 112,
|
||||
13456, 17890, 1567, -1890, -1123};
|
||||
const CallSendStatistics kCallStats = {112, 13456, 17890};
|
||||
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
|
||||
const int kTelephoneEventPayloadType = 123;
|
||||
const int kTelephoneEventPayloadFrequency = 65432;
|
||||
|
||||
711
audio/channel_receive.cc
Normal file
711
audio/channel_receive.cc
Normal file
@ -0,0 +1,711 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "audio/channel_receive.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "audio/channel_send.h"
|
||||
#include "audio/utility/audio_frame_operations.h"
|
||||
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
|
||||
#include "logging/rtc_event_log/rtc_event_log.h"
|
||||
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
|
||||
#include "modules/audio_device/include/audio_device.h"
|
||||
#include "modules/pacing/packet_router.h"
|
||||
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "modules/utility/include/process_thread.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/criticalsection.h"
|
||||
#include "rtc_base/format_macros.h"
|
||||
#include "rtc_base/location.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace voe {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr double kAudioSampleDurationSeconds = 0.01;
|
||||
constexpr int64_t kMaxRetransmissionWindowMs = 1000;
|
||||
constexpr int64_t kMinRetransmissionWindowMs = 30;
|
||||
|
||||
// Video Sync.
|
||||
constexpr int kVoiceEngineMinMinPlayoutDelayMs = 0;
|
||||
constexpr int kVoiceEngineMaxMinPlayoutDelayMs = 10000;
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ChannelReceive::SendRtp(const uint8_t* data,
|
||||
size_t len,
|
||||
const PacketOptions& options) {
|
||||
RTC_NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelReceive::SendRtcp(const uint8_t* data, size_t len) {
|
||||
rtc::CritScope cs(&_callbackCritSect);
|
||||
if (_transportPtr == NULL) {
|
||||
RTC_DLOG(LS_ERROR)
|
||||
<< "ChannelReceive::SendRtcp() failed to send RTCP packet due to"
|
||||
<< " invalid transport object";
|
||||
return false;
|
||||
}
|
||||
|
||||
int n = _transportPtr->SendRtcp(data, len);
|
||||
if (n < 0) {
|
||||
RTC_DLOG(LS_ERROR) << "ChannelReceive::SendRtcp() transmission failed";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t ChannelReceive::OnReceivedPayloadData(
|
||||
const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const WebRtcRTPHeader* rtpHeader) {
|
||||
if (!channel_state_.Get().playing) {
|
||||
// Avoid inserting into NetEQ when we are not playing. Count the
|
||||
// packet as discarded.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Push the incoming payload (parsed and ready for decoding) into the ACM
|
||||
if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
|
||||
0) {
|
||||
RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to "
|
||||
"push data to the ACM";
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t round_trip_time = 0;
|
||||
_rtpRtcpModule->RTT(remote_ssrc_, &round_trip_time, NULL, NULL, NULL);
|
||||
|
||||
std::vector<uint16_t> nack_list = audio_coding_->GetNackList(round_trip_time);
|
||||
if (!nack_list.empty()) {
|
||||
// Can't use nack_list.data() since it's not supported by all
|
||||
// compilers.
|
||||
ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioMixer::Source::AudioFrameInfo ChannelReceive::GetAudioFrameWithInfo(
|
||||
int sample_rate_hz,
|
||||
AudioFrame* audio_frame) {
|
||||
audio_frame->sample_rate_hz_ = sample_rate_hz;
|
||||
|
||||
unsigned int ssrc;
|
||||
RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0);
|
||||
event_log_->Log(absl::make_unique<RtcEventAudioPlayout>(ssrc));
|
||||
// Get 10ms raw PCM data from the ACM (mixer limits output frequency)
|
||||
bool muted;
|
||||
if (audio_coding_->PlayoutData10Ms(audio_frame->sample_rate_hz_, audio_frame,
|
||||
&muted) == -1) {
|
||||
RTC_DLOG(LS_ERROR)
|
||||
<< "ChannelReceive::GetAudioFrame() PlayoutData10Ms() failed!";
|
||||
// In all likelihood, the audio in this frame is garbage. We return an
|
||||
// error so that the audio mixer module doesn't add it to the mix. As
|
||||
// a result, it won't be played out and the actions skipped here are
|
||||
// irrelevant.
|
||||
return AudioMixer::Source::AudioFrameInfo::kError;
|
||||
}
|
||||
|
||||
if (muted) {
|
||||
// TODO(henrik.lundin): We should be able to do better than this. But we
|
||||
// will have to go through all the cases below where the audio samples may
|
||||
// be used, and handle the muted case in some way.
|
||||
AudioFrameOperations::Mute(audio_frame);
|
||||
}
|
||||
|
||||
{
|
||||
// Pass the audio buffers to an optional sink callback, before applying
|
||||
// scaling/panning, as that applies to the mix operation.
|
||||
// External recipients of the audio (e.g. via AudioTrack), will do their
|
||||
// own mixing/dynamic processing.
|
||||
rtc::CritScope cs(&_callbackCritSect);
|
||||
if (audio_sink_) {
|
||||
AudioSinkInterface::Data data(
|
||||
audio_frame->data(), audio_frame->samples_per_channel_,
|
||||
audio_frame->sample_rate_hz_, audio_frame->num_channels_,
|
||||
audio_frame->timestamp_);
|
||||
audio_sink_->OnData(data);
|
||||
}
|
||||
}
|
||||
|
||||
float output_gain = 1.0f;
|
||||
{
|
||||
rtc::CritScope cs(&volume_settings_critsect_);
|
||||
output_gain = _outputGain;
|
||||
}
|
||||
|
||||
// Output volume scaling
|
||||
if (output_gain < 0.99f || output_gain > 1.01f) {
|
||||
// TODO(solenberg): Combine with mute state - this can cause clicks!
|
||||
AudioFrameOperations::ScaleWithSat(output_gain, audio_frame);
|
||||
}
|
||||
|
||||
// Measure audio level (0-9)
|
||||
// TODO(henrik.lundin) Use the |muted| information here too.
|
||||
// TODO(deadbeef): Use RmsLevel for |_outputAudioLevel| (see
|
||||
// https://crbug.com/webrtc/7517).
|
||||
_outputAudioLevel.ComputeLevel(*audio_frame, kAudioSampleDurationSeconds);
|
||||
|
||||
if (capture_start_rtp_time_stamp_ < 0 && audio_frame->timestamp_ != 0) {
|
||||
// The first frame with a valid rtp timestamp.
|
||||
capture_start_rtp_time_stamp_ = audio_frame->timestamp_;
|
||||
}
|
||||
|
||||
if (capture_start_rtp_time_stamp_ >= 0) {
|
||||
// audio_frame.timestamp_ should be valid from now on.
|
||||
|
||||
// Compute elapsed time.
|
||||
int64_t unwrap_timestamp =
|
||||
rtp_ts_wraparound_handler_->Unwrap(audio_frame->timestamp_);
|
||||
audio_frame->elapsed_time_ms_ =
|
||||
(unwrap_timestamp - capture_start_rtp_time_stamp_) /
|
||||
(GetRtpTimestampRateHz() / 1000);
|
||||
|
||||
{
|
||||
rtc::CritScope lock(&ts_stats_lock_);
|
||||
// Compute ntp time.
|
||||
audio_frame->ntp_time_ms_ =
|
||||
ntp_estimator_.Estimate(audio_frame->timestamp_);
|
||||
// |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received.
|
||||
if (audio_frame->ntp_time_ms_ > 0) {
|
||||
// Compute |capture_start_ntp_time_ms_| so that
|
||||
// |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_|
|
||||
capture_start_ntp_time_ms_ =
|
||||
audio_frame->ntp_time_ms_ - audio_frame->elapsed_time_ms_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.TargetJitterBufferDelayMs",
|
||||
audio_coding_->TargetDelayMs());
|
||||
const int jitter_buffer_delay = audio_coding_->FilteredCurrentDelayMs();
|
||||
rtc::CritScope lock(&video_sync_lock_);
|
||||
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverDelayEstimateMs",
|
||||
jitter_buffer_delay + playout_delay_ms_);
|
||||
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverJitterBufferDelayMs",
|
||||
jitter_buffer_delay);
|
||||
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Audio.ReceiverDeviceDelayMs",
|
||||
playout_delay_ms_);
|
||||
}
|
||||
|
||||
return muted ? AudioMixer::Source::AudioFrameInfo::kMuted
|
||||
: AudioMixer::Source::AudioFrameInfo::kNormal;
|
||||
}
|
||||
|
||||
int ChannelReceive::PreferredSampleRate() const {
|
||||
// Return the bigger of playout and receive frequency in the ACM.
|
||||
return std::max(audio_coding_->ReceiveFrequency(),
|
||||
audio_coding_->PlayoutFrequency());
|
||||
}
|
||||
|
||||
ChannelReceive::ChannelReceive(
|
||||
ProcessThread* module_process_thread,
|
||||
AudioDeviceModule* audio_device_module,
|
||||
RtcpRttStats* rtcp_rtt_stats,
|
||||
RtcEventLog* rtc_event_log,
|
||||
uint32_t remote_ssrc,
|
||||
size_t jitter_buffer_max_packets,
|
||||
bool jitter_buffer_fast_playout,
|
||||
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id)
|
||||
: event_log_(rtc_event_log),
|
||||
rtp_receive_statistics_(
|
||||
ReceiveStatistics::Create(Clock::GetRealTimeClock())),
|
||||
remote_ssrc_(remote_ssrc),
|
||||
_outputAudioLevel(),
|
||||
ntp_estimator_(Clock::GetRealTimeClock()),
|
||||
playout_timestamp_rtp_(0),
|
||||
playout_delay_ms_(0),
|
||||
rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
|
||||
capture_start_rtp_time_stamp_(-1),
|
||||
capture_start_ntp_time_ms_(-1),
|
||||
_moduleProcessThreadPtr(module_process_thread),
|
||||
_audioDeviceModulePtr(audio_device_module),
|
||||
_transportPtr(NULL),
|
||||
_outputGain(1.0f),
|
||||
associated_send_channel_(nullptr) {
|
||||
RTC_DCHECK(module_process_thread);
|
||||
RTC_DCHECK(audio_device_module);
|
||||
AudioCodingModule::Config acm_config;
|
||||
acm_config.decoder_factory = decoder_factory;
|
||||
acm_config.neteq_config.codec_pair_id = codec_pair_id;
|
||||
acm_config.neteq_config.max_packets_in_buffer = jitter_buffer_max_packets;
|
||||
acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout;
|
||||
acm_config.neteq_config.enable_muted_state = true;
|
||||
audio_coding_.reset(AudioCodingModule::Create(acm_config));
|
||||
|
||||
_outputAudioLevel.Clear();
|
||||
|
||||
rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true);
|
||||
RtpRtcp::Configuration configuration;
|
||||
configuration.audio = true;
|
||||
configuration.outgoing_transport = this;
|
||||
configuration.receive_statistics = rtp_receive_statistics_.get();
|
||||
|
||||
configuration.event_log = event_log_;
|
||||
configuration.rtt_stats = rtcp_rtt_stats;
|
||||
|
||||
_rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
|
||||
_rtpRtcpModule->SetSendingMediaStatus(false);
|
||||
_rtpRtcpModule->SetRemoteSSRC(remote_ssrc_);
|
||||
Init();
|
||||
}
|
||||
|
||||
ChannelReceive::~ChannelReceive() {
|
||||
Terminate();
|
||||
RTC_DCHECK(!channel_state_.Get().playing);
|
||||
}
|
||||
|
||||
void ChannelReceive::Init() {
|
||||
channel_state_.Reset();
|
||||
|
||||
// --- Add modules to process thread (for periodic schedulation)
|
||||
_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get(), RTC_FROM_HERE);
|
||||
|
||||
// --- ACM initialization
|
||||
int error = audio_coding_->InitializeReceiver();
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
|
||||
// --- RTP/RTCP module initialization
|
||||
|
||||
// Ensure that RTCP is enabled by default for the created channel.
|
||||
// Note that, the module will keep generating RTCP until it is explicitly
|
||||
// disabled by the user.
|
||||
// After StopListen (when no sockets exists), RTCP packets will no longer
|
||||
// be transmitted since the Transport object will then be invalid.
|
||||
// RTCP is enabled by default.
|
||||
_rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
|
||||
}
|
||||
|
||||
void ChannelReceive::Terminate() {
|
||||
RTC_DCHECK(construction_thread_.CalledOnValidThread());
|
||||
// Must be called on the same thread as Init().
|
||||
rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
|
||||
|
||||
StopPlayout();
|
||||
|
||||
// The order to safely shutdown modules in a channel is:
|
||||
// 1. De-register callbacks in modules
|
||||
// 2. De-register modules in process thread
|
||||
// 3. Destroy modules
|
||||
int error = audio_coding_->RegisterTransportCallback(NULL);
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
|
||||
// De-register modules in process thread
|
||||
if (_moduleProcessThreadPtr)
|
||||
_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
|
||||
|
||||
// End of modules shutdown
|
||||
}
|
||||
|
||||
void ChannelReceive::SetSink(AudioSinkInterface* sink) {
|
||||
rtc::CritScope cs(&_callbackCritSect);
|
||||
audio_sink_ = sink;
|
||||
}
|
||||
|
||||
int32_t ChannelReceive::StartPlayout() {
|
||||
if (channel_state_.Get().playing) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
channel_state_.SetPlaying(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ChannelReceive::StopPlayout() {
|
||||
if (!channel_state_.Get().playing) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
channel_state_.SetPlaying(false);
|
||||
_outputAudioLevel.Clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ChannelReceive::GetRecCodec(CodecInst& codec) {
|
||||
return (audio_coding_->ReceiveCodec(&codec));
|
||||
}
|
||||
|
||||
std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
|
||||
int64_t now_ms = rtc::TimeMillis();
|
||||
std::vector<RtpSource> sources;
|
||||
{
|
||||
rtc::CritScope cs(&rtp_sources_lock_);
|
||||
sources = contributing_sources_.GetSources(now_ms);
|
||||
if (last_received_rtp_system_time_ms_ >=
|
||||
now_ms - ContributingSources::kHistoryMs) {
|
||||
sources.emplace_back(*last_received_rtp_system_time_ms_, remote_ssrc_,
|
||||
RtpSourceType::SSRC);
|
||||
sources.back().set_audio_level(last_received_rtp_audio_level_);
|
||||
}
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
void ChannelReceive::SetReceiveCodecs(
|
||||
const std::map<int, SdpAudioFormat>& codecs) {
|
||||
for (const auto& kv : codecs) {
|
||||
RTC_DCHECK_GE(kv.second.clockrate_hz, 1000);
|
||||
payload_type_frequencies_[kv.first] = kv.second.clockrate_hz;
|
||||
}
|
||||
audio_coding_->SetReceiveCodecs(codecs);
|
||||
}
|
||||
|
||||
void ChannelReceive::RegisterTransport(Transport* transport) {
|
||||
rtc::CritScope cs(&_callbackCritSect);
|
||||
_transportPtr = transport;
|
||||
}
|
||||
|
||||
// TODO(nisse): Move receive logic up to AudioReceiveStream.
|
||||
void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) {
|
||||
int64_t now_ms = rtc::TimeMillis();
|
||||
uint8_t audio_level;
|
||||
bool voice_activity;
|
||||
bool has_audio_level =
|
||||
packet.GetExtension<::webrtc::AudioLevel>(&voice_activity, &audio_level);
|
||||
|
||||
{
|
||||
rtc::CritScope cs(&rtp_sources_lock_);
|
||||
last_received_rtp_timestamp_ = packet.Timestamp();
|
||||
last_received_rtp_system_time_ms_ = now_ms;
|
||||
if (has_audio_level)
|
||||
last_received_rtp_audio_level_ = audio_level;
|
||||
std::vector<uint32_t> csrcs = packet.Csrcs();
|
||||
contributing_sources_.Update(now_ms, csrcs);
|
||||
}
|
||||
|
||||
// Store playout timestamp for the received RTP packet
|
||||
UpdatePlayoutTimestamp(false);
|
||||
|
||||
const auto& it = payload_type_frequencies_.find(packet.PayloadType());
|
||||
if (it == payload_type_frequencies_.end())
|
||||
return;
|
||||
// TODO(nisse): Set payload_type_frequency earlier, when packet is parsed.
|
||||
RtpPacketReceived packet_copy(packet);
|
||||
packet_copy.set_payload_type_frequency(it->second);
|
||||
|
||||
rtp_receive_statistics_->OnRtpPacket(packet_copy);
|
||||
|
||||
RTPHeader header;
|
||||
packet_copy.GetHeader(&header);
|
||||
|
||||
ReceivePacket(packet_copy.data(), packet_copy.size(), header);
|
||||
}
|
||||
|
||||
bool ChannelReceive::ReceivePacket(const uint8_t* packet,
|
||||
size_t packet_length,
|
||||
const RTPHeader& header) {
|
||||
const uint8_t* payload = packet + header.headerLength;
|
||||
assert(packet_length >= header.headerLength);
|
||||
size_t payload_length = packet_length - header.headerLength;
|
||||
WebRtcRTPHeader webrtc_rtp_header = {};
|
||||
webrtc_rtp_header.header = header;
|
||||
|
||||
const size_t payload_data_length = payload_length - header.paddingLength;
|
||||
if (payload_data_length == 0) {
|
||||
webrtc_rtp_header.frameType = kEmptyFrame;
|
||||
return OnReceivedPayloadData(nullptr, 0, &webrtc_rtp_header);
|
||||
}
|
||||
return OnReceivedPayloadData(payload, payload_data_length,
|
||||
&webrtc_rtp_header);
|
||||
}
|
||||
|
||||
int32_t ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
|
||||
// Store playout timestamp for the received RTCP packet
|
||||
UpdatePlayoutTimestamp(true);
|
||||
|
||||
// Deliver RTCP packet to RTP/RTCP module for parsing
|
||||
_rtpRtcpModule->IncomingRtcpPacket(data, length);
|
||||
|
||||
int64_t rtt = GetRTT();
|
||||
if (rtt == 0) {
|
||||
// Waiting for valid RTT.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t nack_window_ms = rtt;
|
||||
if (nack_window_ms < kMinRetransmissionWindowMs) {
|
||||
nack_window_ms = kMinRetransmissionWindowMs;
|
||||
} else if (nack_window_ms > kMaxRetransmissionWindowMs) {
|
||||
nack_window_ms = kMaxRetransmissionWindowMs;
|
||||
}
|
||||
|
||||
uint32_t ntp_secs = 0;
|
||||
uint32_t ntp_frac = 0;
|
||||
uint32_t rtp_timestamp = 0;
|
||||
if (0 != _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
|
||||
&rtp_timestamp)) {
|
||||
// Waiting for RTCP.
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
rtc::CritScope lock(&ts_stats_lock_);
|
||||
ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ChannelReceive::GetSpeechOutputLevelFullRange() const {
|
||||
return _outputAudioLevel.LevelFullRange();
|
||||
}
|
||||
|
||||
double ChannelReceive::GetTotalOutputEnergy() const {
|
||||
return _outputAudioLevel.TotalEnergy();
|
||||
}
|
||||
|
||||
double ChannelReceive::GetTotalOutputDuration() const {
|
||||
return _outputAudioLevel.TotalDuration();
|
||||
}
|
||||
|
||||
void ChannelReceive::SetChannelOutputVolumeScaling(float scaling) {
|
||||
rtc::CritScope cs(&volume_settings_critsect_);
|
||||
_outputGain = scaling;
|
||||
}
|
||||
|
||||
int ChannelReceive::SetLocalSSRC(unsigned int ssrc) {
|
||||
_rtpRtcpModule->SetSSRC(ssrc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(nisse): Pass ssrc in return value instead.
|
||||
int ChannelReceive::GetRemoteSSRC(unsigned int& ssrc) {
|
||||
ssrc = remote_ssrc_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChannelReceive::RegisterReceiverCongestionControlObjects(
|
||||
PacketRouter* packet_router) {
|
||||
RTC_DCHECK(packet_router);
|
||||
RTC_DCHECK(!packet_router_);
|
||||
constexpr bool remb_candidate = false;
|
||||
packet_router->AddReceiveRtpModule(_rtpRtcpModule.get(), remb_candidate);
|
||||
packet_router_ = packet_router;
|
||||
}
|
||||
|
||||
void ChannelReceive::ResetReceiverCongestionControlObjects() {
|
||||
RTC_DCHECK(packet_router_);
|
||||
packet_router_->RemoveReceiveRtpModule(_rtpRtcpModule.get());
|
||||
packet_router_ = nullptr;
|
||||
}
|
||||
|
||||
int ChannelReceive::GetRTPStatistics(CallReceiveStatistics& stats) {
|
||||
// --- RtcpStatistics
|
||||
|
||||
// The jitter statistics is updated for each received RTP packet and is
|
||||
// based on received packets.
|
||||
RtcpStatistics statistics;
|
||||
StreamStatistician* statistician =
|
||||
rtp_receive_statistics_->GetStatistician(remote_ssrc_);
|
||||
if (statistician) {
|
||||
statistician->GetStatistics(&statistics,
|
||||
_rtpRtcpModule->RTCP() == RtcpMode::kOff);
|
||||
}
|
||||
|
||||
stats.fractionLost = statistics.fraction_lost;
|
||||
stats.cumulativeLost = statistics.packets_lost;
|
||||
stats.extendedMax = statistics.extended_highest_sequence_number;
|
||||
stats.jitterSamples = statistics.jitter;
|
||||
|
||||
// --- RTT
|
||||
stats.rttMs = GetRTT();
|
||||
|
||||
// --- Data counters
|
||||
|
||||
size_t bytesReceived(0);
|
||||
uint32_t packetsReceived(0);
|
||||
|
||||
if (statistician) {
|
||||
statistician->GetDataCounters(&bytesReceived, &packetsReceived);
|
||||
}
|
||||
|
||||
stats.bytesReceived = bytesReceived;
|
||||
stats.packetsReceived = packetsReceived;
|
||||
|
||||
// --- Timestamps
|
||||
{
|
||||
rtc::CritScope lock(&ts_stats_lock_);
|
||||
stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChannelReceive::SetNACKStatus(bool enable, int maxNumberOfPackets) {
|
||||
// None of these functions can fail.
|
||||
rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
|
||||
if (enable)
|
||||
audio_coding_->EnableNack(maxNumberOfPackets);
|
||||
else
|
||||
audio_coding_->DisableNack();
|
||||
}
|
||||
|
||||
// Called when we are missing one or more packets.
|
||||
int ChannelReceive::ResendPackets(const uint16_t* sequence_numbers,
|
||||
int length) {
|
||||
return _rtpRtcpModule->SendNACK(sequence_numbers, length);
|
||||
}
|
||||
|
||||
void ChannelReceive::SetAssociatedSendChannel(ChannelSend* channel) {
|
||||
rtc::CritScope lock(&assoc_send_channel_lock_);
|
||||
associated_send_channel_ = channel;
|
||||
}
|
||||
|
||||
int ChannelReceive::GetNetworkStatistics(NetworkStatistics& stats) {
|
||||
return audio_coding_->GetNetworkStatistics(&stats);
|
||||
}
|
||||
|
||||
void ChannelReceive::GetDecodingCallStatistics(
|
||||
AudioDecodingCallStats* stats) const {
|
||||
audio_coding_->GetDecodingCallStatistics(stats);
|
||||
}
|
||||
|
||||
uint32_t ChannelReceive::GetDelayEstimate() const {
|
||||
rtc::CritScope lock(&video_sync_lock_);
|
||||
return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
|
||||
}
|
||||
|
||||
int ChannelReceive::SetMinimumPlayoutDelay(int delayMs) {
|
||||
if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
|
||||
(delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
|
||||
RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay";
|
||||
return -1;
|
||||
}
|
||||
if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
|
||||
RTC_DLOG(LS_ERROR)
|
||||
<< "SetMinimumPlayoutDelay() failed to set min playout delay";
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ChannelReceive::GetPlayoutTimestamp(unsigned int& timestamp) {
|
||||
uint32_t playout_timestamp_rtp = 0;
|
||||
{
|
||||
rtc::CritScope lock(&video_sync_lock_);
|
||||
playout_timestamp_rtp = playout_timestamp_rtp_;
|
||||
}
|
||||
if (playout_timestamp_rtp == 0) {
|
||||
RTC_DLOG(LS_ERROR) << "GetPlayoutTimestamp() failed to retrieve timestamp";
|
||||
return -1;
|
||||
}
|
||||
timestamp = playout_timestamp_rtp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
absl::optional<Syncable::Info> ChannelReceive::GetSyncInfo() const {
|
||||
Syncable::Info info;
|
||||
if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs,
|
||||
&info.capture_time_ntp_frac, nullptr, nullptr,
|
||||
&info.capture_time_source_clock) != 0) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
{
|
||||
rtc::CritScope cs(&rtp_sources_lock_);
|
||||
if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_ms_) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
|
||||
info.latest_receive_time_ms = *last_received_rtp_system_time_ms_;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void ChannelReceive::UpdatePlayoutTimestamp(bool rtcp) {
|
||||
jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp();
|
||||
|
||||
if (!jitter_buffer_playout_timestamp_) {
|
||||
// This can happen if this channel has not received any RTP packets. In
|
||||
// this case, NetEq is not capable of computing a playout timestamp.
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t delay_ms = 0;
|
||||
if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
|
||||
RTC_DLOG(LS_WARNING)
|
||||
<< "ChannelReceive::UpdatePlayoutTimestamp() failed to read"
|
||||
<< " playout delay from the ADM";
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_DCHECK(jitter_buffer_playout_timestamp_);
|
||||
uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_;
|
||||
|
||||
// Remove the playout delay.
|
||||
playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000));
|
||||
|
||||
{
|
||||
rtc::CritScope lock(&video_sync_lock_);
|
||||
if (!rtcp) {
|
||||
playout_timestamp_rtp_ = playout_timestamp;
|
||||
}
|
||||
playout_delay_ms_ = delay_ms;
|
||||
}
|
||||
}
|
||||
|
||||
int ChannelReceive::GetRtpTimestampRateHz() const {
|
||||
const auto format = audio_coding_->ReceiveFormat();
|
||||
// Default to the playout frequency if we've not gotten any packets yet.
|
||||
// TODO(ossu): Zero clockrate can only happen if we've added an external
|
||||
// decoder for a format we don't support internally. Remove once that way of
|
||||
// adding decoders is gone!
|
||||
return (format && format->clockrate_hz != 0)
|
||||
? format->clockrate_hz
|
||||
: audio_coding_->PlayoutFrequency();
|
||||
}
|
||||
|
||||
int64_t ChannelReceive::GetRTT() const {
|
||||
RtcpMode method = _rtpRtcpModule->RTCP();
|
||||
if (method == RtcpMode::kOff) {
|
||||
return 0;
|
||||
}
|
||||
std::vector<RTCPReportBlock> report_blocks;
|
||||
_rtpRtcpModule->RemoteRTCPStat(&report_blocks);
|
||||
|
||||
// TODO(nisse): Could we check the return value from the ->RTT() call below,
|
||||
// instead of checking if we have any report blocks?
|
||||
if (report_blocks.empty()) {
|
||||
rtc::CritScope lock(&assoc_send_channel_lock_);
|
||||
// Tries to get RTT from an associated channel.
|
||||
if (!associated_send_channel_) {
|
||||
return 0;
|
||||
}
|
||||
return associated_send_channel_->GetRTT();
|
||||
}
|
||||
|
||||
int64_t rtt = 0;
|
||||
int64_t avg_rtt = 0;
|
||||
int64_t max_rtt = 0;
|
||||
int64_t min_rtt = 0;
|
||||
if (_rtpRtcpModule->RTT(remote_ssrc_, &rtt, &avg_rtt, &min_rtt, &max_rtt) !=
|
||||
0) {
|
||||
return 0;
|
||||
}
|
||||
return rtt;
|
||||
}
|
||||
|
||||
} // namespace voe
|
||||
} // namespace webrtc
|
||||
271
audio/channel_receive.h
Normal file
271
audio/channel_receive.h
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_CHANNEL_RECEIVE_H_
|
||||
#define AUDIO_CHANNEL_RECEIVE_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio/audio_mixer.h"
|
||||
#include "api/call/audio_sink.h"
|
||||
#include "api/call/transport.h"
|
||||
#include "api/rtpreceiverinterface.h"
|
||||
#include "audio/audio_level.h"
|
||||
#include "call/syncable.h"
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/audio_coding/include/audio_coding_module.h"
|
||||
#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||
#include "modules/rtp_rtcp/source/contributing_sources.h"
|
||||
#include "rtc_base/criticalsection.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
|
||||
// TODO(solenberg, nisse): This file contains a few NOLINT marks, to silence
|
||||
// warnings about use of unsigned short, and non-const reference arguments.
|
||||
// These need cleanup, in a separate cl.
|
||||
|
||||
namespace rtc {
|
||||
class TimestampWrapAroundHandler;
|
||||
}
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDeviceModule;
|
||||
class PacketRouter;
|
||||
class ProcessThread;
|
||||
class RateLimiter;
|
||||
class ReceiveStatistics;
|
||||
class RtcEventLog;
|
||||
class RtpPacketReceived;
|
||||
class RtpRtcp;
|
||||
|
||||
struct CallReceiveStatistics {
|
||||
unsigned short fractionLost; // NOLINT
|
||||
unsigned int cumulativeLost;
|
||||
unsigned int extendedMax;
|
||||
unsigned int jitterSamples;
|
||||
int64_t rttMs;
|
||||
size_t bytesReceived;
|
||||
int packetsReceived;
|
||||
// The capture ntp time (in local timebase) of the first played out audio
|
||||
// frame.
|
||||
int64_t capture_start_ntp_time_ms_;
|
||||
};
|
||||
|
||||
namespace voe {
|
||||
|
||||
class ChannelSend;
|
||||
|
||||
// Helper class to simplify locking scheme for members that are accessed from
|
||||
// multiple threads.
|
||||
// Example: a member can be set on thread T1 and read by an internal audio
|
||||
// thread T2. Accessing the member via this class ensures that we are
|
||||
// safe and also avoid TSan v2 warnings.
|
||||
class ChannelReceiveState {
|
||||
public:
|
||||
struct State {
|
||||
bool playing = false;
|
||||
};
|
||||
|
||||
ChannelReceiveState() {}
|
||||
virtual ~ChannelReceiveState() {}
|
||||
|
||||
void Reset() {
|
||||
rtc::CritScope lock(&lock_);
|
||||
state_ = State();
|
||||
}
|
||||
|
||||
State Get() const {
|
||||
rtc::CritScope lock(&lock_);
|
||||
return state_;
|
||||
}
|
||||
|
||||
void SetPlaying(bool enable) {
|
||||
rtc::CritScope lock(&lock_);
|
||||
state_.playing = enable;
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::CriticalSection lock_;
|
||||
State state_;
|
||||
};
|
||||
|
||||
class ChannelReceive : public RtpData, public Transport {
|
||||
public:
|
||||
// Used for receive streams.
|
||||
ChannelReceive(ProcessThread* module_process_thread,
|
||||
AudioDeviceModule* audio_device_module,
|
||||
RtcpRttStats* rtcp_rtt_stats,
|
||||
RtcEventLog* rtc_event_log,
|
||||
uint32_t remote_ssrc,
|
||||
size_t jitter_buffer_max_packets,
|
||||
bool jitter_buffer_fast_playout,
|
||||
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id);
|
||||
virtual ~ChannelReceive();
|
||||
|
||||
void SetSink(AudioSinkInterface* sink);
|
||||
|
||||
void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
|
||||
|
||||
// API methods
|
||||
|
||||
// VoEBase
|
||||
int32_t StartPlayout();
|
||||
int32_t StopPlayout();
|
||||
|
||||
// Codecs
|
||||
int32_t GetRecCodec(CodecInst& codec); // NOLINT
|
||||
|
||||
// Network
|
||||
void RegisterTransport(Transport* transport);
|
||||
// TODO(nisse, solenberg): Delete when VoENetwork is deleted.
|
||||
int32_t ReceivedRTCPPacket(const uint8_t* data, size_t length);
|
||||
void OnRtpPacket(const RtpPacketReceived& packet);
|
||||
|
||||
// Muting, Volume and Level.
|
||||
void SetChannelOutputVolumeScaling(float scaling);
|
||||
int GetSpeechOutputLevelFullRange() const;
|
||||
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
||||
double GetTotalOutputEnergy() const;
|
||||
double GetTotalOutputDuration() const;
|
||||
|
||||
// Stats.
|
||||
int GetNetworkStatistics(NetworkStatistics& stats); // NOLINT
|
||||
void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
|
||||
|
||||
// Audio+Video Sync.
|
||||
uint32_t GetDelayEstimate() const;
|
||||
int SetMinimumPlayoutDelay(int delayMs);
|
||||
int GetPlayoutTimestamp(unsigned int& timestamp); // NOLINT
|
||||
|
||||
// Produces the transport-related timestamps; current_delay_ms is left unset.
|
||||
absl::optional<Syncable::Info> GetSyncInfo() const;
|
||||
|
||||
// RTP+RTCP
|
||||
int SetLocalSSRC(unsigned int ssrc);
|
||||
|
||||
void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router);
|
||||
void ResetReceiverCongestionControlObjects();
|
||||
|
||||
int GetRTPStatistics(CallReceiveStatistics& stats); // NOLINT
|
||||
void SetNACKStatus(bool enable, int maxNumberOfPackets);
|
||||
|
||||
// From RtpData in the RTP/RTCP module
|
||||
int32_t OnReceivedPayloadData(const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const WebRtcRTPHeader* rtpHeader) override;
|
||||
|
||||
// From Transport (called by the RTP/RTCP module)
|
||||
bool SendRtp(const uint8_t* data,
|
||||
size_t len,
|
||||
const PacketOptions& packet_options) override;
|
||||
bool SendRtcp(const uint8_t* data, size_t len) override;
|
||||
|
||||
// From AudioMixer::Source.
|
||||
AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
|
||||
int sample_rate_hz,
|
||||
AudioFrame* audio_frame);
|
||||
|
||||
int PreferredSampleRate() const;
|
||||
|
||||
// Associate to a send channel.
|
||||
// Used for obtaining RTT for a receive-only channel.
|
||||
void SetAssociatedSendChannel(ChannelSend* channel);
|
||||
|
||||
std::vector<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;
|
||||
|
||||
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;
|
||||
Transport* _transportPtr; // WebRtc socket or external transport
|
||||
float _outputGain RTC_GUARDED_BY(volume_settings_critsect_);
|
||||
|
||||
// An associated send channel.
|
||||
rtc::CriticalSection assoc_send_channel_lock_;
|
||||
ChannelSend* associated_send_channel_
|
||||
RTC_GUARDED_BY(assoc_send_channel_lock_);
|
||||
|
||||
PacketRouter* packet_router_ = nullptr;
|
||||
|
||||
rtc::ThreadChecker construction_thread_;
|
||||
};
|
||||
|
||||
} // namespace voe
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // AUDIO_CHANNEL_RECEIVE_H_
|
||||
@ -23,7 +23,8 @@ namespace webrtc {
|
||||
namespace voe {
|
||||
ChannelReceiveProxy::ChannelReceiveProxy() {}
|
||||
|
||||
ChannelReceiveProxy::ChannelReceiveProxy(std::unique_ptr<Channel> channel)
|
||||
ChannelReceiveProxy::ChannelReceiveProxy(
|
||||
std::unique_ptr<ChannelReceive> channel)
|
||||
: channel_(std::move(channel)) {
|
||||
RTC_DCHECK(channel_);
|
||||
module_process_thread_checker_.DetachFromThread();
|
||||
@ -42,9 +43,9 @@ void ChannelReceiveProxy::SetNACKStatus(bool enable, int max_packets) {
|
||||
channel_->SetNACKStatus(enable, max_packets);
|
||||
}
|
||||
|
||||
CallStatistics ChannelReceiveProxy::GetRTCPStatistics() const {
|
||||
CallReceiveStatistics ChannelReceiveProxy::GetRTCPStatistics() const {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
CallStatistics stats = {0};
|
||||
CallReceiveStatistics stats = {0};
|
||||
int error = channel_->GetRTPStatistics(stats);
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
return stats;
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
#include "api/audio/audio_mixer.h"
|
||||
#include "api/rtpreceiverinterface.h"
|
||||
#include "audio/channel.h"
|
||||
#include "audio/channel_receive.h"
|
||||
#include "call/rtp_packet_sink_interface.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/race_checker.h"
|
||||
@ -43,13 +43,13 @@ class ChannelSendProxy;
|
||||
class ChannelReceiveProxy : public RtpPacketSinkInterface {
|
||||
public:
|
||||
ChannelReceiveProxy();
|
||||
explicit ChannelReceiveProxy(std::unique_ptr<Channel> channel);
|
||||
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 CallStatistics GetRTCPStatistics() const;
|
||||
virtual CallReceiveStatistics GetRTCPStatistics() const;
|
||||
virtual void RegisterTransport(Transport* transport);
|
||||
virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
|
||||
|
||||
@ -100,7 +100,7 @@ class ChannelReceiveProxy : public RtpPacketSinkInterface {
|
||||
// audio thread to another, but access is still sequential.
|
||||
rtc::RaceChecker audio_thread_race_checker_;
|
||||
rtc::RaceChecker video_capture_thread_race_checker_;
|
||||
std::unique_ptr<Channel> channel_;
|
||||
std::unique_ptr<ChannelReceive> channel_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ChannelReceiveProxy);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -8,31 +8,22 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_CHANNEL_H_
|
||||
#define AUDIO_CHANNEL_H_
|
||||
#ifndef AUDIO_CHANNEL_SEND_H_
|
||||
#define AUDIO_CHANNEL_SEND_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio/audio_mixer.h"
|
||||
#include "api/audio/audio_frame.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/call/audio_sink.h"
|
||||
#include "api/call/transport.h"
|
||||
#include "api/rtpreceiverinterface.h"
|
||||
#include "audio/audio_level.h"
|
||||
#include "call/syncable.h"
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/audio_coding/include/audio_coding_module.h"
|
||||
#include "modules/audio_processing/rms_level.h"
|
||||
#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||
#include "modules/rtp_rtcp/source/contributing_sources.h"
|
||||
#include "rtc_base/criticalsection.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
|
||||
@ -46,32 +37,19 @@ class TimestampWrapAroundHandler;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDeviceModule;
|
||||
class PacketRouter;
|
||||
class ProcessThread;
|
||||
class RateLimiter;
|
||||
class ReceiveStatistics;
|
||||
class RemoteNtpTimeEstimator;
|
||||
class RtcEventLog;
|
||||
class RtpPacketReceived;
|
||||
class RtpRtcp;
|
||||
class RtpTransportControllerSendInterface;
|
||||
|
||||
struct SenderInfo;
|
||||
|
||||
struct CallStatistics {
|
||||
unsigned short fractionLost; // NOLINT
|
||||
unsigned int cumulativeLost;
|
||||
unsigned int extendedMax;
|
||||
unsigned int jitterSamples;
|
||||
struct CallSendStatistics {
|
||||
int64_t rttMs;
|
||||
size_t bytesSent;
|
||||
int packetsSent;
|
||||
size_t bytesReceived;
|
||||
int packetsReceived;
|
||||
// The capture ntp time (in local timebase) of the first played out audio
|
||||
// frame.
|
||||
int64_t capture_start_ntp_time_ms_;
|
||||
};
|
||||
|
||||
// See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details.
|
||||
@ -98,15 +76,14 @@ class VoERtcpObserver;
|
||||
// Example: a member can be set on thread T1 and read by an internal audio
|
||||
// thread T2. Accessing the member via this class ensures that we are
|
||||
// safe and also avoid TSan v2 warnings.
|
||||
class ChannelState {
|
||||
class ChannelSendState {
|
||||
public:
|
||||
struct State {
|
||||
bool playing = false;
|
||||
bool sending = false;
|
||||
};
|
||||
|
||||
ChannelState() {}
|
||||
virtual ~ChannelState() {}
|
||||
ChannelSendState() {}
|
||||
virtual ~ChannelSendState() {}
|
||||
|
||||
void Reset() {
|
||||
rtc::CritScope lock(&lock_);
|
||||
@ -118,11 +95,6 @@ class ChannelState {
|
||||
return state_;
|
||||
}
|
||||
|
||||
void SetPlaying(bool enable) {
|
||||
rtc::CritScope lock(&lock_);
|
||||
state_.playing = enable;
|
||||
}
|
||||
|
||||
void SetSending(bool enable) {
|
||||
rtc::CritScope lock(&lock_);
|
||||
state_.sending = enable;
|
||||
@ -133,38 +105,22 @@ class ChannelState {
|
||||
State state_;
|
||||
};
|
||||
|
||||
class Channel
|
||||
: public RtpData,
|
||||
public Transport,
|
||||
class ChannelSend
|
||||
: public Transport,
|
||||
public AudioPacketizationCallback, // receive encoded packets from the
|
||||
// ACM
|
||||
public OverheadObserver {
|
||||
public:
|
||||
// TODO(nisse): Make OnUplinkPacketLossRate public, and delete friend
|
||||
// declaration.
|
||||
friend class VoERtcpObserver;
|
||||
|
||||
enum { KNumSocketThreads = 1 };
|
||||
enum { KNumberOfSocketBuffers = 8 };
|
||||
// Used for send streams.
|
||||
Channel(rtc::TaskQueue* encoder_queue,
|
||||
ProcessThread* module_process_thread,
|
||||
AudioDeviceModule* audio_device_module,
|
||||
RtcpRttStats* rtcp_rtt_stats,
|
||||
RtcEventLog* rtc_event_log);
|
||||
// Used for receive streams.
|
||||
Channel(ProcessThread* module_process_thread,
|
||||
AudioDeviceModule* audio_device_module,
|
||||
RtcpRttStats* rtcp_rtt_stats,
|
||||
RtcEventLog* rtc_event_log,
|
||||
uint32_t remote_ssrc,
|
||||
size_t jitter_buffer_max_packets,
|
||||
bool jitter_buffer_fast_playout,
|
||||
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id);
|
||||
virtual ~Channel();
|
||||
ChannelSend(rtc::TaskQueue* encoder_queue,
|
||||
ProcessThread* module_process_thread,
|
||||
RtcpRttStats* rtcp_rtt_stats,
|
||||
RtcEventLog* rtc_event_log);
|
||||
|
||||
void SetSink(AudioSinkInterface* sink);
|
||||
|
||||
void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs);
|
||||
virtual ~ChannelSend();
|
||||
|
||||
// Send using this encoder, with this payload type.
|
||||
bool SetEncoder(int payload_type, std::unique_ptr<AudioEncoder> encoder);
|
||||
@ -174,16 +130,15 @@ class Channel
|
||||
// API methods
|
||||
|
||||
// VoEBase
|
||||
int32_t StartPlayout();
|
||||
int32_t StopPlayout();
|
||||
int32_t StartSend();
|
||||
void StopSend();
|
||||
|
||||
// Codecs
|
||||
int32_t GetRecCodec(CodecInst& codec); // NOLINT
|
||||
void SetBitRate(int bitrate_bps, int64_t probing_interval_ms);
|
||||
bool EnableAudioNetworkAdaptor(const std::string& config_string);
|
||||
void DisableAudioNetworkAdaptor();
|
||||
|
||||
// TODO(nisse): Modifies decoder, but not used?
|
||||
void SetReceiverFrameLengthRange(int min_frame_length_ms,
|
||||
int max_frame_length_ms);
|
||||
|
||||
@ -191,32 +146,16 @@ class Channel
|
||||
void RegisterTransport(Transport* transport);
|
||||
// TODO(nisse, solenberg): Delete when VoENetwork is deleted.
|
||||
int32_t ReceivedRTCPPacket(const uint8_t* data, size_t length);
|
||||
void OnRtpPacket(const RtpPacketReceived& packet);
|
||||
|
||||
// Muting, Volume and Level.
|
||||
void SetInputMute(bool enable);
|
||||
void SetChannelOutputVolumeScaling(float scaling);
|
||||
int GetSpeechOutputLevelFullRange() const;
|
||||
// See description of "totalAudioEnergy" in the WebRTC stats spec:
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy
|
||||
double GetTotalOutputEnergy() const;
|
||||
double GetTotalOutputDuration() const;
|
||||
|
||||
// Stats.
|
||||
int GetNetworkStatistics(NetworkStatistics& stats); // NOLINT
|
||||
void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
|
||||
ANAStats GetANAStatistics() const;
|
||||
|
||||
// Audio+Video Sync.
|
||||
uint32_t GetDelayEstimate() const;
|
||||
int SetMinimumPlayoutDelay(int delayMs);
|
||||
int GetPlayoutTimestamp(unsigned int& timestamp); // NOLINT
|
||||
|
||||
// Used by AudioSendStream.
|
||||
RtpRtcp* GetRtpRtcp() const;
|
||||
|
||||
// Produces the transport-related timestamps; current_delay_ms is left unset.
|
||||
absl::optional<Syncable::Info> GetSyncInfo() const;
|
||||
// DTMF.
|
||||
int SendTelephoneEventOutband(int event, int duration_ms);
|
||||
int SetSendTelephoneEventPayloadType(int payload_type, int payload_frequency);
|
||||
@ -231,13 +170,11 @@ class Channel
|
||||
void RegisterSenderCongestionControlObjects(
|
||||
RtpTransportControllerSendInterface* transport,
|
||||
RtcpBandwidthObserver* bandwidth_observer);
|
||||
void RegisterReceiverCongestionControlObjects(PacketRouter* packet_router);
|
||||
void ResetSenderCongestionControlObjects();
|
||||
void ResetReceiverCongestionControlObjects();
|
||||
void SetRTCPStatus(bool enable);
|
||||
int SetRTCP_CNAME(const char cName[256]);
|
||||
int GetRemoteRTCPReportBlocks(std::vector<ReportBlock>* report_blocks);
|
||||
int GetRTPStatistics(CallStatistics& stats); // NOLINT
|
||||
int GetRTPStatistics(CallSendStatistics& stats); // NOLINT
|
||||
void SetNACKStatus(bool enable, int maxNumberOfPackets);
|
||||
|
||||
// From AudioPacketizationCallback in the ACM
|
||||
@ -248,25 +185,14 @@ class Channel
|
||||
size_t payloadSize,
|
||||
const RTPFragmentationHeader* fragmentation) override;
|
||||
|
||||
// From RtpData in the RTP/RTCP module
|
||||
int32_t OnReceivedPayloadData(const uint8_t* payloadData,
|
||||
size_t payloadSize,
|
||||
const WebRtcRTPHeader* rtpHeader) override;
|
||||
|
||||
// From Transport (called by the RTP/RTCP module)
|
||||
bool SendRtp(const uint8_t* data,
|
||||
size_t len,
|
||||
const PacketOptions& packet_options) override;
|
||||
bool SendRtcp(const uint8_t* data, size_t len) override;
|
||||
|
||||
// From AudioMixer::Source.
|
||||
AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
|
||||
int sample_rate_hz,
|
||||
AudioFrame* audio_frame);
|
||||
|
||||
int PreferredSampleRate() const;
|
||||
|
||||
bool Playing() const { return channel_state_.Get().playing; }
|
||||
bool Sending() const { return channel_state_.Get().sending; }
|
||||
RtpRtcp* RtpRtcpModulePtr() const { return _rtpRtcpModule.get(); }
|
||||
|
||||
@ -281,10 +207,6 @@ class Channel
|
||||
// packet.
|
||||
void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame);
|
||||
|
||||
// Associate to a send channel.
|
||||
// Used for obtaining RTT for a receive-only channel.
|
||||
void SetAssociatedSendChannel(Channel* channel);
|
||||
|
||||
void SetTransportOverhead(size_t transport_overhead_per_packet);
|
||||
|
||||
// From OverheadObserver in the RTP/RTCP module
|
||||
@ -298,7 +220,7 @@ class Channel
|
||||
|
||||
void OnRecoverableUplinkPacketLossRate(float recoverable_packet_loss_rate);
|
||||
|
||||
std::vector<RtpSource> GetSources() const;
|
||||
int64_t GetRTT() const;
|
||||
|
||||
private:
|
||||
class ProcessAndEncodeAudioTask;
|
||||
@ -306,15 +228,10 @@ class Channel
|
||||
void Init();
|
||||
void Terminate();
|
||||
|
||||
int GetRemoteSSRC(unsigned int& ssrc); // NOLINT
|
||||
void OnUplinkPacketLossRate(float packet_loss_rate);
|
||||
bool InputMute() const;
|
||||
|
||||
bool ReceivePacket(const uint8_t* packet,
|
||||
size_t packet_length,
|
||||
const RTPHeader& header);
|
||||
int ResendPackets(const uint16_t* sequence_numbers, int length);
|
||||
void UpdatePlayoutTimestamp(bool rtcp);
|
||||
|
||||
int SetSendRtpHeaderExtension(bool enable,
|
||||
RTPExtensionType type,
|
||||
@ -324,7 +241,6 @@ class Channel
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
|
||||
|
||||
int GetRtpTimestampRateHz() const;
|
||||
int64_t GetRTT(bool allow_associate_channel) const;
|
||||
|
||||
// Called on the encoder task queue when a new input audio frame is ready
|
||||
// for encoding.
|
||||
@ -333,60 +249,23 @@ class Channel
|
||||
rtc::CriticalSection _callbackCritSect;
|
||||
rtc::CriticalSection volume_settings_critsect_;
|
||||
|
||||
ChannelState channel_state_;
|
||||
ChannelSendState channel_state_;
|
||||
|
||||
RtcEventLog* const event_log_;
|
||||
|
||||
// Indexed by payload type.
|
||||
std::map<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;
|
||||
uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_);
|
||||
|
||||
RemoteNtpTimeEstimator ntp_estimator_ RTC_GUARDED_BY(ts_stats_lock_);
|
||||
|
||||
// Timestamp of the audio pulled from NetEq.
|
||||
absl::optional<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_);
|
||||
uint16_t send_sequence_number_;
|
||||
|
||||
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;
|
||||
Transport* _transportPtr; // WebRtc socket or external transport
|
||||
RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_);
|
||||
bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_);
|
||||
bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_);
|
||||
float _outputGain RTC_GUARDED_BY(volume_settings_critsect_);
|
||||
// VoeRTP_RTCP
|
||||
// TODO(henrika): can today be accessed on the main thread and on the
|
||||
// task queue; hence potential race.
|
||||
@ -397,9 +276,6 @@ class Channel
|
||||
rtc::CriticalSection overhead_per_packet_lock_;
|
||||
// RtcpBandwidthObserver
|
||||
std::unique_ptr<VoERtcpObserver> rtcp_observer_;
|
||||
// An associated send channel.
|
||||
rtc::CriticalSection assoc_send_channel_lock_;
|
||||
Channel* associated_send_channel_ RTC_GUARDED_BY(assoc_send_channel_lock_);
|
||||
|
||||
PacketRouter* packet_router_ = nullptr;
|
||||
std::unique_ptr<TransportFeedbackProxy> feedback_observer_proxy_;
|
||||
@ -419,4 +295,4 @@ class Channel
|
||||
} // namespace voe
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // AUDIO_CHANNEL_H_
|
||||
#endif // AUDIO_CHANNEL_SEND_H_
|
||||
@ -22,7 +22,7 @@ namespace webrtc {
|
||||
namespace voe {
|
||||
ChannelSendProxy::ChannelSendProxy() {}
|
||||
|
||||
ChannelSendProxy::ChannelSendProxy(std::unique_ptr<Channel> channel)
|
||||
ChannelSendProxy::ChannelSendProxy(std::unique_ptr<ChannelSend> channel)
|
||||
: channel_(std::move(channel)) {
|
||||
RTC_DCHECK(channel_);
|
||||
module_process_thread_checker_.DetachFromThread();
|
||||
@ -41,9 +41,9 @@ void ChannelSendProxy::SetNACKStatus(bool enable, int max_packets) {
|
||||
channel_->SetNACKStatus(enable, max_packets);
|
||||
}
|
||||
|
||||
CallStatistics ChannelSendProxy::GetRTCPStatistics() const {
|
||||
CallSendStatistics ChannelSendProxy::GetRTCPStatistics() const {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
CallStatistics stats = {0};
|
||||
CallSendStatistics stats = {0};
|
||||
int error = channel_->GetRTPStatistics(stats);
|
||||
RTC_DCHECK_EQ(0, error);
|
||||
return stats;
|
||||
@ -193,7 +193,7 @@ void ChannelSendProxy::StopSend() {
|
||||
channel_->StopSend();
|
||||
}
|
||||
|
||||
Channel* ChannelSendProxy::GetChannel() const {
|
||||
ChannelSend* ChannelSendProxy::GetChannel() const {
|
||||
return channel_.get();
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "audio/channel.h"
|
||||
#include "audio/channel_send.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/race_checker.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
@ -39,13 +39,13 @@ namespace voe {
|
||||
class ChannelSendProxy {
|
||||
public:
|
||||
ChannelSendProxy();
|
||||
explicit ChannelSendProxy(std::unique_ptr<Channel> channel);
|
||||
explicit ChannelSendProxy(std::unique_ptr<ChannelSend> channel);
|
||||
virtual ~ChannelSendProxy();
|
||||
|
||||
// Shared with ChannelReceiveProxy
|
||||
virtual void SetLocalSSRC(uint32_t ssrc);
|
||||
virtual void SetNACKStatus(bool enable, int max_packets);
|
||||
virtual CallStatistics GetRTCPStatistics() const;
|
||||
virtual CallSendStatistics GetRTCPStatistics() const;
|
||||
virtual void RegisterTransport(Transport* transport);
|
||||
virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
|
||||
|
||||
@ -82,7 +82,7 @@ class ChannelSendProxy {
|
||||
virtual void StopSend();
|
||||
|
||||
// Needed by ChannelReceiveProxy::AssociateSendChannel.
|
||||
virtual Channel* GetChannel() const;
|
||||
virtual ChannelSend* GetChannel() const;
|
||||
|
||||
private:
|
||||
// Thread checkers document and lock usage of some methods on voe::Channel to
|
||||
@ -97,7 +97,7 @@ class ChannelSendProxy {
|
||||
// audio thread to another, but access is still sequential.
|
||||
rtc::RaceChecker audio_thread_race_checker_;
|
||||
rtc::RaceChecker video_capture_thread_race_checker_;
|
||||
std::unique_ptr<Channel> channel_;
|
||||
std::unique_ptr<ChannelSend> channel_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ChannelSendProxy);
|
||||
};
|
||||
|
||||
@ -31,7 +31,7 @@ class MockChannelReceiveProxy : public voe::ChannelReceiveProxy {
|
||||
MOCK_METHOD1(RegisterReceiverCongestionControlObjects,
|
||||
void(PacketRouter* packet_router));
|
||||
MOCK_METHOD0(ResetReceiverCongestionControlObjects, void());
|
||||
MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics());
|
||||
MOCK_CONST_METHOD0(GetRTCPStatistics, CallReceiveStatistics());
|
||||
MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
|
||||
MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
|
||||
MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int());
|
||||
@ -82,7 +82,7 @@ class MockChannelSendProxy : public voe::ChannelSendProxy {
|
||||
void(RtpTransportControllerSendInterface* transport,
|
||||
RtcpBandwidthObserver* bandwidth_observer));
|
||||
MOCK_METHOD0(ResetSenderCongestionControlObjects, void());
|
||||
MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics());
|
||||
MOCK_CONST_METHOD0(GetRTCPStatistics, CallSendStatistics());
|
||||
MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector<ReportBlock>());
|
||||
MOCK_CONST_METHOD0(GetANAStatistics, ANAStats());
|
||||
MOCK_METHOD2(SetSendTelephoneEventPayloadType,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user