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