output_device_mixer_manager.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // Copyright 2021 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 "services/audio/output_device_mixer_manager.h"
  5. #include "base/check.h"
  6. #include "base/logging.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/metrics/histogram_functions.h"
  9. #include "base/trace_event/trace_event.h"
  10. #include "media/audio/audio_io.h"
  11. #include "media/audio/audio_manager.h"
  12. #include "media/base/audio_latency.h"
  13. #include "services/audio/audio_manager_power_user.h"
  14. #include "services/audio/device_listener_output_stream.h"
  15. #include "services/audio/output_device_mixer.h"
  16. namespace {
  17. const char kNormalizedDefaultDeviceId[] = "";
  18. // Helper function which returns a consistent representation of the default
  19. // device ID.
  20. std::string NormalizeIfDefault(const std::string& device_id) {
  21. return media::AudioDeviceDescription::IsDefaultDevice(device_id)
  22. ? kNormalizedDefaultDeviceId
  23. : device_id;
  24. }
  25. // These values are persisted to logs. Entries should not be renumbered and
  26. // numeric values should never be reused.
  27. // Aligned with AudioOutputDeviceMixerManagerStreamCreation enum.
  28. enum class StreamCreation {
  29. kUnmixable,
  30. kFallbackToUnmixable,
  31. kUsingNewMixer,
  32. kUsingExistingMixer,
  33. kMaxValue = kUsingExistingMixer,
  34. };
  35. } // namespace
  36. namespace audio {
  37. OutputDeviceMixerManager::OutputDeviceMixerManager(
  38. media::AudioManager* audio_manager,
  39. OutputDeviceMixer::CreateCallback create_mixer_callback)
  40. : audio_manager_(audio_manager),
  41. current_default_device_id_(
  42. AudioManagerPowerUser(audio_manager_).GetDefaultOutputDeviceID()),
  43. current_communication_device_id_(AudioManagerPowerUser(audio_manager_)
  44. .GetCommunicationsOutputDeviceID()),
  45. create_mixer_callback_(std::move(create_mixer_callback)),
  46. device_change_weak_ptr_factory_(this) {
  47. // This should be a static_assert, but there is no compile time way to run
  48. // AudioDeviceDescription::IsDefaultDevice().
  49. DCHECK(media::AudioDeviceDescription::IsDefaultDevice(
  50. kNormalizedDefaultDeviceId));
  51. }
  52. OutputDeviceMixerManager::~OutputDeviceMixerManager() {
  53. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  54. }
  55. media::AudioOutputStream* OutputDeviceMixerManager::MakeOutputStream(
  56. const std::string& device_id,
  57. const media::AudioParameters& params,
  58. base::OnceClosure close_stream_on_device_change) {
  59. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  60. OutputDeviceMixer* mixer = nullptr;
  61. StreamCreation stream_creation = StreamCreation::kUnmixable;
  62. if (params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY) {
  63. std::string mixer_device_id = ToMixerDeviceId(device_id);
  64. mixer = FindMixer(mixer_device_id);
  65. if (mixer) {
  66. stream_creation = StreamCreation::kUsingExistingMixer;
  67. } else {
  68. mixer = AddMixer(mixer_device_id);
  69. stream_creation = mixer ? StreamCreation::kUsingNewMixer
  70. : StreamCreation::kFallbackToUnmixable;
  71. }
  72. }
  73. base::UmaHistogramEnumeration(
  74. "Media.Audio.OutputDeviceMixerManager.StreamCreation", stream_creation);
  75. if (mixer) {
  76. return mixer->MakeMixableStream(params,
  77. std::move(close_stream_on_device_change));
  78. }
  79. DLOG(WARNING) << "Making unmixable output stream";
  80. return CreateDeviceListenerStream(std::move(close_stream_on_device_change),
  81. device_id, params);
  82. }
  83. void OutputDeviceMixerManager::OnDeviceChange() {
  84. TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio"),
  85. "OutputDeviceMixerManager::OnDeviceChange");
  86. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  87. current_default_device_id_ =
  88. AudioManagerPowerUser(audio_manager_).GetDefaultOutputDeviceID();
  89. current_communication_device_id_ =
  90. AudioManagerPowerUser(audio_manager_).GetCommunicationsOutputDeviceID();
  91. // Invalidate WeakPtrs, cancelling any pending device change callbacks
  92. // generated by the same device change event.
  93. device_change_weak_ptr_factory_.InvalidateWeakPtrs();
  94. OutputDeviceMixers old_mixers;
  95. output_device_mixers_.swap(old_mixers);
  96. // Do not call StopListening(), as |old_mixers| are being destroyed anyways.
  97. for (auto&& mixer : old_mixers)
  98. mixer->ProcessDeviceChange();
  99. }
  100. void OutputDeviceMixerManager::StartNewListener(
  101. ReferenceOutput::Listener* listener,
  102. const std::string& listener_device_id) {
  103. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  104. DCHECK(IsNormalizedIfDefault(listener_device_id));
  105. DCHECK(!listener_registration_.contains(listener));
  106. listener_registration_[listener] = listener_device_id;
  107. OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(listener_device_id));
  108. if (!mixer)
  109. return;
  110. mixer->StartListening(listener);
  111. }
  112. void OutputDeviceMixerManager::StartListening(
  113. ReferenceOutput::Listener* listener,
  114. const std::string& output_device_id) {
  115. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  116. std::string listener_device_id = NormalizeIfDefault(output_device_id);
  117. if (!listener_registration_.contains(listener)) {
  118. StartNewListener(listener, listener_device_id);
  119. return;
  120. }
  121. std::string registered_listener_device_id =
  122. listener_registration_.at(listener);
  123. if (ToMixerDeviceId(registered_listener_device_id) !=
  124. ToMixerDeviceId(listener_device_id)) {
  125. // |listener| is listening to a completely different mixer.
  126. StopListening(listener);
  127. StartNewListener(listener, listener_device_id);
  128. return;
  129. }
  130. // |listener| is listening to the right mixer, but we might need to update
  131. // its registration (e.g. when switching between
  132. // |current_default_device_id_| and kNormalizedDefaultId, or
  133. // |current_communications_device_id_| and kCommunicationsDeviceId).
  134. if (registered_listener_device_id != listener_device_id)
  135. listener_registration_[listener] = listener_device_id;
  136. }
  137. void OutputDeviceMixerManager::StopListening(
  138. ReferenceOutput::Listener* listener) {
  139. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  140. const std::string listener_device_id = listener_registration_.at(listener);
  141. listener_registration_.erase(listener);
  142. OutputDeviceMixer* mixer = FindMixer(ToMixerDeviceId(listener_device_id));
  143. // The mixer was never created, because there was no playback to that device
  144. // (possibly after a device device change). Listening never started, so there
  145. // is nothing to stop.
  146. if (!mixer)
  147. return;
  148. mixer->StopListening(listener);
  149. }
  150. std::string OutputDeviceMixerManager::ToMixerDeviceId(
  151. const std::string& device_id) {
  152. if (media::AudioDeviceDescription::IsDefaultDevice(device_id))
  153. return kNormalizedDefaultDeviceId;
  154. DCHECK(!device_id.empty());
  155. if (device_id == current_default_device_id_)
  156. return kNormalizedDefaultDeviceId;
  157. // It's possible for |current_communication_device_id_| and
  158. // |current_default_device_id_| to match. In that case, replace the
  159. // communications mixer device ID with the default mixer device ID.
  160. // Similarly, replace "communications" with kNormalizedDefaultDeviceId when
  161. // |current_communication_device_id_| is unsupported/unconfigured.
  162. if (device_id == media::AudioDeviceDescription::kCommunicationsDeviceId &&
  163. (current_communication_device_id_.empty() ||
  164. current_communication_device_id_ == current_default_device_id_)) {
  165. return kNormalizedDefaultDeviceId;
  166. }
  167. if (device_id == current_communication_device_id_)
  168. return media::AudioDeviceDescription::kCommunicationsDeviceId;
  169. return device_id;
  170. }
  171. OutputDeviceMixer* OutputDeviceMixerManager::FindMixer(
  172. const std::string& device_id) {
  173. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  174. DCHECK_EQ(ToMixerDeviceId(device_id), device_id);
  175. for (const auto& mixer : output_device_mixers_) {
  176. if (mixer->device_id() == device_id)
  177. return mixer.get();
  178. }
  179. return nullptr;
  180. }
  181. OutputDeviceMixer* OutputDeviceMixerManager::AddMixer(
  182. const std::string& device_id) {
  183. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  184. DCHECK_EQ(ToMixerDeviceId(device_id), device_id);
  185. DCHECK(!FindMixer(device_id));
  186. media::AudioParameters output_params =
  187. AudioManagerPowerUser(audio_manager_)
  188. .GetOutputStreamParameters(device_id);
  189. if (!output_params.IsValid()) {
  190. LOG(ERROR) << "Adding OutputDeviceMixer failed: invalid output parameters";
  191. return nullptr;
  192. }
  193. output_params.set_frames_per_buffer(media::AudioLatency::GetRtcBufferSize(
  194. output_params.sample_rate(), output_params.frames_per_buffer()));
  195. // TODO(crbug/1295658): Temporary work around. Mix all audio as stereo and
  196. // rely on the system channel mapping.
  197. if (output_params.channel_layout() == media::CHANNEL_LAYOUT_DISCRETE &&
  198. output_params.channels() >= 2) {
  199. output_params.Reset(output_params.format(), media::CHANNEL_LAYOUT_STEREO,
  200. output_params.sample_rate(),
  201. output_params.frames_per_buffer());
  202. }
  203. // base::Unretained(this) is safe here, because |output_device_mixers_|
  204. // are owned by |this|.
  205. std::unique_ptr<OutputDeviceMixer> output_device_mixer =
  206. create_mixer_callback_.Run(
  207. device_id, output_params,
  208. base::BindRepeating(&OutputDeviceMixerManager::CreateMixerOwnedStream,
  209. base::Unretained(this)),
  210. audio_manager_->GetTaskRunner());
  211. // The |device_id| might no longer be valid, e.g. if a device was unplugged.
  212. if (!output_device_mixer) {
  213. LOG(ERROR) << "Adding OutputDeviceMixer failed: creation error";
  214. return nullptr;
  215. }
  216. auto* mixer = output_device_mixer.get();
  217. output_device_mixers_.push_back(std::move(output_device_mixer));
  218. // Attach any interested listeners.
  219. for (auto&& listener_device_kvp : listener_registration_) {
  220. if (ToMixerDeviceId(listener_device_kvp.second) == mixer->device_id())
  221. mixer->StartListening(listener_device_kvp.first);
  222. }
  223. return mixer;
  224. }
  225. base::OnceClosure OutputDeviceMixerManager::GetOnDeviceChangeCallback() {
  226. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  227. return base::BindOnce(&OutputDeviceMixerManager::OnDeviceChange,
  228. device_change_weak_ptr_factory_.GetWeakPtr());
  229. }
  230. media::AudioOutputStream* OutputDeviceMixerManager::CreateMixerOwnedStream(
  231. const std::string& device_id,
  232. const media::AudioParameters& params) {
  233. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  234. return CreateDeviceListenerStream(GetOnDeviceChangeCallback(), device_id,
  235. params);
  236. }
  237. media::AudioOutputStream* OutputDeviceMixerManager::CreateDeviceListenerStream(
  238. base::OnceClosure on_device_change_callback,
  239. const std::string& device_id,
  240. const media::AudioParameters& params) {
  241. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  242. media::AudioOutputStream* stream =
  243. audio_manager_->MakeAudioOutputStreamProxy(params, device_id);
  244. if (!stream) {
  245. LOG(ERROR) << "Stream proxy limit reached";
  246. return nullptr;
  247. }
  248. // If this stream is created via CreateMixerOwnedStream(),
  249. // |on_device_change_callback| will call OnDeviceChange(), cancel pending
  250. // calls to OnDeviceChange(), and release all mixer owned streams.
  251. //
  252. // If we are directly creating this stream, |on_device_change_callback| will
  253. // synchronously close the returned stream.
  254. return new DeviceListenerOutputStream(audio_manager_, stream,
  255. std::move(on_device_change_callback));
  256. }
  257. bool OutputDeviceMixerManager::IsNormalizedIfDefault(
  258. const std::string& device_id) {
  259. return device_id == kNormalizedDefaultDeviceId ||
  260. !media::AudioDeviceDescription::IsDefaultDevice(device_id);
  261. }
  262. } // namespace audio