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.
5 #ifndef MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
6 #define MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_
8 #include "base/atomic_ref_count.h"
9 #include "base/callback.h"
10 #include "base/cancelable_callback.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/timer/timer.h"
13 #include "media/audio/audio_io.h"
14 #include "media/audio/audio_manager.h"
15 #include "media/audio/audio_power_monitor.h"
16 #include "media/audio/audio_source_diverter.h"
17 #include "media/audio/simple_sources.h"
18 #include "media/base/media_export.h"
20 // An AudioOutputController controls an AudioOutputStream and provides data
21 // to this output stream. It has an important function that it executes
22 // audio operations like play, pause, stop, etc. on a separate thread,
23 // namely the audio manager thread.
25 // All the public methods of AudioOutputController are non-blocking.
26 // The actual operations are performed on the audio manager thread.
28 // Here is a state transition diagram for the AudioOutputController:
30 // *[ Empty ] --> [ Created ] --> [ Playing ] -------.
34 // | | | `----- [ Paused ]
37 // `-----------> [ Closed ] <-----------'
41 // At any time after reaching the Created state but before Closed, the
42 // AudioOutputController may be notified of a device change via
43 // OnDeviceChange(). As the OnDeviceChange() is processed, state transitions
44 // will occur, ultimately ending up in an equivalent pre-call state. E.g., if
45 // the state was Paused, the new state will be Created, since these states are
46 // all functionally equivalent and require a Play() call to continue to the next
49 // The AudioOutputStream can request data from the AudioOutputController via the
50 // AudioSourceCallback interface. AudioOutputController uses the SyncReader
51 // passed to it via construction to synchronously fulfill this read request.
56 // Only do power monitoring for non-mobile platforms that need it for the UI.
57 #if !defined(OS_ANDROID) && !defined(OS_IOS)
58 #define AUDIO_POWER_MONITORING
61 class MEDIA_EXPORT AudioOutputController
62 : public base::RefCountedThreadSafe<AudioOutputController>,
63 public AudioOutputStream::AudioSourceCallback,
64 public AudioSourceDiverter,
65 NON_EXPORTED_BASE(public AudioManager::AudioDeviceListener) {
67 // An event handler that receives events from the AudioOutputController. The
68 // following methods are called on the audio manager thread.
69 class MEDIA_EXPORT EventHandler {
71 virtual void OnCreated() = 0;
72 virtual void OnPlaying() = 0;
73 virtual void OnPowerMeasured(float power_dbfs, bool clipped) = 0;
74 virtual void OnPaused() = 0;
75 virtual void OnError() = 0;
76 virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate) = 0;
79 virtual ~EventHandler() {}
82 // A synchronous reader interface used by AudioOutputController for
83 // synchronous reading.
84 // TODO(crogers): find a better name for this class and the Read() method
85 // now that it can handle synchronized I/O.
88 virtual ~SyncReader() {}
90 // Notify the synchronous reader the number of bytes in the
91 // AudioOutputController not yet played. This is used by SyncReader to
92 // prepare more data and perform synchronization.
93 virtual void UpdatePendingBytes(uint32 bytes) = 0;
95 // Attempts to completely fill |dest|, zeroing |dest| if the request can not
96 // be fulfilled (due to timeout). |source| may optionally be provided for
98 virtual void Read(const AudioBus* source, AudioBus* dest) = 0;
100 // Close this synchronous reader.
101 virtual void Close() = 0;
104 // Factory method for creating an AudioOutputController.
105 // This also creates and opens an AudioOutputStream on the audio manager
106 // thread, and if this is successful, the |event_handler| will receive an
107 // OnCreated() call from the same audio manager thread. |audio_manager| must
108 // outlive AudioOutputController.
109 // The |output_device_id| can be either empty (default device) or specify a
110 // specific hardware device for audio output. The |input_device_id| is
111 // used only for unified audio when opening up input and output at the same
112 // time (controlled by |params.input_channel_count()|).
113 static scoped_refptr<AudioOutputController> Create(
114 AudioManager* audio_manager, EventHandler* event_handler,
115 const AudioParameters& params, const std::string& output_device_id,
116 const std::string& input_device_id, SyncReader* sync_reader);
118 // Methods to control playback of the stream.
120 // Starts the playback of this audio output stream.
123 // Pause this audio output stream.
126 // Closes the audio output stream. The state is changed and the resources
127 // are freed on the audio manager thread. closed_task is executed after that.
128 // Callbacks (EventHandler and SyncReader) must exist until closed_task is
131 // It is safe to call this method more than once. Calls after the first one
132 // will have no effect.
133 void Close(const base::Closure& closed_task);
135 // Sets the volume of the audio output stream.
136 void SetVolume(double volume);
138 // Calls |callback| (on the caller's thread) with the current output
140 void GetOutputDeviceId(
141 base::Callback<void(const std::string&)> callback) const;
143 // Changes which output device to use. If desired, you can provide a
144 // callback that will be notified (on the thread you called from)
145 // when the function has completed execution.
147 // Changing the output device causes the controller to go through
148 // the same state transition back to the current state as a call to
149 // OnDeviceChange (unless it is currently diverting, see
150 // Start/StopDiverting below, in which case the state transition
151 // will happen when StopDiverting is called).
152 void SwitchOutputDevice(const std::string& output_device_id,
153 const base::Closure& callback);
155 // AudioSourceCallback implementation.
156 virtual int OnMoreData(AudioBus* dest,
157 AudioBuffersState buffers_state) OVERRIDE;
158 virtual int OnMoreIOData(AudioBus* source,
160 AudioBuffersState buffers_state) OVERRIDE;
161 virtual void OnError(AudioOutputStream* stream) OVERRIDE;
163 // AudioDeviceListener implementation. When called AudioOutputController will
164 // shutdown the existing |stream_|, transition to the kRecreating state,
165 // create a new stream, and then transition back to an equivalent state prior
167 virtual void OnDeviceChange() OVERRIDE;
169 // AudioSourceDiverter implementation.
170 virtual const AudioParameters& GetAudioParameters() OVERRIDE;
171 virtual void StartDiverting(AudioOutputStream* to_stream) OVERRIDE;
172 virtual void StopDiverting() OVERRIDE;
175 // Internal state of the source.
185 friend class base::RefCountedThreadSafe<AudioOutputController>;
186 virtual ~AudioOutputController();
189 // We are polling sync reader if data became available.
190 static const int kPollNumAttempts;
191 static const int kPollPauseInMilliseconds;
193 AudioOutputController(AudioManager* audio_manager, EventHandler* handler,
194 const AudioParameters& params,
195 const std::string& output_device_id,
196 const std::string& input_device_id,
197 SyncReader* sync_reader);
199 // The following methods are executed on the audio manager thread.
200 void DoCreate(bool is_for_device_change);
204 void DoSetVolume(double volume);
205 std::string DoGetOutputDeviceId() const;
206 void DoSwitchOutputDevice(const std::string& output_device_id);
207 void DoReportError();
208 void DoStartDiverting(AudioOutputStream* to_stream);
209 void DoStopDiverting();
211 // Calls EventHandler::OnPowerMeasured() with the current power level and then
212 // schedules itself to be called again later.
213 void ReportPowerMeasurementPeriodically();
215 // Helper method that stops the physical stream.
218 // Helper method that stops, closes, and NULLs |*stream_|.
219 void DoStopCloseAndClearStream();
221 // Sanity-check that entry/exit to OnMoreIOData() by the hardware audio thread
222 // happens only between AudioOutputStream::Start() and Stop().
223 void AllowEntryToOnMoreIOData();
224 void DisallowEntryToOnMoreIOData();
226 // Checks if a stream was started successfully but never calls OnMoreIOData().
229 AudioManager* const audio_manager_;
230 const AudioParameters params_;
231 EventHandler* const handler_;
233 // Specifies the device id of the output device to open or empty for the
234 // default output device.
235 std::string output_device_id_;
237 // Used by the unified IO to open the correct input device.
238 const std::string input_device_id_;
240 AudioOutputStream* stream_;
242 // When non-NULL, audio is being diverted to this stream.
243 AudioOutputStream* diverting_to_stream_;
245 // The current volume of the audio stream.
248 // |state_| is written on the audio manager thread and is read on the
249 // hardware audio thread. These operations need to be locked. But lock
250 // is not required for reading on the audio manager thread.
253 // Binary semaphore, used to ensure that only one thread enters the
254 // OnMoreIOData() method, and only when it is valid to do so. This is for
255 // sanity-checking the behavior of platform implementations of
256 // AudioOutputStream. In other words, multiple contention is not expected,
257 // nor in the design here.
258 base::AtomicRefCount num_allowed_io_;
260 // SyncReader is used only in low latency mode for synchronous reading.
261 SyncReader* const sync_reader_;
263 // The message loop of audio manager thread that this object runs on.
264 const scoped_refptr<base::SingleThreadTaskRunner> message_loop_;
266 #if defined(AUDIO_POWER_MONITORING)
267 // Scans audio samples from OnMoreIOData() as input to compute power levels.
268 AudioPowerMonitor power_monitor_;
270 // Periodic callback to report power levels during playback.
271 base::CancelableClosure power_poll_callback_;
274 // Flags when we've asked for a stream to start but it never did.
275 base::AtomicRefCount on_more_io_data_called_;
276 scoped_ptr<base::OneShotTimer<AudioOutputController> > wedge_timer_;
278 DISALLOW_COPY_AND_ASSIGN(AudioOutputController);
283 #endif // MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_