Commit be525a56 authored by Yu-Hsuan Hsu's avatar Yu-Hsuan Hsu Committed by Commit Bot

Add audio_manager_cras

Create a new audio manager for using CRAS on linux.

Bug: 151905045
Change-Id: I968fae4da617a568ff0af97a5fd3f67d119d15d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2340359Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Commit-Queue: Yu-Hsuan Hsu <yuhsuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798446}
parent af2bb007
......@@ -268,6 +268,11 @@ source_set("audio") {
"cras/audio_manager_chromeos.h",
]
deps += [ "//chromeos/audio" ]
} else if (is_linux) {
sources += [
"cras/audio_manager_cras.cc",
"cras/audio_manager_cras.h",
]
}
}
......
......@@ -54,12 +54,14 @@
#include "media/audio/pulse/pulse_util.h"
#endif // defined(USE_PULSEAUDIO)
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
#include "chromeos/audio/audio_devices_pref_handler_stub.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/audio/fake_cras_audio_client.h"
#include "media/audio/cras/audio_manager_chromeos.h"
#endif // defined(USE_CRAS)
#elif defined(USE_CRAS) && defined(OS_LINUX)
#include "media/audio/cras/audio_manager_cras.h"
#endif
namespace media {
......@@ -98,7 +100,7 @@ struct TestAudioManagerFactory<std::nullptr_t> {
}
};
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
using chromeos::AudioNode;
using chromeos::AudioNodeList;
......@@ -294,7 +296,7 @@ class AudioManagerTest : public ::testing::Test {
device_info_accessor_->GetAssociatedOutputDeviceID(input_device_id);
}
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
void TearDown() override {
chromeos::CrasAudioHandler::Shutdown();
audio_pref_handler_ = nullptr;
......@@ -331,7 +333,7 @@ class AudioManagerTest : public ::testing::Test {
AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
limits::kMaxAudioBufferSize));
}
#endif // defined(USE_CRAS)
#endif // defined(USE_CRAS) && defined(OS_CHROMEOS)
protected:
AudioManagerTest() {
......@@ -375,7 +377,7 @@ class AudioManagerTest : public ::testing::Test {
}
}
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
// Helper method for (USE_CRAS) which verifies that the device list starts
// with a valid default record followed by physical device names.
static void CheckDeviceDescriptionsCras(
......@@ -431,7 +433,7 @@ class AudioManagerTest : public ::testing::Test {
EXPECT_NE(it, device_descriptions.end());
return it->group_id;
}
#endif // defined(USE_CRAS)
#endif // defined(USE_CRAS) && defined(OS_CHROMEOS)
bool InputDevicesAvailable() {
return device_info_accessor_->HasAudioInputDevices();
......@@ -466,13 +468,13 @@ class AudioManagerTest : public ::testing::Test {
std::unique_ptr<AudioManager> audio_manager_;
std::unique_ptr<AudioDeviceInfoAccessorForTests> device_info_accessor_;
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
chromeos::CrasAudioHandler* cras_audio_handler_ = nullptr; // Not owned.
scoped_refptr<chromeos::AudioDevicesPrefHandlerStub> audio_pref_handler_;
#endif // defined(USE_CRAS)
#endif // defined(USE_CRAS) && defined(OS_CHROMEOS)
};
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
TEST_F(AudioManagerTest, EnumerateInputDevicesCras) {
// Setup the devices without internal mic, so that it doesn't exist
// beamforming capable mic.
......@@ -697,7 +699,7 @@ TEST_F(AudioManagerTest, LookupDefaultOutputDeviceWithProperGroupId) {
EXPECT_EQ(default_device_group_id, speaker_group_id);
EXPECT_EQ(base::NumberToString(kInternalSpeaker.id), new_default_device_id);
}
#else // !defined(USE_CRAS)
#else // !(defined(USE_CRAS) && defined(OS_CHROMEOS))
TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) {
// Use a fake manager so we can makeup device ids, this will still use the
......@@ -841,7 +843,7 @@ TEST_F(AudioManagerTest, GetAssociatedOutputDeviceID) {
EXPECT_TRUE(found_an_associated_device);
#endif // defined(OS_WIN) || defined(OS_MAC)
}
#endif // defined(USE_CRAS)
#endif // defined(USE_CRAS) && defined(OS_CHROMEOS)
class TestAudioManager : public FakeAudioManager {
// For testing the default implementation of GetGroupId(Input|Output)
......@@ -1004,7 +1006,7 @@ TEST_F(AudioManagerTest, CheckMinMaxAudioBufferSizeCallbacks) {
#if defined(OS_MAC)
CreateAudioManagerForTesting<AudioManagerMac>();
#elif defined(USE_CRAS)
#elif defined(USE_CRAS) && defined(OS_CHROMEOS)
CreateAudioManagerForTesting<AudioManagerChromeOS>();
#endif
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/audio/cras/audio_manager_cras.h"
#include <stddef.h>
#include <algorithm>
#include <map>
#include <utility>
#include "base/bind.h"
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/environment.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"
#include "base/system/sys_info.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_features.h"
#include "media/audio/cras/cras_input.h"
#include "media/audio/cras/cras_unified.h"
#include "media/base/channel_layout.h"
#include "media/base/limits.h"
#include "media/base/localized_strings.h"
namespace media {
namespace {
// Default sample rate for input and output streams.
const int kDefaultSampleRate = 48000;
// Default input buffer size.
const int kDefaultInputBufferSize = 1024;
// Default output buffer size.
const int kDefaultOutputBufferSize = 512;
} // namespace
bool AudioManagerCras::HasAudioOutputDevices() {
return true;
}
bool AudioManagerCras::HasAudioInputDevices() {
return true;
}
AudioManagerCras::AudioManagerCras(
std::unique_ptr<AudioThread> audio_thread,
AudioLogFactory* audio_log_factory)
: AudioManagerCrasBase(std::move(audio_thread), audio_log_factory),
main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
weak_ptr_factory_(this) {
weak_this_ = weak_ptr_factory_.GetWeakPtr();
}
AudioManagerCras::~AudioManagerCras() = default;
void AudioManagerCras::GetAudioInputDeviceNames(
AudioDeviceNames* device_names) {
device_names->push_back(AudioDeviceName::CreateDefault());
}
void AudioManagerCras::GetAudioOutputDeviceNames(
AudioDeviceNames* device_names) {
device_names->push_back(AudioDeviceName::CreateDefault());
}
AudioParameters AudioManagerCras::GetInputStreamParameters(
const std::string& device_id) {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
int user_buffer_size = GetUserBufferSize();
int buffer_size =
user_buffer_size ? user_buffer_size : kDefaultInputBufferSize;
AudioParameters params(
AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
kDefaultSampleRate, buffer_size,
AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
limits::kMaxAudioBufferSize));
return params;
}
std::string AudioManagerCras::GetDefaultInputDeviceID() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return base::NumberToString(GetPrimaryActiveInputNode());
}
std::string AudioManagerCras::GetDefaultOutputDeviceID() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return base::NumberToString(GetPrimaryActiveOutputNode());
}
AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
const std::string& output_device_id,
const AudioParameters& input_params) {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
int sample_rate = kDefaultSampleRate;
int buffer_size = GetUserBufferSize();
if (input_params.IsValid()) {
channel_layout = input_params.channel_layout();
sample_rate = input_params.sample_rate();
if (!buffer_size) // Not user-provided.
buffer_size =
std::min(static_cast<int>(limits::kMaxAudioBufferSize),
std::max(static_cast<int>(limits::kMinAudioBufferSize),
input_params.frames_per_buffer()));
}
if (!buffer_size) // Not user-provided.
buffer_size = kDefaultOutputBufferSize;
return AudioParameters(
AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
buffer_size,
AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
limits::kMaxAudioBufferSize));
}
uint64_t AudioManagerCras::GetPrimaryActiveInputNode() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return 0;
}
uint64_t AudioManagerCras::GetPrimaryActiveOutputNode() {
DCHECK(GetTaskRunner()->BelongsToCurrentThread());
return 0;
}
bool AudioManagerCras::IsDefault(const std::string& device_id, bool is_input) {
return true;
}
} // namespace media
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CRAS_H_
#define MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CRAS_H_
#include <cras_types.h>
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "media/audio/cras/audio_manager_cras_base.h"
namespace media {
class MEDIA_EXPORT AudioManagerCras : public AudioManagerCrasBase {
public:
AudioManagerCras(std::unique_ptr<AudioThread> audio_thread,
AudioLogFactory* audio_log_factory);
~AudioManagerCras() override;
// AudioManager implementation.
bool HasAudioOutputDevices() override;
bool HasAudioInputDevices() override;
void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
AudioParameters GetInputStreamParameters(
const std::string& device_id) override;
std::string GetDefaultInputDeviceID() override;
std::string GetDefaultOutputDeviceID() override;
// AudioManagerCras implementation.
bool IsDefault(const std::string& device_id, bool is_input) override;
protected:
AudioParameters GetPreferredOutputStreamParameters(
const std::string& output_device_id,
const AudioParameters& input_params) override;
private:
uint64_t GetPrimaryActiveInputNode();
uint64_t GetPrimaryActiveOutputNode();
void GetPrimaryActiveInputNodeOnMainThread(uint64_t* active_input_node_id,
base::WaitableEvent* event);
void GetPrimaryActiveOutputNodeOnMainThread(uint64_t* active_output_node_id,
base::WaitableEvent* event);
void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
base::WaitableEvent* event);
// Task runner of browser main thread. CrasAudioHandler should be only
// accessed on this thread.
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
// For posting tasks from audio thread to |main_task_runner_|.
base::WeakPtr<AudioManagerCras> weak_this_;
base::WeakPtrFactory<AudioManagerCras> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AudioManagerCras);
};
} // namespace media
#endif // MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CRAS_H_
......@@ -13,9 +13,13 @@
#if defined(USE_ALSA)
#include "media/audio/alsa/audio_manager_alsa.h"
#endif
#if defined(USE_CRAS)
#if defined(USE_CRAS) && defined(OS_CHROMEOS)
#include "media/audio/cras/audio_manager_chromeos.h"
#elif defined(USE_CRAS)
#include "media/audio/cras/audio_manager_cras.h"
#endif
#if defined(USE_PULSEAUDIO)
#include "media/audio/pulse/audio_manager_pulse.h"
#include "media/audio/pulse/pulse_util.h"
......@@ -43,10 +47,15 @@ std::unique_ptr<media::AudioManager> CreateAudioManager(
#if defined(USE_CRAS)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kCras, kAudioIOMax + 1);
#if defined(OS_CHROMEOS)
return std::make_unique<AudioManagerChromeOS>(std::move(audio_thread),
audio_log_factory);
}
#else
return std::make_unique<AudioManagerCras>(std::move(audio_thread),
audio_log_factory);
#endif
}
#endif // defined(USE_CRAS)
#if defined(USE_PULSEAUDIO)
pa_threaded_mainloop* pa_mainloop = nullptr;
......
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