Commit 1f46b374 authored by Hsin-Yu Chao's avatar Hsin-Yu Chao Committed by Commit Bot

Expose experimental AEC on Chrome OS

Bug: 710465
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I6c42f67335f9335ac3e8d2e003bfdde1d6bfa433
Reviewed-on: https://chromium-review.googlesource.com/1086893
Commit-Queue: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: default avatarOskar Sundbom <ossu@chromium.org>
Reviewed-by: default avatarHenrik Andreasson <henrika@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576514}
parent bd8cc342
...@@ -910,6 +910,7 @@ void CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable( ...@@ -910,6 +910,7 @@ void CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable(
cras_service_available_ = true; cras_service_available_ = true;
GetDefaultOutputBufferSizeInternal(); GetDefaultOutputBufferSizeInternal();
GetSystemAecSupported();
GetNodes(); GetNodes();
GetNumberOfOutputStreams(); GetNumberOfOutputStreams();
} }
...@@ -1675,4 +1676,28 @@ void CrasAudioHandler::HandleGetDefaultOutputBufferSize( ...@@ -1675,4 +1676,28 @@ void CrasAudioHandler::HandleGetDefaultOutputBufferSize(
default_output_buffer_size_ = buffer_size.value(); default_output_buffer_size_ = buffer_size.value();
} }
bool CrasAudioHandler::system_aec_supported() const {
DCHECK(main_task_runner_->BelongsToCurrentThread());
return system_aec_supported_;
}
// GetSystemAecSupported() is only called in the same thread
// as the CrasAudioHanler constructor. We are safe here without
// thread check, because unittest may not have the task runner
// for the current thread.
void CrasAudioHandler::GetSystemAecSupported() {
GetCrasAudioClient()->GetSystemAecSupported(
base::BindOnce(&CrasAudioHandler::HandleGetSystemAecSupported,
weak_ptr_factory_.GetWeakPtr()));
}
void CrasAudioHandler::HandleGetSystemAecSupported(
base::Optional<bool> system_aec_supported) {
if (!system_aec_supported.has_value()) {
LOG(ERROR) << "Failed to retrieve system aec supported";
return;
}
system_aec_supported_ = system_aec_supported.value();
}
} // namespace chromeos } // namespace chromeos
...@@ -274,6 +274,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -274,6 +274,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// the use case. It should be called from a user initiated action. // the use case. It should be called from a user initiated action.
void SwitchToFrontOrRearMic(); void SwitchToFrontOrRearMic();
// Returns if system AEC is supported in CRAS.
bool system_aec_supported() const;
protected: protected:
explicit CrasAudioHandler( explicit CrasAudioHandler(
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler); scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler);
...@@ -475,6 +478,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -475,6 +478,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Handle dbus callback for GetDefaultOutputBufferSize. // Handle dbus callback for GetDefaultOutputBufferSize.
void HandleGetDefaultOutputBufferSize(base::Optional<int> buffer_size); void HandleGetDefaultOutputBufferSize(base::Optional<int> buffer_size);
// Calling dbus to get system AEC supported flag.
void GetSystemAecSupported();
// Calling dbus to get system AEC supported flag on main thread.
void GetSystemAecSupportedOnMainThread();
// Handle dbus callback for GetSystemAecSupported.
void HandleGetSystemAecSupported(base::Optional<bool> system_aec_supported);
void OnVideoCaptureStartedOnMainThread(media::VideoFacingMode facing); void OnVideoCaptureStartedOnMainThread(media::VideoFacingMode facing);
void OnVideoCaptureStoppedOnMainThread(media::VideoFacingMode facing); void OnVideoCaptureStoppedOnMainThread(media::VideoFacingMode facing);
...@@ -521,6 +533,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -521,6 +533,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Default output buffer size in frames. // Default output buffer size in frames.
int32_t default_output_buffer_size_; int32_t default_output_buffer_size_;
bool system_aec_supported_ = false;
int num_active_output_streams_ = 0; int num_active_output_streams_ = 0;
// Task runner of browser main thread. All member variables should be accessed // Task runner of browser main thread. All member variables should be accessed
......
...@@ -59,6 +59,15 @@ class CrasAudioClientImpl : public CrasAudioClient { ...@@ -59,6 +59,15 @@ class CrasAudioClientImpl : public CrasAudioClient {
weak_ptr_factory_.GetWeakPtr(), std::move(callback))); weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} }
void GetSystemAecSupported(DBusMethodCallback<bool> callback) override {
dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetSystemAecSupported);
cras_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&CrasAudioClientImpl::OnGetSystemAecSupported,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void GetNodes(DBusMethodCallback<AudioNodeList> callback) override { void GetNodes(DBusMethodCallback<AudioNodeList> callback) override {
dbus::MethodCall method_call(cras::kCrasControlInterface, dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetNodes); cras::kGetNodes);
...@@ -434,6 +443,25 @@ class CrasAudioClientImpl : public CrasAudioClient { ...@@ -434,6 +443,25 @@ class CrasAudioClientImpl : public CrasAudioClient {
std::move(callback).Run(buffer_size); std::move(callback).Run(buffer_size);
} }
void OnGetSystemAecSupported(DBusMethodCallback<bool> callback,
dbus::Response* response) {
if (!response) {
LOG(ERROR) << "Error calling " << cras::kGetSystemAecSupported;
std::move(callback).Run(base::nullopt);
return;
}
bool system_aec_supported = 0;
dbus::MessageReader reader(response);
if (!reader.PopBool(&system_aec_supported)) {
LOG(ERROR) << "Error reading response from cras: "
<< response->ToString();
std::move(callback).Run(base::nullopt);
return;
}
std::move(callback).Run(system_aec_supported);
}
void OnGetNodes(DBusMethodCallback<AudioNodeList> callback, void OnGetNodes(DBusMethodCallback<AudioNodeList> callback,
dbus::Response* response) { dbus::Response* response) {
if (!response) { if (!response) {
......
...@@ -73,6 +73,9 @@ class CHROMEOS_EXPORT CrasAudioClient : public DBusClient { ...@@ -73,6 +73,9 @@ class CHROMEOS_EXPORT CrasAudioClient : public DBusClient {
// Gets the default output buffer size in frames. // Gets the default output buffer size in frames.
virtual void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) = 0; virtual void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) = 0;
// Gets if system AEC is supported.
virtual void GetSystemAecSupported(DBusMethodCallback<bool> callback) = 0;
// Gets an array of audio input and output nodes. // Gets an array of audio input and output nodes.
virtual void GetNodes(DBusMethodCallback<AudioNodeList> callback) = 0; virtual void GetNodes(DBusMethodCallback<AudioNodeList> callback) = 0;
......
...@@ -106,6 +106,11 @@ void FakeCrasAudioClient::GetDefaultOutputBufferSize( ...@@ -106,6 +106,11 @@ void FakeCrasAudioClient::GetDefaultOutputBufferSize(
std::move(callback).Run(512); std::move(callback).Run(512);
} }
void FakeCrasAudioClient::GetSystemAecSupported(
DBusMethodCallback<bool> callback) {
std::move(callback).Run(false);
}
void FakeCrasAudioClient::GetNodes(DBusMethodCallback<AudioNodeList> callback) { void FakeCrasAudioClient::GetNodes(DBusMethodCallback<AudioNodeList> callback) {
std::move(callback).Run(node_list_); std::move(callback).Run(node_list_);
} }
......
...@@ -28,6 +28,7 @@ class CHROMEOS_EXPORT FakeCrasAudioClient : public CrasAudioClient { ...@@ -28,6 +28,7 @@ class CHROMEOS_EXPORT FakeCrasAudioClient : public CrasAudioClient {
bool HasObserver(const Observer* observer) const override; bool HasObserver(const Observer* observer) const override;
void GetVolumeState(DBusMethodCallback<VolumeState> callback) override; void GetVolumeState(DBusMethodCallback<VolumeState> callback) override;
void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) override; void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) override;
void GetSystemAecSupported(DBusMethodCallback<bool> callback) override;
void GetNodes(DBusMethodCallback<AudioNodeList> callback) override; void GetNodes(DBusMethodCallback<AudioNodeList> callback) override;
void GetNumberOfActiveOutputStreams( void GetNumberOfActiveOutputStreams(
DBusMethodCallback<int> callback) override; DBusMethodCallback<int> callback) override;
......
...@@ -186,6 +186,10 @@ AudioParameters AudioManagerCras::GetInputStreamParameters( ...@@ -186,6 +186,10 @@ AudioParameters AudioManagerCras::GetInputStreamParameters(
if (HasKeyboardMic(devices)) if (HasKeyboardMic(devices))
params.set_effects(AudioParameters::KEYBOARD_MIC); params.set_effects(AudioParameters::KEYBOARD_MIC);
if (GetSystemAecSupportedPerBoard())
params.set_effects(params.effects() |
AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
return params; return params;
} }
...@@ -310,6 +314,27 @@ int AudioManagerCras::GetDefaultOutputBufferSizePerBoard() { ...@@ -310,6 +314,27 @@ int AudioManagerCras::GetDefaultOutputBufferSizePerBoard() {
return static_cast<int>(buffer_size); return static_cast<int>(buffer_size);
} }
bool AudioManagerCras::GetSystemAecSupportedPerBoard() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
bool system_aec_supported = false;
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
if (main_task_runner_->BelongsToCurrentThread()) {
// Unittest may use the same thread for audio thread.
GetSystemAecSupportedOnMainThread(&system_aec_supported, &event);
} else {
// Using base::Unretained is safe here because we wait for callback be
// executed in main thread before local variables are destructed.
main_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&AudioManagerCras::GetSystemAecSupportedOnMainThread,
weak_this_, base::Unretained(&system_aec_supported),
base::Unretained(&event)));
}
WaitEventOrShutdown(&event);
return system_aec_supported;
}
AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters( AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
const std::string& output_device_id, const std::string& output_device_id,
const AudioParameters& input_params) { const AudioParameters& input_params) {
...@@ -466,6 +491,17 @@ void AudioManagerCras::GetDefaultOutputBufferSizeOnMainThread( ...@@ -466,6 +491,17 @@ void AudioManagerCras::GetDefaultOutputBufferSizeOnMainThread(
event->Signal(); event->Signal();
} }
void AudioManagerCras::GetSystemAecSupportedOnMainThread(
bool* system_aec_supported,
base::WaitableEvent* event) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
if (chromeos::CrasAudioHandler::IsInitialized()) {
*system_aec_supported =
chromeos::CrasAudioHandler::Get()->system_aec_supported();
}
event->Signal();
}
void AudioManagerCras::WaitEventOrShutdown(base::WaitableEvent* event) { void AudioManagerCras::WaitEventOrShutdown(base::WaitableEvent* event) {
base::WaitableEvent* waitables[] = {event, &on_shutdown_}; base::WaitableEvent* waitables[] = {event, &on_shutdown_};
base::WaitableEvent::WaitMany(waitables, arraysize(waitables)); base::WaitableEvent::WaitMany(waitables, arraysize(waitables));
......
...@@ -79,6 +79,9 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase { ...@@ -79,6 +79,9 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
// Get default output buffer size for this board. // Get default output buffer size for this board.
int GetDefaultOutputBufferSizePerBoard(); int GetDefaultOutputBufferSizePerBoard();
// Get if system AEC is supported or not for this board.
bool GetSystemAecSupportedPerBoard();
void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names); void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names);
std::string GetHardwareDeviceFromDeviceId( std::string GetHardwareDeviceFromDeviceId(
...@@ -97,6 +100,8 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase { ...@@ -97,6 +100,8 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
base::WaitableEvent* event); base::WaitableEvent* event);
void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size, void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
base::WaitableEvent* event); base::WaitableEvent* event);
void GetSystemAecSupportedOnMainThread(bool* system_aec_supported,
base::WaitableEvent* event);
void WaitEventOrShutdown(base::WaitableEvent* event); void WaitEventOrShutdown(base::WaitableEvent* event);
......
...@@ -121,6 +121,10 @@ void CrasInputStream::Close() { ...@@ -121,6 +121,10 @@ void CrasInputStream::Close() {
audio_manager_->ReleaseInputStream(this); audio_manager_->ReleaseInputStream(this);
} }
inline bool CrasInputStream::UseCrasAec() const {
return params_.effects() & AudioParameters::ECHO_CANCELLER;
}
void CrasInputStream::Start(AudioInputCallback* callback) { void CrasInputStream::Start(AudioInputCallback* callback) {
DCHECK(client_); DCHECK(client_);
DCHECK(callback); DCHECK(callback);
...@@ -204,6 +208,9 @@ void CrasInputStream::Start(AudioInputCallback* callback) { ...@@ -204,6 +208,9 @@ void CrasInputStream::Start(AudioInputCallback* callback) {
return; return;
} }
if (UseCrasAec())
cras_client_stream_params_enable_aec(stream_params);
// Before starting the stream, save the number of bytes in a frame for use in // Before starting the stream, save the number of bytes in a frame for use in
// the callback. // the callback.
bytes_per_frame_ = cras_client_format_bytes_per_frame(audio_format); bytes_per_frame_ = cras_client_format_bytes_per_frame(audio_format);
......
...@@ -78,6 +78,9 @@ class MEDIA_EXPORT CrasInputStream : public AgcAudioStream<AudioInputStream> { ...@@ -78,6 +78,9 @@ class MEDIA_EXPORT CrasInputStream : public AgcAudioStream<AudioInputStream> {
// Convert from a volume ratio to dB. // Convert from a volume ratio to dB.
double GetDecibelsFromVolumeRatio(double volume_ratio) const; double GetDecibelsFromVolumeRatio(double volume_ratio) const;
// Return true to use AEC in CRAS for this input stream.
inline bool UseCrasAec() const;
// Non-refcounted pointer back to the audio manager. // Non-refcounted pointer back to the audio manager.
// The AudioManager indirectly holds on to stream objects, so we don't // The AudioManager indirectly holds on to stream objects, so we don't
// want circular references. Additionally, stream objects live on the audio // want circular references. Additionally, stream objects live on the audio
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment