Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: media/audio/audio_input_controller.cc

Issue 21183002: Adding key press detection in the browser process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 KeyPressMonitor* key_press_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 key_press_monitor_(key_press_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 KeyPressMonitor* key_press_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, key_press_monitor);
68 scoped_refptr<AudioInputController> controller(new AudioInputController( 72 }
69 event_handler, NULL)); 73 scoped_refptr<AudioInputController> controller(
74 new AudioInputController(event_handler, NULL, key_press_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 KeyPressMonitor* key_press_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, key_press_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 KeyPressMonitor* key_press_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, key_press_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
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 key_press_monitor_->AddKeyPressListener(this);
236 } 245 }
237 246
238 void AudioInputController::DoClose() { 247 void AudioInputController::DoClose() {
239 DCHECK(message_loop_->BelongsToCurrentThread()); 248 DCHECK(message_loop_->BelongsToCurrentThread());
240 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); 249 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
241 250
242 // Delete the timer on the same thread that created it. 251 // Delete the timer on the same thread that created it.
243 no_data_timer_.reset(); 252 no_data_timer_.reset();
244 253
245 if (state_ != kClosed) { 254 if (state_ != kClosed) {
246 DoStopCloseAndClearStream(NULL); 255 DoStopCloseAndClearStream(NULL);
247 SetDataIsActive(false); 256 SetDataIsActive(false);
248 257
249 if (LowLatencyMode()) { 258 if (LowLatencyMode()) {
250 sync_writer_->Close(); 259 sync_writer_->Close();
251 } 260 }
252 261
253 state_ = kClosed; 262 state_ = kClosed;
254 } 263 }
264 key_press_monitor_->RemoveKeyPressListener(this);
255 } 265 }
256 266
257 void AudioInputController::DoReportError() { 267 void AudioInputController::DoReportError() {
258 DCHECK(message_loop_->BelongsToCurrentThread()); 268 DCHECK(message_loop_->BelongsToCurrentThread());
259 handler_->OnError(this); 269 handler_->OnError(this);
260 } 270 }
261 271
262 void AudioInputController::DoSetVolume(double volume) { 272 void AudioInputController::DoSetVolume(double volume) {
263 DCHECK(message_loop_->BelongsToCurrentThread()); 273 DCHECK(message_loop_->BelongsToCurrentThread());
264 DCHECK_GE(volume, 0); 274 DCHECK_GE(volume, 0);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 // |kTimerResetIntervalSeconds|. 323 // |kTimerResetIntervalSeconds|.
314 no_data_timer_->Start( 324 no_data_timer_->Start(
315 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), 325 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds),
316 base::Bind(&AudioInputController::DoCheckForNoData, 326 base::Bind(&AudioInputController::DoCheckForNoData,
317 base::Unretained(this))); 327 base::Unretained(this)));
318 } 328 }
319 329
320 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, 330 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
321 uint32 size, uint32 hardware_delay_bytes, 331 uint32 size, uint32 hardware_delay_bytes,
322 double volume) { 332 double volume) {
333 bool key_pressed;
323 { 334 {
324 base::AutoLock auto_lock(lock_); 335 base::AutoLock auto_lock(lock_);
325 if (state_ != kRecording) 336 if (state_ != kRecording)
326 return; 337 return;
338
339 key_pressed = key_pressed_;
DaleCurtis 2013/08/02 01:01:17 You could initialize key_pressed to false above an
jiayl 2013/08/02 20:32:20 Done.
340 key_pressed_ = false;
327 } 341 }
328 342
329 // Mark data as active to ensure that the periodic calls to 343 // Mark data as active to ensure that the periodic calls to
330 // DoCheckForNoData() does not report an error to the event handler. 344 // DoCheckForNoData() does not report an error to the event handler.
331 SetDataIsActive(true); 345 SetDataIsActive(true);
332 346
333 // Use SyncSocket if we are in a low-latency mode. 347 // Use SyncSocket if we are in a low-latency mode.
334 if (LowLatencyMode()) { 348 if (LowLatencyMode()) {
335 sync_writer_->Write(data, size, volume); 349 sync_writer_->Write(data, size, volume, key_pressed);
336 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 350 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
337 return; 351 return;
338 } 352 }
339 353
340 handler_->OnData(this, data, size); 354 handler_->OnData(this, data, size);
341 } 355 }
342 356
343 void AudioInputController::OnClose(AudioInputStream* stream) { 357 void AudioInputController::OnClose(AudioInputStream* stream) {
344 DVLOG(1) << "AudioInputController::OnClose()"; 358 DVLOG(1) << "AudioInputController::OnClose()";
345 // TODO(satish): Sometimes the device driver closes the input stream without 359 // 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 360 // us asking for it (may be if the device was unplugged?). Check how to handle
347 // such cases here. 361 // such cases here.
348 } 362 }
349 363
350 void AudioInputController::OnError(AudioInputStream* stream) { 364 void AudioInputController::OnError(AudioInputStream* stream) {
351 // Handle error on the audio-manager thread. 365 // Handle error on the audio-manager thread.
352 message_loop_->PostTask(FROM_HERE, base::Bind( 366 message_loop_->PostTask(FROM_HERE, base::Bind(
353 &AudioInputController::DoReportError, this)); 367 &AudioInputController::DoReportError, this));
354 } 368 }
355 369
370 void AudioInputController::OnKeyPressed() {
371 base::AutoLock auto_lock(lock_);
372 key_pressed_ = true;
373 }
374
356 void AudioInputController::DoStopCloseAndClearStream( 375 void AudioInputController::DoStopCloseAndClearStream(
357 base::WaitableEvent *done) { 376 base::WaitableEvent* done) {
358 DCHECK(message_loop_->BelongsToCurrentThread()); 377 DCHECK(message_loop_->BelongsToCurrentThread());
359 378
360 // Allow calling unconditionally and bail if we don't have a stream to close. 379 // Allow calling unconditionally and bail if we don't have a stream to close.
361 if (stream_ != NULL) { 380 if (stream_ != NULL) {
362 stream_->Stop(); 381 stream_->Stop();
363 stream_->Close(); 382 stream_->Close();
364 stream_ = NULL; 383 stream_ = NULL;
365 } 384 }
366 385
367 // Should be last in the method, do not touch "this" from here on. 386 // Should be last in the method, do not touch "this" from here on.
368 if (done != NULL) 387 if (done != NULL)
369 done->Signal(); 388 done->Signal();
370 } 389 }
371 390
372 void AudioInputController::SetDataIsActive(bool enabled) { 391 void AudioInputController::SetDataIsActive(bool enabled) {
373 base::subtle::Release_Store(&data_is_active_, enabled); 392 base::subtle::Release_Store(&data_is_active_, enabled);
374 } 393 }
375 394
376 bool AudioInputController::GetDataIsActive() { 395 bool AudioInputController::GetDataIsActive() {
377 return (base::subtle::Acquire_Load(&data_is_active_) != false); 396 return (base::subtle::Acquire_Load(&data_is_active_) != false);
378 } 397 }
379 398
380 } // namespace media 399 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698