audio_manager_base.cc 23 KB

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