OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/audio_input_controller.h" | 5 #include "media/audio/audio_input_controller.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/threading/thread_restrictions.h" | 8 #include "base/threading/thread_restrictions.h" |
9 #include "media/base/limits.h" | 9 #include "media/base/limits.h" |
10 #include "media/base/scoped_histogram_timer.h" | 10 #include "media/base/scoped_histogram_timer.h" |
(...skipping 18 matching lines...) Expand all Loading... | |
29 const int kTimerInitialIntervalSeconds = 5; | 29 const int kTimerInitialIntervalSeconds = 5; |
30 #endif // defined(OS_IOS) | 30 #endif // defined(OS_IOS) |
31 } | 31 } |
32 | 32 |
33 namespace media { | 33 namespace media { |
34 | 34 |
35 // static | 35 // static |
36 AudioInputController::Factory* AudioInputController::factory_ = NULL; | 36 AudioInputController::Factory* AudioInputController::factory_ = NULL; |
37 | 37 |
38 AudioInputController::AudioInputController(EventHandler* handler, | 38 AudioInputController::AudioInputController(EventHandler* handler, |
39 SyncWriter* sync_writer) | 39 SyncWriter* sync_writer, |
40 UserInputMonitor* user_input_monitor) | |
40 : creator_loop_(base::MessageLoopProxy::current()), | 41 : creator_loop_(base::MessageLoopProxy::current()), |
41 handler_(handler), | 42 handler_(handler), |
42 stream_(NULL), | 43 stream_(NULL), |
43 data_is_active_(false), | 44 data_is_active_(false), |
44 state_(kEmpty), | 45 state_(kEmpty), |
45 sync_writer_(sync_writer), | 46 sync_writer_(sync_writer), |
46 max_volume_(0.0) { | 47 max_volume_(0.0), |
48 user_input_monitor_(user_input_monitor), | |
49 key_pressed_(false) { | |
47 DCHECK(creator_loop_.get()); | 50 DCHECK(creator_loop_.get()); |
48 } | 51 } |
49 | 52 |
50 AudioInputController::~AudioInputController() { | 53 AudioInputController::~AudioInputController() { |
51 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); | 54 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); |
52 } | 55 } |
53 | 56 |
54 // static | 57 // static |
55 scoped_refptr<AudioInputController> AudioInputController::Create( | 58 scoped_refptr<AudioInputController> AudioInputController::Create( |
56 AudioManager* audio_manager, | 59 AudioManager* audio_manager, |
57 EventHandler* event_handler, | 60 EventHandler* event_handler, |
58 const AudioParameters& params, | 61 const AudioParameters& params, |
59 const std::string& device_id) { | 62 const std::string& device_id, |
63 UserInputMonitor* user_input_monitor) { | |
60 DCHECK(audio_manager); | 64 DCHECK(audio_manager); |
61 | 65 |
62 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 66 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
63 return NULL; | 67 return NULL; |
64 | 68 |
65 if (factory_) | 69 if (factory_) { |
66 return factory_->Create(audio_manager, event_handler, params); | 70 return factory_->Create( |
67 | 71 audio_manager, event_handler, params, user_input_monitor); |
68 scoped_refptr<AudioInputController> controller(new AudioInputController( | 72 } |
69 event_handler, NULL)); | 73 scoped_refptr<AudioInputController> controller( |
74 new AudioInputController(event_handler, NULL, user_input_monitor)); | |
70 | 75 |
71 controller->message_loop_ = audio_manager->GetMessageLoop(); | 76 controller->message_loop_ = audio_manager->GetMessageLoop(); |
72 | 77 |
73 // Create and open a new audio input stream from the existing | 78 // Create and open a new audio input stream from the existing |
74 // audio-device thread. | 79 // audio-device thread. |
75 if (!controller->message_loop_->PostTask(FROM_HERE, | 80 if (!controller->message_loop_->PostTask(FROM_HERE, |
76 base::Bind(&AudioInputController::DoCreate, controller, | 81 base::Bind(&AudioInputController::DoCreate, controller, |
77 base::Unretained(audio_manager), params, device_id))) { | 82 base::Unretained(audio_manager), params, device_id))) { |
78 controller = NULL; | 83 controller = NULL; |
79 } | 84 } |
80 | 85 |
81 return controller; | 86 return controller; |
82 } | 87 } |
83 | 88 |
84 // static | 89 // static |
85 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( | 90 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( |
86 AudioManager* audio_manager, | 91 AudioManager* audio_manager, |
87 EventHandler* event_handler, | 92 EventHandler* event_handler, |
88 const AudioParameters& params, | 93 const AudioParameters& params, |
89 const std::string& device_id, | 94 const std::string& device_id, |
90 SyncWriter* sync_writer) { | 95 SyncWriter* sync_writer, |
96 UserInputMonitor* user_input_monitor) { | |
91 DCHECK(audio_manager); | 97 DCHECK(audio_manager); |
92 DCHECK(sync_writer); | 98 DCHECK(sync_writer); |
93 | 99 |
94 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 100 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
95 return NULL; | 101 return NULL; |
96 | 102 |
97 // Create the AudioInputController object and ensure that it runs on | 103 // Create the AudioInputController object and ensure that it runs on |
98 // the audio-manager thread. | 104 // the audio-manager thread. |
99 scoped_refptr<AudioInputController> controller(new AudioInputController( | 105 scoped_refptr<AudioInputController> controller( |
100 event_handler, sync_writer)); | 106 new AudioInputController(event_handler, sync_writer, user_input_monitor)); |
101 controller->message_loop_ = audio_manager->GetMessageLoop(); | 107 controller->message_loop_ = audio_manager->GetMessageLoop(); |
102 | 108 |
103 // Create and open a new audio input stream from the existing | 109 // Create and open a new audio input stream from the existing |
104 // audio-device thread. Use the provided audio-input device. | 110 // audio-device thread. Use the provided audio-input device. |
105 if (!controller->message_loop_->PostTask(FROM_HERE, | 111 if (!controller->message_loop_->PostTask(FROM_HERE, |
106 base::Bind(&AudioInputController::DoCreate, controller, | 112 base::Bind(&AudioInputController::DoCreate, controller, |
107 base::Unretained(audio_manager), params, device_id))) { | 113 base::Unretained(audio_manager), params, device_id))) { |
108 controller = NULL; | 114 controller = NULL; |
109 } | 115 } |
110 | 116 |
111 return controller; | 117 return controller; |
112 } | 118 } |
113 | 119 |
114 // static | 120 // static |
115 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( | 121 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( |
116 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 122 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
117 EventHandler* event_handler, | 123 EventHandler* event_handler, |
118 AudioInputStream* stream, | 124 AudioInputStream* stream, |
119 SyncWriter* sync_writer) { | 125 SyncWriter* sync_writer, |
126 UserInputMonitor* user_input_monitor) { | |
120 DCHECK(sync_writer); | 127 DCHECK(sync_writer); |
121 DCHECK(stream); | 128 DCHECK(stream); |
122 | 129 |
123 // Create the AudioInputController object and ensure that it runs on | 130 // Create the AudioInputController object and ensure that it runs on |
124 // the audio-manager thread. | 131 // the audio-manager thread. |
125 scoped_refptr<AudioInputController> controller(new AudioInputController( | 132 scoped_refptr<AudioInputController> controller( |
126 event_handler, sync_writer)); | 133 new AudioInputController(event_handler, sync_writer, user_input_monitor)); |
127 controller->message_loop_ = message_loop; | 134 controller->message_loop_ = message_loop; |
128 | 135 |
129 // TODO(miu): See TODO at top of file. Until that's resolved, we need to | 136 // TODO(miu): See TODO at top of file. Until that's resolved, we need to |
130 // disable the error auto-detection here (since the audio mirroring | 137 // disable the error auto-detection here (since the audio mirroring |
131 // implementation will reliably report error and close events). Note, of | 138 // implementation will reliably report error and close events). Note, of |
132 // course, that we're assuming CreateForStream() has been called for the audio | 139 // course, that we're assuming CreateForStream() has been called for the audio |
133 // mirroring use case only. | 140 // mirroring use case only. |
134 if (!controller->message_loop_->PostTask( | 141 if (!controller->message_loop_->PostTask( |
135 FROM_HERE, | 142 FROM_HERE, |
136 base::Bind(&AudioInputController::DoCreateForStream, controller, | 143 base::Bind(&AudioInputController::DoCreateForStream, controller, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 } | 233 } |
227 | 234 |
228 if (no_data_timer_) { | 235 if (no_data_timer_) { |
229 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, | 236 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, |
230 // a callback to DoCheckForNoData() is made. | 237 // a callback to DoCheckForNoData() is made. |
231 no_data_timer_->Reset(); | 238 no_data_timer_->Reset(); |
232 } | 239 } |
233 | 240 |
234 stream_->Start(this); | 241 stream_->Start(this); |
235 handler_->OnRecording(this); | 242 handler_->OnRecording(this); |
243 | |
244 if (user_input_monitor_) | |
245 user_input_monitor_->AddKeyStrokeListener(this); | |
236 } | 246 } |
237 | 247 |
238 void AudioInputController::DoClose() { | 248 void AudioInputController::DoClose() { |
239 DCHECK(message_loop_->BelongsToCurrentThread()); | 249 DCHECK(message_loop_->BelongsToCurrentThread()); |
240 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); | 250 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); |
241 | 251 |
242 // Delete the timer on the same thread that created it. | 252 // Delete the timer on the same thread that created it. |
243 no_data_timer_.reset(); | 253 no_data_timer_.reset(); |
244 | 254 |
245 if (state_ != kClosed) { | 255 if (state_ != kClosed) { |
246 DoStopCloseAndClearStream(NULL); | 256 DoStopCloseAndClearStream(NULL); |
247 SetDataIsActive(false); | 257 SetDataIsActive(false); |
248 | 258 |
249 if (LowLatencyMode()) { | 259 if (LowLatencyMode()) { |
250 sync_writer_->Close(); | 260 sync_writer_->Close(); |
251 } | 261 } |
252 | 262 |
253 state_ = kClosed; | 263 state_ = kClosed; |
254 } | 264 } |
265 if (user_input_monitor_) | |
DaleCurtis
2013/08/12 20:24:11
Should this be in the (state_ != kClosed) block? Y
| |
266 user_input_monitor_->RemoveKeyStrokeListener(this); | |
255 } | 267 } |
256 | 268 |
257 void AudioInputController::DoReportError() { | 269 void AudioInputController::DoReportError() { |
258 DCHECK(message_loop_->BelongsToCurrentThread()); | 270 DCHECK(message_loop_->BelongsToCurrentThread()); |
259 handler_->OnError(this); | 271 handler_->OnError(this); |
260 } | 272 } |
261 | 273 |
262 void AudioInputController::DoSetVolume(double volume) { | 274 void AudioInputController::DoSetVolume(double volume) { |
263 DCHECK(message_loop_->BelongsToCurrentThread()); | 275 DCHECK(message_loop_->BelongsToCurrentThread()); |
264 DCHECK_GE(volume, 0); | 276 DCHECK_GE(volume, 0); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 // |kTimerResetIntervalSeconds|. | 325 // |kTimerResetIntervalSeconds|. |
314 no_data_timer_->Start( | 326 no_data_timer_->Start( |
315 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), | 327 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), |
316 base::Bind(&AudioInputController::DoCheckForNoData, | 328 base::Bind(&AudioInputController::DoCheckForNoData, |
317 base::Unretained(this))); | 329 base::Unretained(this))); |
318 } | 330 } |
319 | 331 |
320 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, | 332 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, |
321 uint32 size, uint32 hardware_delay_bytes, | 333 uint32 size, uint32 hardware_delay_bytes, |
322 double volume) { | 334 double volume) { |
335 bool key_pressed = false; | |
323 { | 336 { |
324 base::AutoLock auto_lock(lock_); | 337 base::AutoLock auto_lock(lock_); |
325 if (state_ != kRecording) | 338 if (state_ != kRecording) |
326 return; | 339 return; |
340 | |
341 std::swap(key_pressed, key_pressed_); | |
327 } | 342 } |
328 | 343 |
329 // Mark data as active to ensure that the periodic calls to | 344 // Mark data as active to ensure that the periodic calls to |
330 // DoCheckForNoData() does not report an error to the event handler. | 345 // DoCheckForNoData() does not report an error to the event handler. |
331 SetDataIsActive(true); | 346 SetDataIsActive(true); |
332 | 347 |
333 // Use SyncSocket if we are in a low-latency mode. | 348 // Use SyncSocket if we are in a low-latency mode. |
334 if (LowLatencyMode()) { | 349 if (LowLatencyMode()) { |
335 sync_writer_->Write(data, size, volume); | 350 sync_writer_->Write(data, size, volume, key_pressed); |
336 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 351 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
337 return; | 352 return; |
338 } | 353 } |
339 | 354 |
340 handler_->OnData(this, data, size); | 355 handler_->OnData(this, data, size); |
341 } | 356 } |
342 | 357 |
343 void AudioInputController::OnClose(AudioInputStream* stream) { | 358 void AudioInputController::OnClose(AudioInputStream* stream) { |
344 DVLOG(1) << "AudioInputController::OnClose()"; | 359 DVLOG(1) << "AudioInputController::OnClose()"; |
345 // TODO(satish): Sometimes the device driver closes the input stream without | 360 // TODO(satish): Sometimes the device driver closes the input stream without |
346 // us asking for it (may be if the device was unplugged?). Check how to handle | 361 // us asking for it (may be if the device was unplugged?). Check how to handle |
347 // such cases here. | 362 // such cases here. |
348 } | 363 } |
349 | 364 |
350 void AudioInputController::OnError(AudioInputStream* stream) { | 365 void AudioInputController::OnError(AudioInputStream* stream) { |
351 // Handle error on the audio-manager thread. | 366 // Handle error on the audio-manager thread. |
352 message_loop_->PostTask(FROM_HERE, base::Bind( | 367 message_loop_->PostTask(FROM_HERE, base::Bind( |
353 &AudioInputController::DoReportError, this)); | 368 &AudioInputController::DoReportError, this)); |
354 } | 369 } |
355 | 370 |
371 void AudioInputController::OnKeyPressed() { | |
372 base::AutoLock auto_lock(lock_); | |
373 key_pressed_ = true; | |
374 } | |
375 | |
356 void AudioInputController::DoStopCloseAndClearStream( | 376 void AudioInputController::DoStopCloseAndClearStream( |
357 base::WaitableEvent *done) { | 377 base::WaitableEvent* done) { |
358 DCHECK(message_loop_->BelongsToCurrentThread()); | 378 DCHECK(message_loop_->BelongsToCurrentThread()); |
359 | 379 |
360 // Allow calling unconditionally and bail if we don't have a stream to close. | 380 // Allow calling unconditionally and bail if we don't have a stream to close. |
361 if (stream_ != NULL) { | 381 if (stream_ != NULL) { |
362 stream_->Stop(); | 382 stream_->Stop(); |
363 stream_->Close(); | 383 stream_->Close(); |
364 stream_ = NULL; | 384 stream_ = NULL; |
365 } | 385 } |
366 | 386 |
367 // Should be last in the method, do not touch "this" from here on. | 387 // Should be last in the method, do not touch "this" from here on. |
368 if (done != NULL) | 388 if (done != NULL) |
369 done->Signal(); | 389 done->Signal(); |
370 } | 390 } |
371 | 391 |
372 void AudioInputController::SetDataIsActive(bool enabled) { | 392 void AudioInputController::SetDataIsActive(bool enabled) { |
373 base::subtle::Release_Store(&data_is_active_, enabled); | 393 base::subtle::Release_Store(&data_is_active_, enabled); |
374 } | 394 } |
375 | 395 |
376 bool AudioInputController::GetDataIsActive() { | 396 bool AudioInputController::GetDataIsActive() { |
377 return (base::subtle::Acquire_Load(&data_is_active_) != false); | 397 return (base::subtle::Acquire_Load(&data_is_active_) != false); |
378 } | 398 } |
379 | 399 |
380 } // namespace media | 400 } // namespace media |
OLD | NEW |