1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/audio/audio_manager_base.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/macros.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/optional.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "build/build_config.h"
20 #include "build/buildflag.h"
21 #include "media/audio/audio_device_description.h"
22 #include "media/audio/audio_output_dispatcher_impl.h"
23 #include "media/audio/audio_output_proxy.h"
24 #include "media/audio/audio_output_resampler.h"
25 #include "media/audio/fake_audio_input_stream.h"
26 #include "media/audio/fake_audio_output_stream.h"
27 #include "media/base/media_switches.h"
28
29 #include "base/logging.h"
30 #include "build/chromeos_buildflags.h"
31 #include "media/audio/audio_input_stream_data_interceptor.h"
32
33 namespace media {
34
35 namespace {
36
37 const int kStreamCloseDelaySeconds = 5;
38
39 // Default maximum number of output streams that can be open simultaneously
40 // for all platforms.
41 const int kDefaultMaxOutputStreams = 16;
42
43 // Default maximum number of input streams that can be open simultaneously
44 // for all platforms.
45 const int kMaxInputStreams = 16;
46
47 const int kMaxInputChannels = 3;
48
49 // Helper function to pass as callback when the audio debug recording is not
50 // enabled.
GetNullptrAudioDebugRecorder(const AudioParameters & params)51 std::unique_ptr<AudioDebugRecorder> GetNullptrAudioDebugRecorder(
52 const AudioParameters& params) {
53 return nullptr;
54 }
55
56 // This enum must match the numbering for AudioOutputProxyStreamFormat in
57 // enums.xml. Do not reorder or remove items, only add new items before
58 // STREAM_FORMAT_MAX.
59 enum StreamFormat {
60 STREAM_FORMAT_BITSTREAM = 0,
61 STREAM_FORMAT_PCM_LINEAR = 1,
62 STREAM_FORMAT_PCM_LOW_LATENCY = 2,
63 STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE = 3,
64 STREAM_FORMAT_FAKE = 4,
65 STREAM_FORMAT_MAX = 4,
66 };
67
68 PRINTF_FORMAT(2, 3)
SendLogMessage(const AudioManagerBase::LogCallback & callback,const char * format,...)69 void SendLogMessage(const AudioManagerBase::LogCallback& callback,
70 const char* format,
71 ...) {
72 if (callback.is_null())
73 return;
74 va_list args;
75 va_start(args, format);
76 callback.Run("AMB::" + base::StringPrintV(format, args));
77 va_end(args);
78 }
79
80 } // namespace
81
82 struct AudioManagerBase::DispatcherParams {
DispatcherParamsmedia::AudioManagerBase::DispatcherParams83 DispatcherParams(const AudioParameters& input,
84 const AudioParameters& output,
85 const std::string& output_device_id)
86 : input_params(input),
87 output_params(output),
88 output_device_id(output_device_id) {}
89 ~DispatcherParams() = default;
90
91 const AudioParameters input_params;
92 const AudioParameters output_params;
93 const std::string output_device_id;
94 std::unique_ptr<AudioOutputDispatcher> dispatcher;
95
96 private:
97 DISALLOW_COPY_AND_ASSIGN(DispatcherParams);
98 };
99
100 class AudioManagerBase::CompareByParams {
101 public:
CompareByParams(const DispatcherParams * dispatcher)102 explicit CompareByParams(const DispatcherParams* dispatcher)
103 : dispatcher_(dispatcher) {}
operator ()(const std::unique_ptr<DispatcherParams> & dispatcher_in) const104 bool operator()(
105 const std::unique_ptr<DispatcherParams>& dispatcher_in) const {
106 // We will reuse the existing dispatcher when:
107 // 1) Unified IO is not used, input_params and output_params of the
108 // existing dispatcher are the same as the requested dispatcher.
109 // 2) Unified IO is used, input_params and output_params of the existing
110 // dispatcher are the same as the request dispatcher.
111 return (dispatcher_->input_params.Equals(dispatcher_in->input_params) &&
112 dispatcher_->output_params.Equals(dispatcher_in->output_params) &&
113 dispatcher_->output_device_id == dispatcher_in->output_device_id);
114 }
115
116 private:
117 const DispatcherParams* dispatcher_;
118 };
119
AudioManagerBase(std::unique_ptr<AudioThread> audio_thread,AudioLogFactory * audio_log_factory)120 AudioManagerBase::AudioManagerBase(std::unique_ptr<AudioThread> audio_thread,
121 AudioLogFactory* audio_log_factory)
122 : AudioManager(std::move(audio_thread)),
123 max_num_output_streams_(kDefaultMaxOutputStreams),
124 num_output_streams_(0),
125 // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we
126 // don't block the UI thread when swapping devices.
127 output_listeners_(base::ObserverListPolicy::EXISTING_ONLY),
128 audio_log_factory_(audio_log_factory) {}
129
~AudioManagerBase()130 AudioManagerBase::~AudioManagerBase() {
131 // All the output streams should have been deleted.
132 CHECK_EQ(0, num_output_streams_);
133 // All the input streams should have been deleted.
134 CHECK(input_streams_.empty());
135 }
136
GetAudioInputDeviceDescriptions(AudioDeviceDescriptions * device_descriptions)137 void AudioManagerBase::GetAudioInputDeviceDescriptions(
138 AudioDeviceDescriptions* device_descriptions) {
139 CHECK(GetTaskRunner()->BelongsToCurrentThread());
140 GetAudioDeviceDescriptions(device_descriptions,
141 &AudioManagerBase::GetAudioInputDeviceNames,
142 &AudioManagerBase::GetDefaultInputDeviceID,
143 &AudioManagerBase::GetCommunicationsInputDeviceID,
144 &AudioManagerBase::GetGroupIDInput);
145 }
146
GetAudioOutputDeviceDescriptions(AudioDeviceDescriptions * device_descriptions)147 void AudioManagerBase::GetAudioOutputDeviceDescriptions(
148 AudioDeviceDescriptions* device_descriptions) {
149 CHECK(GetTaskRunner()->BelongsToCurrentThread());
150 GetAudioDeviceDescriptions(device_descriptions,
151 &AudioManagerBase::GetAudioOutputDeviceNames,
152 &AudioManagerBase::GetDefaultOutputDeviceID,
153 &AudioManagerBase::GetCommunicationsOutputDeviceID,
154 &AudioManagerBase::GetGroupIDOutput);
155 }
156
GetAudioDeviceDescriptions(AudioDeviceDescriptions * device_descriptions,void (AudioManagerBase::* get_device_names)(AudioDeviceNames *),std::string (AudioManagerBase::* get_default_device_id)(),std::string (AudioManagerBase::* get_communications_device_id)(),std::string (AudioManagerBase::* get_group_id)(const std::string &))157 void AudioManagerBase::GetAudioDeviceDescriptions(
158 AudioDeviceDescriptions* device_descriptions,
159 void (AudioManagerBase::*get_device_names)(AudioDeviceNames*),
160 std::string (AudioManagerBase::*get_default_device_id)(),
161 std::string (AudioManagerBase::*get_communications_device_id)(),
162 std::string (AudioManagerBase::*get_group_id)(const std::string&)) {
163 CHECK(GetTaskRunner()->BelongsToCurrentThread());
164 AudioDeviceNames device_names;
165 (this->*get_device_names)(&device_names);
166 std::string real_default_device_id = (this->*get_default_device_id)();
167 std::string real_communications_device_id =
168 (this->*get_communications_device_id)();
169 std::string real_default_name;
170 std::string real_communications_name;
171
172 // Find the names for the real devices that are mapped to the default and
173 // communications devices.
174 for (const auto& name : device_names) {
175 if (name.unique_id == real_default_device_id)
176 real_default_name = name.device_name;
177 if (name.unique_id == real_communications_device_id)
178 real_communications_name = name.device_name;
179 }
180
181 for (auto& name : device_names) {
182 if (AudioDeviceDescription::IsDefaultDevice(name.unique_id))
183 name.device_name = real_default_name;
184 else if (AudioDeviceDescription::IsCommunicationsDevice(name.unique_id))
185 name.device_name = real_communications_name;
186 std::string group_id = (this->*get_group_id)(name.unique_id);
187 device_descriptions->emplace_back(std::move(name.device_name),
188 std::move(name.unique_id),
189 std::move(group_id));
190 }
191 }
192
MakeAudioOutputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)193 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
194 const AudioParameters& params,
195 const std::string& device_id,
196 const LogCallback& log_callback) {
197 CHECK(GetTaskRunner()->BelongsToCurrentThread());
198 DCHECK(params.IsValid());
199
200 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
201 switches::kFailAudioStreamCreation)) {
202 return nullptr;
203 }
204
205 SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
206 device_id.c_str(), params.AsHumanReadableString().c_str());
207
208 // Limit the number of audio streams opened. This is to prevent using
209 // excessive resources for a large number of audio streams. More
210 // importantly it prevents instability on certain systems.
211 // See bug: http://crbug.com/30242.
212 if (num_output_streams_ >= max_num_output_streams_) {
213 LOG(ERROR) << "Number of opened output audio streams "
214 << num_output_streams_ << " exceed the max allowed number "
215 << max_num_output_streams_;
216 return nullptr;
217 }
218
219 AudioOutputStream* stream;
220 switch (params.format()) {
221 case AudioParameters::AUDIO_PCM_LINEAR:
222 DCHECK(AudioDeviceDescription::IsDefaultDevice(device_id))
223 << "AUDIO_PCM_LINEAR supports only the default device.";
224 stream = MakeLinearOutputStream(params, log_callback);
225 break;
226 case AudioParameters::AUDIO_PCM_LOW_LATENCY:
227 stream = MakeLowLatencyOutputStream(params, device_id, log_callback);
228 break;
229 case AudioParameters::AUDIO_BITSTREAM_AC3:
230 case AudioParameters::AUDIO_BITSTREAM_EAC3:
231 stream = MakeBitstreamOutputStream(params, device_id, log_callback);
232 break;
233 case AudioParameters::AUDIO_FAKE:
234 stream = FakeAudioOutputStream::MakeFakeStream(this, params);
235 break;
236 default:
237 stream = nullptr;
238 break;
239 }
240
241 if (stream) {
242 ++num_output_streams_;
243 SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
244 output_stream_count());
245 }
246
247 return stream;
248 }
249
MakeBitstreamOutputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)250 AudioOutputStream* AudioManagerBase::MakeBitstreamOutputStream(
251 const AudioParameters& params,
252 const std::string& device_id,
253 const LogCallback& log_callback) {
254 return nullptr;
255 }
256
MakeAudioInputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)257 AudioInputStream* AudioManagerBase::MakeAudioInputStream(
258 const AudioParameters& params,
259 const std::string& device_id,
260 const LogCallback& log_callback) {
261 CHECK(GetTaskRunner()->BelongsToCurrentThread());
262
263 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
264 switches::kFailAudioStreamCreation)) {
265 return nullptr;
266 }
267
268 SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
269 device_id.c_str(), params.AsHumanReadableString().c_str());
270
271 if (!params.IsValid() || (params.channels() > kMaxInputChannels) ||
272 device_id.empty()) {
273 DLOG(ERROR) << "Audio parameters are invalid for device " << device_id
274 << ", params: " << params.AsHumanReadableString();
275 return nullptr;
276 }
277
278 if (input_stream_count() >= kMaxInputStreams) {
279 LOG(ERROR) << "Number of opened input audio streams "
280 << input_stream_count() << " exceed the max allowed number "
281 << kMaxInputStreams;
282 return nullptr;
283 }
284
285 DVLOG(2) << "Creating a new AudioInputStream with buffer size = "
286 << params.frames_per_buffer();
287
288 AudioInputStream* stream;
289 switch (params.format()) {
290 case AudioParameters::AUDIO_PCM_LINEAR:
291 stream = MakeLinearInputStream(params, device_id, log_callback);
292 break;
293 case AudioParameters::AUDIO_PCM_LOW_LATENCY:
294 stream = MakeLowLatencyInputStream(params, device_id, log_callback);
295 break;
296 case AudioParameters::AUDIO_FAKE:
297 stream = FakeAudioInputStream::MakeFakeStream(this, params);
298 break;
299 default:
300 stream = nullptr;
301 break;
302 }
303
304 if (stream) {
305 input_streams_.insert(stream);
306 if (!log_callback.is_null()) {
307 SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
308 input_stream_count());
309 }
310
311 if (!params.IsBitstreamFormat() && debug_recording_manager_) {
312 // Using unretained for |debug_recording_manager_| is safe since it
313 // outlives the audio thread, on which streams are operated.
314 // Note: The AudioInputStreamDataInterceptor takes ownership of the
315 // created stream and cleans it up when it is Close()d, transparently to
316 // the user of the stream. I the case where the audio manager closes the
317 // stream (Mac), this will result in a dangling pointer.
318 stream = new AudioInputStreamDataInterceptor(
319 base::BindRepeating(
320 &AudioDebugRecordingManager::RegisterDebugRecordingSource,
321 base::Unretained(debug_recording_manager_.get()),
322 AudioDebugRecordingStreamType::kInput, params),
323 stream);
324 }
325 }
326
327 return stream;
328 }
329
MakeAudioOutputStreamProxy(const AudioParameters & params,const std::string & device_id)330 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
331 const AudioParameters& params,
332 const std::string& device_id) {
333 CHECK(GetTaskRunner()->BelongsToCurrentThread());
334 DCHECK(params.IsValid());
335 base::Optional<StreamFormat> uma_stream_format;
336
337 // If the caller supplied an empty device id to select the default device,
338 // we fetch the actual device id of the default device so that the lookup
339 // will find the correct device regardless of whether it was opened as
340 // "default" or via the specific id.
341 // NOTE: Implementations that don't yet support opening non-default output
342 // devices may return an empty string from GetDefaultOutputDeviceID().
343 std::string output_device_id =
344 AudioDeviceDescription::IsDefaultDevice(device_id)
345 ?
346 #if BUILDFLAG(IS_ASH)
347 // On ChromeOS, it is expected that, if the default device is given,
348 // no specific device ID should be used since the actual output device
349 // should change dynamically if the system default device changes.
350 // See http://crbug.com/750614.
351 std::string()
352 #else
353 GetDefaultOutputDeviceID()
354 #endif
355 : device_id;
356
357 // If we're not using AudioOutputResampler our output parameters are the same
358 // as our input parameters.
359 AudioParameters output_params = params;
360
361 // If audio has been disabled force usage of a fake audio stream.
362 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
363 switches::kDisableAudioOutput)) {
364 output_params.set_format(AudioParameters::AUDIO_FAKE);
365 }
366
367 if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY &&
368 output_params.format() != AudioParameters::AUDIO_FAKE) {
369 output_params =
370 GetPreferredOutputStreamParameters(output_device_id, params);
371
372 // Ensure we only pass on valid output parameters.
373 if (output_params.IsValid()) {
374 if (params.effects() & AudioParameters::MULTIZONE) {
375 // Never turn off the multizone effect even if it is not preferred.
376 output_params.set_effects(output_params.effects() |
377 AudioParameters::MULTIZONE);
378 }
379 if (params.effects() != output_params.effects()) {
380 // Turn off effects that weren't requested.
381 output_params.set_effects(params.effects() & output_params.effects());
382 }
383
384 uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY;
385 } else {
386 // We've received invalid audio output parameters, so switch to a mock
387 // output device based on the input parameters. This may happen if the OS
388 // provided us junk values for the hardware configuration.
389 LOG(ERROR) << "Invalid audio output parameters received; using fake "
390 << "audio path: " << output_params.AsHumanReadableString();
391
392 // Tell the AudioManager to create a fake output device.
393 output_params = params;
394 output_params.set_format(AudioParameters::AUDIO_FAKE);
395 uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE;
396 }
397
398 output_params.set_latency_tag(params.latency_tag());
399 } else {
400 switch (output_params.format()) {
401 case AudioParameters::AUDIO_PCM_LINEAR:
402 uma_stream_format = STREAM_FORMAT_PCM_LINEAR;
403 break;
404 case AudioParameters::AUDIO_FAKE:
405 uma_stream_format = STREAM_FORMAT_FAKE;
406 break;
407 default:
408 if (output_params.IsBitstreamFormat())
409 uma_stream_format = STREAM_FORMAT_BITSTREAM;
410 else
411 NOTREACHED();
412 }
413 }
414
415 if (uma_stream_format) {
416 UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputStreamProxy.StreamFormat",
417 *uma_stream_format, STREAM_FORMAT_MAX + 1);
418 } else {
419 NOTREACHED();
420 }
421
422 std::unique_ptr<DispatcherParams> dispatcher_params =
423 std::make_unique<DispatcherParams>(params, output_params,
424 output_device_id);
425
426 auto it = std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
427 CompareByParams(dispatcher_params.get()));
428 if (it != output_dispatchers_.end())
429 return (*it)->dispatcher->CreateStreamProxy();
430
431 const base::TimeDelta kCloseDelay =
432 base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds);
433 std::unique_ptr<AudioOutputDispatcher> dispatcher;
434 if (output_params.format() != AudioParameters::AUDIO_FAKE &&
435 !output_params.IsBitstreamFormat()) {
436 // Using unretained for |debug_recording_manager_| is safe since it
437 // outlives the dispatchers (cleared in ShutdownOnAudioThread()).
438 dispatcher = std::make_unique<AudioOutputResampler>(
439 this, params, output_params, output_device_id, kCloseDelay,
440 debug_recording_manager_
441 ? base::BindRepeating(
442 &AudioDebugRecordingManager::RegisterDebugRecordingSource,
443 base::Unretained(debug_recording_manager_.get()),
444 AudioDebugRecordingStreamType::kOutput)
445 : base::BindRepeating(&GetNullptrAudioDebugRecorder));
446 } else {
447 dispatcher = std::make_unique<AudioOutputDispatcherImpl>(
448 this, output_params, output_device_id, kCloseDelay);
449 }
450
451 dispatcher_params->dispatcher = std::move(dispatcher);
452 output_dispatchers_.push_back(std::move(dispatcher_params));
453 return output_dispatchers_.back()->dispatcher->CreateStreamProxy();
454 }
455
GetAudioInputDeviceNames(AudioDeviceNames * device_names)456 void AudioManagerBase::GetAudioInputDeviceNames(
457 AudioDeviceNames* device_names) {
458 }
459
GetAudioOutputDeviceNames(AudioDeviceNames * device_names)460 void AudioManagerBase::GetAudioOutputDeviceNames(
461 AudioDeviceNames* device_names) {
462 }
463
ReleaseOutputStream(AudioOutputStream * stream)464 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
465 CHECK(GetTaskRunner()->BelongsToCurrentThread());
466 DCHECK(stream);
467 CHECK_GT(num_output_streams_, 0);
468 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
469 // For example, pass the ownership to AudioManager so it can delete the
470 // streams.
471 --num_output_streams_;
472 delete stream;
473 }
474
ReleaseInputStream(AudioInputStream * stream)475 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
476 CHECK(GetTaskRunner()->BelongsToCurrentThread());
477 DCHECK(stream);
478 // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
479 CHECK_EQ(1u, input_streams_.erase(stream));
480 delete stream;
481 }
482
ShutdownOnAudioThread()483 void AudioManagerBase::ShutdownOnAudioThread() {
484 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
485
486 // Close all output streams.
487 output_dispatchers_.clear();
488 }
489
AddOutputDeviceChangeListener(AudioDeviceListener * listener)490 void AudioManagerBase::AddOutputDeviceChangeListener(
491 AudioDeviceListener* listener) {
492 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
493 output_listeners_.AddObserver(listener);
494 }
495
RemoveOutputDeviceChangeListener(AudioDeviceListener * listener)496 void AudioManagerBase::RemoveOutputDeviceChangeListener(
497 AudioDeviceListener* listener) {
498 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
499 output_listeners_.RemoveObserver(listener);
500 }
501
NotifyAllOutputDeviceChangeListeners()502 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() {
503 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
504 DVLOG(1) << "Firing OnDeviceChange() notifications.";
505 for (auto& observer : output_listeners_)
506 observer.OnDeviceChange();
507 }
508
GetDefaultOutputStreamParameters()509 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() {
510 return GetPreferredOutputStreamParameters(GetDefaultOutputDeviceID(),
511 AudioParameters());
512 }
513
GetOutputStreamParameters(const std::string & device_id)514 AudioParameters AudioManagerBase::GetOutputStreamParameters(
515 const std::string& device_id) {
516 return GetPreferredOutputStreamParameters(device_id,
517 AudioParameters());
518 }
519
GetInputStreamParameters(const std::string & device_id)520 AudioParameters AudioManagerBase::GetInputStreamParameters(
521 const std::string& device_id) {
522 NOTREACHED();
523 return AudioParameters();
524 }
525
GetAssociatedOutputDeviceID(const std::string & input_device_id)526 std::string AudioManagerBase::GetAssociatedOutputDeviceID(
527 const std::string& input_device_id) {
528 return std::string();
529 }
530
GetGroupIDOutput(const std::string & output_device_id)531 std::string AudioManagerBase::GetGroupIDOutput(
532 const std::string& output_device_id) {
533 if (output_device_id == AudioDeviceDescription::kDefaultDeviceId) {
534 std::string real_device_id = GetDefaultOutputDeviceID();
535 if (!real_device_id.empty())
536 return real_device_id;
537 } else if (output_device_id ==
538 AudioDeviceDescription::kCommunicationsDeviceId) {
539 std::string real_device_id = GetCommunicationsOutputDeviceID();
540 if (!real_device_id.empty())
541 return real_device_id;
542 }
543 return output_device_id;
544 }
545
GetGroupIDInput(const std::string & input_device_id)546 std::string AudioManagerBase::GetGroupIDInput(
547 const std::string& input_device_id) {
548 const std::string& real_input_device_id =
549 input_device_id == AudioDeviceDescription::kDefaultDeviceId
550 ? GetDefaultInputDeviceID()
551 : input_device_id == AudioDeviceDescription::kCommunicationsDeviceId
552 ? GetCommunicationsInputDeviceID()
553 : input_device_id;
554 std::string output_device_id =
555 GetAssociatedOutputDeviceID(real_input_device_id);
556 if (output_device_id.empty()) {
557 // Some characters are added to avoid accidentally
558 // giving the input the same group id as an output.
559 return real_input_device_id + "input";
560 }
561 return GetGroupIDOutput(output_device_id);
562 }
563
CloseAllInputStreams()564 void AudioManagerBase::CloseAllInputStreams() {
565 for (auto iter = input_streams_.begin(); iter != input_streams_.end();) {
566 // Note: Closing the stream will invalidate the iterator.
567 // Increment the iterator before closing the stream.
568 AudioInputStream* stream = *iter++;
569 stream->Close();
570 }
571 CHECK(input_streams_.empty());
572 }
573
GetDefaultInputDeviceID()574 std::string AudioManagerBase::GetDefaultInputDeviceID() {
575 return std::string();
576 }
577
GetDefaultOutputDeviceID()578 std::string AudioManagerBase::GetDefaultOutputDeviceID() {
579 return std::string();
580 }
581
GetCommunicationsInputDeviceID()582 std::string AudioManagerBase::GetCommunicationsInputDeviceID() {
583 return std::string();
584 }
585
GetCommunicationsOutputDeviceID()586 std::string AudioManagerBase::GetCommunicationsOutputDeviceID() {
587 return std::string();
588 }
589
590 // static
GetUserBufferSize()591 int AudioManagerBase::GetUserBufferSize() {
592 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
593 int buffer_size = 0;
594 std::string buffer_size_str(cmd_line->GetSwitchValueASCII(
595 switches::kAudioBufferSize));
596 if (base::StringToInt(buffer_size_str, &buffer_size) && buffer_size > 0)
597 return buffer_size;
598
599 return 0;
600 }
601
CreateAudioLog(AudioLogFactory::AudioComponent component,int component_id)602 std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
603 AudioLogFactory::AudioComponent component,
604 int component_id) {
605 return audio_log_factory_->CreateAudioLog(component, component_id);
606 }
607
InitializeDebugRecording()608 void AudioManagerBase::InitializeDebugRecording() {
609 if (!GetTaskRunner()->BelongsToCurrentThread()) {
610 // AudioManager is deleted on the audio thread, so it's safe to post
611 // unretained.
612 GetTaskRunner()->PostTask(
613 FROM_HERE, base::BindOnce(&AudioManagerBase::InitializeDebugRecording,
614 base::Unretained(this)));
615 return;
616 }
617
618 DCHECK(!debug_recording_manager_);
619 debug_recording_manager_ = CreateAudioDebugRecordingManager(GetTaskRunner());
620 }
621
622 std::unique_ptr<AudioDebugRecordingManager>
CreateAudioDebugRecordingManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner)623 AudioManagerBase::CreateAudioDebugRecordingManager(
624 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
625 return std::make_unique<AudioDebugRecordingManager>(std::move(task_runner));
626 }
627
GetAudioDebugRecordingManager()628 AudioDebugRecordingManager* AudioManagerBase::GetAudioDebugRecordingManager() {
629 DCHECK(GetTaskRunner()->BelongsToCurrentThread());
630 return debug_recording_manager_.get();
631 }
632
633 } // namespace media
634