| 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 |