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.
5 #include "media/audio/audio_input_controller.h"
8 #include "base/threading/thread_restrictions.h"
9 #include "media/base/limits.h"
12 const int kMaxInputChannels
= 2;
13 const int kTimerResetIntervalSeconds
= 1;
15 // The first callback on iOS is received after the current background
16 // audio has faded away.
17 const int kTimerInitialIntervalSeconds
= 4;
19 // We have received reports that the timer can be too trigger happy on some
20 // Mac devices and the initial timer interval has therefore been increased
21 // from 1 second to 5 seconds.
22 // TODO(henrika): remove usage of timers and add support for proper
23 // notification of when the input device is removed.
24 // See http://crbug.com/226327 for details.
25 const int kTimerInitialIntervalSeconds
= 5;
26 #endif // defined(OS_IOS)
32 AudioInputController::Factory
* AudioInputController::factory_
= NULL
;
34 AudioInputController::AudioInputController(EventHandler
* handler
,
35 SyncWriter
* sync_writer
)
36 : creator_loop_(base::MessageLoopProxy::current()),
39 data_is_active_(false),
41 sync_writer_(sync_writer
),
43 DCHECK(creator_loop_
);
46 AudioInputController::~AudioInputController() {
47 DCHECK(kClosed
== state_
|| kCreated
== state_
|| kEmpty
== state_
);
51 scoped_refptr
<AudioInputController
> AudioInputController::Create(
52 AudioManager
* audio_manager
,
53 EventHandler
* event_handler
,
54 const AudioParameters
& params
) {
55 DCHECK(audio_manager
);
57 if (!params
.IsValid() || (params
.channels() > kMaxInputChannels
))
61 return factory_
->Create(audio_manager
, event_handler
, params
);
63 scoped_refptr
<AudioInputController
> controller(new AudioInputController(
64 event_handler
, NULL
));
66 controller
->message_loop_
= audio_manager
->GetMessageLoop();
68 // Create and open a new audio input stream from the existing
69 // audio-device thread. Use the default audio-input device.
70 std::string device_id
= AudioManagerBase::kDefaultDeviceId
;
71 if (!controller
->message_loop_
->PostTask(FROM_HERE
,
72 base::Bind(&AudioInputController::DoCreate
, controller
,
73 base::Unretained(audio_manager
), params
, device_id
))) {
81 scoped_refptr
<AudioInputController
> AudioInputController::CreateLowLatency(
82 AudioManager
* audio_manager
,
83 EventHandler
* event_handler
,
84 const AudioParameters
& params
,
85 const std::string
& device_id
,
86 SyncWriter
* sync_writer
) {
87 DCHECK(audio_manager
);
90 if (!params
.IsValid() || (params
.channels() > kMaxInputChannels
))
93 // Create the AudioInputController object and ensure that it runs on
94 // the audio-manager thread.
95 scoped_refptr
<AudioInputController
> controller(new AudioInputController(
96 event_handler
, sync_writer
));
97 controller
->message_loop_
= audio_manager
->GetMessageLoop();
99 // Create and open a new audio input stream from the existing
100 // audio-device thread. Use the provided audio-input device.
101 if (!controller
->message_loop_
->PostTask(FROM_HERE
,
102 base::Bind(&AudioInputController::DoCreate
, controller
,
103 base::Unretained(audio_manager
), params
, device_id
))) {
111 scoped_refptr
<AudioInputController
> AudioInputController::CreateForStream(
112 AudioManager
* audio_manager
,
113 EventHandler
* event_handler
,
114 AudioInputStream
* stream
,
115 SyncWriter
* sync_writer
) {
116 DCHECK(audio_manager
);
120 // Create the AudioInputController object and ensure that it runs on
121 // the audio-manager thread.
122 scoped_refptr
<AudioInputController
> controller(new AudioInputController(
123 event_handler
, sync_writer
));
124 controller
->message_loop_
= audio_manager
->GetMessageLoop();
126 if (!controller
->message_loop_
->PostTask(
128 base::Bind(&AudioInputController::DoCreateForStream
, controller
,
136 void AudioInputController::Record() {
137 message_loop_
->PostTask(FROM_HERE
, base::Bind(
138 &AudioInputController::DoRecord
, this));
141 void AudioInputController::Close(const base::Closure
& closed_task
) {
142 DCHECK(!closed_task
.is_null());
143 DCHECK(creator_loop_
->BelongsToCurrentThread());
145 message_loop_
->PostTaskAndReply(
146 FROM_HERE
, base::Bind(&AudioInputController::DoClose
, this), closed_task
);
149 void AudioInputController::SetVolume(double volume
) {
150 message_loop_
->PostTask(FROM_HERE
, base::Bind(
151 &AudioInputController::DoSetVolume
, this, volume
));
154 void AudioInputController::SetAutomaticGainControl(bool enabled
) {
155 message_loop_
->PostTask(FROM_HERE
, base::Bind(
156 &AudioInputController::DoSetAutomaticGainControl
, this, enabled
));
159 void AudioInputController::DoCreate(AudioManager
* audio_manager
,
160 const AudioParameters
& params
,
161 const std::string
& device_id
) {
162 DCHECK(message_loop_
->BelongsToCurrentThread());
163 DoCreateForStream(audio_manager
->MakeAudioInputStream(params
, device_id
));
166 void AudioInputController::DoCreateForStream(
167 AudioInputStream
* stream_to_control
) {
168 DCHECK(message_loop_
->BelongsToCurrentThread());
171 stream_
= stream_to_control
;
174 handler_
->OnError(this);
178 if (stream_
&& !stream_
->Open()) {
181 handler_
->OnError(this);
185 DCHECK(!no_data_timer_
.get());
186 // Create the data timer which will call DoCheckForNoData(). The timer
187 // is started in DoRecord() and restarted in each DoCheckForNoData() callback.
188 no_data_timer_
.reset(new base::Timer(
189 FROM_HERE
, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds
),
190 base::Bind(&AudioInputController::DoCheckForNoData
,
191 base::Unretained(this)), false));
193 handler_
->OnCreated(this);
196 void AudioInputController::DoRecord() {
197 DCHECK(message_loop_
->BelongsToCurrentThread());
199 if (state_
!= kCreated
)
203 base::AutoLock
auto_lock(lock_
);
207 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed,
208 // a callback to DoCheckForNoData() is made.
209 no_data_timer_
->Reset();
211 stream_
->Start(this);
212 handler_
->OnRecording(this);
215 void AudioInputController::DoClose() {
216 DCHECK(message_loop_
->BelongsToCurrentThread());
218 // Delete the timer on the same thread that created it.
219 no_data_timer_
.reset();
221 if (state_
!= kClosed
) {
222 DoStopCloseAndClearStream(NULL
);
223 SetDataIsActive(false);
225 if (LowLatencyMode()) {
226 sync_writer_
->Close();
233 void AudioInputController::DoReportError() {
234 DCHECK(message_loop_
->BelongsToCurrentThread());
235 handler_
->OnError(this);
238 void AudioInputController::DoSetVolume(double volume
) {
239 DCHECK(message_loop_
->BelongsToCurrentThread());
240 DCHECK_GE(volume
, 0);
241 DCHECK_LE(volume
, 1.0);
243 if (state_
!= kCreated
&& state_
!= kRecording
)
246 // Only ask for the maximum volume at first call and use cached value
247 // for remaining function calls.
249 max_volume_
= stream_
->GetMaxVolume();
252 if (max_volume_
== 0.0) {
253 DLOG(WARNING
) << "Failed to access input volume control";
257 // Set the stream volume and scale to a range matched to the platform.
258 stream_
->SetVolume(max_volume_
* volume
);
261 void AudioInputController::DoSetAutomaticGainControl(bool enabled
) {
262 DCHECK(message_loop_
->BelongsToCurrentThread());
263 DCHECK_NE(state_
, kRecording
);
265 // Ensure that the AGC state only can be modified before streaming starts.
266 if (state_
!= kCreated
|| state_
== kRecording
)
269 stream_
->SetAutomaticGainControl(enabled
);
272 void AudioInputController::DoCheckForNoData() {
273 DCHECK(message_loop_
->BelongsToCurrentThread());
275 if (!GetDataIsActive()) {
276 // The data-is-active marker will be false only if it has been more than
277 // one second since a data packet was recorded. This can happen if a
278 // capture device has been removed or disabled.
279 handler_
->OnError(this);
283 // Mark data as non-active. The flag will be re-enabled in OnData() each
284 // time a data packet is received. Hence, under normal conditions, the
285 // flag will only be disabled during a very short period.
286 SetDataIsActive(false);
288 // Restart the timer to ensure that we check the flag again in
289 // |kTimerResetIntervalSeconds|.
290 no_data_timer_
->Start(
291 FROM_HERE
, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds
),
292 base::Bind(&AudioInputController::DoCheckForNoData
,
293 base::Unretained(this)));
296 void AudioInputController::OnData(AudioInputStream
* stream
, const uint8
* data
,
297 uint32 size
, uint32 hardware_delay_bytes
,
300 base::AutoLock
auto_lock(lock_
);
301 if (state_
!= kRecording
)
305 // Mark data as active to ensure that the periodic calls to
306 // DoCheckForNoData() does not report an error to the event handler.
307 SetDataIsActive(true);
309 // Use SyncSocket if we are in a low-latency mode.
310 if (LowLatencyMode()) {
311 sync_writer_
->Write(data
, size
, volume
);
312 sync_writer_
->UpdateRecordedBytes(hardware_delay_bytes
);
316 handler_
->OnData(this, data
, size
);
319 void AudioInputController::OnClose(AudioInputStream
* stream
) {
320 DVLOG(1) << "AudioInputController::OnClose()";
321 // TODO(satish): Sometimes the device driver closes the input stream without
322 // us asking for it (may be if the device was unplugged?). Check how to handle
326 void AudioInputController::OnError(AudioInputStream
* stream
) {
327 // Handle error on the audio-manager thread.
328 message_loop_
->PostTask(FROM_HERE
, base::Bind(
329 &AudioInputController::DoReportError
, this));
332 void AudioInputController::DoStopCloseAndClearStream(
333 base::WaitableEvent
*done
) {
334 DCHECK(message_loop_
->BelongsToCurrentThread());
336 // Allow calling unconditionally and bail if we don't have a stream to close.
337 if (stream_
!= NULL
) {
343 // Should be last in the method, do not touch "this" from here on.
348 void AudioInputController::SetDataIsActive(bool enabled
) {
349 base::subtle::Release_Store(&data_is_active_
, enabled
);
352 bool AudioInputController::GetDataIsActive() {
353 return (base::subtle::Acquire_Load(&data_is_active_
) != false);