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

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

Issue 66183002: Replace MessageLoopProxy with SingleThreadTaskRunner for the rest of media/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win and audio tests Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/audio/audio_input_device.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 15 matching lines...) Expand all
26 } 26 }
27 27
28 namespace media { 28 namespace media {
29 29
30 // static 30 // static
31 AudioInputController::Factory* AudioInputController::factory_ = NULL; 31 AudioInputController::Factory* AudioInputController::factory_ = NULL;
32 32
33 AudioInputController::AudioInputController(EventHandler* handler, 33 AudioInputController::AudioInputController(EventHandler* handler,
34 SyncWriter* sync_writer, 34 SyncWriter* sync_writer,
35 UserInputMonitor* user_input_monitor) 35 UserInputMonitor* user_input_monitor)
36 : creator_loop_(base::MessageLoopProxy::current()), 36 : creator_task_runner_(base::MessageLoopProxy::current()),
37 handler_(handler), 37 handler_(handler),
38 stream_(NULL), 38 stream_(NULL),
39 data_is_active_(false), 39 data_is_active_(false),
40 state_(kEmpty), 40 state_(kEmpty),
41 sync_writer_(sync_writer), 41 sync_writer_(sync_writer),
42 max_volume_(0.0), 42 max_volume_(0.0),
43 user_input_monitor_(user_input_monitor), 43 user_input_monitor_(user_input_monitor),
44 prev_key_down_count_(0) { 44 prev_key_down_count_(0) {
45 DCHECK(creator_loop_.get()); 45 DCHECK(creator_task_runner_.get());
46 } 46 }
47 47
48 AudioInputController::~AudioInputController() { 48 AudioInputController::~AudioInputController() {
49 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); 49 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
50 } 50 }
51 51
52 // static 52 // static
53 scoped_refptr<AudioInputController> AudioInputController::Create( 53 scoped_refptr<AudioInputController> AudioInputController::Create(
54 AudioManager* audio_manager, 54 AudioManager* audio_manager,
55 EventHandler* event_handler, 55 EventHandler* event_handler,
56 const AudioParameters& params, 56 const AudioParameters& params,
57 const std::string& device_id, 57 const std::string& device_id,
58 UserInputMonitor* user_input_monitor) { 58 UserInputMonitor* user_input_monitor) {
59 DCHECK(audio_manager); 59 DCHECK(audio_manager);
60 60
61 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) 61 if (!params.IsValid() || (params.channels() > kMaxInputChannels))
62 return NULL; 62 return NULL;
63 63
64 if (factory_) { 64 if (factory_) {
65 return factory_->Create( 65 return factory_->Create(
66 audio_manager, event_handler, params, user_input_monitor); 66 audio_manager, event_handler, params, user_input_monitor);
67 } 67 }
68 scoped_refptr<AudioInputController> controller( 68 scoped_refptr<AudioInputController> controller(
69 new AudioInputController(event_handler, NULL, user_input_monitor)); 69 new AudioInputController(event_handler, NULL, user_input_monitor));
70 70
71 controller->message_loop_ = audio_manager->GetMessageLoop(); 71 controller->task_runner_ = audio_manager->GetTaskRunner();
72 72
73 // Create and open a new audio input stream from the existing 73 // Create and open a new audio input stream from the existing
74 // audio-device thread. 74 // audio-device thread.
75 if (!controller->message_loop_->PostTask(FROM_HERE, 75 if (!controller->task_runner_->PostTask(FROM_HERE,
76 base::Bind(&AudioInputController::DoCreate, controller, 76 base::Bind(&AudioInputController::DoCreate, controller,
77 base::Unretained(audio_manager), params, device_id))) { 77 base::Unretained(audio_manager), params, device_id))) {
78 controller = NULL; 78 controller = NULL;
79 } 79 }
80 80
81 return controller; 81 return controller;
82 } 82 }
83 83
84 // static 84 // static
85 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( 85 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
86 AudioManager* audio_manager, 86 AudioManager* audio_manager,
87 EventHandler* event_handler, 87 EventHandler* event_handler,
88 const AudioParameters& params, 88 const AudioParameters& params,
89 const std::string& device_id, 89 const std::string& device_id,
90 SyncWriter* sync_writer, 90 SyncWriter* sync_writer,
91 UserInputMonitor* user_input_monitor) { 91 UserInputMonitor* user_input_monitor) {
92 DCHECK(audio_manager); 92 DCHECK(audio_manager);
93 DCHECK(sync_writer); 93 DCHECK(sync_writer);
94 94
95 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) 95 if (!params.IsValid() || (params.channels() > kMaxInputChannels))
96 return NULL; 96 return NULL;
97 97
98 // Create the AudioInputController object and ensure that it runs on 98 // Create the AudioInputController object and ensure that it runs on
99 // the audio-manager thread. 99 // the audio-manager thread.
100 scoped_refptr<AudioInputController> controller( 100 scoped_refptr<AudioInputController> controller(
101 new AudioInputController(event_handler, sync_writer, user_input_monitor)); 101 new AudioInputController(event_handler, sync_writer, user_input_monitor));
102 controller->message_loop_ = audio_manager->GetMessageLoop(); 102 controller->task_runner_ = audio_manager->GetTaskRunner();
103 103
104 // Create and open a new audio input stream from the existing 104 // Create and open a new audio input stream from the existing
105 // audio-device thread. Use the provided audio-input device. 105 // audio-device thread. Use the provided audio-input device.
106 if (!controller->message_loop_->PostTask(FROM_HERE, 106 if (!controller->task_runner_->PostTask(FROM_HERE,
107 base::Bind(&AudioInputController::DoCreate, controller, 107 base::Bind(&AudioInputController::DoCreate, controller,
108 base::Unretained(audio_manager), params, device_id))) { 108 base::Unretained(audio_manager), params, device_id))) {
109 controller = NULL; 109 controller = NULL;
110 } 110 }
111 111
112 return controller; 112 return controller;
113 } 113 }
114 114
115 // static 115 // static
116 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( 116 scoped_refptr<AudioInputController> AudioInputController::CreateForStream(
117 const scoped_refptr<base::MessageLoopProxy>& message_loop, 117 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
118 EventHandler* event_handler, 118 EventHandler* event_handler,
119 AudioInputStream* stream, 119 AudioInputStream* stream,
120 SyncWriter* sync_writer, 120 SyncWriter* sync_writer,
121 UserInputMonitor* user_input_monitor) { 121 UserInputMonitor* user_input_monitor) {
122 DCHECK(sync_writer); 122 DCHECK(sync_writer);
123 DCHECK(stream); 123 DCHECK(stream);
124 124
125 // Create the AudioInputController object and ensure that it runs on 125 // Create the AudioInputController object and ensure that it runs on
126 // the audio-manager thread. 126 // the audio-manager thread.
127 scoped_refptr<AudioInputController> controller( 127 scoped_refptr<AudioInputController> controller(
128 new AudioInputController(event_handler, sync_writer, user_input_monitor)); 128 new AudioInputController(event_handler, sync_writer, user_input_monitor));
129 controller->message_loop_ = message_loop; 129 controller->task_runner_ = task_runner;
130 130
131 // TODO(miu): See TODO at top of file. Until that's resolved, we need to 131 // TODO(miu): See TODO at top of file. Until that's resolved, we need to
132 // disable the error auto-detection here (since the audio mirroring 132 // disable the error auto-detection here (since the audio mirroring
133 // implementation will reliably report error and close events). Note, of 133 // implementation will reliably report error and close events). Note, of
134 // course, that we're assuming CreateForStream() has been called for the audio 134 // course, that we're assuming CreateForStream() has been called for the audio
135 // mirroring use case only. 135 // mirroring use case only.
136 if (!controller->message_loop_->PostTask( 136 if (!controller->task_runner_->PostTask(
137 FROM_HERE, 137 FROM_HERE,
138 base::Bind(&AudioInputController::DoCreateForStream, controller, 138 base::Bind(&AudioInputController::DoCreateForStream, controller,
139 stream, false))) { 139 stream, false))) {
140 controller = NULL; 140 controller = NULL;
141 } 141 }
142 142
143 return controller; 143 return controller;
144 } 144 }
145 145
146 void AudioInputController::Record() { 146 void AudioInputController::Record() {
147 message_loop_->PostTask(FROM_HERE, base::Bind( 147 task_runner_->PostTask(FROM_HERE, base::Bind(
148 &AudioInputController::DoRecord, this)); 148 &AudioInputController::DoRecord, this));
149 } 149 }
150 150
151 void AudioInputController::Close(const base::Closure& closed_task) { 151 void AudioInputController::Close(const base::Closure& closed_task) {
152 DCHECK(!closed_task.is_null()); 152 DCHECK(!closed_task.is_null());
153 DCHECK(creator_loop_->BelongsToCurrentThread()); 153 DCHECK(creator_task_runner_->BelongsToCurrentThread());
154 154
155 message_loop_->PostTaskAndReply( 155 task_runner_->PostTaskAndReply(
156 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); 156 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task);
157 } 157 }
158 158
159 void AudioInputController::SetVolume(double volume) { 159 void AudioInputController::SetVolume(double volume) {
160 message_loop_->PostTask(FROM_HERE, base::Bind( 160 task_runner_->PostTask(FROM_HERE, base::Bind(
161 &AudioInputController::DoSetVolume, this, volume)); 161 &AudioInputController::DoSetVolume, this, volume));
162 } 162 }
163 163
164 void AudioInputController::SetAutomaticGainControl(bool enabled) { 164 void AudioInputController::SetAutomaticGainControl(bool enabled) {
165 message_loop_->PostTask(FROM_HERE, base::Bind( 165 task_runner_->PostTask(FROM_HERE, base::Bind(
166 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); 166 &AudioInputController::DoSetAutomaticGainControl, this, enabled));
167 } 167 }
168 168
169 void AudioInputController::DoCreate(AudioManager* audio_manager, 169 void AudioInputController::DoCreate(AudioManager* audio_manager,
170 const AudioParameters& params, 170 const AudioParameters& params,
171 const std::string& device_id) { 171 const std::string& device_id) {
172 DCHECK(message_loop_->BelongsToCurrentThread()); 172 DCHECK(task_runner_->BelongsToCurrentThread());
173 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); 173 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime");
174 // TODO(miu): See TODO at top of file. Until that's resolved, assume all 174 // TODO(miu): See TODO at top of file. Until that's resolved, assume all
175 // platform audio input requires the |no_data_timer_| be used to auto-detect 175 // platform audio input requires the |no_data_timer_| be used to auto-detect
176 // errors. In reality, probably only Windows needs to be treated as 176 // errors. In reality, probably only Windows needs to be treated as
177 // unreliable here. 177 // unreliable here.
178 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), 178 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id),
179 true); 179 true);
180 } 180 }
181 181
182 void AudioInputController::DoCreateForStream( 182 void AudioInputController::DoCreateForStream(
183 AudioInputStream* stream_to_control, bool enable_nodata_timer) { 183 AudioInputStream* stream_to_control, bool enable_nodata_timer) {
184 DCHECK(message_loop_->BelongsToCurrentThread()); 184 DCHECK(task_runner_->BelongsToCurrentThread());
185 185
186 DCHECK(!stream_); 186 DCHECK(!stream_);
187 stream_ = stream_to_control; 187 stream_ = stream_to_control;
188 188
189 if (!stream_) { 189 if (!stream_) {
190 handler_->OnError(this); 190 handler_->OnError(this);
191 return; 191 return;
192 } 192 }
193 193
194 if (stream_ && !stream_->Open()) { 194 if (stream_ && !stream_->Open()) {
(...skipping 19 matching lines...) Expand all
214 state_ = kCreated; 214 state_ = kCreated;
215 handler_->OnCreated(this); 215 handler_->OnCreated(this);
216 216
217 if (user_input_monitor_) { 217 if (user_input_monitor_) {
218 user_input_monitor_->EnableKeyPressMonitoring(); 218 user_input_monitor_->EnableKeyPressMonitoring();
219 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); 219 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount();
220 } 220 }
221 } 221 }
222 222
223 void AudioInputController::DoRecord() { 223 void AudioInputController::DoRecord() {
224 DCHECK(message_loop_->BelongsToCurrentThread()); 224 DCHECK(task_runner_->BelongsToCurrentThread());
225 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); 225 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
226 226
227 if (state_ != kCreated) 227 if (state_ != kCreated)
228 return; 228 return;
229 229
230 { 230 {
231 base::AutoLock auto_lock(lock_); 231 base::AutoLock auto_lock(lock_);
232 state_ = kRecording; 232 state_ = kRecording;
233 } 233 }
234 234
235 if (no_data_timer_) { 235 if (no_data_timer_) {
236 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, 236 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed,
237 // a callback to DoCheckForNoData() is made. 237 // a callback to DoCheckForNoData() is made.
238 no_data_timer_->Reset(); 238 no_data_timer_->Reset();
239 } 239 }
240 240
241 stream_->Start(this); 241 stream_->Start(this);
242 handler_->OnRecording(this); 242 handler_->OnRecording(this);
243 } 243 }
244 244
245 void AudioInputController::DoClose() { 245 void AudioInputController::DoClose() {
246 DCHECK(message_loop_->BelongsToCurrentThread()); 246 DCHECK(task_runner_->BelongsToCurrentThread());
247 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); 247 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
248 248
249 // Delete the timer on the same thread that created it. 249 // Delete the timer on the same thread that created it.
250 no_data_timer_.reset(); 250 no_data_timer_.reset();
251 251
252 if (state_ != kClosed) { 252 if (state_ != kClosed) {
253 DoStopCloseAndClearStream(NULL); 253 DoStopCloseAndClearStream(NULL);
254 SetDataIsActive(false); 254 SetDataIsActive(false);
255 255
256 if (LowLatencyMode()) { 256 if (LowLatencyMode()) {
257 sync_writer_->Close(); 257 sync_writer_->Close();
258 } 258 }
259 259
260 state_ = kClosed; 260 state_ = kClosed;
261 261
262 if (user_input_monitor_) 262 if (user_input_monitor_)
263 user_input_monitor_->DisableKeyPressMonitoring(); 263 user_input_monitor_->DisableKeyPressMonitoring();
264 } 264 }
265 } 265 }
266 266
267 void AudioInputController::DoReportError() { 267 void AudioInputController::DoReportError() {
268 DCHECK(message_loop_->BelongsToCurrentThread()); 268 DCHECK(task_runner_->BelongsToCurrentThread());
269 handler_->OnError(this); 269 handler_->OnError(this);
270 } 270 }
271 271
272 void AudioInputController::DoSetVolume(double volume) { 272 void AudioInputController::DoSetVolume(double volume) {
273 DCHECK(message_loop_->BelongsToCurrentThread()); 273 DCHECK(task_runner_->BelongsToCurrentThread());
274 DCHECK_GE(volume, 0); 274 DCHECK_GE(volume, 0);
275 DCHECK_LE(volume, 1.0); 275 DCHECK_LE(volume, 1.0);
276 276
277 if (state_ != kCreated && state_ != kRecording) 277 if (state_ != kCreated && state_ != kRecording)
278 return; 278 return;
279 279
280 // Only ask for the maximum volume at first call and use cached value 280 // Only ask for the maximum volume at first call and use cached value
281 // for remaining function calls. 281 // for remaining function calls.
282 if (!max_volume_) { 282 if (!max_volume_) {
283 max_volume_ = stream_->GetMaxVolume(); 283 max_volume_ = stream_->GetMaxVolume();
284 } 284 }
285 285
286 if (max_volume_ == 0.0) { 286 if (max_volume_ == 0.0) {
287 DLOG(WARNING) << "Failed to access input volume control"; 287 DLOG(WARNING) << "Failed to access input volume control";
288 return; 288 return;
289 } 289 }
290 290
291 // Set the stream volume and scale to a range matched to the platform. 291 // Set the stream volume and scale to a range matched to the platform.
292 stream_->SetVolume(max_volume_ * volume); 292 stream_->SetVolume(max_volume_ * volume);
293 } 293 }
294 294
295 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { 295 void AudioInputController::DoSetAutomaticGainControl(bool enabled) {
296 DCHECK(message_loop_->BelongsToCurrentThread()); 296 DCHECK(task_runner_->BelongsToCurrentThread());
297 DCHECK_NE(state_, kRecording); 297 DCHECK_NE(state_, kRecording);
298 298
299 // Ensure that the AGC state only can be modified before streaming starts. 299 // Ensure that the AGC state only can be modified before streaming starts.
300 if (state_ != kCreated || state_ == kRecording) 300 if (state_ != kCreated || state_ == kRecording)
301 return; 301 return;
302 302
303 stream_->SetAutomaticGainControl(enabled); 303 stream_->SetAutomaticGainControl(enabled);
304 } 304 }
305 305
306 void AudioInputController::DoCheckForNoData() { 306 void AudioInputController::DoCheckForNoData() {
307 DCHECK(message_loop_->BelongsToCurrentThread()); 307 DCHECK(task_runner_->BelongsToCurrentThread());
308 308
309 if (!GetDataIsActive()) { 309 if (!GetDataIsActive()) {
310 // The data-is-active marker will be false only if it has been more than 310 // The data-is-active marker will be false only if it has been more than
311 // one second since a data packet was recorded. This can happen if a 311 // one second since a data packet was recorded. This can happen if a
312 // capture device has been removed or disabled. 312 // capture device has been removed or disabled.
313 handler_->OnError(this); 313 handler_->OnError(this);
314 return; 314 return;
315 } 315 }
316 316
317 // Mark data as non-active. The flag will be re-enabled in OnData() each 317 // Mark data as non-active. The flag will be re-enabled in OnData() each
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 sync_writer_->Write(data, size, volume, key_pressed); 355 sync_writer_->Write(data, size, volume, key_pressed);
356 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 356 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
357 return; 357 return;
358 } 358 }
359 359
360 handler_->OnData(this, data, size); 360 handler_->OnData(this, data, size);
361 } 361 }
362 362
363 void AudioInputController::OnError(AudioInputStream* stream) { 363 void AudioInputController::OnError(AudioInputStream* stream) {
364 // Handle error on the audio-manager thread. 364 // Handle error on the audio-manager thread.
365 message_loop_->PostTask(FROM_HERE, base::Bind( 365 task_runner_->PostTask(FROM_HERE, base::Bind(
366 &AudioInputController::DoReportError, this)); 366 &AudioInputController::DoReportError, this));
367 } 367 }
368 368
369 void AudioInputController::DoStopCloseAndClearStream( 369 void AudioInputController::DoStopCloseAndClearStream(
370 base::WaitableEvent* done) { 370 base::WaitableEvent* done) {
371 DCHECK(message_loop_->BelongsToCurrentThread()); 371 DCHECK(task_runner_->BelongsToCurrentThread());
372 372
373 // Allow calling unconditionally and bail if we don't have a stream to close. 373 // Allow calling unconditionally and bail if we don't have a stream to close.
374 if (stream_ != NULL) { 374 if (stream_ != NULL) {
375 stream_->Stop(); 375 stream_->Stop();
376 stream_->Close(); 376 stream_->Close();
377 stream_ = NULL; 377 stream_ = NULL;
378 } 378 }
379 379
380 // Should be last in the method, do not touch "this" from here on. 380 // Should be last in the method, do not touch "this" from here on.
381 if (done != NULL) 381 if (done != NULL)
382 done->Signal(); 382 done->Signal();
383 } 383 }
384 384
385 void AudioInputController::SetDataIsActive(bool enabled) { 385 void AudioInputController::SetDataIsActive(bool enabled) {
386 base::subtle::Release_Store(&data_is_active_, enabled); 386 base::subtle::Release_Store(&data_is_active_, enabled);
387 } 387 }
388 388
389 bool AudioInputController::GetDataIsActive() { 389 bool AudioInputController::GetDataIsActive() {
390 return (base::subtle::Acquire_Load(&data_is_active_) != false); 390 return (base::subtle::Acquire_Load(&data_is_active_) != false);
391 } 391 }
392 392
393 } // namespace media 393 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/audio/audio_input_device.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698