// 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_INPUT_CONTROLLER_H_ #define MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_ #include #include #include #include #include "base/files/file.h" #include "base/memory/weak_ptr.h" #include "media/audio/audio_debug_file_writer.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager_base.h" #include "media/base/audio_bus.h" #include "media/base/audio_parameters.h" // An AudioInputController controls an AudioInputStream and records data // from this input stream. The two main methods are Record() and Close() and // they are both executed on the audio thread which is injected by the two // alternative factory methods, Create() or CreateForStream(). // // All public methods of AudioInputController are non-blocking. // // Here is a state diagram for the AudioInputController: // // .--> [ Closed / Error ] <--. // | | // | | // [ Created ] ----------> [ Recording ] // ^ // | // *[ Empty ] // // * Initial state // // State sequences: // // [Creating Thread] [Audio Thread] // // User AudioInputController EventHandler // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Create() ==> DoCreate() // AudioManager::MakeAudioInputStream() // AudioInputStream::Open() // .- - - - - - - - - - - - -> OnError() // .-------------------------> OnCreated() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Record() ==> DoRecord() // AudioInputStream::Start() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Close() ==> DoClose() // AudioInputStream::Stop() // AudioInputStream::Close() // SyncWriter::Close() // Closure::Run() <-----------------. // (closure-task) // // The audio thread itself is owned by the AudioManager that the // AudioInputController holds a reference to. When performing tasks on the // audio thread, the controller must not add or release references to the // AudioManager or itself (since it in turn holds a reference to the manager). // namespace media { // Only do power monitoring for non-mobile platforms to save resources. #if !defined(OS_ANDROID) && !defined(OS_IOS) #define AUDIO_POWER_MONITORING #endif class UserInputMonitor; class MEDIA_EXPORT AudioInputController : public base::RefCountedThreadSafe { public: // Error codes to make native logging more clear. These error codes are added // to generic error strings to provide a higher degree of details. // Changing these values can lead to problems when matching native debug // logs with the actual cause of error. enum ErrorCode { // An unspecified error occured. UNKNOWN_ERROR = 0, // Failed to create an audio input stream. STREAM_CREATE_ERROR, // = 1 // Failed to open an audio input stream. STREAM_OPEN_ERROR, // = 2 // Native input stream reports an error. Exact reason differs between // platforms. STREAM_ERROR, // = 3 }; // An event handler that receives events from the AudioInputController. The // following methods are all called on the audio thread. class MEDIA_EXPORT EventHandler { public: virtual void OnCreated(AudioInputController* controller) = 0; virtual void OnError(AudioInputController* controller, ErrorCode error_code) = 0; virtual void OnLog(AudioInputController* controller, const std::string& message) = 0; protected: virtual ~EventHandler() {} }; // A synchronous writer interface used by AudioInputController for // synchronous writing. class MEDIA_EXPORT SyncWriter { public: virtual ~SyncWriter() {} // Write certain amount of data from |data|. virtual void Write(const AudioBus* data, double volume, bool key_pressed, uint32_t hardware_delay_bytes) = 0; // Close this synchronous writer. virtual void Close() = 0; }; // enum used for determining what UMA stats to report. enum StreamType { VIRTUAL = 0, HIGH_LATENCY = 1, LOW_LATENCY = 2, FAKE = 3, }; // AudioInputController::Create() can use the currently registered Factory // to create the AudioInputController. Factory is intended for testing only. // |user_input_monitor| is used for typing detection and can be NULL. class Factory { public: virtual AudioInputController* Create( scoped_refptr task_runner, SyncWriter* sync_writer, AudioManager* audio_manager, EventHandler* event_handler, AudioParameters params, UserInputMonitor* user_input_monitor, StreamType type) = 0; protected: virtual ~Factory() {} }; // Sets the factory used by the static method Create(). AudioInputController // does not take ownership of |factory|. A value of NULL results in an // AudioInputController being created directly. static void set_factory_for_testing(Factory* factory) { factory_ = factory; } AudioInputStream* stream_for_testing() { return stream_; } // The audio device will be created on the audio thread, and when that is // done, the event handler will receive an OnCreated() call from that same // thread. |user_input_monitor| is used for typing detection and can be NULL. // |file_task_runner| is used for debug recordings. // TODO(grunell): Move handling of debug recording to AudioManager. static scoped_refptr Create( AudioManager* audio_manager, EventHandler* event_handler, SyncWriter* sync_writer, UserInputMonitor* user_input_monitor, const AudioParameters& params, const std::string& device_id, // External synchronous writer for audio controller. bool agc_is_enabled, scoped_refptr file_task_runner); // Factory method for creating an AudioInputController with an existing // |stream|. The stream will be opened on the audio thread, and when that is // done, the event handler will receive an OnCreated() call from that same // thread. |user_input_monitor| is used for typing detection and can be NULL. // |file_task_runner| and |params| are used for debug recordings. static scoped_refptr CreateForStream( const scoped_refptr& task_runner, EventHandler* event_handler, AudioInputStream* stream, // External synchronous writer for audio controller. SyncWriter* sync_writer, UserInputMonitor* user_input_monitor, scoped_refptr file_task_runner, const AudioParameters& params); // Starts recording using the created audio input stream. // This method is called on the creator thread. virtual void Record(); // Closes the audio input stream. The state is changed and the resources // are freed on the audio thread. |closed_task| is then executed on the thread // that called Close(). // Callbacks (EventHandler and SyncWriter) 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. // This method trampolines to the audio thread. virtual void Close(const base::Closure& closed_task); // Sets the capture volume of the input stream. The value 0.0 corresponds // to muted and 1.0 to maximum volume. virtual void SetVolume(double volume); // Enable debug recording of audio input. virtual void EnableDebugRecording(const base::FilePath& file_name); // Disable debug recording of audio input. virtual void DisableDebugRecording(); protected: friend class base::RefCountedThreadSafe; // Used to log the result of capture startup. // This was previously logged as a boolean with only the no callback and OK // options. The enum order is kept to ensure backwards compatibility. // Elements in this enum should not be deleted or rearranged; the only // permitted operation is to add new elements before // CAPTURE_STARTUP_RESULT_MAX and update CAPTURE_STARTUP_RESULT_MAX. // // The NO_DATA_CALLBACK enum has been replaced with NEVER_GOT_DATA, // and there are also other histograms such as // Media.Audio.InputStartupSuccessMac to cover issues similar // to the ones the NO_DATA_CALLBACK was intended for. enum CaptureStartupResult { CAPTURE_STARTUP_OK = 0, CAPTURE_STARTUP_CREATE_STREAM_FAILED = 1, CAPTURE_STARTUP_OPEN_STREAM_FAILED = 2, CAPTURE_STARTUP_NEVER_GOT_DATA = 3, CAPTURE_STARTUP_STOPPED_EARLY = 4, CAPTURE_STARTUP_RESULT_MAX = CAPTURE_STARTUP_STOPPED_EARLY, }; #if defined(AUDIO_POWER_MONITORING) // Used to log a silence report (see OnData). // Elements in this enum should not be deleted or rearranged; the only // permitted operation is to add new elements before SILENCE_STATE_MAX and // update SILENCE_STATE_MAX. // Possible silence state transitions: // SILENCE_STATE_AUDIO_AND_SILENCE // ^ ^ // SILENCE_STATE_ONLY_AUDIO SILENCE_STATE_ONLY_SILENCE // ^ ^ // SILENCE_STATE_NO_MEASUREMENT enum SilenceState { SILENCE_STATE_NO_MEASUREMENT = 0, SILENCE_STATE_ONLY_AUDIO = 1, SILENCE_STATE_ONLY_SILENCE = 2, SILENCE_STATE_AUDIO_AND_SILENCE = 3, SILENCE_STATE_MAX = SILENCE_STATE_AUDIO_AND_SILENCE }; #endif AudioInputController( scoped_refptr task_runner, EventHandler* handler, SyncWriter* sync_writer, UserInputMonitor* user_input_monitor, const AudioParameters& params, StreamType type, scoped_refptr file_task_runner); virtual ~AudioInputController(); const scoped_refptr& GetTaskRunnerForTesting() const { return task_runner_; } EventHandler* GetHandlerForTesting() const { return handler_; } private: // Methods called on the audio thread (owned by the AudioManager). void DoCreate(AudioManager* audio_manager, const AudioParameters& params, const std::string& device_id, bool enable_agc); void DoCreateForStream(AudioInputStream* stream_to_control, bool enable_agc); void DoRecord(); void DoClose(); void DoReportError(); void DoSetVolume(double volume); void DoLogAudioLevels(float level_dbfs, int microphone_volume_percent); #if defined(AUDIO_POWER_MONITORING) // Updates the silence state, see enum SilenceState above for state // transitions. void UpdateSilenceState(bool silence); // Logs the silence state as UMA stat. void LogSilenceState(SilenceState value); #endif // Logs the result of creating an AudioInputController. void LogCaptureStartupResult(CaptureStartupResult result); // Logs whether an error was encountered suring the stream. void LogCallbackError(); // Enable and disable debug recording of audio input. Called on the audio // thread. void DoEnableDebugRecording(const base::FilePath& file_name); void DoDisableDebugRecording(); // Called on the audio thread. void WriteInputDataForDebugging(std::unique_ptr data); // Called by the stream with log messages. void LogMessage(const std::string& message); // Called on the hw callback thread. Checks for keyboard input if // user_input_monitor_ is set otherwise returns false. bool CheckForKeyboardInput(); // Does power monitoring on supported platforms. // Called on the hw callback thread. // Returns true iff average power and mic volume was returned and should // be posted to DoLogAudioLevels on the audio thread. // Returns false if either power measurements are disabled or aren't needed // right now (they're done periodically). bool CheckAudioPower(const AudioBus* source, double volume, float* average_power_dbfs, int* mic_volume_percent); static StreamType ParamsToStreamType(const AudioParameters& params); // Gives access to the task runner of the creating thread. scoped_refptr const creator_task_runner_; // The task runner of audio-manager thread that this object runs on. scoped_refptr const task_runner_; // Contains the AudioInputController::EventHandler which receives state // notifications from this class. EventHandler* const handler_; // Pointer to the audio input stream object. // Only used on the audio thread. AudioInputStream* stream_ = nullptr; // SyncWriter is used only in low-latency mode for synchronous writing. SyncWriter* const sync_writer_; StreamType type_; static Factory* factory_; double max_volume_ = 0.0; UserInputMonitor* const user_input_monitor_; #if defined(AUDIO_POWER_MONITORING) // Whether the silence state and microphone levels should be checked and sent // as UMA stats. bool power_measurement_is_enabled_ = false; // Updated each time a power measurement is performed. base::TimeTicks last_audio_level_log_time_; // The silence report sent as UMA stat at the end of a session. SilenceState silence_state_ = SILENCE_STATE_NO_MEASUREMENT; #endif size_t prev_key_down_count_ = 0; // Time when the stream started recording. base::TimeTicks stream_create_time_; // Used for audio debug recordings. Accessed on audio thread. const std::unique_ptr debug_writer_; class AudioCallback; // Holds a pointer to the callback object that receives audio data from // the lower audio layer. Valid only while 'recording' (between calls to // stream_->Start() and stream_->Stop()). // The value of this pointer is only set and read on the audio thread while // the callbacks themselves occur on the hw callback thread. More details // in the AudioCallback class in the cc file. std::unique_ptr audio_callback_; // A weak pointer factory that we use when posting tasks to the audio thread // that we want to be automatically discarded after Close() has been called // and that we do not want to keep the AudioInputController instance alive // beyond what is desired by the user of the instance (e.g. // AudioInputRendererHost). An example of where this is important is when // we fire error notifications from the hw callback thread, post them to // the audio thread. In that case, we do not want the error notification to // keep the AudioInputController alive for as long as the error notification // is pending and then make a callback from an AudioInputController that has // already been closed. // The weak_ptr_factory_ and all outstanding weak pointers, are invalidated // at the end of DoClose. base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(AudioInputController); }; } // namespace media #endif // MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_