Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(504)

Side by Side Diff: media/audio/cras/audio_manager_cras.cc

Issue 1275783003: Add a virtual beamforming audio device on ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More constructors. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/cras/audio_manager_cras.h" 5 #include "media/audio/cras/audio_manager_cras.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/environment.h" 10 #include "base/environment.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/nix/xdg_util.h" 12 #include "base/nix/xdg_util.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "chromeos/audio/audio_device.h" 14 #include "chromeos/audio/audio_device.h"
15 #include "chromeos/audio/cras_audio_handler.h" 15 #include "chromeos/audio/cras_audio_handler.h"
16 #include "media/audio/cras/cras_input.h" 16 #include "media/audio/cras/cras_input.h"
17 #include "media/audio/cras/cras_unified.h" 17 #include "media/audio/cras/cras_unified.h"
18 #include "media/base/channel_layout.h" 18 #include "media/base/channel_layout.h"
19 19
20 // cras_util.h headers pull in min/max macros... 20 // cras_util.h headers pull in min/max macros...
21 // TODO(dgreid): Fix headers such that these aren't imported. 21 // TODO(dgreid): Fix headers such that these aren't imported.
22 #undef min 22 #undef min
23 #undef max 23 #undef max
24 24
25 namespace media { 25 namespace media {
26 namespace {
26 27
27 static void AddDefaultDevice(AudioDeviceNames* device_names) { 28 void AddDefaultDevice(AudioDeviceNames* device_names) {
28 DCHECK(device_names->empty());
Henrik Grunell 2015/08/27 08:38:18 Why remove the dcheck?
29
30 // Cras will route audio from a proper physical device automatically. 29 // Cras will route audio from a proper physical device automatically.
31 device_names->push_back( 30 device_names->push_back(
32 AudioDeviceName(AudioManagerBase::kDefaultDeviceName, 31 AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
33 AudioManagerBase::kDefaultDeviceId)); 32 AudioManagerBase::kDefaultDeviceId));
34 } 33 }
35 34
35 std::string GetMicPositions() {
Henrik Grunell 2015/08/27 08:38:18 Add comment. Can the function be called on any th
36 // Get the list of devices from CRAS. An internal mic with a non-empty
37 // positions field indicates the machine has a beamforming capable mic array.
38 chromeos::AudioDeviceList devices;
39 chromeos::CrasAudioHandler::Get()->GetAudioDevices(&devices);
40 for (const auto& device : devices) {
41 if (device.type == chromeos::AUDIO_TYPE_INTERNAL_MIC) {
42 // There should be only one internal mic device.
43 return device.mic_positions;
44 }
45 }
46 return "";
47 }
48
36 // Maximum number of output streams that can be open simultaneously. 49 // Maximum number of output streams that can be open simultaneously.
37 static const int kMaxOutputStreams = 50; 50 const int kMaxOutputStreams = 50;
38 51
39 // Default sample rate for input and output streams. 52 // Default sample rate for input and output streams.
40 static const int kDefaultSampleRate = 48000; 53 const int kDefaultSampleRate = 48000;
41 54
42 // Define bounds for the output buffer size. 55 // Define bounds for the output buffer size.
43 static const int kMinimumOutputBufferSize = 512; 56 const int kMinimumOutputBufferSize = 512;
44 static const int kMaximumOutputBufferSize = 8192; 57 const int kMaximumOutputBufferSize = 8192;
45 58
46 // Default input buffer size. 59 // Default input buffer size.
47 static const int kDefaultInputBufferSize = 1024; 60 const int kDefaultInputBufferSize = 1024;
61
62 const char kBeamformingDeviceNameSuffix[] = " with beamforming";
63 const char kBeamformingDeviceIdSuffix[] = "-beamforming";
aluebs-chromium 2015/08/28 19:14:30 Since they are user-facing strings, is this the ri
ajm 2015/08/28 20:17:18 Great question, I wonder the same thing! The exist
dgreid 2015/08/28 20:24:55 I don't think we ever bothered to translate "Defau
64
65 } // namespace
48 66
49 bool AudioManagerCras::HasAudioOutputDevices() { 67 bool AudioManagerCras::HasAudioOutputDevices() {
50 return true; 68 return true;
51 } 69 }
52 70
53 bool AudioManagerCras::HasAudioInputDevices() { 71 bool AudioManagerCras::HasAudioInputDevices() {
54 chromeos::AudioDeviceList devices; 72 chromeos::AudioDeviceList devices;
55 chromeos::CrasAudioHandler::Get()->GetAudioDevices(&devices); 73 chromeos::CrasAudioHandler::Get()->GetAudioDevices(&devices);
56 for (size_t i = 0; i < devices.size(); ++i) { 74 for (size_t i = 0; i < devices.size(); ++i) {
57 if (devices[i].is_input && devices[i].is_for_simple_usage()) 75 if (devices[i].is_input && devices[i].is_for_simple_usage())
58 return true; 76 return true;
59 } 77 }
60 return false; 78 return false;
61 } 79 }
62 80
63 AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory) 81 AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory)
64 : AudioManagerBase(audio_log_factory), 82 : AudioManagerBase(audio_log_factory),
65 has_keyboard_mic_(false) { 83 has_keyboard_mic_(false),
84 beamforming_device_name_(
85 std::string(AudioManagerBase::kDefaultDeviceName) +
86 kBeamformingDeviceNameSuffix,
87 std::string(AudioManagerBase::kDefaultDeviceId) +
88 kBeamformingDeviceIdSuffix),
89 mic_positions_(GetMicPositions()) {
66 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 90 SetMaxOutputStreamsAllowed(kMaxOutputStreams);
67 } 91 }
68 92
69 AudioManagerCras::~AudioManagerCras() { 93 AudioManagerCras::~AudioManagerCras() {
70 Shutdown(); 94 Shutdown();
71 } 95 }
72 96
73 void AudioManagerCras::ShowAudioInputSettings() { 97 void AudioManagerCras::ShowAudioInputSettings() {
74 NOTIMPLEMENTED(); 98 NOTIMPLEMENTED();
75 } 99 }
76 100
77 void AudioManagerCras::GetAudioInputDeviceNames( 101 void AudioManagerCras::GetAudioInputDeviceNames(
78 AudioDeviceNames* device_names) { 102 AudioDeviceNames* device_names) {
103 // A non-empty mic_positions indicates we have a beamforming capable mic
104 // array. Add the virtual beamforming device to the list. When this device is
105 // queried through GetInputStreamParameters, provide the cached mic positions.
106 if (!mic_positions_.empty()) {
aluebs-chromium 2015/08/28 19:14:30 Shouldn't we be more restrictive here? For instanc
ajm 2015/08/28 23:38:31 That's a good point. I have those checks in MSAP f
aluebs-chromium 2015/08/29 00:00:26 Yes, I know it was in MSAP, but if we do it here w
ajm 2015/09/02 20:38:41 Forgot to switch the check to > 1 mic. Done in PS#
107 device_names->push_back(beamforming_device_name_);
108 }
109
79 AddDefaultDevice(device_names); 110 AddDefaultDevice(device_names);
80 } 111 }
81 112
82 void AudioManagerCras::GetAudioOutputDeviceNames( 113 void AudioManagerCras::GetAudioOutputDeviceNames(
83 AudioDeviceNames* device_names) { 114 AudioDeviceNames* device_names) {
84 AddDefaultDevice(device_names); 115 AddDefaultDevice(device_names);
85 } 116 }
86 117
87 AudioParameters AudioManagerCras::GetInputStreamParameters( 118 AudioParameters AudioManagerCras::GetInputStreamParameters(
88 const std::string& device_id) { 119 const std::string& device_id) {
89 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 120 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
90 121
91 int user_buffer_size = GetUserBufferSize(); 122 int user_buffer_size = GetUserBufferSize();
92 int buffer_size = user_buffer_size ? 123 int buffer_size = user_buffer_size ?
93 user_buffer_size : kDefaultInputBufferSize; 124 user_buffer_size : kDefaultInputBufferSize;
94 AudioParameters::PlatformEffectsMask effects = 125 AudioParameters::PlatformEffectsMask effects =
95 has_keyboard_mic_ ? AudioParameters::KEYBOARD_MIC 126 has_keyboard_mic_ ? AudioParameters::KEYBOARD_MIC
96 : AudioParameters::NO_EFFECTS; 127 : AudioParameters::NO_EFFECTS;
128 // Return the cached mic positions in the case of the beamforming device.
129 const std::string& mic_positions =
130 device_id == beamforming_device_name_.unique_id ? mic_positions_ : "";
97 131
98 // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal 132 // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
99 // parameters for the loopback stream may differ from the default. 133 // parameters for the loopback stream may differ from the default.
100 return AudioParameters( 134 return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
101 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 135 CHANNEL_LAYOUT_STEREO, kDefaultSampleRate, 16,
aluebs-chromium 2015/08/28 19:14:30 What does CHANNEL_LAYOUT_STEREO represent? Is this
ajm 2015/08/28 23:38:31 This represents the channel layout for the audio c
aluebs-chromium 2015/08/29 00:00:26 Agreed that this CL is big enough. But it needs to
102 kDefaultSampleRate, 16, buffer_size, effects); 136 buffer_size, mic_positions, effects);
103 } 137 }
104 138
105 void AudioManagerCras::SetHasKeyboardMic() { 139 void AudioManagerCras::SetHasKeyboardMic() {
106 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); 140 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
107 has_keyboard_mic_ = true; 141 has_keyboard_mic_ = true;
108 } 142 }
109 143
110 AudioOutputStream* AudioManagerCras::MakeLinearOutputStream( 144 AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
111 const AudioParameters& params) { 145 const AudioParameters& params) {
112 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 146 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 channel_layout = input_params.channel_layout(); 183 channel_layout = input_params.channel_layout();
150 buffer_size = 184 buffer_size =
151 std::min(kMaximumOutputBufferSize, 185 std::min(kMaximumOutputBufferSize,
152 std::max(buffer_size, input_params.frames_per_buffer())); 186 std::max(buffer_size, input_params.frames_per_buffer()));
153 } 187 }
154 188
155 int user_buffer_size = GetUserBufferSize(); 189 int user_buffer_size = GetUserBufferSize();
156 if (user_buffer_size) 190 if (user_buffer_size)
157 buffer_size = user_buffer_size; 191 buffer_size = user_buffer_size;
158 192
159 return AudioParameters( 193 return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
160 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 194 sample_rate, bits_per_sample, buffer_size);
161 sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
162 } 195 }
163 196
164 AudioOutputStream* AudioManagerCras::MakeOutputStream( 197 AudioOutputStream* AudioManagerCras::MakeOutputStream(
165 const AudioParameters& params) { 198 const AudioParameters& params) {
166 return new CrasUnifiedStream(params, this); 199 return new CrasUnifiedStream(params, this);
167 } 200 }
168 201
169 AudioInputStream* AudioManagerCras::MakeInputStream( 202 AudioInputStream* AudioManagerCras::MakeInputStream(
170 const AudioParameters& params, const std::string& device_id) { 203 const AudioParameters& params, const std::string& device_id) {
171 return new CrasInputStream(params, this, device_id); 204 return new CrasInputStream(params, this, device_id);
172 } 205 }
173 206
174 snd_pcm_format_t AudioManagerCras::BitsToFormat(int bits_per_sample) { 207 snd_pcm_format_t AudioManagerCras::BitsToFormat(int bits_per_sample) {
175 switch (bits_per_sample) { 208 switch (bits_per_sample) {
176 case 8: 209 case 8:
177 return SND_PCM_FORMAT_U8; 210 return SND_PCM_FORMAT_U8;
178 case 16: 211 case 16:
179 return SND_PCM_FORMAT_S16; 212 return SND_PCM_FORMAT_S16;
180 case 24: 213 case 24:
181 return SND_PCM_FORMAT_S24; 214 return SND_PCM_FORMAT_S24;
182 case 32: 215 case 32:
183 return SND_PCM_FORMAT_S32; 216 return SND_PCM_FORMAT_S32;
184 default: 217 default:
185 return SND_PCM_FORMAT_UNKNOWN; 218 return SND_PCM_FORMAT_UNKNOWN;
186 } 219 }
187 } 220 }
188 221
189 } // namespace media 222 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698