#include "base/timer/timer.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_manager_base.h"
+#include "media/audio/audio_parameters.h"
+#include "media/audio/audio_power_monitor.h"
+#include "media/base/audio_bus.h"
// An AudioInputController controls an AudioInputStream and records data
// from this input stream. The two main methods are Record() and Close() and
//
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<AudioInputController>,
public AudioInputStream::AudioInputCallback {
public:
+
+ // Error codes to make native loggin 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
+
+ // This can happen if a capture device has been removed or disabled.
+ NO_DATA_ERROR, // = 4
+ };
+
// 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 OnRecording(AudioInputController* controller) = 0;
- virtual void OnError(AudioInputController* controller) = 0;
- virtual void OnData(AudioInputController* controller, const uint8* data,
- uint32 size) = 0;
+ virtual void OnError(AudioInputController* controller,
+ ErrorCode error_code) = 0;
+ virtual void OnData(AudioInputController* controller,
+ const AudioBus* data) = 0;
+ virtual void OnLog(AudioInputController* controller,
+ const std::string& message) = 0;
protected:
virtual ~EventHandler() {}
// soundcard which has been recorded.
virtual void UpdateRecordedBytes(uint32 bytes) = 0;
- // Write certain amount of data from |data|. This method returns
- // number of written bytes.
- virtual uint32 Write(const void* data,
- uint32 size,
- double volume,
- bool key_pressed) = 0;
+ // Write certain amount of data from |data|.
+ virtual void Write(const AudioBus* data,
+ double volume,
+ bool key_pressed) = 0;
// Close this synchronous writer.
virtual void Close() = 0;
SyncWriter* sync_writer,
UserInputMonitor* user_input_monitor);
- // Factory method for creating an AudioInputController for low-latency mode,
- // taking ownership of |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.
+ // Factory method for creating an AudioInputController with an existing
+ // |stream| for low-latency mode, taking ownership of |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.
static scoped_refptr<AudioInputController> CreateForStream(
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
EventHandler* event_handler,
AudioInputStream* stream,
// External synchronous writer for audio controller.
// AudioInputCallback implementation. Threading details depends on the
// device-specific implementation.
- virtual void OnData(AudioInputStream* stream, const uint8* src, uint32 size,
- uint32 hardware_delay_bytes, double volume) OVERRIDE;
- virtual void OnClose(AudioInputStream* stream) OVERRIDE;
+ virtual void OnData(AudioInputStream* stream,
+ const AudioBus* source,
+ uint32 hardware_delay_bytes,
+ double volume) OVERRIDE;
virtual void OnError(AudioInputStream* stream) OVERRIDE;
- bool LowLatencyMode() const { return sync_writer_ != NULL; }
+ bool SharedMemoryAndSyncSocketMode() const { return sync_writer_ != NULL; }
protected:
friend class base::RefCountedThreadSafe<AudioInputController>;
// Internal state of the source.
enum State {
- kEmpty,
- kCreated,
- kRecording,
- kClosed,
- kError
+ CREATED,
+ RECORDING,
+ CLOSED
};
+#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(EventHandler* handler,
SyncWriter* sync_writer,
UserInputMonitor* user_input_monitor);
virtual ~AudioInputController();
// Methods called on the audio thread (owned by the AudioManager).
- void DoCreate(AudioManager* audio_manager, const AudioParameters& params,
+ void DoCreate(AudioManager* audio_manager,
+ const AudioParameters& params,
const std::string& device_id);
- void DoCreateForStream(AudioInputStream* stream_to_control,
- bool enable_nodata_timer);
+ void DoCreateForLowLatency(AudioManager* audio_manager,
+ const AudioParameters& params,
+ const std::string& device_id);
+ void DoCreateForStream(AudioInputStream* stream_to_control);
void DoRecord();
void DoClose();
void DoReportError();
void DoSetVolume(double volume);
void DoSetAutomaticGainControl(bool enabled);
+ void DoOnData(scoped_ptr<AudioBus> data);
+ void DoLogAudioLevel(float level_dbfs);
+
+ // Method to check if we get recorded data after a stream was started,
+ // and log the result to UMA.
+ void FirstCheckForNoData();
// Method which ensures that OnError() is triggered when data recording
// times out. Called on the audio thread.
void DoCheckForNoData();
// Helper method that stops, closes, and NULL:s |*stream_|.
- // Signals event when done if the event is not NULL.
- void DoStopCloseAndClearStream(base::WaitableEvent* done);
+ void DoStopCloseAndClearStream();
void SetDataIsActive(bool enabled);
bool GetDataIsActive();
- // Gives access to the message loop of the creating thread.
- scoped_refptr<base::MessageLoopProxy> creator_loop_;
+#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
+
+ // Gives access to the task runner of the creating thread.
+ scoped_refptr<base::SingleThreadTaskRunner> creator_task_runner_;
- // The message loop of audio-manager thread that this object runs on.
- scoped_refptr<base::MessageLoopProxy> message_loop_;
+ // The task runner of audio-manager thread that this object runs on.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Contains the AudioInputController::EventHandler which receives state
// notifications from this class.
AudioInputStream* stream_;
// |no_data_timer_| is used to call OnError() when we stop receiving
- // OnData() calls without an OnClose() call. This can occur
- // when an audio input device is unplugged whilst recording on Windows.
+ // OnData() calls. This can occur when an audio input device is unplugged
+ // whilst recording on Windows.
// See http://crbug.com/79936 for details.
// This member is only touched by the audio thread.
scoped_ptr<base::Timer> no_data_timer_;
UserInputMonitor* user_input_monitor_;
+#if defined(AUDIO_POWER_MONITORING)
+ // Scans audio samples from OnData() as input to compute audio levels.
+ scoped_ptr<AudioPowerMonitor> audio_level_;
+
+ // We need these to be able to feed data to the AudioPowerMonitor.
+ media::AudioParameters audio_params_;
+ base::TimeTicks last_audio_level_log_time_;
+
+ // Whether the silence state should sent as UMA stat.
+ bool log_silence_state_;
+
+ // The silence report sent as UMA stat at the end of a session.
+ SilenceState silence_state_;
+#endif
+
size_t prev_key_down_count_;
DISALLOW_COPY_AND_ASSIGN(AudioInputController);