aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsolenberg <solenberg@webrtc.org>2015-11-06 15:34:49 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-06 23:34:58 +0000
commit566ef247b9779f6c9d0e7ec9eea6b037f4682c53 (patch)
treeb26cdb03d6c5840b7e39146db5953a4e2536a4dc
parent19299fb28b2578d721649fff65419d4eb9ea1af3 (diff)
downloadwebrtc-566ef247b9779f6c9d0e7ec9eea6b037f4682c53.tar.gz
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}
-rw-r--r--talk/app/webrtc/mediacontroller.cc14
-rw-r--r--talk/media/base/fakemediaengine.h4
-rw-r--r--talk/media/base/mediaengine.h8
-rw-r--r--talk/media/webrtc/fakewebrtccall.h16
-rw-r--r--talk/media/webrtc/webrtcvoiceengine.cc223
-rw-r--r--talk/media/webrtc/webrtcvoiceengine.h54
-rw-r--r--talk/media/webrtc/webrtcvoiceengine_unittest.cc19
-rw-r--r--webrtc/audio/BUILD.gn2
-rw-r--r--webrtc/audio/audio_receive_stream.cc41
-rw-r--r--webrtc/audio/audio_receive_stream.h10
-rw-r--r--webrtc/audio/audio_receive_stream_unittest.cc167
-rw-r--r--webrtc/audio/audio_send_stream.cc30
-rw-r--r--webrtc/audio/audio_send_stream.h12
-rw-r--r--webrtc/audio/audio_send_stream_unittest.cc146
-rw-r--r--webrtc/audio/audio_state.cc79
-rw-r--r--webrtc/audio/audio_state.h61
-rw-r--r--webrtc/audio/audio_state_unittest.cc80
-rw-r--r--webrtc/audio/webrtc_audio.gypi2
-rw-r--r--webrtc/audio_state.h43
-rw-r--r--webrtc/call.h19
-rw-r--r--webrtc/call/bitrate_estimator_tests.cc10
-rw-r--r--webrtc/call/call.cc36
-rw-r--r--webrtc/call/call_perf_tests.cc4
-rw-r--r--webrtc/call/call_unittest.cc15
-rw-r--r--webrtc/video/video_send_stream.cc2
-rw-r--r--webrtc/webrtc.gyp1
-rw-r--r--webrtc/webrtc_tests.gypi1
27 files changed, 701 insertions, 398 deletions
diff --git a/talk/app/webrtc/mediacontroller.cc b/talk/app/webrtc/mediacontroller.cc
index f7d85116b1..24f5877483 100644
--- a/talk/app/webrtc/mediacontroller.cc
+++ b/talk/app/webrtc/mediacontroller.cc
@@ -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
diff --git a/talk/media/base/fakemediaengine.h b/talk/media/base/fakemediaengine.h
index a6fa960dee..44499e403d 100644
--- a/talk/media/base/fakemediaengine.h
+++ b/talk/media/base/fakemediaengine.h
@@ -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_;
}
diff --git a/talk/media/base/mediaengine.h b/talk/media/base/mediaengine.h
index 1a992d7d4a..7411b876ed 100644
--- a/talk/media/base/mediaengine.h
+++ b/talk/media/base/mediaengine.h
@@ -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) {
diff --git a/talk/media/webrtc/fakewebrtccall.h b/talk/media/webrtc/fakewebrtccall.h
index 88edc60d78..2e7039014c 100644
--- a/talk/media/webrtc/fakewebrtccall.h
+++ b/talk/media/webrtc/fakewebrtccall.h
@@ -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;
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index a5c8089d10..37df244f4f 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -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)) {
diff --git a/talk/media/webrtc/webrtcvoiceengine.h b/talk/media/webrtc/webrtcvoiceengine.h
index d9caf085be..b9b50bb93d 100644
--- a/talk/media/webrtc/webrtcvoiceengine.h
+++ b/talk/media/webrtc/webrtcvoiceengine.h
@@ -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_
diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index f61641cb6d..efa195d204 100644
--- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -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;
diff --git a/webrtc/audio/BUILD.gn b/webrtc/audio/BUILD.gn
index d5061db9dc..abae4347dc 100644
--- a/webrtc/audio/BUILD.gn
+++ b/webrtc/audio/BUILD.gn
@@ -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",
]
diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc
index 34197c3ff7..8caac6f87e 100644
--- a/webrtc/audio/audio_receive_stream.cc
+++ b/webrtc/audio/audio_receive_stream.cc
@@ -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;
diff --git a/webrtc/audio/audio_receive_stream.h b/webrtc/audio/audio_receive_stream.h
index bc4981bbb1..a461aadc5f 100644
--- a/webrtc/audio/audio_receive_stream.h
+++ b/webrtc/audio/audio_receive_stream.h
@@ -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);
diff --git a/webrtc/audio/audio_receive_stream_unittest.cc b/webrtc/audio/audio_receive_stream_unittest.cc
index 0bb9b51e16..755d634d56 100644
--- a/webrtc/audio/audio_receive_stream_unittest.cc
+++ b/webrtc/audio/audio_receive_stream_unittest.cc
@@ -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);
}
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index ccfdca546d..da242498f9 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -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;
}
diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h
index ae81dfc8fc..3d911c1f5f 100644
--- a/webrtc/audio/audio_send_stream.h
+++ b/webrtc/audio/audio_send_stream.h
@@ -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);
};
diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc
index 727178ed5b..ada15acddf 100644
--- a/webrtc/audio/audio_send_stream_unittest.cc
+++ b/webrtc/audio/audio_send_stream_unittest.cc
@@ -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
diff --git a/webrtc/audio/audio_state.cc b/webrtc/audio/audio_state.cc
new file mode 100644
index 0000000000..e63f97af2d
--- /dev/null
+++ b/webrtc/audio/audio_state.cc
@@ -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
diff --git a/webrtc/audio/audio_state.h b/webrtc/audio/audio_state.h
new file mode 100644
index 0000000000..2cb83e4989
--- /dev/null
+++ b/webrtc/audio/audio_state.h
@@ -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_
diff --git a/webrtc/audio/audio_state_unittest.cc b/webrtc/audio/audio_state_unittest.cc
new file mode 100644
index 0000000000..170eff5e85
--- /dev/null
+++ b/webrtc/audio/audio_state_unittest.cc
@@ -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
diff --git a/webrtc/audio/webrtc_audio.gypi b/webrtc/audio/webrtc_audio.gypi
index b9d45db56d..9b4879a70b 100644
--- a/webrtc/audio/webrtc_audio.gypi
+++ b/webrtc/audio/webrtc_audio.gypi
@@ -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',
],
diff --git a/webrtc/audio_state.h b/webrtc/audio_state.h
new file mode 100644
index 0000000000..c6168237a9
--- /dev/null
+++ b/webrtc/audio_state.h
@@ -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_
diff --git a/webrtc/call.h b/webrtc/call.h
index e6e8cdee0b..313c5e58c1 100644
--- a/webrtc/call.h
+++ b/webrtc/call.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 {
diff --git a/webrtc/call/bitrate_estimator_tests.cc b/webrtc/call/bitrate_estimator_tests.cc
index f6dac6bc06..6bccb43e56 100644
--- a/webrtc/call/bitrate_estimator_tests.cc
+++ b/webrtc/call/bitrate_estimator_tests.cc
@@ -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:
diff --git a/webrtc/call/call.cc b/webrtc/call/call.cc
index 39357d57df..1144506727 100644
--- a/webrtc/call/call.cc
+++ b/webrtc/call/call.cc
@@ -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);
}
}
}
diff --git a/webrtc/call/call_perf_tests.cc b/webrtc/call/call_perf_tests.cc
index 95fd32e258..69f090a63f 100644
--- a/webrtc/call/call_perf_tests.cc
+++ b/webrtc/call/call_perf_tests.cc
@@ -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};
diff --git a/webrtc/call/call_unittest.cc b/webrtc/call/call_unittest.cc
index 25fb119895..b26024d91e 100644
--- a/webrtc/call/call_unittest.cc
+++ b/webrtc/call/call_unittest.cc
@@ -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
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index 958aa33352..33e1f57575 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -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;
diff --git a/webrtc/webrtc.gyp b/webrtc/webrtc.gyp
index c9b3ab52db..75ed645106 100644
--- a/webrtc/webrtc.gyp
+++ b/webrtc/webrtc.gyp
@@ -98,6 +98,7 @@
'sources': [
'audio_receive_stream.h',
'audio_send_stream.h',
+ 'audio_state.h',
'call.h',
'config.h',
'frame_callback.h',
diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi
index 811bbd772f..782cb1aa30 100644
--- a/webrtc/webrtc_tests.gypi
+++ b/webrtc/webrtc_tests.gypi
@@ -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',