diff options
author | solenberg <solenberg@webrtc.org> | 2015-11-06 15:34:49 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-06 23:34:58 +0000 |
commit | 566ef247b9779f6c9d0e7ec9eea6b037f4682c53 (patch) | |
tree | b26cdb03d6c5840b7e39146db5953a4e2536a4dc | |
parent | 19299fb28b2578d721649fff65419d4eb9ea1af3 (diff) | |
download | webrtc-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}
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', |