output_device_mixer_impl.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. #ifndef SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_IMPL_H_
  5. #define SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_IMPL_H_
  6. #include <memory>
  7. #include <set>
  8. #include <string>
  9. #include "base/callback.h"
  10. #include "base/check.h"
  11. #include "base/containers/unique_ptr_adapters.h"
  12. #include "base/dcheck_is_on.h"
  13. #include "base/synchronization/lock.h"
  14. #include "base/timer/timer.h"
  15. #include "media/audio/audio_io.h"
  16. #include "media/base/audio_parameters.h"
  17. #include "media/base/reentrancy_checker.h"
  18. #include "services/audio/mixing_graph.h"
  19. #include "services/audio/output_device_mixer.h"
  20. namespace audio {
  21. class MixingGraph;
  22. // OutputDeviceMixerImpl manages the rendering of all output streams created by
  23. // MakeMixableStream(). It has two rendering modes: if there
  24. // are not listeners attached, each active output stream is rendered
  25. // independently. If the mixer has listeners and at least one of the managed
  26. // streams there is playing, all output streams are mixed by
  27. // |mixing_graph_| and the result is played by |mixing_graph_output_stream_|.
  28. // After mixing started, the mixed playback will stop only when the last
  29. // listener is gone; this means the mixed playback will continue even when there
  30. // are no managed streams playing. That is done because the listeners do not
  31. // like when the reference signal stops and then starts again: it can cause
  32. // reference signal delay jumps. TODO(olka): add metrics for how often/how long
  33. // we may have listeners forsing such silent mixed playback.
  34. class OutputDeviceMixerImpl final : public OutputDeviceMixer {
  35. public:
  36. using ErrorType = media::AudioOutputStream::AudioSourceCallback::ErrorType;
  37. static constexpr base::TimeDelta kSwitchToUnmixedPlaybackDelay =
  38. base::Seconds(1);
  39. static constexpr double kDefaultVolume = 1.0;
  40. // |device_id| is the id of the device to manage the playback for (expected to
  41. // be a valid physical output device id); |output_params| are the parameters
  42. // of the audio mix the mixer will be playing in case there are listeners
  43. // attached (otherwise, each output stream is played independently using its
  44. // individual parameters); |create_mixing_graph_callback| is used to create
  45. // a mixing graph object which will combine individual audio streams into a
  46. // mixed signal; |create_stream_callback| is used to create physical output
  47. // streams to be used for audio rendering.
  48. OutputDeviceMixerImpl(
  49. const std::string& device_id,
  50. const media::AudioParameters& output_params,
  51. MixingGraph::CreateCallback create_mixing_graph_callback,
  52. CreateStreamCallback create_stream_callback);
  53. OutputDeviceMixerImpl(const OutputDeviceMixerImpl&) = delete;
  54. OutputDeviceMixerImpl& operator=(const OutputDeviceMixerImpl&) = delete;
  55. ~OutputDeviceMixerImpl() final;
  56. // Creates an output stream managed by |this|.
  57. media::AudioOutputStream* MakeMixableStream(
  58. const media::AudioParameters& params,
  59. base::OnceCallback<void()> on_device_change_callback) final;
  60. void ProcessDeviceChange() final;
  61. // ReferenceOutput implementation.
  62. // Starts listening to the mixed audio stream.
  63. void StartListening(Listener* listener) final;
  64. // Stops listening to the mixed audio stream.
  65. void StopListening(Listener* listener) final;
  66. private:
  67. class MixTrack;
  68. class MixableOutputStream;
  69. class MixingStats;
  70. struct StreamAutoClose {
  71. void operator()(media::AudioOutputStream* stream) {
  72. if (!stream)
  73. return;
  74. stream->Close();
  75. stream = nullptr;
  76. }
  77. };
  78. // Do not change: used for UMA reporting, matches
  79. // AudioOutputDeviceMixerMixedPlaybackStatus from enums.xml.
  80. enum class MixingError {
  81. kNone = 0,
  82. kOpenFailed,
  83. kPlaybackFailed,
  84. kMaxValue = kPlaybackFailed
  85. };
  86. using MixTracks =
  87. std::set<std::unique_ptr<MixTrack>, base::UniquePtrComparator>;
  88. using ActiveTracks = std::set<MixTrack*>;
  89. using Listeners = std::set<Listener*>;
  90. // Operations delegated by MixableOutputStream.
  91. bool OpenStream(MixTrack* mix_track);
  92. void StartStream(MixTrack* mix_track,
  93. media::AudioOutputStream::AudioSourceCallback* callback);
  94. void StopStream(MixTrack* mix_track);
  95. void CloseStream(MixTrack* mix_track);
  96. // Helper to create physical audio streams.
  97. media::AudioOutputStream* CreateAndOpenDeviceStream(
  98. const media::AudioParameters& params);
  99. // Delivers audio to listeners; provided as a callback to MixingGraph.
  100. void BroadcastToListeners(const media::AudioBus& audio_bus,
  101. base::TimeDelta delay);
  102. // Processes |mixing_output_stream_| rendering errors; provided as a callback
  103. // to MixingGraph.
  104. void OnMixingGraphError(ErrorType error);
  105. // Helpers to manage audio playback.
  106. bool HasListeners() const;
  107. bool MixingInProgress() const { return !!mixing_session_stats_; }
  108. void EnsureMixingGraphOutputStreamOpen();
  109. void StartMixingGraphPlayback();
  110. void StopMixingGraphPlayback(MixingError mixing_error);
  111. void SwitchToUnmixedPlaybackTimerHelper();
  112. static const char* ErrorToString(MixingError error);
  113. SEQUENCE_CHECKER(owning_sequence_);
  114. // Callback to create physical audio streams.
  115. const CreateStreamCallback create_stream_callback_;
  116. // Streams managed by the mixer.
  117. MixTracks mix_tracks_ GUARDED_BY_CONTEXT(owning_sequence_);
  118. // Active tracks rendering audio.
  119. ActiveTracks active_tracks_ GUARDED_BY_CONTEXT(owning_sequence_);
  120. // Listeners receiving the reference output (mixed playback). Playback is
  121. // mixed if and only if there is at least one listener.
  122. mutable base::Lock listener_lock_;
  123. Listeners listeners_ GUARDED_BY(listener_lock_);
  124. // Audio parameters for mixed playback.
  125. const media::AudioParameters mixing_graph_output_params_;
  126. // Provides the audio mix combined of |active_members_| audio to
  127. // |mixing_output_stream_| for playback.
  128. const std::unique_ptr<MixingGraph> mixing_graph_
  129. GUARDED_BY_CONTEXT(owning_sequence_);
  130. // Stream to render the audio mix. Non-null if and only if the playback is
  131. // being mixed at the moment.
  132. std::unique_ptr<media::AudioOutputStream, StreamAutoClose>
  133. mixing_graph_output_stream_ GUARDED_BY_CONTEXT(owning_sequence_);
  134. // Delays switching to unmixed playback in case a new listener is coming
  135. // soon (within kSwitchToIndependentPlaybackDelay).
  136. base::OneShotTimer switch_to_unmixed_playback_delay_timer_
  137. GUARDED_BY_CONTEXT(owning_sequence_);
  138. // Non-null when the playback is being mixed. Collects mixing statistics.
  139. // Logs them upon the destruction when mixing stops. Non-null while mixing
  140. // is in progress, and is used as an indicator of that.
  141. std::unique_ptr<MixingStats> mixing_session_stats_;
  142. #if DCHECK_IS_ON()
  143. bool device_changed_ = false;
  144. #endif
  145. // A mixable stream operation cannot be invoked within a context of another
  146. // such operation. In practice it means that AudioOutputStream created by the
  147. // mixer cannot be stopped/closed synchronously from AudioSourceCallback
  148. // provided to it on AudioOutputStream::Start().
  149. REENTRANCY_CHECKER(reentrancy_checker_);
  150. // Supplies weak pointers to |this| for MixableOutputStream instances.
  151. base::WeakPtrFactory<OutputDeviceMixerImpl> weak_factory_{this};
  152. };
  153. } // namespace audio
  154. #endif // SERVICES_AUDIO_OUTPUT_DEVICE_MIXER_IMPL_H_