stream_factory.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2018 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/stream_factory.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/feature_list.h"
  8. #include "base/trace_event/trace_event.h"
  9. #include "base/unguessable_token.h"
  10. #include "build/chromecast_buildflags.h"
  11. #include "media/audio/audio_device_description.h"
  12. #include "media/base/media_switches.h"
  13. #include "services/audio/input_stream.h"
  14. #include "services/audio/local_muter.h"
  15. #include "services/audio/loopback_stream.h"
  16. #include "services/audio/output_stream.h"
  17. #include "services/audio/user_input_monitor.h"
  18. #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
  19. #include "services/audio/output_device_mixer.h"
  20. #endif
  21. namespace audio {
  22. namespace {
  23. #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
  24. std::unique_ptr<OutputDeviceMixerManager> MaybeCreateOutputDeviceMixerManager(
  25. media::AudioManager* audio_manager) {
  26. if (!media::IsChromeWideEchoCancellationEnabled())
  27. return nullptr;
  28. return std::make_unique<OutputDeviceMixerManager>(
  29. audio_manager, base::BindRepeating(&OutputDeviceMixer::Create));
  30. }
  31. #endif // BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
  32. // Ideally, this would be based on the incoming audio's buffer durations.
  33. // However, we might deal with multiple streams, with multiple buffer durations.
  34. // Using a 10ms constant instead is acceptable (and better than the default)
  35. // since there are no super-strict realtime requirements (no system audio calls
  36. // waiting on these threads).
  37. constexpr base::TimeDelta kReatimeThreadPeriod = base::Milliseconds(10);
  38. } // namespace
  39. StreamFactory::StreamFactory(media::AudioManager* audio_manager,
  40. AecdumpRecordingManager* aecdump_recording_manager)
  41. : audio_manager_(audio_manager),
  42. aecdump_recording_manager_(aecdump_recording_manager),
  43. #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
  44. output_device_mixer_manager_(
  45. MaybeCreateOutputDeviceMixerManager(audio_manager)),
  46. #endif
  47. loopback_worker_thread_("Loopback Worker", kReatimeThreadPeriod) {
  48. }
  49. StreamFactory::~StreamFactory() {
  50. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  51. }
  52. void StreamFactory::Bind(
  53. mojo::PendingReceiver<media::mojom::AudioStreamFactory> receiver) {
  54. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  55. receivers_.Add(this, std::move(receiver));
  56. }
  57. void StreamFactory::CreateInputStream(
  58. mojo::PendingReceiver<media::mojom::AudioInputStream> stream_receiver,
  59. mojo::PendingRemote<media::mojom::AudioInputStreamClient> client,
  60. mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer,
  61. mojo::PendingRemote<media::mojom::AudioLog> pending_log,
  62. const std::string& device_id,
  63. const media::AudioParameters& params,
  64. uint32_t shared_memory_count,
  65. bool enable_agc,
  66. base::ReadOnlySharedMemoryRegion key_press_count_buffer,
  67. media::mojom::AudioProcessingConfigPtr processing_config,
  68. CreateInputStreamCallback created_callback) {
  69. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  70. TRACE_EVENT_NESTABLE_ASYNC_INSTANT2("audio", "CreateInputStream", this,
  71. "device id", device_id, "params",
  72. params.AsHumanReadableString());
  73. // Unretained is safe since |this| indirectly owns the InputStream.
  74. auto deleter_callback = base::BindOnce(&StreamFactory::DestroyInputStream,
  75. base::Unretained(this));
  76. input_streams_.insert(std::make_unique<InputStream>(
  77. std::move(created_callback), std::move(deleter_callback),
  78. std::move(stream_receiver), std::move(client), std::move(observer),
  79. std::move(pending_log), audio_manager_, aecdump_recording_manager_,
  80. UserInputMonitor::Create(std::move(key_press_count_buffer)),
  81. &stream_count_metric_reporter_,
  82. #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
  83. output_device_mixer_manager_.get(), std::move(processing_config),
  84. #else
  85. nullptr, nullptr,
  86. #endif
  87. device_id, params, shared_memory_count, enable_agc));
  88. }
  89. void StreamFactory::AssociateInputAndOutputForAec(
  90. const base::UnguessableToken& input_stream_id,
  91. const std::string& output_device_id) {
  92. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  93. for (const auto& stream : input_streams_) {
  94. if (stream->id() == input_stream_id) {
  95. stream->SetOutputDeviceForAec(output_device_id);
  96. return;
  97. }
  98. }
  99. }
  100. void StreamFactory::CreateOutputStream(
  101. mojo::PendingReceiver<media::mojom::AudioOutputStream> stream_receiver,
  102. mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
  103. observer,
  104. mojo::PendingRemote<media::mojom::AudioLog> log,
  105. const std::string& output_device_id,
  106. const media::AudioParameters& params,
  107. const base::UnguessableToken& group_id,
  108. CreateOutputStreamCallback created_callback) {
  109. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  110. TRACE_EVENT_NESTABLE_ASYNC_INSTANT2("audio", "CreateOutputStream", this,
  111. "device id", output_device_id, "params",
  112. params.AsHumanReadableString());
  113. // Unretained is safe since |this| indirectly owns the OutputStream.
  114. auto deleter_callback = base::BindOnce(&StreamFactory::DestroyOutputStream,
  115. base::Unretained(this));
  116. // This is required for multizone audio playback on Cast devices.
  117. // See //chromecast/media/cast_audio_manager.h for more information.
  118. //
  119. // TODO(crbug.com/1336055): Determine if this condition should instead be
  120. // ENABLE_CAST_RECEIVER && !IS_FUCHSIA.
  121. const std::string device_id_or_group_id =
  122. #if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
  123. (::media::AudioDeviceDescription::IsCommunicationsDevice(
  124. output_device_id) ||
  125. group_id.is_empty())
  126. ? output_device_id
  127. : group_id.ToString();
  128. #else
  129. output_device_id;
  130. #endif
  131. // base::Unretained() is safe since |this| owns both |output_mixer_manager_|
  132. // and |output_streams_|, and ensures the correct order of destruction.
  133. OutputStream::ManagedDeviceOutputStreamCreateCallback
  134. managed_device_output_stream_create_callback;
  135. #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION)
  136. if (output_device_mixer_manager_) {
  137. managed_device_output_stream_create_callback = base::BindRepeating(
  138. &OutputDeviceMixerManager::MakeOutputStream,
  139. base::Unretained(output_device_mixer_manager_.get()));
  140. }
  141. #endif
  142. output_streams_.insert(std::make_unique<OutputStream>(
  143. std::move(created_callback), std::move(deleter_callback),
  144. std::move(managed_device_output_stream_create_callback),
  145. std::move(stream_receiver), std::move(observer), std::move(log),
  146. audio_manager_, &stream_count_metric_reporter_, device_id_or_group_id,
  147. params, &coordinator_, group_id));
  148. }
  149. void StreamFactory::BindMuter(
  150. mojo::PendingAssociatedReceiver<media::mojom::LocalMuter> receiver,
  151. const base::UnguessableToken& group_id) {
  152. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  153. TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("audio", "BindMuter", this, "group id",
  154. group_id);
  155. // Find the existing LocalMuter for this group, or create one on-demand.
  156. auto it = std::find_if(muters_.begin(), muters_.end(),
  157. [&group_id](const std::unique_ptr<LocalMuter>& muter) {
  158. return muter->group_id() == group_id;
  159. });
  160. LocalMuter* muter;
  161. if (it == muters_.end()) {
  162. auto muter_ptr = std::make_unique<LocalMuter>(&coordinator_, group_id);
  163. muter = muter_ptr.get();
  164. muter->SetAllBindingsLostCallback(base::BindRepeating(
  165. &StreamFactory::DestroyMuter, base::Unretained(this), muter));
  166. muters_.emplace_back(std::move(muter_ptr));
  167. } else {
  168. muter = it->get();
  169. }
  170. // Add the receiver.
  171. muter->AddReceiver(std::move(receiver));
  172. }
  173. void StreamFactory::CreateLoopbackStream(
  174. mojo::PendingReceiver<media::mojom::AudioInputStream> receiver,
  175. mojo::PendingRemote<media::mojom::AudioInputStreamClient> client,
  176. mojo::PendingRemote<media::mojom::AudioInputStreamObserver> observer,
  177. const media::AudioParameters& params,
  178. uint32_t shared_memory_count,
  179. const base::UnguessableToken& group_id,
  180. CreateLoopbackStreamCallback created_callback) {
  181. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  182. TRACE_EVENT_NESTABLE_ASYNC_INSTANT2("audio", "CreateLoopbackStream", this,
  183. "group id", group_id, "params",
  184. params.AsHumanReadableString());
  185. // All LoopbackStreams share a single realtime worker thread. This is because
  186. // the execution timing of scheduled tasks must be precise, and top priority
  187. // should be given to the smooth continuous flow of audio while in low-CPU
  188. // situations; all to avoid glitches. The thread is started just before the
  189. // first LoopbackStream will be created, and stopped after all LoopbackStreams
  190. // are gone.
  191. scoped_refptr<base::SequencedTaskRunner> task_runner;
  192. if (loopback_worker_thread_.IsRunning()) {
  193. task_runner = loopback_worker_thread_.task_runner();
  194. } else {
  195. TRACE_EVENT_BEGIN0("audio", "Start Loopback Worker");
  196. base::Thread::Options options;
  197. options.timer_slack = base::TIMER_SLACK_NONE;
  198. options.thread_type = base::ThreadType::kRealtimeAudio;
  199. if (loopback_worker_thread_.StartWithOptions(std::move(options))) {
  200. task_runner = loopback_worker_thread_.task_runner();
  201. TRACE_EVENT_END1("audio", "Start Loopback Worker", "success", true);
  202. } else {
  203. // Something about this platform or its current environment has prevented
  204. // a realtime audio thread from being started. Fall-back to using the
  205. // AudioManager worker thread.
  206. LOG(ERROR) << "Unable to start realtime loopback worker thread.";
  207. task_runner = audio_manager_->GetWorkerTaskRunner();
  208. TRACE_EVENT_END1("audio", "Start Loopback Worker", "success", false);
  209. }
  210. }
  211. auto stream = std::make_unique<LoopbackStream>(
  212. std::move(created_callback),
  213. base::BindOnce(&StreamFactory::DestroyLoopbackStream,
  214. base::Unretained(this)),
  215. std::move(task_runner), std::move(receiver), std::move(client),
  216. std::move(observer), params, shared_memory_count, &coordinator_,
  217. group_id);
  218. loopback_streams_.emplace_back(std::move(stream));
  219. }
  220. void StreamFactory::DestroyInputStream(InputStream* stream) {
  221. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  222. size_t erased = input_streams_.erase(stream);
  223. DCHECK_EQ(1u, erased);
  224. }
  225. void StreamFactory::DestroyOutputStream(OutputStream* stream) {
  226. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  227. size_t erased = output_streams_.erase(stream);
  228. DCHECK_EQ(1u, erased);
  229. }
  230. void StreamFactory::DestroyMuter(LocalMuter* muter) {
  231. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  232. DCHECK(muter);
  233. // Output streams have a task posting before destruction (see the OnError
  234. // function in output_stream.cc). To ensure that stream destruction and
  235. // unmuting is done in the intended order (the order in which the messages are
  236. // received by the service), we post a task for destroying the muter as well.
  237. // Otherwise, a "destroy all streams, then destroy the muter" sequence may
  238. // result in a brief blip of audio.
  239. auto do_destroy = [](base::WeakPtr<StreamFactory> weak_this,
  240. LocalMuter* muter) {
  241. if (weak_this) {
  242. const auto it =
  243. std::find_if(weak_this->muters_.begin(), weak_this->muters_.end(),
  244. base::MatchesUniquePtr(muter));
  245. DCHECK(it != weak_this->muters_.end());
  246. // The LocalMuter can still have receivers if a receiver was bound after
  247. // DestroyMuter is called but before the do_destroy task is run.
  248. if (!muter->HasReceivers()) {
  249. weak_this->muters_.erase(it);
  250. }
  251. }
  252. };
  253. base::SequencedTaskRunnerHandle::Get()->PostTask(
  254. FROM_HERE,
  255. base::BindOnce(do_destroy, weak_ptr_factory_.GetWeakPtr(), muter));
  256. }
  257. void StreamFactory::DestroyLoopbackStream(LoopbackStream* stream) {
  258. DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
  259. DCHECK(stream);
  260. const auto it =
  261. std::find_if(loopback_streams_.begin(), loopback_streams_.end(),
  262. base::MatchesUniquePtr(stream));
  263. DCHECK(it != loopback_streams_.end());
  264. loopback_streams_.erase(it);
  265. // If all LoopbackStreams have ended, stop and join the worker thread.
  266. if (loopback_streams_.empty()) {
  267. TRACE_EVENT0("audio", "Stop Loopback Worker");
  268. loopback_worker_thread_.Stop();
  269. }
  270. }
  271. } // namespace audio