// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_ #define MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_ #include "base/atomic_ref_count.h" #include "base/callback.h" #include "base/cancelable_callback.h" #include "base/memory/ref_counted.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" #include "media/audio/audio_power_monitor.h" #include "media/audio/audio_source_diverter.h" #include "media/audio/simple_sources.h" #include "media/base/media_export.h" // An AudioOutputController controls an AudioOutputStream and provides data // to this output stream. It has an important function that it executes // audio operations like play, pause, stop, etc. on a separate thread, // namely the audio manager thread. // // All the public methods of AudioOutputController are non-blocking. // The actual operations are performed on the audio manager thread. // // Here is a state transition diagram for the AudioOutputController: // // *[ Empty ] --> [ Created ] --> [ Playing ] -------. // | | | ^ | // | | | | | // | | | | v // | | | `----- [ Paused ] // | | | | // | v v | // `-----------> [ Closed ] <-----------' // // * Initial state // // At any time after reaching the Created state but before Closed, the // AudioOutputController may be notified of a device change via // OnDeviceChange(). As the OnDeviceChange() is processed, state transitions // will occur, ultimately ending up in an equivalent pre-call state. E.g., if // the state was Paused, the new state will be Created, since these states are // all functionally equivalent and require a Play() call to continue to the next // state. // // The AudioOutputStream can request data from the AudioOutputController via the // AudioSourceCallback interface. AudioOutputController uses the SyncReader // passed to it via construction to synchronously fulfill this read request. // namespace media { class MEDIA_EXPORT AudioOutputController : public base::RefCountedThreadSafe, public AudioOutputStream::AudioSourceCallback, public AudioSourceDiverter, NON_EXPORTED_BASE(public AudioManager::AudioDeviceListener) { public: // An event handler that receives events from the AudioOutputController. The // following methods are called on the audio manager thread. class MEDIA_EXPORT EventHandler { public: virtual void OnCreated() = 0; virtual void OnPlaying() = 0; virtual void OnPowerMeasured(float power_dbfs, bool clipped) = 0; virtual void OnPaused() = 0; virtual void OnError() = 0; virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate) = 0; protected: virtual ~EventHandler() {} }; // A synchronous reader interface used by AudioOutputController for // synchronous reading. // TODO(crogers): find a better name for this class and the Read() method // now that it can handle synchronized I/O. class SyncReader { public: virtual ~SyncReader() {} // Notify the synchronous reader the number of bytes in the // AudioOutputController not yet played. This is used by SyncReader to // prepare more data and perform synchronization. virtual void UpdatePendingBytes(uint32 bytes) = 0; // Attempt to completely fill |dest|, return the actual number of frames // that could be read. |source| may optionally be provided for input data. // If |block| is specified, the Read() will block until data is available // or a timeout is reached. virtual int Read(bool block, const AudioBus* source, AudioBus* dest) = 0; // Close this synchronous reader. virtual void Close() = 0; }; // Factory method for creating an AudioOutputController. // This also creates and opens an AudioOutputStream on the audio manager // thread, and if this is successful, the |event_handler| will receive an // OnCreated() call from the same audio manager thread. |audio_manager| must // outlive AudioOutputController. static scoped_refptr Create( AudioManager* audio_manager, EventHandler* event_handler, const AudioParameters& params, const std::string& input_device_id, SyncReader* sync_reader); // Methods to control playback of the stream. // Starts the playback of this audio output stream. void Play(); // Pause this audio output stream. void Pause(); // Closes the audio output stream. The state is changed and the resources // are freed on the audio manager thread. closed_task is executed after that. // Callbacks (EventHandler and SyncReader) must exist until closed_task is // called. // // It is safe to call this method more than once. Calls after the first one // will have no effect. void Close(const base::Closure& closed_task); // Sets the volume of the audio output stream. void SetVolume(double volume); // AudioSourceCallback implementation. virtual int OnMoreData(AudioBus* dest, AudioBuffersState buffers_state) OVERRIDE; virtual int OnMoreIOData(AudioBus* source, AudioBus* dest, AudioBuffersState buffers_state) OVERRIDE; virtual void OnError(AudioOutputStream* stream) OVERRIDE; // AudioDeviceListener implementation. When called AudioOutputController will // shutdown the existing |stream_|, transition to the kRecreating state, // create a new stream, and then transition back to an equivalent state prior // to being called. virtual void OnDeviceChange() OVERRIDE; // AudioSourceDiverter implementation. virtual const AudioParameters& GetAudioParameters() OVERRIDE; virtual void StartDiverting(AudioOutputStream* to_stream) OVERRIDE; virtual void StopDiverting() OVERRIDE; protected: // Internal state of the source. enum State { kEmpty, kCreated, kPlaying, kPaused, kClosed, kError, }; friend class base::RefCountedThreadSafe; virtual ~AudioOutputController(); private: // We are polling sync reader if data became available. static const int kPollNumAttempts; static const int kPollPauseInMilliseconds; AudioOutputController(AudioManager* audio_manager, EventHandler* handler, const AudioParameters& params, const std::string& input_device_id, SyncReader* sync_reader); // The following methods are executed on the audio manager thread. void DoCreate(bool is_for_device_change); void DoPlay(); void DoPause(); void DoClose(); void DoSetVolume(double volume); void DoReportError(); void DoStartDiverting(AudioOutputStream* to_stream); void DoStopDiverting(); // Calls EventHandler::OnPowerMeasured() with the current power level and then // schedules itself to be called again later. void ReportPowerMeasurementPeriodically(); // Helper method that stops the physical stream. void StopStream(); // Helper method that stops, closes, and NULLs |*stream_|. void DoStopCloseAndClearStream(); // Sanity-check that entry/exit to OnMoreIOData() by the hardware audio thread // happens only between AudioOutputStream::Start() and Stop(). void AllowEntryToOnMoreIOData(); void DisallowEntryToOnMoreIOData(); AudioManager* const audio_manager_; const AudioParameters params_; EventHandler* const handler_; // Used by the unified IO to open the correct input device. std::string input_device_id_; AudioOutputStream* stream_; // When non-NULL, audio is being diverted to this stream. AudioOutputStream* diverting_to_stream_; // The current volume of the audio stream. double volume_; // |state_| is written on the audio manager thread and is read on the // hardware audio thread. These operations need to be locked. But lock // is not required for reading on the audio manager thread. State state_; // Binary semaphore, used to ensure that only one thread enters the // OnMoreIOData() method, and only when it is valid to do so. This is for // sanity-checking the behavior of platform implementations of // AudioOutputStream. In other words, multiple contention is not expected, // nor in the design here. base::AtomicRefCount num_allowed_io_; // SyncReader is used only in low latency mode for synchronous reading. SyncReader* const sync_reader_; // The message loop of audio manager thread that this object runs on. const scoped_refptr message_loop_; // When starting stream we wait for data to become available. // Number of times left. int number_polling_attempts_left_; // Scans audio samples from OnMoreIOData() as input to compute power levels. AudioPowerMonitor power_monitor_; // Periodic callback to report power levels during playback. base::CancelableClosure power_poll_callback_; DISALLOW_COPY_AND_ASSIGN(AudioOutputController); }; } // namespace media #endif // MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_