Commit 5dade9ff authored by Per Åhgren's avatar Per Åhgren Committed by Commit Bot

CRAS System AEC: Add support for using AEC group ID in AEC selection

This CL adds the functionality to have an aec group ID, which allow
Chromium to take actions that is specific for the echo canceller
parameter set that is being used in the Chrome Audio Server.

BUG=chromium:907917
CQ-DEPEND=CL:1349280,CL:1349353

Change-Id: I391fd0a65858a2635c8927dc2a8816dfb9cd4221
Reviewed-on: https://chromium-review.googlesource.com/c/1349260Reviewed-by: default avatarJenny Zhang <jennyz@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarMax Morin <maxmorin@chromium.org>
Commit-Queue: Per Åhgren <peah@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612852}
parent 5ed82cdb
......@@ -911,6 +911,7 @@ void CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable(
cras_service_available_ = true;
GetDefaultOutputBufferSizeInternal();
GetSystemAecSupported();
GetSystemAecGroupId();
GetNodes();
GetNumberOfOutputStreams();
}
......@@ -1700,4 +1701,29 @@ void CrasAudioHandler::HandleGetSystemAecSupported(
system_aec_supported_ = system_aec_supported.value();
}
int32_t CrasAudioHandler::system_aec_group_id() const {
DCHECK(main_task_runner_->BelongsToCurrentThread());
return system_aec_group_id_;
}
// GetSystemAecGroupId() 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::GetSystemAecGroupId() {
GetCrasAudioClient()->GetSystemAecGroupId(
base::BindOnce(&CrasAudioHandler::HandleGetSystemAecGroupId,
weak_ptr_factory_.GetWeakPtr()));
}
void CrasAudioHandler::HandleGetSystemAecGroupId(
base::Optional<int32_t> system_aec_group_id) {
if (!system_aec_group_id.has_value()) {
// If the group Id is not available, set the ID to reflect that.
system_aec_group_id_ = kSystemAecGroupIdNotAvailable;
return;
}
system_aec_group_id_ = system_aec_group_id.value();
}
} // namespace chromeos
......@@ -44,6 +44,7 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
priority_queue<AudioDevice, std::vector<AudioDevice>, AudioDeviceCompare>
AudioDevicePriorityQueue;
typedef std::vector<uint64_t> NodeIdList;
static constexpr int32_t kSystemAecGroupIdNotAvailable = -1;
class AudioObserver {
public:
......@@ -277,6 +278,10 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Returns if system AEC is supported in CRAS.
bool system_aec_supported() const;
// Returns the system AEC group ID. If no group ID is specified, -1 is
// returned.
int32_t system_aec_group_id() const;
protected:
explicit CrasAudioHandler(
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler);
......@@ -487,6 +492,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Handle dbus callback for GetSystemAecSupported.
void HandleGetSystemAecSupported(base::Optional<bool> system_aec_supported);
// Calling dbus to get the system AEC group id if available.
void GetSystemAecGroupId();
// Calling dbus to get any available system AEC group id on main thread.
void GetSystemAecGroupIdOnMainThread();
// Handle dbus callback for GetSystemAecGroupId.
void HandleGetSystemAecGroupId(base::Optional<int32_t> system_aec_group_id);
void OnVideoCaptureStartedOnMainThread(media::VideoFacingMode facing);
void OnVideoCaptureStoppedOnMainThread(media::VideoFacingMode facing);
......@@ -534,6 +548,7 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
int32_t default_output_buffer_size_;
bool system_aec_supported_ = false;
int32_t system_aec_group_id_ = kSystemAecGroupIdNotAvailable;
int num_active_output_streams_ = 0;
......
......@@ -68,6 +68,16 @@ class CrasAudioClientImpl : public CrasAudioClient {
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void GetSystemAecGroupId(DBusMethodCallback<int32_t> callback) override {
dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetSystemAecGroupId);
cras_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&CrasAudioClientImpl::OnGetSystemAecGroupId,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void GetNodes(DBusMethodCallback<AudioNodeList> callback) override {
dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetNodes);
......@@ -462,6 +472,25 @@ class CrasAudioClientImpl : public CrasAudioClient {
std::move(callback).Run(system_aec_supported);
}
void OnGetSystemAecGroupId(DBusMethodCallback<int32_t> callback,
dbus::Response* response) {
if (!response) {
LOG(ERROR) << "Error calling " << cras::kGetSystemAecGroupId;
std::move(callback).Run(base::nullopt);
return;
}
int32_t system_aec_group_id = 0;
dbus::MessageReader reader(response);
if (!reader.PopInt32(&system_aec_group_id)) {
LOG(ERROR) << "Error reading response from cras: "
<< response->ToString();
std::move(callback).Run(base::nullopt);
return;
}
std::move(callback).Run(system_aec_group_id);
}
void OnGetNodes(DBusMethodCallback<AudioNodeList> callback,
dbus::Response* response) {
if (!response) {
......
......@@ -76,6 +76,9 @@ class CHROMEOS_EXPORT CrasAudioClient : public DBusClient {
// Gets if system AEC is supported.
virtual void GetSystemAecSupported(DBusMethodCallback<bool> callback) = 0;
// Gets any available group ID for the system AEC
virtual void GetSystemAecGroupId(DBusMethodCallback<int32_t> callback) = 0;
// Gets an array of audio input and output nodes.
virtual void GetNodes(DBusMethodCallback<AudioNodeList> callback) = 0;
......
......@@ -111,6 +111,11 @@ void FakeCrasAudioClient::GetSystemAecSupported(
std::move(callback).Run(false);
}
void FakeCrasAudioClient::GetSystemAecGroupId(
DBusMethodCallback<int32_t> callback) {
std::move(callback).Run(1);
}
void FakeCrasAudioClient::GetNodes(DBusMethodCallback<AudioNodeList> callback) {
std::move(callback).Run(node_list_);
}
......
......@@ -29,6 +29,7 @@ class CHROMEOS_EXPORT FakeCrasAudioClient : public CrasAudioClient {
void GetVolumeState(DBusMethodCallback<VolumeState> callback) override;
void GetDefaultOutputBufferSize(DBusMethodCallback<int> callback) override;
void GetSystemAecSupported(DBusMethodCallback<bool> callback) override;
void GetSystemAecGroupId(DBusMethodCallback<int32_t> callback) override;
void GetNodes(DBusMethodCallback<AudioNodeList> callback) override;
void GetNumberOfActiveOutputStreams(
DBusMethodCallback<int> callback) override;
......
......@@ -13,6 +13,8 @@ const base::Feature kEnumerateAudioDevices{"EnumerateAudioDevices",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kCrOSSystemAEC{"CrOSSystemAEC",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kCrOSSystemAECDeactivatedGroups{
"CrOSSystemAECDeactivatedGroups", base::FEATURE_ENABLED_BY_DEFAULT};
#endif
#if defined(OS_WIN)
......
......@@ -14,6 +14,7 @@ namespace features {
#if defined(OS_CHROMEOS)
MEDIA_EXPORT extern const base::Feature kEnumerateAudioDevices;
MEDIA_EXPORT extern const base::Feature kCrOSSystemAEC;
MEDIA_EXPORT extern const base::Feature kCrOSSystemAECDeactivatedGroups;
#endif
#if defined(OS_WIN)
......
......@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/environment.h"
#include "base/logging.h"
#include "base/metrics/field_trial_params.h"
#include "base/nix/xdg_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
......@@ -192,10 +193,22 @@ AudioParameters AudioManagerCras::GetInputStreamParameters(
// but enable it by default on devices that actually support it.
params.set_effects(params.effects() |
AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
if (base::FeatureList::IsEnabled(features::kCrOSSystemAEC) &&
GetSystemAecSupportedPerBoard()) {
if (base::FeatureList::IsEnabled(features::kCrOSSystemAEC)) {
if (GetSystemAecSupportedPerBoard()) {
const int32_t aec_group_id = GetSystemAecGroupIdPerBoard();
// Check if the system AEC has a group ID which is flagged to be
// deactivated by the field trial.
const bool system_aec_deactivated =
base::GetFieldTrialParamByFeatureAsBool(
features::kCrOSSystemAECDeactivatedGroups,
std::to_string(aec_group_id), false);
if (!system_aec_deactivated) {
params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER);
}
}
}
return params;
}
......@@ -342,6 +355,27 @@ bool AudioManagerCras::GetSystemAecSupportedPerBoard() {
return system_aec_supported;
}
int32_t AudioManagerCras::GetSystemAecGroupIdPerBoard() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
int32_t group_id = chromeos::CrasAudioHandler::kSystemAecGroupIdNotAvailable;
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.
GetSystemAecGroupIdOnMainThread(&group_id, &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::GetSystemAecGroupIdOnMainThread,
weak_this_, base::Unretained(&group_id),
base::Unretained(&event)));
}
WaitEventOrShutdown(&event);
return group_id;
}
AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
const std::string& output_device_id,
const AudioParameters& input_params) {
......@@ -514,6 +548,16 @@ void AudioManagerCras::GetSystemAecSupportedOnMainThread(
event->Signal();
}
void AudioManagerCras::GetSystemAecGroupIdOnMainThread(
int32_t* group_id,
base::WaitableEvent* event) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
if (chromeos::CrasAudioHandler::IsInitialized()) {
*group_id = chromeos::CrasAudioHandler::Get()->system_aec_group_id();
}
event->Signal();
}
void AudioManagerCras::WaitEventOrShutdown(base::WaitableEvent* event) {
base::WaitableEvent* waitables[] = {event, &on_shutdown_};
base::WaitableEvent::WaitMany(waitables, arraysize(waitables));
......
......@@ -82,6 +82,9 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
// Get if system AEC is supported or not for this board.
bool GetSystemAecSupportedPerBoard();
// Get what the system AEC group ID is for this board.
int32_t GetSystemAecGroupIdPerBoard();
void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names);
std::string GetHardwareDeviceFromDeviceId(
......@@ -102,6 +105,8 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
base::WaitableEvent* event);
void GetSystemAecSupportedOnMainThread(bool* system_aec_supported,
base::WaitableEvent* event);
void GetSystemAecGroupIdOnMainThread(int32_t* group_id,
base::WaitableEvent* event);
void WaitEventOrShutdown(base::WaitableEvent* event);
......
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