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(
cras_service_available_ = true;
GetDefaultOutputBufferSizeInternal();
GetSystemAecSupported();
GetNodes();
GetNumberOfOutputStreams();
}
......@@ -1675,4 +1676,28 @@ void CrasAudioHandler::HandleGetDefaultOutputBufferSize(
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
......@@ -274,6 +274,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// the use case. It should be called from a user initiated action.
void SwitchToFrontOrRearMic();
// Returns if system AEC is supported in CRAS.
bool system_aec_supported() const;
protected:
explicit CrasAudioHandler(
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler);
......@@ -475,6 +478,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Handle dbus callback for GetDefaultOutputBufferSize.
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 OnVideoCaptureStoppedOnMainThread(media::VideoFacingMode facing);
......@@ -521,6 +533,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Default output buffer size in frames.
int32_t default_output_buffer_size_;
bool system_aec_supported_ = false;
int num_active_output_streams_ = 0;
// Task runner of browser main thread. All member variables should be accessed
......
......@@ -59,6 +59,15 @@ class CrasAudioClientImpl : public CrasAudioClient {
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 {
dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetNodes);
......@@ -434,6 +443,25 @@ class CrasAudioClientImpl : public CrasAudioClient {
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,
dbus::Response* response) {
if (!response) {
......
......@@ -73,6 +73,9 @@ class CHROMEOS_EXPORT CrasAudioClient : public DBusClient {
// Gets the default output buffer size in frames.
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.
virtual void GetNodes(DBusMethodCallback<AudioNodeList> callback) = 0;
......
......@@ -106,6 +106,11 @@ void FakeCrasAudioClient::GetDefaultOutputBufferSize(
std::move(callback).Run(512);
}
void FakeCrasAudioClient::GetSystemAecSupported(
DBusMethodCallback<bool> callback) {
std::move(callback).Run(false);
}
void FakeCrasAudioClient::GetNodes(DBusMethodCallback<AudioNodeList> callback) {
std::move(callback).Run(node_list_);
}
......
......@@ -28,6 +28,7 @@ class CHROMEOS_EXPORT FakeCrasAudioClient : public CrasAudioClient {
bool HasObserver(const Observer* observer) const override;
void GetVolumeState(DBusMethodCallback<VolumeState> callback) override;
void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) override;
void GetSystemAecSupported(DBusMethodCallback<bool> callback) override;
void GetNodes(DBusMethodCallback<AudioNodeList> callback) override;
void GetNumberOfActiveOutputStreams(
DBusMethodCallback<int> callback) override;
......
......@@ -186,6 +186,10 @@ AudioParameters AudioManagerCras::GetInputStreamParameters(
if (HasKeyboardMic(devices))
params.set_effects(AudioParameters::KEYBOARD_MIC);
if (GetSystemAecSupportedPerBoard())
params.set_effects(params.effects() |
AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
return params;
}
......@@ -310,6 +314,27 @@ int AudioManagerCras::GetDefaultOutputBufferSizePerBoard() {
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(
const std::string& output_device_id,
const AudioParameters& input_params) {
......@@ -466,6 +491,17 @@ void AudioManagerCras::GetDefaultOutputBufferSizeOnMainThread(
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) {
base::WaitableEvent* waitables[] = {event, &on_shutdown_};
base::WaitableEvent::WaitMany(waitables, arraysize(waitables));
......
......@@ -79,6 +79,9 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
// Get default output buffer size for this board.
int GetDefaultOutputBufferSizePerBoard();
// Get if system AEC is supported or not for this board.
bool GetSystemAecSupportedPerBoard();
void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names);
std::string GetHardwareDeviceFromDeviceId(
......@@ -97,6 +100,8 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
base::WaitableEvent* event);
void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
base::WaitableEvent* event);
void GetSystemAecSupportedOnMainThread(bool* system_aec_supported,
base::WaitableEvent* event);
void WaitEventOrShutdown(base::WaitableEvent* event);
......
......@@ -121,6 +121,10 @@ void CrasInputStream::Close() {
audio_manager_->ReleaseInputStream(this);
}
inline bool CrasInputStream::UseCrasAec() const {
return params_.effects() & AudioParameters::ECHO_CANCELLER;
}
void CrasInputStream::Start(AudioInputCallback* callback) {
DCHECK(client_);
DCHECK(callback);
......@@ -204,6 +208,9 @@ void CrasInputStream::Start(AudioInputCallback* callback) {
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
// the callback.
bytes_per_frame_ = cras_client_format_bytes_per_frame(audio_format);
......
......@@ -78,6 +78,9 @@ class MEDIA_EXPORT CrasInputStream : public AgcAudioStream<AudioInputStream> {
// Convert from a volume ratio to dB.
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.
// The AudioManager indirectly holds on to stream objects, so we don't
// 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