Move VoiceEngineObserver into AudioSendStream so that we detect typing noises and return properly in GetStats().
BUG=webrtc:4690 Review URL: https://codereview.webrtc.org/1403363003 Cr-Commit-Position: refs/heads/master@{#10548}
This commit is contained in:
parent
19299fb28b
commit
566ef247b9
@ -47,11 +47,10 @@ class MediaController : public webrtc::MediaControllerInterface,
|
||||
RTC_DCHECK(nullptr != worker_thread);
|
||||
worker_thread_->Invoke<void>(
|
||||
rtc::Bind(&MediaController::Construct_w, this,
|
||||
channel_manager_->media_engine()->GetVoE()));
|
||||
channel_manager_->media_engine()));
|
||||
}
|
||||
~MediaController() override {
|
||||
worker_thread_->Invoke<void>(
|
||||
rtc::Bind(&MediaController::Destruct_w, this));
|
||||
worker_thread_->Invoke<void>(rtc::Bind(&MediaController::Destruct_w, this));
|
||||
}
|
||||
|
||||
webrtc::Call* call_w() override {
|
||||
@ -64,10 +63,11 @@ class MediaController : public webrtc::MediaControllerInterface,
|
||||
}
|
||||
|
||||
private:
|
||||
void Construct_w(webrtc::VoiceEngine* voice_engine) {
|
||||
void Construct_w(cricket::MediaEngineInterface* media_engine) {
|
||||
RTC_DCHECK(worker_thread_->IsCurrent());
|
||||
RTC_DCHECK(media_engine);
|
||||
webrtc::Call::Config config;
|
||||
config.voice_engine = voice_engine;
|
||||
config.audio_state = media_engine->GetAudioState();
|
||||
config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
|
||||
config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
|
||||
config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;
|
||||
@ -84,7 +84,7 @@ class MediaController : public webrtc::MediaControllerInterface,
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MediaController);
|
||||
};
|
||||
} // namespace {
|
||||
} // namespace {
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -93,4 +93,4 @@ MediaControllerInterface* MediaControllerInterface::Create(
|
||||
cricket::ChannelManager* channel_manager) {
|
||||
return new MediaController(worker_thread, channel_manager);
|
||||
}
|
||||
} // namespace webrtc
|
||||
} // namespace webrtc
|
||||
|
||||
@ -733,7 +733,9 @@ class FakeVoiceEngine : public FakeBaseEngine {
|
||||
}
|
||||
bool Init(rtc::Thread* worker_thread) { return true; }
|
||||
void Terminate() {}
|
||||
webrtc::VoiceEngine* GetVoE() { return nullptr; }
|
||||
rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const {
|
||||
return rtc::scoped_refptr<webrtc::AudioState>();
|
||||
}
|
||||
AudioOptions GetOptions() const {
|
||||
return options_;
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
#include "talk/media/base/videocommon.h"
|
||||
#include "talk/media/base/voiceprocessor.h"
|
||||
#include "talk/media/devices/devicemanager.h"
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/base/fileutils.h"
|
||||
#include "webrtc/base/sigslotrepeater.h"
|
||||
|
||||
@ -51,7 +52,6 @@
|
||||
|
||||
namespace webrtc {
|
||||
class Call;
|
||||
class VoiceEngine;
|
||||
}
|
||||
|
||||
namespace cricket {
|
||||
@ -72,7 +72,7 @@ class MediaEngineInterface {
|
||||
// Shuts down the engine.
|
||||
virtual void Terminate() = 0;
|
||||
// TODO(solenberg): Remove once VoE API refactoring is done.
|
||||
virtual webrtc::VoiceEngine* GetVoE() = 0;
|
||||
virtual rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const = 0;
|
||||
|
||||
// MediaChannel creation
|
||||
// Creates a voice media channel. Returns NULL on failure.
|
||||
@ -167,8 +167,8 @@ class CompositeMediaEngine : public MediaEngineInterface {
|
||||
voice_.Terminate();
|
||||
}
|
||||
|
||||
virtual webrtc::VoiceEngine* GetVoE() {
|
||||
return voice_.GetVoE();
|
||||
virtual rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const {
|
||||
return voice_.GetAudioState();
|
||||
}
|
||||
virtual VoiceMediaChannel* CreateChannel(webrtc::Call* call,
|
||||
const AudioOptions& options) {
|
||||
|
||||
@ -47,11 +47,9 @@
|
||||
#include "webrtc/video_send_stream.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class FakeAudioSendStream : public webrtc::AudioSendStream {
|
||||
class FakeAudioSendStream final : public webrtc::AudioSendStream {
|
||||
public:
|
||||
explicit FakeAudioSendStream(
|
||||
const webrtc::AudioSendStream::Config& config);
|
||||
explicit FakeAudioSendStream(const webrtc::AudioSendStream::Config& config);
|
||||
|
||||
const webrtc::AudioSendStream::Config& GetConfig() const;
|
||||
void SetStats(const webrtc::AudioSendStream::Stats& stats);
|
||||
@ -72,7 +70,7 @@ class FakeAudioSendStream : public webrtc::AudioSendStream {
|
||||
webrtc::AudioSendStream::Stats stats_;
|
||||
};
|
||||
|
||||
class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
|
||||
class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
|
||||
public:
|
||||
explicit FakeAudioReceiveStream(
|
||||
const webrtc::AudioReceiveStream::Config& config);
|
||||
@ -104,8 +102,8 @@ class FakeAudioReceiveStream : public webrtc::AudioReceiveStream {
|
||||
int received_packets_;
|
||||
};
|
||||
|
||||
class FakeVideoSendStream : public webrtc::VideoSendStream,
|
||||
public webrtc::VideoCaptureInput {
|
||||
class FakeVideoSendStream final : public webrtc::VideoSendStream,
|
||||
public webrtc::VideoCaptureInput {
|
||||
public:
|
||||
FakeVideoSendStream(const webrtc::VideoSendStream::Config& config,
|
||||
const webrtc::VideoEncoderConfig& encoder_config);
|
||||
@ -153,7 +151,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream,
|
||||
webrtc::VideoSendStream::Stats stats_;
|
||||
};
|
||||
|
||||
class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
|
||||
class FakeVideoReceiveStream final : public webrtc::VideoReceiveStream {
|
||||
public:
|
||||
explicit FakeVideoReceiveStream(
|
||||
const webrtc::VideoReceiveStream::Config& config);
|
||||
@ -188,7 +186,7 @@ class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
|
||||
webrtc::VideoReceiveStream::Stats stats_;
|
||||
};
|
||||
|
||||
class FakeCall : public webrtc::Call, public webrtc::PacketReceiver {
|
||||
class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
|
||||
public:
|
||||
explicit FakeCall(const webrtc::Call::Config& config);
|
||||
~FakeCall() override;
|
||||
|
||||
@ -388,14 +388,20 @@ AudioOptions GetDefaultEngineOptions() {
|
||||
std::string GetEnableString(bool enable) {
|
||||
return enable ? "enable" : "disable";
|
||||
}
|
||||
|
||||
webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) {
|
||||
webrtc::AudioState::Config config;
|
||||
config.voice_engine = voe_wrapper->engine();
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace {
|
||||
|
||||
WebRtcVoiceEngine::WebRtcVoiceEngine()
|
||||
: voe_wrapper_(new VoEWrapper()),
|
||||
tracing_(new VoETraceWrapper()),
|
||||
adm_(NULL),
|
||||
log_filter_(SeverityToFilter(kDefaultLogSeverity)),
|
||||
is_dumping_aec_(false) {
|
||||
audio_state_(webrtc::AudioState::Create(MakeAudioStateConfig(voe()))),
|
||||
log_filter_(SeverityToFilter(kDefaultLogSeverity)) {
|
||||
Construct();
|
||||
}
|
||||
|
||||
@ -403,25 +409,20 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper,
|
||||
VoETraceWrapper* tracing)
|
||||
: voe_wrapper_(voe_wrapper),
|
||||
tracing_(tracing),
|
||||
adm_(NULL),
|
||||
log_filter_(SeverityToFilter(kDefaultLogSeverity)),
|
||||
is_dumping_aec_(false) {
|
||||
log_filter_(SeverityToFilter(kDefaultLogSeverity)) {
|
||||
Construct();
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::Construct() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
signal_thread_checker_.DetachFromThread();
|
||||
std::memset(&default_agc_config_, 0, sizeof(default_agc_config_));
|
||||
SetTraceFilter(log_filter_);
|
||||
initialized_ = false;
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
|
||||
SetTraceOptions("");
|
||||
if (tracing_->SetTraceCallback(this) == -1) {
|
||||
LOG_RTCERR0(SetTraceCallback);
|
||||
}
|
||||
if (voe_wrapper_->base()->RegisterVoiceEngineObserver(*this) == -1) {
|
||||
LOG_RTCERR0(RegisterVoiceEngineObserver);
|
||||
}
|
||||
// Clear the default agc state.
|
||||
memset(&default_agc_config_, 0, sizeof(default_agc_config_));
|
||||
|
||||
// Load our audio codec list.
|
||||
ConstructCodecs();
|
||||
@ -442,6 +443,7 @@ void WebRtcVoiceEngine::Construct() {
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::ConstructCodecs() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
|
||||
int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
|
||||
for (int i = 0; i < ncodecs; ++i) {
|
||||
@ -499,6 +501,7 @@ void WebRtcVoiceEngine::ConstructCodecs() {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (voe_wrapper_->codec()->GetCodec(index, *codec) == -1) {
|
||||
return false;
|
||||
}
|
||||
@ -508,10 +511,8 @@ bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
|
||||
}
|
||||
|
||||
WebRtcVoiceEngine::~WebRtcVoiceEngine() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
|
||||
if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) {
|
||||
LOG_RTCERR0(DeRegisterVoiceEngineObserver);
|
||||
}
|
||||
if (adm_) {
|
||||
voe_wrapper_.reset();
|
||||
adm_->Release();
|
||||
@ -522,6 +523,7 @@ WebRtcVoiceEngine::~WebRtcVoiceEngine() {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread == rtc::Thread::Current());
|
||||
LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
|
||||
bool res = InitInternal();
|
||||
@ -535,6 +537,7 @@ bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::InitInternal() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// Temporarily turn logging level up for the Init call
|
||||
int old_filter = log_filter_;
|
||||
int extended_filter = log_filter_ | SeverityToFilter(rtc::LS_INFO);
|
||||
@ -588,6 +591,7 @@ bool WebRtcVoiceEngine::InitInternal() {
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::Terminate() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
|
||||
initialized_ = false;
|
||||
|
||||
@ -596,12 +600,20 @@ void WebRtcVoiceEngine::Terminate() {
|
||||
voe_wrapper_->base()->Terminate();
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<webrtc::AudioState>
|
||||
WebRtcVoiceEngine::GetAudioState() const {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return audio_state_;
|
||||
}
|
||||
|
||||
VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call,
|
||||
const AudioOptions& options) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return new WebRtcVoiceMediaChannel(this, options, call);
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (!ApplyOptions(options)) {
|
||||
return false;
|
||||
}
|
||||
@ -612,6 +624,7 @@ bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
|
||||
// AudioOptions defaults are set in InitInternal (for options with corresponding
|
||||
// MediaEngineInterface flags) and in SetOptions(int) for flagless options.
|
||||
bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "ApplyOptions: " << options_in.ToString();
|
||||
AudioOptions options = options_in; // The options are modified below.
|
||||
// kEcConference is AEC with high suppression.
|
||||
@ -887,6 +900,7 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
|
||||
// soundclip device. At that time, reinstate the soundclip pause/resume code.
|
||||
bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
|
||||
const Device* out_device) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
#if !defined(IOS)
|
||||
int in_id = in_device ? rtc::FromString<int>(in_device->id) :
|
||||
kDefaultAudioDeviceId;
|
||||
@ -976,6 +990,7 @@ bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
|
||||
|
||||
bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
|
||||
bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// In Linux, VoiceEngine uses the same device dev_id as the device manager.
|
||||
#if defined(LINUX) || defined(ANDROID)
|
||||
*rtc_id = dev_id;
|
||||
@ -1025,6 +1040,7 @@ bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
unsigned int ulevel;
|
||||
if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) {
|
||||
LOG_RTCERR1(GetSpeakerVolume, level);
|
||||
@ -1035,6 +1051,7 @@ bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::SetOutputVolume(int level) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(level >= 0 && level <= 255);
|
||||
if (voe_wrapper_->volume()->SetSpeakerVolume(level) == -1) {
|
||||
LOG_RTCERR1(SetSpeakerVolume, level);
|
||||
@ -1044,22 +1061,26 @@ bool WebRtcVoiceEngine::SetOutputVolume(int level) {
|
||||
}
|
||||
|
||||
int WebRtcVoiceEngine::GetInputLevel() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
unsigned int ulevel;
|
||||
return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ?
|
||||
static_cast<int>(ulevel) : -1;
|
||||
}
|
||||
|
||||
const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
return codecs_;
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return FindWebRtcCodec(in, NULL);
|
||||
}
|
||||
|
||||
// Get the VoiceEngine codec that matches |in|, with the supplied settings.
|
||||
bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
|
||||
webrtc::CodecInst* out) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
|
||||
for (int i = 0; i < ncodecs; ++i) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
@ -1101,10 +1122,12 @@ bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
|
||||
}
|
||||
const std::vector<RtpHeaderExtension>&
|
||||
WebRtcVoiceEngine::rtp_header_extensions() const {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
return rtp_header_extensions_;
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// if min_sev == -1, we keep the current log level.
|
||||
if (min_sev >= 0) {
|
||||
SetTraceFilter(SeverityToFilter(min_sev));
|
||||
@ -1114,10 +1137,12 @@ void WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
|
||||
}
|
||||
|
||||
int WebRtcVoiceEngine::GetLastEngineError() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return voe_wrapper_->error();
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::SetTraceFilter(int filter) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
log_filter_ = filter;
|
||||
tracing_->SetTraceFilter(filter);
|
||||
}
|
||||
@ -1135,6 +1160,7 @@ void WebRtcVoiceEngine::SetTraceFilter(int filter) {
|
||||
// For more details see: "https://sites.google.com/a/google.com/wavelet/Home/
|
||||
// Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters"
|
||||
void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// Set encrypted trace file.
|
||||
std::vector<std::string> opts;
|
||||
rtc::tokenize(options, ' ', '"', '"', &opts);
|
||||
@ -1174,6 +1200,7 @@ void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
|
||||
|
||||
void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
|
||||
int length) {
|
||||
// Note: This callback can happen on any thread!
|
||||
rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
|
||||
if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
|
||||
sev = rtc::LS_ERROR;
|
||||
@ -1195,34 +1222,24 @@ void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::CallbackOnError(int channel_id, int err_code) {
|
||||
RTC_DCHECK(channel_id == -1);
|
||||
LOG(LS_WARNING) << "VoiceEngine error " << err_code << " reported on channel "
|
||||
<< channel_id << ".";
|
||||
rtc::CritScope lock(&channels_cs_);
|
||||
for (WebRtcVoiceMediaChannel* channel : channels_) {
|
||||
channel->OnError(err_code);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
|
||||
RTC_DCHECK(channel != NULL);
|
||||
rtc::CritScope lock(&channels_cs_);
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(channel);
|
||||
channels_.push_back(channel);
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
|
||||
rtc::CritScope lock(&channels_cs_);
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
auto it = std::find(channels_.begin(), channels_.end(), channel);
|
||||
if (it != channels_.end()) {
|
||||
channels_.erase(it);
|
||||
}
|
||||
RTC_DCHECK(it != channels_.end());
|
||||
channels_.erase(it);
|
||||
}
|
||||
|
||||
// Adjusts the default AGC target level by the specified delta.
|
||||
// NB: If we start messing with other config fields, we'll want
|
||||
// to save the current webrtc::AgcConfig as well.
|
||||
bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
webrtc::AgcConfig config = default_agc_config_;
|
||||
config.targetLeveldBOv -= delta;
|
||||
|
||||
@ -1238,6 +1255,7 @@ bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (initialized_) {
|
||||
LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init.";
|
||||
return false;
|
||||
@ -1254,6 +1272,7 @@ bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
FILE* aec_dump_file_stream = rtc::FdopenPlatformFileForWriting(file);
|
||||
if (!aec_dump_file_stream) {
|
||||
LOG(LS_ERROR) << "Could not open AEC dump file stream.";
|
||||
@ -1273,6 +1292,7 @@ bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (!is_dumping_aec_) {
|
||||
// Start dumping AEC when we are not dumping.
|
||||
if (voe_wrapper_->processing()->StartDebugRecording(
|
||||
@ -1285,6 +1305,7 @@ void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::StopAecDump() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (is_dumping_aec_) {
|
||||
// Stop dumping AEC when we are dumping.
|
||||
if (voe_wrapper_->processing()->StopDebugRecording() !=
|
||||
@ -1296,14 +1317,17 @@ void WebRtcVoiceEngine::StopAecDump() {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceEngine::StartRtcEventLog(rtc::PlatformFile file) {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return voe_wrapper_->codec()->GetEventLog()->StartLogging(file);
|
||||
}
|
||||
|
||||
void WebRtcVoiceEngine::StopRtcEventLog() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
voe_wrapper_->codec()->GetEventLog()->StopLogging();
|
||||
}
|
||||
|
||||
int WebRtcVoiceEngine::CreateVoEChannel() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return voe_wrapper_->base()->CreateChannel(voe_config_);
|
||||
}
|
||||
|
||||
@ -1327,7 +1351,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
RTC_DCHECK(stream_);
|
||||
}
|
||||
~WebRtcAudioSendStream() override {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
Stop();
|
||||
call_->DestroyAudioSendStream(stream_);
|
||||
}
|
||||
@ -1337,7 +1361,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
// This method is called on the libjingle worker thread.
|
||||
// TODO(xians): Make sure Start() is called only once.
|
||||
void Start(AudioRenderer* renderer) {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(renderer);
|
||||
if (renderer_) {
|
||||
RTC_DCHECK(renderer_ == renderer);
|
||||
@ -1348,7 +1372,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
}
|
||||
|
||||
webrtc::AudioSendStream::Stats GetStats() const {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return stream_->GetStats();
|
||||
}
|
||||
|
||||
@ -1356,7 +1380,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
// callback will be received after this method.
|
||||
// This method is called on the libjingle worker thread.
|
||||
void Stop() {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (renderer_) {
|
||||
renderer_->SetSink(nullptr);
|
||||
renderer_ = nullptr;
|
||||
@ -1370,6 +1394,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
int sample_rate,
|
||||
int number_of_channels,
|
||||
size_t number_of_frames) override {
|
||||
RTC_DCHECK(!worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(audio_capture_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(voe_audio_transport_);
|
||||
voe_audio_transport_->OnData(channel_,
|
||||
@ -1383,7 +1408,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
// Callback from the |renderer_| when it is going away. In case Start() has
|
||||
// never been called, this callback won't be triggered.
|
||||
void OnClose() override {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// Set |renderer_| to nullptr to make sure no more callback will get into
|
||||
// the renderer.
|
||||
renderer_ = nullptr;
|
||||
@ -1391,12 +1416,12 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
||||
|
||||
// Accessor to the VoE channel ID.
|
||||
int channel() const {
|
||||
RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return channel_;
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::ThreadChecker signal_thread_checker_;
|
||||
rtc::ThreadChecker worker_thread_checker_;
|
||||
rtc::ThreadChecker audio_capture_thread_checker_;
|
||||
const int channel_ = -1;
|
||||
webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
|
||||
@ -1428,26 +1453,15 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
|
||||
WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
|
||||
const AudioOptions& options,
|
||||
webrtc::Call* call)
|
||||
: engine_(engine),
|
||||
send_bitrate_setting_(false),
|
||||
send_bitrate_bps_(0),
|
||||
options_(),
|
||||
dtmf_allowed_(false),
|
||||
desired_playout_(false),
|
||||
nack_enabled_(false),
|
||||
playout_(false),
|
||||
typing_noise_detected_(false),
|
||||
desired_send_(SEND_NOTHING),
|
||||
send_(SEND_NOTHING),
|
||||
call_(call) {
|
||||
: engine_(engine), call_(call) {
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
|
||||
RTC_DCHECK(nullptr != call);
|
||||
RTC_DCHECK(call);
|
||||
engine->RegisterChannel(this);
|
||||
SetOptions(options);
|
||||
}
|
||||
|
||||
WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
|
||||
|
||||
// Remove any remaining send streams.
|
||||
@ -1467,7 +1481,7 @@ WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetSendParameters(
|
||||
const AudioSendParameters& params) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// TODO(pthatcher): Refactor this to be more clean now that we have
|
||||
// all the information at once.
|
||||
return (SetSendCodecs(params.codecs) &&
|
||||
@ -1478,7 +1492,7 @@ bool WebRtcVoiceMediaChannel::SetSendParameters(
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetRecvParameters(
|
||||
const AudioRecvParameters& params) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// TODO(pthatcher): Refactor this to be more clean now that we have
|
||||
// all the information at once.
|
||||
return (SetRecvCodecs(params.codecs) &&
|
||||
@ -1486,7 +1500,7 @@ bool WebRtcVoiceMediaChannel::SetRecvParameters(
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "Setting voice channel options: "
|
||||
<< options.ToString();
|
||||
|
||||
@ -1525,7 +1539,7 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetRecvCodecs(
|
||||
const std::vector<AudioCodec>& codecs) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
|
||||
// Set the payload types to be used for incoming media.
|
||||
LOG(LS_INFO) << "Setting receive voice codecs.";
|
||||
@ -1783,7 +1797,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
||||
const std::vector<AudioCodec>& codecs) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
|
||||
dtmf_allowed_ = false;
|
||||
for (const AudioCodec& codec : codecs) {
|
||||
@ -1840,7 +1854,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodec(
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions(
|
||||
const std::vector<RtpHeaderExtension>& extensions) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (receive_extensions_ == extensions) {
|
||||
return true;
|
||||
}
|
||||
@ -1901,7 +1915,7 @@ bool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions(
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
|
||||
const std::vector<RtpHeaderExtension>& extensions) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (send_extensions_ == extensions) {
|
||||
return true;
|
||||
}
|
||||
@ -1952,7 +1966,7 @@ bool WebRtcVoiceMediaChannel::ResumePlayout() {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (playout_ == playout) {
|
||||
return true;
|
||||
}
|
||||
@ -2033,7 +2047,7 @@ bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
|
||||
bool enable,
|
||||
const AudioOptions* options,
|
||||
AudioRenderer* renderer) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
// TODO(solenberg): The state change should be fully rolled back if any one of
|
||||
// these calls fail.
|
||||
if (!SetLocalRenderer(ssrc, renderer)) {
|
||||
@ -2074,7 +2088,7 @@ bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
|
||||
|
||||
uint32_t ssrc = sp.first_ssrc();
|
||||
@ -2148,7 +2162,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
auto it = send_streams_.find(ssrc);
|
||||
if (it == send_streams_.end()) {
|
||||
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
|
||||
@ -2177,7 +2191,7 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
|
||||
|
||||
if (!ValidateStreamParams(sp)) {
|
||||
@ -2224,7 +2238,7 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
|
||||
int send_channel = GetSendChannelId(receiver_reports_ssrc_);
|
||||
if (send_channel != -1) {
|
||||
@ -2279,7 +2293,7 @@ bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
|
||||
|
||||
auto it = receive_channels_.find(ssrc);
|
||||
@ -2331,7 +2345,7 @@ bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32_t ssrc,
|
||||
|
||||
bool WebRtcVoiceMediaChannel::GetActiveStreams(
|
||||
AudioInfo::StreamList* actives) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
actives->clear();
|
||||
for (const auto& ch : receive_channels_) {
|
||||
int level = GetOutputLevel(ch.second->channel());
|
||||
@ -2343,7 +2357,7 @@ bool WebRtcVoiceMediaChannel::GetActiveStreams(
|
||||
}
|
||||
|
||||
int WebRtcVoiceMediaChannel::GetOutputLevel() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
int highest = 0;
|
||||
for (const auto& ch : receive_channels_) {
|
||||
highest = std::max(GetOutputLevel(ch.second->channel()), highest);
|
||||
@ -2377,7 +2391,7 @@ void WebRtcVoiceMediaChannel::SetTypingDetectionParameters(int time_window,
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (ssrc == 0) {
|
||||
default_recv_volume_ = volume;
|
||||
if (default_recv_ssrc_ == -1) {
|
||||
@ -2409,7 +2423,7 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
|
||||
int event,
|
||||
int duration,
|
||||
int flags) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
if (!dtmf_allowed_) {
|
||||
return false;
|
||||
}
|
||||
@ -2451,7 +2465,7 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc,
|
||||
|
||||
void WebRtcVoiceMediaChannel::OnPacketReceived(
|
||||
rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
|
||||
uint32_t ssrc = 0;
|
||||
if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
|
||||
@ -2494,7 +2508,7 @@ void WebRtcVoiceMediaChannel::OnPacketReceived(
|
||||
|
||||
void WebRtcVoiceMediaChannel::OnRtcpReceived(
|
||||
rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
|
||||
// Forward packet to Call as well.
|
||||
const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
|
||||
@ -2536,7 +2550,7 @@ void WebRtcVoiceMediaChannel::OnRtcpReceived(
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
int channel = GetSendChannelId(ssrc);
|
||||
if (channel == -1) {
|
||||
LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
|
||||
@ -2623,7 +2637,7 @@ bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(info);
|
||||
|
||||
// Get SSRC and stats for each sender.
|
||||
@ -2646,9 +2660,8 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||
sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
|
||||
sinfo.echo_return_loss = stats.echo_return_loss;
|
||||
sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
|
||||
sinfo.typing_noise_detected = typing_noise_detected_;
|
||||
// TODO(solenberg): Move to AudioSendStream.
|
||||
// sinfo.typing_noise_detected = stats.typing_noise_detected;
|
||||
sinfo.typing_noise_detected =
|
||||
(send_ == SEND_NOTHING ? false : stats.typing_noise_detected);
|
||||
info->senders.push_back(sinfo);
|
||||
}
|
||||
|
||||
@ -2688,17 +2701,6 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebRtcVoiceMediaChannel::OnError(int error) {
|
||||
if (send_ == SEND_NOTHING) {
|
||||
return;
|
||||
}
|
||||
if (error == VE_TYPING_NOISE_WARNING) {
|
||||
typing_noise_detected_ = true;
|
||||
} else if (error == VE_TYPING_NOISE_OFF_WARNING) {
|
||||
typing_noise_detected_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
|
||||
unsigned int ulevel = 0;
|
||||
int ret = engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel);
|
||||
@ -2706,7 +2708,7 @@ int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
|
||||
}
|
||||
|
||||
int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
const auto it = receive_channels_.find(ssrc);
|
||||
if (it != receive_channels_.end()) {
|
||||
return it->second->channel();
|
||||
@ -2715,7 +2717,7 @@ int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
|
||||
}
|
||||
|
||||
int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
const auto it = send_streams_.find(ssrc);
|
||||
if (it != send_streams_.end()) {
|
||||
return it->second->channel();
|
||||
@ -2781,39 +2783,6 @@ bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert VoiceEngine error code into VoiceMediaChannel::Error enum.
|
||||
VoiceMediaChannel::Error
|
||||
WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) {
|
||||
switch (err_code) {
|
||||
case 0:
|
||||
return ERROR_NONE;
|
||||
case VE_CANNOT_START_RECORDING:
|
||||
case VE_MIC_VOL_ERROR:
|
||||
case VE_GET_MIC_VOL_ERROR:
|
||||
case VE_CANNOT_ACCESS_MIC_VOL:
|
||||
return ERROR_REC_DEVICE_OPEN_FAILED;
|
||||
case VE_SATURATION_WARNING:
|
||||
return ERROR_REC_DEVICE_SATURATION;
|
||||
case VE_REC_DEVICE_REMOVED:
|
||||
return ERROR_REC_DEVICE_REMOVED;
|
||||
case VE_RUNTIME_REC_WARNING:
|
||||
case VE_RUNTIME_REC_ERROR:
|
||||
return ERROR_REC_RUNTIME_ERROR;
|
||||
case VE_CANNOT_START_PLAYOUT:
|
||||
case VE_SPEAKER_VOL_ERROR:
|
||||
case VE_GET_SPEAKER_VOL_ERROR:
|
||||
case VE_CANNOT_ACCESS_SPEAKER_VOL:
|
||||
return ERROR_PLAY_DEVICE_OPEN_FAILED;
|
||||
case VE_RUNTIME_PLAY_WARNING:
|
||||
case VE_RUNTIME_PLAY_ERROR:
|
||||
return ERROR_PLAY_RUNTIME_ERROR;
|
||||
case VE_TYPING_NOISE_WARNING:
|
||||
return ERROR_REC_TYPING_NOISE_DETECTED;
|
||||
default:
|
||||
return VoiceMediaChannel::ERROR_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
|
||||
int channel_id, const RtpHeaderExtension* extension) {
|
||||
bool enable = false;
|
||||
@ -2832,7 +2801,7 @@ bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
|
||||
}
|
||||
|
||||
void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
for (const auto& it : receive_channels_) {
|
||||
RemoveAudioReceiveStream(it.first);
|
||||
}
|
||||
@ -2842,7 +2811,7 @@ void WebRtcVoiceMediaChannel::RecreateAudioReceiveStreams() {
|
||||
}
|
||||
|
||||
void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
WebRtcAudioReceiveStream* stream = receive_channels_[ssrc];
|
||||
RTC_DCHECK(stream != nullptr);
|
||||
RTC_DCHECK(receive_streams_.find(ssrc) == receive_streams_.end());
|
||||
@ -2859,7 +2828,7 @@ void WebRtcVoiceMediaChannel::AddAudioReceiveStream(uint32_t ssrc) {
|
||||
}
|
||||
|
||||
void WebRtcVoiceMediaChannel::RemoveAudioReceiveStream(uint32_t ssrc) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
auto stream_it = receive_streams_.find(ssrc);
|
||||
if (stream_it != receive_streams_.end()) {
|
||||
call_->DestroyAudioReceiveStream(stream_it->second);
|
||||
@ -2869,7 +2838,7 @@ void WebRtcVoiceMediaChannel::RemoveAudioReceiveStream(uint32_t ssrc) {
|
||||
|
||||
bool WebRtcVoiceMediaChannel::SetRecvCodecsInternal(
|
||||
const std::vector<AudioCodec>& new_codecs) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
for (const AudioCodec& codec : new_codecs) {
|
||||
webrtc::CodecInst voe_codec;
|
||||
if (engine()->FindWebRtcCodec(codec, &voe_codec)) {
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include "talk/media/webrtc/webrtccommon.h"
|
||||
#include "talk/media/webrtc/webrtcvoe.h"
|
||||
#include "talk/session/media/channel.h"
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/base/buffer.h"
|
||||
#include "webrtc/base/byteorder.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
@ -57,9 +58,7 @@ class WebRtcVoiceMediaChannel;
|
||||
|
||||
// WebRtcVoiceEngine is a class to be used with CompositeMediaEngine.
|
||||
// It uses the WebRtc VoiceEngine library for audio handling.
|
||||
class WebRtcVoiceEngine
|
||||
: public webrtc::VoiceEngineObserver,
|
||||
public webrtc::TraceCallback {
|
||||
class WebRtcVoiceEngine final : public webrtc::TraceCallback {
|
||||
friend class WebRtcVoiceMediaChannel;
|
||||
|
||||
public:
|
||||
@ -70,7 +69,7 @@ class WebRtcVoiceEngine
|
||||
bool Init(rtc::Thread* worker_thread);
|
||||
void Terminate();
|
||||
|
||||
webrtc::VoiceEngine* GetVoE() { return voe()->engine(); }
|
||||
rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const;
|
||||
VoiceMediaChannel* CreateChannel(webrtc::Call* call,
|
||||
const AudioOptions& options);
|
||||
|
||||
@ -133,9 +132,6 @@ class WebRtcVoiceEngine
|
||||
// webrtc::TraceCallback:
|
||||
void Print(webrtc::TraceLevel level, const char* trace, int length) override;
|
||||
|
||||
// webrtc::VoiceEngineObserver:
|
||||
void CallbackOnError(int channel_id, int errCode) override;
|
||||
|
||||
// Given the device type, name, and id, find device id. Return true and
|
||||
// set the output parameter rtc_id if successful.
|
||||
bool FindWebRtcAudioDeviceId(
|
||||
@ -146,25 +142,26 @@ class WebRtcVoiceEngine
|
||||
|
||||
static const int kDefaultLogSeverity = rtc::LS_WARNING;
|
||||
|
||||
rtc::ThreadChecker signal_thread_checker_;
|
||||
rtc::ThreadChecker worker_thread_checker_;
|
||||
|
||||
// The primary instance of WebRtc VoiceEngine.
|
||||
rtc::scoped_ptr<VoEWrapper> voe_wrapper_;
|
||||
rtc::scoped_ptr<VoETraceWrapper> tracing_;
|
||||
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
|
||||
// The external audio device manager
|
||||
webrtc::AudioDeviceModule* adm_;
|
||||
webrtc::AudioDeviceModule* adm_ = nullptr;
|
||||
int log_filter_;
|
||||
std::string log_options_;
|
||||
bool is_dumping_aec_;
|
||||
bool is_dumping_aec_ = false;
|
||||
std::vector<AudioCodec> codecs_;
|
||||
std::vector<RtpHeaderExtension> rtp_header_extensions_;
|
||||
std::vector<WebRtcVoiceMediaChannel*> channels_;
|
||||
// channels_ can be read from WebRtc callback thread. We need a lock on that
|
||||
// callback as well as the RegisterChannel/UnregisterChannel.
|
||||
rtc::CriticalSection channels_cs_;
|
||||
webrtc::AgcConfig default_agc_config_;
|
||||
|
||||
webrtc::Config voe_config_;
|
||||
|
||||
bool initialized_;
|
||||
bool initialized_ = false;
|
||||
AudioOptions options_;
|
||||
|
||||
// Cache received extended_filter_aec, delay_agnostic_aec and experimental_ns
|
||||
@ -180,8 +177,8 @@ class WebRtcVoiceEngine
|
||||
|
||||
// WebRtcVoiceMediaChannel is an implementation of VoiceMediaChannel that uses
|
||||
// WebRtc Voice Engine.
|
||||
class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
|
||||
public webrtc::Transport {
|
||||
class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
|
||||
public webrtc::Transport {
|
||||
public:
|
||||
WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
|
||||
const AudioOptions& options,
|
||||
@ -243,8 +240,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
|
||||
return VoiceMediaChannel::SendRtcp(&packet, rtc::PacketOptions());
|
||||
}
|
||||
|
||||
void OnError(int error);
|
||||
|
||||
int GetReceiveChannelId(uint32_t ssrc) const;
|
||||
int GetSendChannelId(uint32_t ssrc) const;
|
||||
|
||||
@ -267,7 +262,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
|
||||
const std::vector<AudioCodec>& all_codecs,
|
||||
webrtc::CodecInst* send_codec);
|
||||
bool SetPlayout(int channel, bool playout);
|
||||
static Error WebRtcErrorToChannelError(int err_code);
|
||||
|
||||
typedef int (webrtc::VoERTP_RTCP::* ExtensionSetterFunction)(int, bool,
|
||||
unsigned char);
|
||||
@ -300,23 +294,22 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
|
||||
int channel_id,
|
||||
const std::vector<RtpHeaderExtension>& extensions);
|
||||
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
rtc::ThreadChecker worker_thread_checker_;
|
||||
|
||||
WebRtcVoiceEngine* const engine_;
|
||||
WebRtcVoiceEngine* const engine_ = nullptr;
|
||||
std::vector<AudioCodec> recv_codecs_;
|
||||
std::vector<AudioCodec> send_codecs_;
|
||||
rtc::scoped_ptr<webrtc::CodecInst> send_codec_;
|
||||
bool send_bitrate_setting_;
|
||||
int send_bitrate_bps_;
|
||||
bool send_bitrate_setting_ = false;
|
||||
int send_bitrate_bps_ = 0;
|
||||
AudioOptions options_;
|
||||
bool dtmf_allowed_;
|
||||
bool desired_playout_;
|
||||
bool nack_enabled_;
|
||||
bool playout_;
|
||||
bool typing_noise_detected_;
|
||||
SendFlags desired_send_;
|
||||
SendFlags send_;
|
||||
webrtc::Call* const call_;
|
||||
bool dtmf_allowed_ = false;
|
||||
bool desired_playout_ = false;
|
||||
bool nack_enabled_ = false;
|
||||
bool playout_ = false;
|
||||
SendFlags desired_send_ = SEND_NOTHING;
|
||||
SendFlags send_ = SEND_NOTHING;
|
||||
webrtc::Call* const call_ = nullptr;
|
||||
|
||||
// SSRC of unsignalled receive stream, or -1 if there isn't one.
|
||||
int64_t default_recv_ssrc_ = -1;
|
||||
@ -342,7 +335,6 @@ class WebRtcVoiceMediaChannel : public VoiceMediaChannel,
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel);
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // TALK_MEDIA_WEBRTCVOICEENGINE_H_
|
||||
|
||||
@ -313,7 +313,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
s->SetStats(GetAudioSendStreamStats());
|
||||
}
|
||||
}
|
||||
void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info) {
|
||||
void VerifyVoiceSenderInfo(const cricket::VoiceSenderInfo& info,
|
||||
bool is_sending) {
|
||||
const auto stats = GetAudioSendStreamStats();
|
||||
EXPECT_EQ(info.ssrc(), stats.local_ssrc);
|
||||
EXPECT_EQ(info.bytes_sent, stats.bytes_sent);
|
||||
@ -331,8 +332,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
|
||||
EXPECT_EQ(info.echo_return_loss, stats.echo_return_loss);
|
||||
EXPECT_EQ(info.echo_return_loss_enhancement,
|
||||
stats.echo_return_loss_enhancement);
|
||||
// TODO(solenberg): Move typing noise detection into AudioSendStream.
|
||||
// EXPECT_EQ(info.typing_noise_detected, stats.typing_noise_detected);
|
||||
EXPECT_EQ(info.typing_noise_detected,
|
||||
stats.typing_noise_detected && is_sending);
|
||||
}
|
||||
|
||||
webrtc::AudioReceiveStream::Stats GetAudioReceiveStreamStats() const {
|
||||
@ -2089,7 +2090,7 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
|
||||
// We have added 4 send streams. We should see empty stats for all.
|
||||
EXPECT_EQ(static_cast<size_t>(ARRAY_SIZE(kSsrcs4)), info.senders.size());
|
||||
for (const auto& sender : info.senders) {
|
||||
VerifyVoiceSenderInfo(sender);
|
||||
VerifyVoiceSenderInfo(sender, false);
|
||||
}
|
||||
|
||||
// We have added one receive stream. We should see empty stats.
|
||||
@ -2359,12 +2360,20 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
|
||||
|
||||
// We have added one send stream. We should see the stats we've set.
|
||||
EXPECT_EQ(1u, info.senders.size());
|
||||
VerifyVoiceSenderInfo(info.senders[0]);
|
||||
VerifyVoiceSenderInfo(info.senders[0], false);
|
||||
// We have added one receive stream. We should see empty stats.
|
||||
EXPECT_EQ(info.receivers.size(), 1u);
|
||||
EXPECT_EQ(info.receivers[0].ssrc(), 0);
|
||||
}
|
||||
|
||||
// Start sending - this affects some reported stats.
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
EXPECT_TRUE(channel_->SetSend(cricket::SEND_MICROPHONE));
|
||||
EXPECT_EQ(true, channel_->GetStats(&info));
|
||||
VerifyVoiceSenderInfo(info.senders[0], true);
|
||||
}
|
||||
|
||||
// Remove the kSsrc2 stream. No receiver stats.
|
||||
{
|
||||
cricket::VoiceMediaInfo info;
|
||||
|
||||
@ -14,6 +14,8 @@ source_set("audio") {
|
||||
"audio_receive_stream.h",
|
||||
"audio_send_stream.cc",
|
||||
"audio_send_stream.h",
|
||||
"audio_state.cc",
|
||||
"audio_state.h",
|
||||
"conversion.h",
|
||||
"scoped_voe_interface.h",
|
||||
]
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/audio/audio_state.h"
|
||||
#include "webrtc/audio/conversion.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
@ -60,19 +61,18 @@ std::string AudioReceiveStream::Config::ToString() const {
|
||||
|
||||
namespace internal {
|
||||
AudioReceiveStream::AudioReceiveStream(
|
||||
RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
const webrtc::AudioReceiveStream::Config& config,
|
||||
VoiceEngine* voice_engine)
|
||||
RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
const webrtc::AudioReceiveStream::Config& config,
|
||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
|
||||
: remote_bitrate_estimator_(remote_bitrate_estimator),
|
||||
config_(config),
|
||||
voice_engine_(voice_engine),
|
||||
voe_base_(voice_engine),
|
||||
audio_state_(audio_state),
|
||||
rtp_header_parser_(RtpHeaderParser::Create()) {
|
||||
LOG(LS_INFO) << "AudioReceiveStream: " << config_.ToString();
|
||||
RTC_DCHECK(config.voe_channel_id != -1);
|
||||
RTC_DCHECK(remote_bitrate_estimator_ != nullptr);
|
||||
RTC_DCHECK(voice_engine_ != nullptr);
|
||||
RTC_DCHECK(rtp_header_parser_ != nullptr);
|
||||
RTC_DCHECK_NE(config_.voe_channel_id, -1);
|
||||
RTC_DCHECK(remote_bitrate_estimator_);
|
||||
RTC_DCHECK(audio_state_.get());
|
||||
RTC_DCHECK(rtp_header_parser_);
|
||||
for (const auto& ext : config.rtp.extensions) {
|
||||
// One-byte-extension local identifiers are in the range 1-14 inclusive.
|
||||
RTC_DCHECK_GE(ext.id, 1);
|
||||
@ -101,11 +101,14 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
webrtc::AudioReceiveStream::Stats stats;
|
||||
stats.remote_ssrc = config_.rtp.remote_ssrc;
|
||||
ScopedVoEInterface<VoECodec> codec(voice_engine_);
|
||||
ScopedVoEInterface<VoENetEqStats> neteq(voice_engine_);
|
||||
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine_);
|
||||
ScopedVoEInterface<VoEVideoSync> sync(voice_engine_);
|
||||
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_);
|
||||
internal::AudioState* audio_state =
|
||||
static_cast<internal::AudioState*>(audio_state_.get());
|
||||
VoiceEngine* voice_engine = audio_state->voice_engine();
|
||||
ScopedVoEInterface<VoECodec> codec(voice_engine);
|
||||
ScopedVoEInterface<VoENetEqStats> neteq(voice_engine);
|
||||
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine);
|
||||
ScopedVoEInterface<VoEVideoSync> sync(voice_engine);
|
||||
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine);
|
||||
unsigned int ssrc = 0;
|
||||
webrtc::CallStatistics call_stats = {0};
|
||||
webrtc::CodecInst codec_inst = {0};
|
||||
@ -132,13 +135,12 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
||||
int playout_buffer_delay_ms = 0;
|
||||
sync->GetDelayEstimate(config_.voe_channel_id, &jitter_buffer_delay_ms,
|
||||
&playout_buffer_delay_ms);
|
||||
stats.delay_estimate_ms =
|
||||
jitter_buffer_delay_ms + playout_buffer_delay_ms;
|
||||
stats.delay_estimate_ms = jitter_buffer_delay_ms + playout_buffer_delay_ms;
|
||||
}
|
||||
{
|
||||
unsigned int level = 0;
|
||||
if (volume->GetSpeechOutputLevelFullRange(config_.voe_channel_id, level)
|
||||
!= -1) {
|
||||
if (volume->GetSpeechOutputLevelFullRange(config_.voe_channel_id, level) !=
|
||||
-1) {
|
||||
stats.audio_level = static_cast<int32_t>(level);
|
||||
}
|
||||
}
|
||||
@ -157,8 +159,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats() const {
|
||||
|
||||
webrtc::AudioDecodingCallStats ds;
|
||||
if (neteq->GetDecodingCallStatistics(config_.voe_channel_id, &ds) != -1) {
|
||||
stats.decoding_calls_to_silence_generator =
|
||||
ds.calls_to_silence_generator;
|
||||
stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
|
||||
stats.decoding_calls_to_neteq = ds.calls_to_neteq;
|
||||
stats.decoding_normal = ds.decoded_normal;
|
||||
stats.decoding_plc = ds.decoded_plc;
|
||||
|
||||
@ -12,15 +12,13 @@
|
||||
#define WEBRTC_AUDIO_AUDIO_RECEIVE_STREAM_H_
|
||||
|
||||
#include "webrtc/audio_receive_stream.h"
|
||||
#include "webrtc/audio/scoped_voe_interface.h"
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RemoteBitrateEstimator;
|
||||
class VoiceEngine;
|
||||
|
||||
namespace internal {
|
||||
|
||||
@ -28,7 +26,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream {
|
||||
public:
|
||||
AudioReceiveStream(RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
const webrtc::AudioReceiveStream::Config& config,
|
||||
VoiceEngine* voice_engine);
|
||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state);
|
||||
~AudioReceiveStream() override;
|
||||
|
||||
// webrtc::ReceiveStream implementation.
|
||||
@ -49,9 +47,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream {
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
RemoteBitrateEstimator* const remote_bitrate_estimator_;
|
||||
const webrtc::AudioReceiveStream::Config config_;
|
||||
VoiceEngine* voice_engine_;
|
||||
// We hold one interface pointer to the VoE to make sure it is kept alive.
|
||||
ScopedVoEInterface<VoEBase> voe_base_;
|
||||
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
|
||||
rtc::scoped_ptr<RtpHeaderParser> rtp_header_parser_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioReceiveStream);
|
||||
|
||||
@ -20,10 +20,84 @@ namespace webrtc {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
AudioDecodingCallStats MakeAudioDecodeStatsForTest() {
|
||||
AudioDecodingCallStats audio_decode_stats;
|
||||
audio_decode_stats.calls_to_silence_generator = 234;
|
||||
audio_decode_stats.calls_to_neteq = 567;
|
||||
audio_decode_stats.decoded_normal = 890;
|
||||
audio_decode_stats.decoded_plc = 123;
|
||||
audio_decode_stats.decoded_cng = 456;
|
||||
audio_decode_stats.decoded_plc_cng = 789;
|
||||
return audio_decode_stats;
|
||||
}
|
||||
|
||||
const int kChannelId = 2;
|
||||
const uint32_t kRemoteSsrc = 1234;
|
||||
const uint32_t kLocalSsrc = 5678;
|
||||
const size_t kAbsoluteSendTimeLength = 4;
|
||||
const int kAbsSendTimeId = 3;
|
||||
const int kJitterBufferDelay = -7;
|
||||
const int kPlayoutBufferDelay = 302;
|
||||
const unsigned int kSpeechOutputLevel = 99;
|
||||
const CallStatistics kCallStats = {
|
||||
345, 678, 901, 234, -12, 3456, 7890, 567, 890, 123};
|
||||
const CodecInst kCodecInst = {
|
||||
123, "codec_name_recv", 96000, -187, -198, -103};
|
||||
const NetworkStatistics kNetworkStats = {
|
||||
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0};
|
||||
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
|
||||
|
||||
struct ConfigHelper {
|
||||
ConfigHelper() {
|
||||
EXPECT_CALL(voice_engine_,
|
||||
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(voice_engine_,
|
||||
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
|
||||
AudioState::Config config;
|
||||
config.voice_engine = &voice_engine_;
|
||||
audio_state_ = AudioState::Create(config);
|
||||
stream_config_.voe_channel_id = kChannelId;
|
||||
stream_config_.rtp.local_ssrc = kLocalSsrc;
|
||||
stream_config_.rtp.remote_ssrc = kRemoteSsrc;
|
||||
}
|
||||
|
||||
MockRemoteBitrateEstimator* remote_bitrate_estimator() {
|
||||
return &remote_bitrate_estimator_;
|
||||
}
|
||||
AudioReceiveStream::Config& config() { return stream_config_; }
|
||||
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
|
||||
MockVoiceEngine& voice_engine() { return voice_engine_; }
|
||||
|
||||
void SetupMockForGetStats() {
|
||||
using testing::_;
|
||||
using testing::DoAll;
|
||||
using testing::Return;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgReferee;
|
||||
EXPECT_CALL(voice_engine_, GetRemoteSSRC(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(0), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetRTCPStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetRecCodec(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetDelayEstimate(kChannelId, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kJitterBufferDelay),
|
||||
SetArgPointee<2>(kPlayoutBufferDelay), Return(0)));
|
||||
EXPECT_CALL(voice_engine_,
|
||||
GetSpeechOutputLevelFullRange(kChannelId, _)).WillOnce(
|
||||
DoAll(SetArgReferee<1>(kSpeechOutputLevel), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetNetworkStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kNetworkStats), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetDecodingCallStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kAudioDecodeStats), Return(0)));
|
||||
}
|
||||
|
||||
private:
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator_;
|
||||
MockVoiceEngine voice_engine_;
|
||||
rtc::scoped_refptr<AudioState> audio_state_;
|
||||
AudioReceiveStream::Config stream_config_;
|
||||
};
|
||||
|
||||
void BuildAbsoluteSendTimeExtension(uint8_t* buffer,
|
||||
int id,
|
||||
@ -62,7 +136,6 @@ size_t CreateRtpHeaderWithAbsSendTime(uint8_t* header,
|
||||
} // namespace
|
||||
|
||||
TEST(AudioReceiveStreamTest, ConfigToString) {
|
||||
const int kAbsSendTimeId = 3;
|
||||
AudioReceiveStream::Config config;
|
||||
config.rtp.remote_ssrc = kRemoteSsrc;
|
||||
config.rtp.local_ssrc = kLocalSsrc;
|
||||
@ -79,31 +152,24 @@ TEST(AudioReceiveStreamTest, ConfigToString) {
|
||||
}
|
||||
|
||||
TEST(AudioReceiveStreamTest, ConstructDestruct) {
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator;
|
||||
MockVoiceEngine voice_engine;
|
||||
AudioReceiveStream::Config config;
|
||||
config.voe_channel_id = kChannelId;
|
||||
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
|
||||
&voice_engine);
|
||||
ConfigHelper helper;
|
||||
internal::AudioReceiveStream recv_stream(
|
||||
helper.remote_bitrate_estimator(), helper.config(), helper.audio_state());
|
||||
}
|
||||
|
||||
TEST(AudioReceiveStreamTest, AudioPacketUpdatesBweWithTimestamp) {
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator;
|
||||
MockVoiceEngine voice_engine;
|
||||
AudioReceiveStream::Config config;
|
||||
config.combined_audio_video_bwe = true;
|
||||
config.voe_channel_id = kChannelId;
|
||||
const int kAbsSendTimeId = 3;
|
||||
config.rtp.extensions.push_back(
|
||||
ConfigHelper helper;
|
||||
helper.config().combined_audio_video_bwe = true;
|
||||
helper.config().rtp.extensions.push_back(
|
||||
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
|
||||
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
|
||||
&voice_engine);
|
||||
internal::AudioReceiveStream recv_stream(
|
||||
helper.remote_bitrate_estimator(), helper.config(), helper.audio_state());
|
||||
uint8_t rtp_packet[30];
|
||||
const int kAbsSendTimeValue = 1234;
|
||||
CreateRtpHeaderWithAbsSendTime(rtp_packet, kAbsSendTimeId, kAbsSendTimeValue);
|
||||
PacketTime packet_time(5678000, 0);
|
||||
const size_t kExpectedHeaderLength = 20;
|
||||
EXPECT_CALL(remote_bitrate_estimator,
|
||||
EXPECT_CALL(*helper.remote_bitrate_estimator(),
|
||||
IncomingPacket(packet_time.timestamp / 1000,
|
||||
sizeof(rtp_packet) - kExpectedHeaderLength,
|
||||
testing::_, false))
|
||||
@ -113,57 +179,10 @@ TEST(AudioReceiveStreamTest, AudioPacketUpdatesBweWithTimestamp) {
|
||||
}
|
||||
|
||||
TEST(AudioReceiveStreamTest, GetStats) {
|
||||
const int kJitterBufferDelay = -7;
|
||||
const int kPlayoutBufferDelay = 302;
|
||||
const unsigned int kSpeechOutputLevel = 99;
|
||||
const CallStatistics kCallStats = {345, 678, 901, 234, -12,
|
||||
3456, 7890, 567, 890, 123};
|
||||
|
||||
const CodecInst kCodecInst = {123, "codec_name_recv", 96000, -187, -198,
|
||||
-103};
|
||||
|
||||
const NetworkStatistics kNetworkStats = {
|
||||
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0};
|
||||
|
||||
webrtc::AudioDecodingCallStats audio_decode_stats;
|
||||
{
|
||||
audio_decode_stats.calls_to_silence_generator = 234;
|
||||
audio_decode_stats.calls_to_neteq = 567;
|
||||
audio_decode_stats.decoded_normal = 890;
|
||||
audio_decode_stats.decoded_plc = 123;
|
||||
audio_decode_stats.decoded_cng = 456;
|
||||
audio_decode_stats.decoded_plc_cng = 789;
|
||||
}
|
||||
|
||||
MockRemoteBitrateEstimator remote_bitrate_estimator;
|
||||
MockVoiceEngine voice_engine;
|
||||
AudioReceiveStream::Config config;
|
||||
config.rtp.remote_ssrc = kRemoteSsrc;
|
||||
config.voe_channel_id = kChannelId;
|
||||
internal::AudioReceiveStream recv_stream(&remote_bitrate_estimator, config,
|
||||
&voice_engine);
|
||||
|
||||
using testing::_;
|
||||
using testing::DoAll;
|
||||
using testing::Return;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgReferee;
|
||||
EXPECT_CALL(voice_engine, GetRemoteSSRC(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(0), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetRTCPStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetRecCodec(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetDelayEstimate(kChannelId, _, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kJitterBufferDelay),
|
||||
SetArgPointee<2>(kPlayoutBufferDelay), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetSpeechOutputLevelFullRange(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kSpeechOutputLevel), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetNetworkStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kNetworkStats), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetDecodingCallStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(audio_decode_stats), Return(0)));
|
||||
|
||||
ConfigHelper helper;
|
||||
internal::AudioReceiveStream recv_stream(
|
||||
helper.remote_bitrate_estimator(), helper.config(), helper.audio_state());
|
||||
helper.SetupMockForGetStats();
|
||||
AudioReceiveStream::Stats stats = recv_stream.GetStats();
|
||||
EXPECT_EQ(kRemoteSsrc, stats.remote_ssrc);
|
||||
EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesReceived), stats.bytes_rcvd);
|
||||
@ -190,13 +209,13 @@ TEST(AudioReceiveStreamTest, GetStats) {
|
||||
stats.accelerate_rate);
|
||||
EXPECT_EQ(Q14ToFloat(kNetworkStats.currentPreemptiveRate),
|
||||
stats.preemptive_expand_rate);
|
||||
EXPECT_EQ(audio_decode_stats.calls_to_silence_generator,
|
||||
EXPECT_EQ(kAudioDecodeStats.calls_to_silence_generator,
|
||||
stats.decoding_calls_to_silence_generator);
|
||||
EXPECT_EQ(audio_decode_stats.calls_to_neteq, stats.decoding_calls_to_neteq);
|
||||
EXPECT_EQ(audio_decode_stats.decoded_normal, stats.decoding_normal);
|
||||
EXPECT_EQ(audio_decode_stats.decoded_plc, stats.decoding_plc);
|
||||
EXPECT_EQ(audio_decode_stats.decoded_cng, stats.decoding_cng);
|
||||
EXPECT_EQ(audio_decode_stats.decoded_plc_cng, stats.decoding_plc_cng);
|
||||
EXPECT_EQ(kAudioDecodeStats.calls_to_neteq, stats.decoding_calls_to_neteq);
|
||||
EXPECT_EQ(kAudioDecodeStats.decoded_normal, stats.decoding_normal);
|
||||
EXPECT_EQ(kAudioDecodeStats.decoded_plc, stats.decoding_plc);
|
||||
EXPECT_EQ(kAudioDecodeStats.decoded_cng, stats.decoding_cng);
|
||||
EXPECT_EQ(kAudioDecodeStats.decoded_plc_cng, stats.decoding_plc_cng);
|
||||
EXPECT_EQ(kCallStats.capture_start_ntp_time_ms_,
|
||||
stats.capture_start_ntp_time_ms);
|
||||
}
|
||||
|
||||
@ -12,7 +12,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/audio/audio_state.h"
|
||||
#include "webrtc/audio/conversion.h"
|
||||
#include "webrtc/audio/scoped_voe_interface.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
||||
@ -48,14 +50,14 @@ std::string AudioSendStream::Config::ToString() const {
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
AudioSendStream::AudioSendStream(const webrtc::AudioSendStream::Config& config,
|
||||
VoiceEngine* voice_engine)
|
||||
: config_(config),
|
||||
voice_engine_(voice_engine),
|
||||
voe_base_(voice_engine) {
|
||||
|
||||
AudioSendStream::AudioSendStream(
|
||||
const webrtc::AudioSendStream::Config& config,
|
||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state)
|
||||
: config_(config), audio_state_(audio_state) {
|
||||
LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
|
||||
RTC_DCHECK_NE(config.voe_channel_id, -1);
|
||||
RTC_DCHECK(voice_engine_);
|
||||
RTC_DCHECK_NE(config_.voe_channel_id, -1);
|
||||
RTC_DCHECK(audio_state_.get());
|
||||
}
|
||||
|
||||
AudioSendStream::~AudioSendStream() {
|
||||
@ -67,10 +69,13 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
webrtc::AudioSendStream::Stats stats;
|
||||
stats.local_ssrc = config_.rtp.ssrc;
|
||||
ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine_);
|
||||
ScopedVoEInterface<VoECodec> codec(voice_engine_);
|
||||
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine_);
|
||||
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine_);
|
||||
internal::AudioState* audio_state =
|
||||
static_cast<internal::AudioState*>(audio_state_.get());
|
||||
VoiceEngine* voice_engine = audio_state->voice_engine();
|
||||
ScopedVoEInterface<VoEAudioProcessing> processing(voice_engine);
|
||||
ScopedVoEInterface<VoECodec> codec(voice_engine);
|
||||
ScopedVoEInterface<VoERTP_RTCP> rtp(voice_engine);
|
||||
ScopedVoEInterface<VoEVolumeControl> volume(voice_engine);
|
||||
unsigned int ssrc = 0;
|
||||
webrtc::CallStatistics call_stats = {0};
|
||||
if (rtp->GetLocalSSRC(config_.voe_channel_id, ssrc) == -1 ||
|
||||
@ -148,8 +153,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(solenberg): Collect typing noise warnings here too!
|
||||
// bool typing_noise_detected = typing_noise_detected_;
|
||||
stats.typing_noise_detected = audio_state->typing_noise_detected();
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
@ -12,20 +12,16 @@
|
||||
#define WEBRTC_AUDIO_AUDIO_SEND_STREAM_H_
|
||||
|
||||
#include "webrtc/audio_send_stream.h"
|
||||
#include "webrtc/audio/scoped_voe_interface.h"
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VoiceEngine;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class AudioSendStream final : public webrtc::AudioSendStream {
|
||||
public:
|
||||
AudioSendStream(const webrtc::AudioSendStream::Config& config,
|
||||
VoiceEngine* voice_engine);
|
||||
const rtc::scoped_refptr<webrtc::AudioState>& audio_state);
|
||||
~AudioSendStream() override;
|
||||
|
||||
// webrtc::SendStream implementation.
|
||||
@ -42,9 +38,7 @@ class AudioSendStream final : public webrtc::AudioSendStream {
|
||||
private:
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
const webrtc::AudioSendStream::Config config_;
|
||||
VoiceEngine* voice_engine_;
|
||||
// We hold one interface pointer to the VoE to make sure it is kept alive.
|
||||
ScopedVoEInterface<VoEBase> voe_base_;
|
||||
rtc::scoped_refptr<webrtc::AudioState> audio_state_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
|
||||
};
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/audio/audio_send_stream.h"
|
||||
#include "webrtc/audio/audio_state.h"
|
||||
#include "webrtc/audio/conversion.h"
|
||||
#include "webrtc/test/mock_voice_engine.h"
|
||||
|
||||
@ -20,6 +21,72 @@ namespace {
|
||||
|
||||
const int kChannelId = 1;
|
||||
const uint32_t kSsrc = 1234;
|
||||
const int kEchoDelayMedian = 254;
|
||||
const int kEchoDelayStdDev = -3;
|
||||
const int kEchoReturnLoss = -65;
|
||||
const int kEchoReturnLossEnhancement = 101;
|
||||
const unsigned int kSpeechInputLevel = 96;
|
||||
const CallStatistics kCallStats = {
|
||||
1345, 1678, 1901, 1234, 112, 13456, 17890, 1567, -1890, -1123};
|
||||
const CodecInst kCodecInst = {-121, "codec_name_send", 48000, -231, -451, -671};
|
||||
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
|
||||
|
||||
struct ConfigHelper {
|
||||
ConfigHelper() : stream_config_(nullptr) {
|
||||
EXPECT_CALL(voice_engine_,
|
||||
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(voice_engine_,
|
||||
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
|
||||
AudioState::Config config;
|
||||
config.voice_engine = &voice_engine_;
|
||||
audio_state_ = AudioState::Create(config);
|
||||
stream_config_.voe_channel_id = kChannelId;
|
||||
stream_config_.rtp.ssrc = kSsrc;
|
||||
}
|
||||
|
||||
AudioSendStream::Config& config() { return stream_config_; }
|
||||
rtc::scoped_refptr<AudioState> audio_state() { return audio_state_; }
|
||||
|
||||
void SetupMockForGetStats() {
|
||||
std::vector<ReportBlock> report_blocks;
|
||||
webrtc::ReportBlock block = kReportBlock;
|
||||
report_blocks.push_back(block); // Has wrong SSRC.
|
||||
block.source_SSRC = kSsrc;
|
||||
report_blocks.push_back(block); // Correct block.
|
||||
block.fraction_lost = 0;
|
||||
report_blocks.push_back(block); // Duplicate SSRC, bad fraction_lost.
|
||||
|
||||
using testing::_;
|
||||
using testing::DoAll;
|
||||
using testing::Return;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgReferee;
|
||||
EXPECT_CALL(voice_engine_, GetLocalSSRC(kChannelId, _))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<1>(0), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetRTCPStatistics(kChannelId, _))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetSendCodec(kChannelId, _))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetRemoteRTCPReportBlocks(kChannelId, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<1>(report_blocks), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetSpeechInputLevelFullRange(_))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<0>(kSpeechInputLevel), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetEcMetricsStatus(_))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<0>(true), Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetEchoMetrics(_, _, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<0>(kEchoReturnLoss),
|
||||
SetArgReferee<1>(kEchoReturnLossEnhancement),
|
||||
Return(0)));
|
||||
EXPECT_CALL(voice_engine_, GetEcDelayMetrics(_, _, _))
|
||||
.WillRepeatedly(DoAll(SetArgReferee<0>(kEchoDelayMedian),
|
||||
SetArgReferee<1>(kEchoDelayStdDev), Return(0)));
|
||||
}
|
||||
|
||||
private:
|
||||
MockVoiceEngine voice_engine_;
|
||||
rtc::scoped_refptr<AudioState> audio_state_;
|
||||
AudioSendStream::Config stream_config_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(AudioSendStreamTest, ConfigToString) {
|
||||
@ -39,67 +106,14 @@ TEST(AudioSendStreamTest, ConfigToString) {
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, ConstructDestruct) {
|
||||
MockVoiceEngine voice_engine;
|
||||
AudioSendStream::Config config(nullptr);
|
||||
config.voe_channel_id = kChannelId;
|
||||
internal::AudioSendStream send_stream(config, &voice_engine);
|
||||
ConfigHelper helper;
|
||||
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, GetStats) {
|
||||
const int kEchoDelayMedian = 254;
|
||||
const int kEchoDelayStdDev = -3;
|
||||
const int kEchoReturnLoss = -65;
|
||||
const int kEchoReturnLossEnhancement = 101;
|
||||
const unsigned int kSpeechInputLevel = 96;
|
||||
|
||||
const CallStatistics kCallStats = {1345, 1678, 1901, 1234, 112,
|
||||
13456, 17890, 1567, -1890, -1123};
|
||||
|
||||
const CodecInst kCodecInst = {-121, "codec_name_send", 48000, -231, -451,
|
||||
-671};
|
||||
|
||||
const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
|
||||
|
||||
std::vector<ReportBlock> report_blocks;
|
||||
{
|
||||
webrtc::ReportBlock block = kReportBlock;
|
||||
report_blocks.push_back(block); // Has wrong SSRC.
|
||||
block.source_SSRC = kSsrc;
|
||||
report_blocks.push_back(block); // Correct block.
|
||||
block.fraction_lost = 0;
|
||||
report_blocks.push_back(block); // Duplicate SSRC, bad fraction_lost.
|
||||
}
|
||||
|
||||
MockVoiceEngine voice_engine;
|
||||
AudioSendStream::Config config(nullptr);
|
||||
config.rtp.ssrc = kSsrc;
|
||||
config.voe_channel_id = kChannelId;
|
||||
internal::AudioSendStream send_stream(config, &voice_engine);
|
||||
|
||||
using testing::_;
|
||||
using testing::DoAll;
|
||||
using testing::Return;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgReferee;
|
||||
EXPECT_CALL(voice_engine, GetLocalSSRC(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(0), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetRTCPStatistics(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kCallStats), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetSendCodec(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgReferee<1>(kCodecInst), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetRemoteRTCPReportBlocks(kChannelId, _))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(report_blocks), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetSpeechInputLevelFullRange(_))
|
||||
.WillOnce(DoAll(SetArgReferee<0>(kSpeechInputLevel), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetEcMetricsStatus(_))
|
||||
.WillOnce(DoAll(SetArgReferee<0>(true), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetEchoMetrics(_, _, _, _))
|
||||
.WillOnce(DoAll(SetArgReferee<0>(kEchoReturnLoss),
|
||||
SetArgReferee<1>(kEchoReturnLossEnhancement), Return(0)));
|
||||
EXPECT_CALL(voice_engine, GetEcDelayMetrics(_, _, _))
|
||||
.WillOnce(DoAll(SetArgReferee<0>(kEchoDelayMedian),
|
||||
SetArgReferee<1>(kEchoDelayStdDev), Return(0)));
|
||||
|
||||
ConfigHelper helper;
|
||||
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
|
||||
helper.SetupMockForGetStats();
|
||||
AudioSendStream::Stats stats = send_stream.GetStats();
|
||||
EXPECT_EQ(kSsrc, stats.local_ssrc);
|
||||
EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesSent), stats.bytes_sent);
|
||||
@ -122,5 +136,21 @@ TEST(AudioSendStreamTest, GetStats) {
|
||||
EXPECT_EQ(kEchoReturnLossEnhancement, stats.echo_return_loss_enhancement);
|
||||
EXPECT_FALSE(stats.typing_noise_detected);
|
||||
}
|
||||
|
||||
TEST(AudioSendStreamTest, GetStatsTypingNoiseDetected) {
|
||||
ConfigHelper helper;
|
||||
internal::AudioSendStream send_stream(helper.config(), helper.audio_state());
|
||||
helper.SetupMockForGetStats();
|
||||
EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
|
||||
|
||||
internal::AudioState* internal_audio_state =
|
||||
static_cast<internal::AudioState*>(helper.audio_state().get());
|
||||
VoiceEngineObserver* voe_observer =
|
||||
static_cast<VoiceEngineObserver*>(internal_audio_state);
|
||||
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_WARNING);
|
||||
EXPECT_TRUE(send_stream.GetStats().typing_noise_detected);
|
||||
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_OFF_WARNING);
|
||||
EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
|
||||
}
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
79
webrtc/audio/audio_state.cc
Normal file
79
webrtc/audio/audio_state.cc
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 "webrtc/audio/audio_state.h"
|
||||
|
||||
#include "webrtc/base/atomicops.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/voice_engine/include/voe_errors.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace internal {
|
||||
|
||||
AudioState::AudioState(const AudioState::Config& config)
|
||||
: config_(config), voe_base_(config.voice_engine) {
|
||||
process_thread_checker_.DetachFromThread();
|
||||
// Only one AudioState should be created per VoiceEngine.
|
||||
RTC_CHECK(voe_base_->RegisterVoiceEngineObserver(*this) != -1);
|
||||
}
|
||||
|
||||
AudioState::~AudioState() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
voe_base_->DeRegisterVoiceEngineObserver();
|
||||
}
|
||||
|
||||
VoiceEngine* AudioState::voice_engine() {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return config_.voice_engine;
|
||||
}
|
||||
|
||||
bool AudioState::typing_noise_detected() const {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
return typing_noise_detected_;
|
||||
}
|
||||
|
||||
// Reference count; implementation copied from rtc::RefCountedObject.
|
||||
int AudioState::AddRef() const {
|
||||
return rtc::AtomicOps::Increment(&ref_count_);
|
||||
}
|
||||
|
||||
// Reference count; implementation copied from rtc::RefCountedObject.
|
||||
int AudioState::Release() const {
|
||||
int count = rtc::AtomicOps::Decrement(&ref_count_);
|
||||
if (!count) {
|
||||
delete this;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void AudioState::CallbackOnError(int channel_id, int err_code) {
|
||||
RTC_DCHECK(process_thread_checker_.CalledOnValidThread());
|
||||
|
||||
// All call sites in VoE, as of this writing, specify -1 as channel_id.
|
||||
RTC_DCHECK(channel_id == -1);
|
||||
LOG(LS_INFO) << "VoiceEngine error " << err_code << " reported on channel "
|
||||
<< channel_id << ".";
|
||||
if (err_code == VE_TYPING_NOISE_WARNING) {
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
typing_noise_detected_ = true;
|
||||
} else if (err_code == VE_TYPING_NOISE_OFF_WARNING) {
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
typing_noise_detected_ = false;
|
||||
}
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
rtc::scoped_refptr<AudioState> AudioState::Create(
|
||||
const AudioState::Config& config) {
|
||||
return rtc::scoped_refptr<AudioState>(new internal::AudioState(config));
|
||||
}
|
||||
} // namespace webrtc
|
||||
61
webrtc/audio/audio_state.h
Normal file
61
webrtc/audio/audio_state.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 WEBRTC_AUDIO_AUDIO_STATE_H_
|
||||
#define WEBRTC_AUDIO_AUDIO_STATE_H_
|
||||
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/audio/scoped_voe_interface.h"
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace internal {
|
||||
|
||||
class AudioState final : public webrtc::AudioState,
|
||||
public webrtc::VoiceEngineObserver {
|
||||
public:
|
||||
explicit AudioState(const AudioState::Config& config);
|
||||
~AudioState() override;
|
||||
|
||||
VoiceEngine* voice_engine();
|
||||
bool typing_noise_detected() const;
|
||||
|
||||
private:
|
||||
// rtc::RefCountInterface implementation.
|
||||
int AddRef() const override;
|
||||
int Release() const override;
|
||||
|
||||
// webrtc::VoiceEngineObserver implementation.
|
||||
void CallbackOnError(int channel_id, int err_code) override;
|
||||
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
rtc::ThreadChecker process_thread_checker_;
|
||||
const webrtc::AudioState::Config config_;
|
||||
|
||||
// We hold one interface pointer to the VoE to make sure it is kept alive.
|
||||
ScopedVoEInterface<VoEBase> voe_base_;
|
||||
|
||||
// The critical section isn't strictly needed in this case, but xSAN bots may
|
||||
// trigger on unprotected cross-thread access.
|
||||
mutable rtc::CriticalSection crit_sect_;
|
||||
bool typing_noise_detected_ GUARDED_BY(crit_sect_) = false;
|
||||
|
||||
// Reference count; implementation copied from rtc::RefCountedObject.
|
||||
mutable volatile int ref_count_ = 0;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioState);
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_AUDIO_AUDIO_STATE_H_
|
||||
80
webrtc/audio/audio_state_unittest.cc
Normal file
80
webrtc/audio/audio_state_unittest.cc
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/audio/audio_state.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/test/mock_voice_engine.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
struct ConfigHelper {
|
||||
ConfigHelper() {
|
||||
EXPECT_CALL(voice_engine_,
|
||||
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(voice_engine_,
|
||||
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
|
||||
config_.voice_engine = &voice_engine_;
|
||||
}
|
||||
AudioState::Config& config() { return config_; }
|
||||
MockVoiceEngine& voice_engine() { return voice_engine_; }
|
||||
|
||||
private:
|
||||
MockVoiceEngine voice_engine_;
|
||||
AudioState::Config config_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(AudioStateTest, Create) {
|
||||
ConfigHelper helper;
|
||||
rtc::scoped_refptr<AudioState> audio_state =
|
||||
AudioState::Create(helper.config());
|
||||
EXPECT_TRUE(audio_state.get());
|
||||
}
|
||||
|
||||
TEST(AudioStateTest, ConstructDestruct) {
|
||||
ConfigHelper helper;
|
||||
rtc::scoped_ptr<internal::AudioState> audio_state(
|
||||
new internal::AudioState(helper.config()));
|
||||
}
|
||||
|
||||
TEST(AudioStateTest, GetVoiceEngine) {
|
||||
ConfigHelper helper;
|
||||
rtc::scoped_ptr<internal::AudioState> audio_state(
|
||||
new internal::AudioState(helper.config()));
|
||||
EXPECT_EQ(audio_state->voice_engine(), &helper.voice_engine());
|
||||
}
|
||||
|
||||
TEST(AudioStateTest, TypingNoiseDetected) {
|
||||
ConfigHelper helper;
|
||||
rtc::scoped_ptr<internal::AudioState> audio_state(
|
||||
new internal::AudioState(helper.config()));
|
||||
VoiceEngineObserver* voe_observer =
|
||||
static_cast<VoiceEngineObserver*>(audio_state.get());
|
||||
EXPECT_FALSE(audio_state->typing_noise_detected());
|
||||
|
||||
voe_observer->CallbackOnError(-1, VE_NOT_INITED);
|
||||
EXPECT_FALSE(audio_state->typing_noise_detected());
|
||||
|
||||
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_WARNING);
|
||||
EXPECT_TRUE(audio_state->typing_noise_detected());
|
||||
voe_observer->CallbackOnError(-1, VE_NOT_INITED);
|
||||
EXPECT_TRUE(audio_state->typing_noise_detected());
|
||||
|
||||
voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_OFF_WARNING);
|
||||
EXPECT_FALSE(audio_state->typing_noise_detected());
|
||||
voe_observer->CallbackOnError(-1, VE_NOT_INITED);
|
||||
EXPECT_FALSE(audio_state->typing_noise_detected());
|
||||
}
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
@ -18,6 +18,8 @@
|
||||
'audio/audio_receive_stream.h',
|
||||
'audio/audio_send_stream.cc',
|
||||
'audio/audio_send_stream.h',
|
||||
'audio/audio_state.cc',
|
||||
'audio/audio_state.h',
|
||||
'audio/conversion.h',
|
||||
'audio/scoped_voe_interface.h',
|
||||
],
|
||||
|
||||
43
webrtc/audio_state.h
Normal file
43
webrtc/audio_state.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 WEBRTC_AUDIO_STATE_H_
|
||||
#define WEBRTC_AUDIO_STATE_H_
|
||||
|
||||
#include "webrtc/base/refcount.h"
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDeviceModule;
|
||||
class VoiceEngine;
|
||||
|
||||
// AudioState holds the state which must be shared between multiple instances of
|
||||
// webrtc::Call for audio processing purposes.
|
||||
class AudioState : public rtc::RefCountInterface {
|
||||
public:
|
||||
struct Config {
|
||||
// VoiceEngine used for audio streams and audio/video synchronization.
|
||||
// AudioState will tickle the VoE refcount to keep it alive for as long as
|
||||
// the AudioState itself.
|
||||
VoiceEngine* voice_engine = nullptr;
|
||||
|
||||
// The AudioDeviceModule associated with the Calls.
|
||||
AudioDeviceModule* audio_device_module = nullptr;
|
||||
};
|
||||
|
||||
// TODO(solenberg): Replace scoped_refptr with shared_ptr once we can use it.
|
||||
static rtc::scoped_refptr<AudioState> Create(
|
||||
const AudioState::Config& config);
|
||||
|
||||
virtual ~AudioState() {}
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_AUDIO_STATE_H_
|
||||
@ -16,16 +16,14 @@
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/audio_receive_stream.h"
|
||||
#include "webrtc/audio_send_stream.h"
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/base/socket.h"
|
||||
#include "webrtc/video_receive_stream.h"
|
||||
#include "webrtc/video_send_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDeviceModule;
|
||||
class AudioProcessing;
|
||||
class VoiceEngine;
|
||||
class VoiceEngineObserver;
|
||||
|
||||
const char* Version();
|
||||
|
||||
@ -74,9 +72,6 @@ class Call {
|
||||
struct Config {
|
||||
static const int kDefaultStartBitrateBps;
|
||||
|
||||
// VoiceEngine used for audio/video synchronization for this Call.
|
||||
VoiceEngine* voice_engine = nullptr;
|
||||
|
||||
// Bitrate config used until valid bitrate estimates are calculated. Also
|
||||
// used to cap total bitrate used.
|
||||
struct BitrateConfig {
|
||||
@ -85,11 +80,13 @@ class Call {
|
||||
int max_bitrate_bps = -1;
|
||||
} bitrate_config;
|
||||
|
||||
struct AudioConfig {
|
||||
AudioDeviceModule* audio_device_module = nullptr;
|
||||
AudioProcessing* audio_processing = nullptr;
|
||||
VoiceEngineObserver* voice_engine_observer = nullptr;
|
||||
} audio_config;
|
||||
// AudioState which is possibly shared between multiple calls.
|
||||
// TODO(solenberg): Change this to a shared_ptr once we can use C++11.
|
||||
rtc::scoped_refptr<AudioState> audio_state;
|
||||
|
||||
// Audio Processing Module to be used in this call.
|
||||
// TODO(solenberg): Change this to a shared_ptr once we can use C++11.
|
||||
AudioProcessing* audio_processing = nullptr;
|
||||
};
|
||||
|
||||
struct Stats {
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
@ -117,11 +118,17 @@ class BitrateEstimatorTest : public test::CallTest {
|
||||
virtual ~BitrateEstimatorTest() { EXPECT_TRUE(streams_.empty()); }
|
||||
|
||||
virtual void SetUp() {
|
||||
EXPECT_CALL(mock_voice_engine_,
|
||||
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(mock_voice_engine_,
|
||||
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(mock_voice_engine_, GetEventLog())
|
||||
.WillRepeatedly(testing::Return(nullptr));
|
||||
|
||||
AudioState::Config audio_state_config;
|
||||
audio_state_config.voice_engine = &mock_voice_engine_;
|
||||
Call::Config config;
|
||||
config.voice_engine = &mock_voice_engine_;
|
||||
config.audio_state = AudioState::Create(audio_state_config);
|
||||
receiver_call_.reset(Call::Create(config));
|
||||
sender_call_.reset(Call::Create(config));
|
||||
|
||||
@ -162,6 +169,7 @@ class BitrateEstimatorTest : public test::CallTest {
|
||||
}
|
||||
|
||||
receiver_call_.reset();
|
||||
sender_call_.reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
#include "webrtc/audio/audio_receive_stream.h"
|
||||
#include "webrtc/audio/audio_send_stream.h"
|
||||
#include "webrtc/audio/audio_state.h"
|
||||
#include "webrtc/audio/scoped_voe_interface.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
@ -94,6 +96,15 @@ class Call : public webrtc::Call, public PacketReceiver {
|
||||
void ConfigureSync(const std::string& sync_group)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(receive_crit_);
|
||||
|
||||
VoiceEngine* voice_engine() {
|
||||
internal::AudioState* audio_state =
|
||||
static_cast<internal::AudioState*>(config_.audio_state.get());
|
||||
if (audio_state)
|
||||
return audio_state->voice_engine();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int num_cpu_cores_;
|
||||
const rtc::scoped_ptr<ProcessThread> module_process_thread_;
|
||||
const rtc::scoped_ptr<CallStats> call_stats_;
|
||||
@ -123,7 +134,6 @@ class Call : public webrtc::Call, public PacketReceiver {
|
||||
VideoSendStream::RtpStateMap suspended_video_send_ssrcs_;
|
||||
|
||||
RtcEventLog* event_log_ = nullptr;
|
||||
VoECodec* voe_codec_ = nullptr;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(Call);
|
||||
};
|
||||
@ -152,12 +162,9 @@ Call::Call(const Call::Config& config)
|
||||
RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps,
|
||||
config.bitrate_config.start_bitrate_bps);
|
||||
}
|
||||
if (config.voice_engine) {
|
||||
// Keep a reference to VoECodec, so we're sure the VoiceEngine lives for the
|
||||
// duration of the call.
|
||||
voe_codec_ = VoECodec::GetInterface(config.voice_engine);
|
||||
if (voe_codec_)
|
||||
event_log_ = voe_codec_->GetEventLog();
|
||||
if (config.audio_state.get()) {
|
||||
ScopedVoEInterface<VoECodec> voe_codec(voice_engine());
|
||||
event_log_ = voe_codec->GetEventLog();
|
||||
}
|
||||
|
||||
Trace::CreateTrace();
|
||||
@ -184,9 +191,6 @@ Call::~Call() {
|
||||
module_process_thread_->DeRegisterModule(call_stats_.get());
|
||||
module_process_thread_->Stop();
|
||||
Trace::ReturnTrace();
|
||||
|
||||
if (voe_codec_)
|
||||
voe_codec_->Release();
|
||||
}
|
||||
|
||||
PacketReceiver* Call::Receiver() {
|
||||
@ -201,7 +205,7 @@ webrtc::AudioSendStream* Call::CreateAudioSendStream(
|
||||
TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
|
||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||
AudioSendStream* send_stream =
|
||||
new AudioSendStream(config, config_.voice_engine);
|
||||
new AudioSendStream(config, config_.audio_state);
|
||||
if (!network_enabled_)
|
||||
send_stream->SignalNetworkState(kNetworkDown);
|
||||
{
|
||||
@ -237,7 +241,7 @@ webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
|
||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||
AudioReceiveStream* receive_stream = new AudioReceiveStream(
|
||||
congestion_controller_->GetRemoteBitrateEstimator(false), config,
|
||||
config_.voice_engine);
|
||||
config_.audio_state);
|
||||
{
|
||||
WriteLockScoped write_lock(*receive_crit_);
|
||||
RTC_DCHECK(audio_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
|
||||
@ -340,7 +344,7 @@ webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
|
||||
RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
|
||||
VideoReceiveStream* receive_stream = new VideoReceiveStream(
|
||||
num_cpu_cores_, congestion_controller_.get(), config,
|
||||
config_.voice_engine, module_process_thread_.get(), call_stats_.get());
|
||||
voice_engine(), module_process_thread_.get(), call_stats_.get());
|
||||
|
||||
WriteLockScoped write_lock(*receive_crit_);
|
||||
RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) ==
|
||||
@ -470,7 +474,7 @@ void Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
|
||||
|
||||
void Call::ConfigureSync(const std::string& sync_group) {
|
||||
// Set sync only if there was no previous one.
|
||||
if (config_.voice_engine == nullptr || sync_group.empty())
|
||||
if (voice_engine() == nullptr || sync_group.empty())
|
||||
return;
|
||||
|
||||
AudioReceiveStream* sync_audio_stream = nullptr;
|
||||
@ -508,10 +512,10 @@ void Call::ConfigureSync(const std::string& sync_group) {
|
||||
}
|
||||
// Only sync the first A/V pair within this sync group.
|
||||
if (sync_audio_stream != nullptr && num_synced_streams == 1) {
|
||||
video_stream->SetSyncChannel(config_.voice_engine,
|
||||
video_stream->SetSyncChannel(voice_engine(),
|
||||
sync_audio_stream->config().voe_channel_id);
|
||||
} else {
|
||||
video_stream->SetSyncChannel(config_.voice_engine, -1);
|
||||
video_stream->SetSyncChannel(voice_engine(), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,8 +232,10 @@ void CallPerfTest::TestAudioVideoSync(bool fec, bool create_audio_first) {
|
||||
|
||||
SyncRtcpObserver audio_observer;
|
||||
|
||||
AudioState::Config audio_state_config;
|
||||
audio_state_config.voice_engine = voice_engine;
|
||||
Call::Config receiver_config;
|
||||
receiver_config.voice_engine = voice_engine;
|
||||
receiver_config.audio_state = AudioState::Create(audio_state_config);
|
||||
CreateCalls(Call::Config(), receiver_config);
|
||||
|
||||
CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
|
||||
|
||||
@ -12,22 +12,31 @@
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/audio_state.h"
|
||||
#include "webrtc/call.h"
|
||||
#include "webrtc/test/mock_voice_engine.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct CallHelper {
|
||||
CallHelper() : voice_engine_(new webrtc::test::MockVoiceEngine()) {
|
||||
CallHelper() {
|
||||
EXPECT_CALL(voice_engine_,
|
||||
RegisterVoiceEngineObserver(testing::_)).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(voice_engine_,
|
||||
DeRegisterVoiceEngineObserver()).WillOnce(testing::Return(0));
|
||||
EXPECT_CALL(voice_engine_,
|
||||
GetEventLog()).WillOnce(testing::Return(nullptr));
|
||||
webrtc::AudioState::Config audio_state_config;
|
||||
audio_state_config.voice_engine = &voice_engine_;
|
||||
webrtc::Call::Config config;
|
||||
config.voice_engine = voice_engine_.get();
|
||||
config.audio_state = webrtc::AudioState::Create(audio_state_config);
|
||||
call_.reset(webrtc::Call::Create(config));
|
||||
}
|
||||
|
||||
webrtc::Call* operator->() { return call_.get(); }
|
||||
|
||||
private:
|
||||
rtc::scoped_ptr<webrtc::test::MockVoiceEngine> voice_engine_;
|
||||
webrtc::test::MockVoiceEngine voice_engine_;
|
||||
rtc::scoped_ptr<webrtc::Call> call_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -97,7 +97,7 @@ std::string VideoSendStream::Config::ToString() const {
|
||||
ss << ", post_encode_callback: " << (post_encode_callback != nullptr
|
||||
? "(EncodedFrameObserver)"
|
||||
: "nullptr");
|
||||
ss << "local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)"
|
||||
ss << ", local_renderer: " << (local_renderer != nullptr ? "(VideoRenderer)"
|
||||
: "nullptr");
|
||||
ss << ", render_delay_ms: " << render_delay_ms;
|
||||
ss << ", target_delay_ms: " << target_delay_ms;
|
||||
|
||||
@ -98,6 +98,7 @@
|
||||
'sources': [
|
||||
'audio_receive_stream.h',
|
||||
'audio_send_stream.h',
|
||||
'audio_state.h',
|
||||
'call.h',
|
||||
'config.h',
|
||||
'frame_callback.h',
|
||||
|
||||
@ -153,6 +153,7 @@
|
||||
'sources': [
|
||||
'audio/audio_receive_stream_unittest.cc',
|
||||
'audio/audio_send_stream_unittest.cc',
|
||||
'audio/audio_state_unittest.cc',
|
||||
'call/bitrate_estimator_tests.cc',
|
||||
'call/call_unittest.cc',
|
||||
'call/packet_injection_tests.cc',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user