• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_
6 #define MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_
7 
8 #include <string>
9 #include "base/atomicops.h"
10 #include "base/callback.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/synchronization/lock.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/threading/thread.h"
16 #include "base/timer/timer.h"
17 #include "media/audio/audio_io.h"
18 #include "media/audio/audio_manager_base.h"
19 #include "media/audio/audio_parameters.h"
20 #include "media/audio/audio_power_monitor.h"
21 #include "media/base/audio_bus.h"
22 
23 // An AudioInputController controls an AudioInputStream and records data
24 // from this input stream. The two main methods are Record() and Close() and
25 // they are both executed on the audio thread which is injected by the two
26 // alternative factory methods, Create() or CreateLowLatency().
27 //
28 // All public methods of AudioInputController are non-blocking.
29 //
30 // Here is a state diagram for the AudioInputController:
31 //
32 //                    .-->  [ Closed / Error ]  <--.
33 //                    |                            |
34 //                    |                            |
35 //               [ Created ]  ---------->  [ Recording ]
36 //                    ^
37 //                    |
38 //              *[  Empty  ]
39 //
40 // * Initial state
41 //
42 // State sequences (assuming low-latency):
43 //
44 //  [Creating Thread]                     [Audio Thread]
45 //
46 //      User               AudioInputController               EventHandler
47 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
48 // CrateLowLatency() ==>        DoCreate()
49 //                   AudioManager::MakeAudioInputStream()
50 //                        AudioInputStream::Open()
51 //                                  .- - - - - - - - - - - - ->   OnError()
52 //                          create the data timer
53 //                                  .------------------------->  OnCreated()
54 //                               kCreated
55 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
56 // Record() ==>                 DoRecord()
57 //                      AudioInputStream::Start()
58 //                                  .------------------------->  OnRecording()
59 //                          start the data timer
60 //                              kRecording
61 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62 // Close() ==>                  DoClose()
63 //                        delete the data timer
64 //                           state_ = kClosed
65 //                        AudioInputStream::Stop()
66 //                        AudioInputStream::Close()
67 //                          SyncWriter::Close()
68 // Closure::Run() <-----------------.
69 // (closure-task)
70 //
71 // The audio thread itself is owned by the AudioManager that the
72 // AudioInputController holds a reference to.  When performing tasks on the
73 // audio thread, the controller must not add or release references to the
74 // AudioManager or itself (since it in turn holds a reference to the manager).
75 //
76 namespace media {
77 
78 // Only do power monitoring for non-mobile platforms to save resources.
79 #if !defined(OS_ANDROID) && !defined(OS_IOS)
80 #define AUDIO_POWER_MONITORING
81 #endif
82 
83 class UserInputMonitor;
84 
85 class MEDIA_EXPORT AudioInputController
86     : public base::RefCountedThreadSafe<AudioInputController>,
87       public AudioInputStream::AudioInputCallback {
88  public:
89 
90   // Error codes to make native loggin more clear. These error codes are added
91   // to generic error strings to provide a higher degree of details.
92   // Changing these values can lead to problems when matching native debug
93   // logs with the actual cause of error.
94   enum ErrorCode {
95     // An unspecified error occured.
96     UNKNOWN_ERROR = 0,
97 
98     // Failed to create an audio input stream.
99     STREAM_CREATE_ERROR,  // = 1
100 
101     // Failed to open an audio input stream.
102     STREAM_OPEN_ERROR,  // = 2
103 
104     // Native input stream reports an error. Exact reason differs between
105     // platforms.
106     STREAM_ERROR,  // = 3
107 
108     // This can happen if a capture device has been removed or disabled.
109     NO_DATA_ERROR,  // = 4
110   };
111 
112   // An event handler that receives events from the AudioInputController. The
113   // following methods are all called on the audio thread.
114   class MEDIA_EXPORT EventHandler {
115    public:
116     virtual void OnCreated(AudioInputController* controller) = 0;
117     virtual void OnRecording(AudioInputController* controller) = 0;
118     virtual void OnError(AudioInputController* controller,
119                          ErrorCode error_code) = 0;
120     virtual void OnData(AudioInputController* controller,
121                         const AudioBus* data) = 0;
122     virtual void OnLog(AudioInputController* controller,
123                        const std::string& message) = 0;
124 
125    protected:
~EventHandler()126     virtual ~EventHandler() {}
127   };
128 
129   // A synchronous writer interface used by AudioInputController for
130   // synchronous writing.
131   class SyncWriter {
132    public:
~SyncWriter()133     virtual ~SyncWriter() {}
134 
135     // Notify the synchronous writer about the number of bytes in the
136     // soundcard which has been recorded.
137     virtual void UpdateRecordedBytes(uint32 bytes) = 0;
138 
139     // Write certain amount of data from |data|.
140     virtual void Write(const AudioBus* data,
141                        double volume,
142                        bool key_pressed) = 0;
143 
144     // Close this synchronous writer.
145     virtual void Close() = 0;
146   };
147 
148   // AudioInputController::Create() can use the currently registered Factory
149   // to create the AudioInputController. Factory is intended for testing only.
150   // |user_input_monitor| is used for typing detection and can be NULL.
151   class Factory {
152    public:
153     virtual AudioInputController* Create(
154         AudioManager* audio_manager,
155         EventHandler* event_handler,
156         AudioParameters params,
157         UserInputMonitor* user_input_monitor) = 0;
158 
159    protected:
~Factory()160     virtual ~Factory() {}
161   };
162 
163   // Factory method for creating an AudioInputController.
164   // The audio device will be created on the audio thread, and when that is
165   // done, the event handler will receive an OnCreated() call from that same
166   // thread. |device_id| is the unique ID of the audio device to be opened.
167   // |user_input_monitor| is used for typing detection and can be NULL.
168   static scoped_refptr<AudioInputController> Create(
169       AudioManager* audio_manager,
170       EventHandler* event_handler,
171       const AudioParameters& params,
172       const std::string& device_id,
173       UserInputMonitor* user_input_monitor);
174 
175   // Sets the factory used by the static method Create(). AudioInputController
176   // does not take ownership of |factory|. A value of NULL results in an
177   // AudioInputController being created directly.
set_factory_for_testing(Factory * factory)178   static void set_factory_for_testing(Factory* factory) { factory_ = factory; }
stream_for_testing()179   AudioInputStream* stream_for_testing() { return stream_; }
180 
181   // Factory method for creating an AudioInputController for low-latency mode.
182   // The audio device will be created on the audio thread, and when that is
183   // done, the event handler will receive an OnCreated() call from that same
184   // thread. |user_input_monitor| is used for typing detection and can be NULL.
185   static scoped_refptr<AudioInputController> CreateLowLatency(
186       AudioManager* audio_manager,
187       EventHandler* event_handler,
188       const AudioParameters& params,
189       const std::string& device_id,
190       // External synchronous writer for audio controller.
191       SyncWriter* sync_writer,
192       UserInputMonitor* user_input_monitor);
193 
194   // Factory method for creating an AudioInputController for low-latency mode,
195   // taking ownership of |stream|.  The stream will be opened on the audio
196   // thread, and when that is done, the event handler will receive an
197   // OnCreated() call from that same thread. |user_input_monitor| is used for
198   // typing detection and can be NULL.
199   static scoped_refptr<AudioInputController> CreateForStream(
200       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
201       EventHandler* event_handler,
202       AudioInputStream* stream,
203       // External synchronous writer for audio controller.
204       SyncWriter* sync_writer,
205       UserInputMonitor* user_input_monitor);
206 
207   // Starts recording using the created audio input stream.
208   // This method is called on the creator thread.
209   virtual void Record();
210 
211   // Closes the audio input stream. The state is changed and the resources
212   // are freed on the audio thread. |closed_task| is then executed on the thread
213   // that called Close().
214   // Callbacks (EventHandler and SyncWriter) must exist until |closed_task|
215   // is called.
216   // It is safe to call this method more than once. Calls after the first one
217   // will have no effect.
218   // This method trampolines to the audio thread.
219   virtual void Close(const base::Closure& closed_task);
220 
221   // Sets the capture volume of the input stream. The value 0.0 corresponds
222   // to muted and 1.0 to maximum volume.
223   virtual void SetVolume(double volume);
224 
225   // Sets the Automatic Gain Control (AGC) state of the input stream.
226   // Changing the AGC state is not supported while recording is active.
227   virtual void SetAutomaticGainControl(bool enabled);
228 
229   // AudioInputCallback implementation. Threading details depends on the
230   // device-specific implementation.
231   virtual void OnData(AudioInputStream* stream,
232                       const AudioBus* source,
233                       uint32 hardware_delay_bytes,
234                       double volume) OVERRIDE;
235   virtual void OnError(AudioInputStream* stream) OVERRIDE;
236 
SharedMemoryAndSyncSocketMode()237   bool SharedMemoryAndSyncSocketMode() const { return sync_writer_ != NULL; }
238 
239  protected:
240   friend class base::RefCountedThreadSafe<AudioInputController>;
241 
242   // Internal state of the source.
243   enum State {
244     CREATED,
245     RECORDING,
246     CLOSED
247   };
248 
249   AudioInputController(EventHandler* handler,
250                        SyncWriter* sync_writer,
251                        UserInputMonitor* user_input_monitor);
252   virtual ~AudioInputController();
253 
254   // Methods called on the audio thread (owned by the AudioManager).
255   void DoCreate(AudioManager* audio_manager, const AudioParameters& params,
256                 const std::string& device_id);
257   void DoCreateForStream(AudioInputStream* stream_to_control,
258                          bool enable_nodata_timer);
259   void DoRecord();
260   void DoClose();
261   void DoReportError();
262   void DoSetVolume(double volume);
263   void DoSetAutomaticGainControl(bool enabled);
264   void DoOnData(scoped_ptr<AudioBus> data);
265   void DoLogAudioLevel(float level_dbfs);
266 
267   // Method to check if we get recorded data after a stream was started,
268   // and log the result to UMA.
269   void FirstCheckForNoData();
270 
271   // Method which ensures that OnError() is triggered when data recording
272   // times out. Called on the audio thread.
273   void DoCheckForNoData();
274 
275   // Helper method that stops, closes, and NULL:s |*stream_|.
276   void DoStopCloseAndClearStream();
277 
278   void SetDataIsActive(bool enabled);
279   bool GetDataIsActive();
280 
281   // Gives access to the task runner of the creating thread.
282   scoped_refptr<base::SingleThreadTaskRunner> creator_task_runner_;
283 
284   // The task runner of audio-manager thread that this object runs on.
285   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
286 
287   // Contains the AudioInputController::EventHandler which receives state
288   // notifications from this class.
289   EventHandler* handler_;
290 
291   // Pointer to the audio input stream object.
292   AudioInputStream* stream_;
293 
294   // |no_data_timer_| is used to call OnError() when we stop receiving
295   // OnData() calls. This can occur when an audio input device is unplugged
296   // whilst recording on Windows.
297   // See http://crbug.com/79936 for details.
298   // This member is only touched by the audio thread.
299   scoped_ptr<base::Timer> no_data_timer_;
300 
301   // This flag is used to signal that we are receiving OnData() calls, i.e,
302   // that data is active. It can be touched by the audio thread and by the
303   // low-level audio thread which calls OnData(). E.g. on Windows, the
304   // low-level audio thread is called wasapi_capture_thread.
305   base::subtle::Atomic32 data_is_active_;
306 
307   // |state_| is written on the audio thread and is read on the hardware audio
308   // thread. These operations need to be locked. But lock is not required for
309   // reading on the audio input controller thread.
310   State state_;
311 
312   base::Lock lock_;
313 
314   // SyncWriter is used only in low-latency mode for synchronous writing.
315   SyncWriter* sync_writer_;
316 
317   static Factory* factory_;
318 
319   double max_volume_;
320 
321   UserInputMonitor* user_input_monitor_;
322 
323 #if defined(AUDIO_POWER_MONITORING)
324   // Scans audio samples from OnData() as input to compute audio levels.
325   scoped_ptr<AudioPowerMonitor> audio_level_;
326 
327   // We need these to be able to feed data to the AudioPowerMonitor.
328   media::AudioParameters audio_params_;
329   base::TimeTicks last_audio_level_log_time_;
330 #endif
331 
332   size_t prev_key_down_count_;
333 
334   DISALLOW_COPY_AND_ASSIGN(AudioInputController);
335 };
336 
337 }  // namespace media
338 
339 #endif  // MEDIA_AUDIO_AUDIO_INPUT_CONTROLLER_H_
340