// 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/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/time.h" #include "media/audio/audio_buffers_state.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" #include "media/audio/simple_sources.h" namespace base { class WaitableEvent; } // namespace base class MessageLoop; // 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 diagram for the AudioOutputController: // // .-----------------------> [ Closed / Error ] <------. // | ^ | // | | | // [ Created ] --> [ Starting ] --> [ Playing ] --> [ Paused ] // ^ | ^ | ^ // | | | | | // | | `----------------' | // | V | // | [ PausedWhenStarting ] ------------------------' // | // *[ Empty ] // // * Initial 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. // // The audio manager thread is owned by the AudioManager that the // AudioOutputController holds a reference to. When performing tasks on this // thread, the controller must not add or release references to the // AudioManager or itself (since it in turn holds a reference to the manager), // for delayed tasks as it can slow down or even prevent normal shut down. // So, for tasks on the audio thread, the controller uses WeakPtr which enables // us to safely cancel pending polling tasks. // // AudioManager will take care of properly shutting down the audio manager // thread. // #include "media/base/media_export.h" namespace media { class MEDIA_EXPORT AudioOutputController : public base::RefCountedThreadSafe, public AudioOutputStream::AudioSourceCallback { public: // Value sent by the controller to the renderer in low-latency mode // indicating that the stream is paused. static const int kPauseMark; // 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 ~EventHandler() {} virtual void OnCreated(AudioOutputController* controller) = 0; virtual void OnPlaying(AudioOutputController* controller) = 0; virtual void OnPaused(AudioOutputController* controller) = 0; virtual void OnError(AudioOutputController* controller, int error_code) = 0; }; // A synchronous reader interface used by AudioOutputController for // synchronous reading. 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; // Read certain amount of data into |data|. This method returns if some // data is available. virtual uint32 Read(void* data, uint32 size) = 0; // Close this synchronous reader. virtual void Close() = 0; // Poll if data is ready. // Not reliable, as there is no guarantee that renderer is "new-style" // renderer that writes metadata into buffer. After several unsuccessful // attempts caller should assume the data is ready even if that function // returns false. virtual bool DataReady() = 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. static scoped_refptr Create( AudioManager* audio_manager, EventHandler* event_handler, const AudioParameters& params, // External synchronous reader for audio controller. 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(); // Discard all audio data buffered in this output stream. This method only // has effect when the stream is paused. void Flush(); // 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 methods. virtual uint32 OnMoreData(uint8* dest, uint32 max_size, AudioBuffersState buffers_state) OVERRIDE; virtual void OnError(AudioOutputStream* stream, int code) OVERRIDE; virtual void WaitTillDataReady() OVERRIDE; protected: // Internal state of the source. enum State { kEmpty, kCreated, kPlaying, kStarting, kPausedWhenStarting, 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(EventHandler* handler, SyncReader* sync_reader); // The following methods are executed on the audio manager thread. void DoCreate(AudioManager* audio_manager, const AudioParameters& params); void DoPlay(); void PollAndStartIfDataReady(); void DoPause(); void DoFlush(); void DoClose(); void DoSetVolume(double volume); void DoReportError(int code); // Helper method that starts physical stream. void StartStream(); // Helper method that stops, closes, and NULLs |*stream_|. // Signals event when done if it is not NULL. void DoStopCloseAndClearStream(base::WaitableEvent *done); // |handler_| may be called only if |state_| is not kClosed. EventHandler* handler_; AudioOutputStream* 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_; // The |lock_| must be acquired whenever we access |state_| from a thread // other than the audio manager thread. base::Lock lock_; // SyncReader is used only in low latency mode for synchronous reading. SyncReader* sync_reader_; // The message loop of audio manager thread that this object runs on. scoped_refptr message_loop_; // When starting stream we wait for data to become available. // Number of times left. int number_polling_attempts_left_; // Used to post delayed tasks to ourselves that we can cancel. // We don't want the tasks to hold onto a reference as it will slow down // shutdown and force it to wait for the most delayed task. // Also, if we're shutting down, we do not want to poll for more data. base::WeakPtrFactory weak_this_; DISALLOW_COPY_AND_ASSIGN(AudioOutputController); }; } // namespace media #endif // MEDIA_AUDIO_AUDIO_OUTPUT_CONTROLLER_H_