OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/renderer/media/webrtc_audio_device_impl.h" | 5 #include "content/renderer/media/webrtc_audio_device_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/win/windows_version.h" | 10 #include "base/win/windows_version.h" |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 // Calling Terminate() multiple times in a row is OK. | 163 // Calling Terminate() multiple times in a row is OK. |
164 if (!initialized_) | 164 if (!initialized_) |
165 return 0; | 165 return 0; |
166 | 166 |
167 StopRecording(); | 167 StopRecording(); |
168 StopPlayout(); | 168 StopPlayout(); |
169 | 169 |
170 DCHECK(!renderer_.get() || !renderer_->IsStarted()) | 170 DCHECK(!renderer_.get() || !renderer_->IsStarted()) |
171 << "The shared audio renderer shouldn't be running"; | 171 << "The shared audio renderer shouldn't be running"; |
172 | 172 |
173 { | 173 // Stop all the capturers to ensure no further OnData() and |
174 base::AutoLock auto_lock(lock_); | 174 // RemoveAudioCapturer() callback. |
175 capturers_.clear(); | 175 // Cache the capturers in a local list since WebRtcAudioCapturer::Stop() |
| 176 // will trigger RemoveAudioCapturer() callback. |
| 177 CapturerList capturers; |
| 178 capturers.swap(capturers_); |
| 179 for (CapturerList::const_iterator iter = capturers.begin(); |
| 180 iter != capturers.end(); ++iter) { |
| 181 (*iter)->Stop(); |
176 } | 182 } |
177 | 183 |
178 initialized_ = false; | 184 initialized_ = false; |
179 return 0; | 185 return 0; |
180 } | 186 } |
181 | 187 |
182 bool WebRtcAudioDeviceImpl::Initialized() const { | 188 bool WebRtcAudioDeviceImpl::Initialized() const { |
183 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 189 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
184 return initialized_; | 190 return initialized_; |
185 } | 191 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 return recording_; | 287 return recording_; |
282 } | 288 } |
283 | 289 |
284 int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { | 290 int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { |
285 DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; | 291 DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; |
286 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 292 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
287 DCHECK(initialized_); | 293 DCHECK(initialized_); |
288 | 294 |
289 // Only one microphone is supported at the moment, which is represented by | 295 // Only one microphone is supported at the moment, which is represented by |
290 // the default capturer. | 296 // the default capturer. |
291 base::AutoLock auto_lock(lock_); | 297 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); |
292 if (capturers_.empty()) | 298 if (!capturer.get()) |
293 return -1; | 299 return -1; |
294 capturers_.back()->SetVolume(volume); | 300 |
| 301 capturer->SetVolume(volume); |
295 return 0; | 302 return 0; |
296 } | 303 } |
297 | 304 |
298 // TODO(henrika): sort out calling thread once we start using this API. | 305 // TODO(henrika): sort out calling thread once we start using this API. |
299 int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { | 306 int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { |
300 DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; | 307 DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; |
301 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 308 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
302 // We only support one microphone now, which is accessed via the default | 309 // We only support one microphone now, which is accessed via the default |
303 // capturer. | 310 // capturer. |
304 DCHECK(initialized_); | 311 DCHECK(initialized_); |
305 base::AutoLock auto_lock(lock_); | 312 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); |
306 if (capturers_.empty()) | 313 if (!capturer.get()) |
307 return -1; | 314 return -1; |
308 *volume = static_cast<uint32_t>(capturers_.back()->Volume()); | 315 |
| 316 *volume = static_cast<uint32_t>(capturer->Volume()); |
| 317 |
309 return 0; | 318 return 0; |
310 } | 319 } |
311 | 320 |
312 int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { | 321 int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { |
313 DCHECK(initialized_); | 322 DCHECK(initialized_); |
314 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 323 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
315 *max_volume = kMaxVolumeLevel; | 324 *max_volume = kMaxVolumeLevel; |
316 return 0; | 325 return 0; |
317 } | 326 } |
318 | 327 |
(...skipping 17 matching lines...) Expand all Loading... |
336 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( | 345 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( |
337 bool* available) const { | 346 bool* available) const { |
338 DCHECK(initialized_); | 347 DCHECK(initialized_); |
339 // This method is called during initialization on the signaling thread and | 348 // This method is called during initialization on the signaling thread and |
340 // then later on the worker thread. Due to this we cannot DCHECK on what | 349 // then later on the worker thread. Due to this we cannot DCHECK on what |
341 // thread we're on since it might incorrectly initialize the | 350 // thread we're on since it might incorrectly initialize the |
342 // worker_thread_checker_. | 351 // worker_thread_checker_. |
343 | 352 |
344 // TODO(xians): These kind of hardware methods do not make much sense since we | 353 // TODO(xians): These kind of hardware methods do not make much sense since we |
345 // support multiple sources. Remove or figure out new APIs for such methods. | 354 // support multiple sources. Remove or figure out new APIs for such methods. |
346 base::AutoLock auto_lock(lock_); | 355 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); |
347 if (capturers_.empty()) | 356 if (!capturer.get()) |
348 return -1; | 357 return -1; |
349 *available = (capturers_.back()->GetInputFormat().channels() == 2); | 358 |
| 359 *available = (capturer->source_audio_parameters().channels() == 2); |
350 return 0; | 360 return 0; |
351 } | 361 } |
352 | 362 |
353 int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { | 363 int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { |
354 DCHECK(worker_thread_checker_.CalledOnValidThread()); | 364 DCHECK(worker_thread_checker_.CalledOnValidThread()); |
355 base::AutoLock auto_lock(lock_); | 365 base::AutoLock auto_lock(lock_); |
356 *delay_ms = static_cast<uint16_t>(output_delay_ms_); | 366 *delay_ms = static_cast<uint16_t>(output_delay_ms_); |
357 return 0; | 367 return 0; |
358 } | 368 } |
359 | 369 |
360 int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { | 370 int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { |
361 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 371 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
362 | 372 |
363 // There is no way to report a correct delay value to WebRTC since there | 373 // There is no way to report a correct delay value to WebRTC since there |
364 // might be multiple WebRtcAudioCapturer instances. | 374 // might be multiple WebRtcAudioCapturer instances. |
365 NOTREACHED(); | 375 NOTREACHED(); |
366 return -1; | 376 return -1; |
367 } | 377 } |
368 | 378 |
369 int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( | 379 int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( |
370 uint32_t* sample_rate) const { | 380 uint32_t* sample_rate) const { |
371 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 381 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
372 // We use the default capturer as the recording sample rate. | 382 // We use the default capturer as the recording sample rate. |
373 base::AutoLock auto_lock(lock_); | 383 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); |
374 if (capturers_.empty()) | 384 if (!capturer.get()) |
375 return -1; | 385 return -1; |
376 const media::AudioParameters& params = capturers_.back()->GetInputFormat(); | 386 |
377 *sample_rate = static_cast<uint32_t>(params.sample_rate()); | 387 *sample_rate = static_cast<uint32_t>( |
| 388 capturer->source_audio_parameters().sample_rate()); |
378 return 0; | 389 return 0; |
379 } | 390 } |
380 | 391 |
381 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( | 392 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( |
382 uint32_t* sample_rate) const { | 393 uint32_t* sample_rate) const { |
383 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 394 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
384 *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; | 395 *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; |
385 return 0; | 396 return 0; |
386 } | 397 } |
387 | 398 |
(...skipping 27 matching lines...) Expand all Loading... |
415 audio_renderer_thread_checker_.DetachFromThread(); | 426 audio_renderer_thread_checker_.DetachFromThread(); |
416 | 427 |
417 // We acquire |lock_| again and assert our precondition, since we are | 428 // We acquire |lock_| again and assert our precondition, since we are |
418 // accessing the internal state again. | 429 // accessing the internal state again. |
419 base::AutoLock auto_lock(lock_); | 430 base::AutoLock auto_lock(lock_); |
420 DCHECK(!renderer_.get()); | 431 DCHECK(!renderer_.get()); |
421 renderer_ = renderer; | 432 renderer_ = renderer; |
422 return true; | 433 return true; |
423 } | 434 } |
424 | 435 |
425 void WebRtcAudioDeviceImpl::AddAudioCapturer(WebRtcAudioCapturer* capturer) { | 436 void WebRtcAudioDeviceImpl::AddAudioCapturer( |
| 437 const scoped_refptr<WebRtcAudioCapturer>& capturer) { |
426 DCHECK(main_thread_checker_.CalledOnValidThread()); | 438 DCHECK(main_thread_checker_.CalledOnValidThread()); |
427 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; | 439 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; |
428 DCHECK(capturer); | 440 DCHECK(capturer.get()); |
429 DCHECK(!capturer->device_info().device.id.empty()); | 441 DCHECK(!capturer->device_id().empty()); |
430 | 442 |
431 base::AutoLock auto_lock(lock_); | 443 base::AutoLock auto_lock(lock_); |
432 DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == | 444 DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == |
433 capturers_.end()); | 445 capturers_.end()); |
434 capturers_.push_back(capturer); | 446 capturers_.push_back(capturer); |
435 } | 447 } |
436 | 448 |
437 void WebRtcAudioDeviceImpl::RemoveAudioCapturer(WebRtcAudioCapturer* capturer) { | 449 void WebRtcAudioDeviceImpl::RemoveAudioCapturer( |
| 450 const scoped_refptr<WebRtcAudioCapturer>& capturer) { |
438 DCHECK(main_thread_checker_.CalledOnValidThread()); | 451 DCHECK(main_thread_checker_.CalledOnValidThread()); |
439 DVLOG(1) << "WebRtcAudioDeviceImpl::RemoveAudioCapturer()"; | 452 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; |
440 DCHECK(capturer); | 453 DCHECK(capturer.get()); |
441 base::AutoLock auto_lock(lock_); | 454 base::AutoLock auto_lock(lock_); |
442 capturers_.remove(capturer); | 455 capturers_.remove(capturer); |
443 } | 456 } |
444 | 457 |
| 458 scoped_refptr<WebRtcAudioCapturer> |
| 459 WebRtcAudioDeviceImpl::GetDefaultCapturer() const { |
| 460 // Called on the signaling thread (during initialization), worker |
| 461 // thread during capture or main thread for a WebAudio source. |
| 462 // We can't DCHECK on those three checks here since GetDefaultCapturer |
| 463 // may be the first call and therefore could incorrectly initialize the |
| 464 // thread checkers. |
| 465 DCHECK(initialized_); |
| 466 base::AutoLock auto_lock(lock_); |
| 467 // Use the last |capturer| which is from the latest getUserMedia call as |
| 468 // the default capture device. |
| 469 return capturers_.empty() ? NULL : capturers_.back(); |
| 470 } |
| 471 |
445 void WebRtcAudioDeviceImpl::AddPlayoutSink( | 472 void WebRtcAudioDeviceImpl::AddPlayoutSink( |
446 WebRtcPlayoutDataSource::Sink* sink) { | 473 WebRtcPlayoutDataSource::Sink* sink) { |
447 DCHECK(main_thread_checker_.CalledOnValidThread()); | 474 DCHECK(main_thread_checker_.CalledOnValidThread()); |
448 DCHECK(sink); | 475 DCHECK(sink); |
449 base::AutoLock auto_lock(lock_); | 476 base::AutoLock auto_lock(lock_); |
450 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == | 477 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == |
451 playout_sinks_.end()); | 478 playout_sinks_.end()); |
452 playout_sinks_.push_back(sink); | 479 playout_sinks_.push_back(sink); |
453 } | 480 } |
454 | 481 |
455 void WebRtcAudioDeviceImpl::RemovePlayoutSink( | 482 void WebRtcAudioDeviceImpl::RemovePlayoutSink( |
456 WebRtcPlayoutDataSource::Sink* sink) { | 483 WebRtcPlayoutDataSource::Sink* sink) { |
457 DCHECK(main_thread_checker_.CalledOnValidThread()); | 484 DCHECK(main_thread_checker_.CalledOnValidThread()); |
458 DCHECK(sink); | 485 DCHECK(sink); |
459 base::AutoLock auto_lock(lock_); | 486 base::AutoLock auto_lock(lock_); |
460 playout_sinks_.remove(sink); | 487 playout_sinks_.remove(sink); |
461 } | 488 } |
462 | 489 |
463 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( | 490 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( |
464 int* session_id, | 491 int* session_id, |
465 int* output_sample_rate, | 492 int* output_sample_rate, |
466 int* output_frames_per_buffer) { | 493 int* output_frames_per_buffer) { |
467 DCHECK(main_thread_checker_.CalledOnValidThread()); | 494 DCHECK(main_thread_checker_.CalledOnValidThread()); |
468 base::AutoLock lock(lock_); | 495 base::AutoLock lock(lock_); |
469 // If there is no capturer or there are more than one open capture devices, | 496 // If there is no capturer or there are more than one open capture devices, |
470 // return false. | 497 // return false. |
471 if (capturers_.size() != 1) | 498 if (capturers_.size() != 1) |
472 return false; | 499 return false; |
473 | 500 |
474 // Don't set output parameters unless all of them are valid. | 501 return capturers_.back()->GetPairedOutputParameters( |
475 const StreamDeviceInfo& device_info = capturers_.back()->device_info(); | 502 session_id, output_sample_rate, output_frames_per_buffer); |
476 if (device_info.session_id <= 0 || | |
477 !device_info.device.matched_output.sample_rate || | |
478 !device_info.device.matched_output.frames_per_buffer) { | |
479 return false; | |
480 } | |
481 | |
482 *session_id = device_info.session_id; | |
483 *output_sample_rate = device_info.device.matched_output.sample_rate; | |
484 *output_frames_per_buffer = | |
485 device_info.device.matched_output.frames_per_buffer; | |
486 | |
487 return true; | |
488 } | 503 } |
489 | 504 |
490 } // namespace content | 505 } // namespace content |
OLD | NEW |