Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "content/browser/renderer_host/media/audio_renderer_host.h" | 5 #include "content/browser/renderer_host/media/audio_renderer_host.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/shared_memory.h" | 10 #include "base/memory/shared_memory.h" |
| 11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "base/process/process.h" | 12 #include "base/process/process.h" |
| 13 #include "content/browser/browser_main_loop.h" | 13 #include "content/browser/browser_main_loop.h" |
| 14 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 14 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 15 #include "content/browser/media/audio_stream_monitor.h" | 15 #include "content/browser/media/audio_stream_monitor.h" |
| 16 #include "content/browser/media/capture/audio_mirroring_manager.h" | 16 #include "content/browser/media/capture/audio_mirroring_manager.h" |
| 17 #include "content/browser/media/media_internals.h" | 17 #include "content/browser/media/media_internals.h" |
| 18 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 18 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 19 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 19 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
| 20 #include "content/browser/renderer_host/media/media_stream_manager.h" | 20 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 21 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | |
| 21 #include "content/browser/renderer_host/render_widget_host_impl.h" | 22 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 22 #include "content/common/media/audio_messages.h" | 23 #include "content/common/media/audio_messages.h" |
| 23 #include "content/public/browser/content_browser_client.h" | 24 #include "content/public/browser/content_browser_client.h" |
| 25 #include "content/public/browser/media_device_id.h" | |
| 24 #include "content/public/browser/media_observer.h" | 26 #include "content/public/browser/media_observer.h" |
| 25 #include "content/public/browser/render_frame_host.h" | 27 #include "content/public/browser/render_frame_host.h" |
| 26 #include "content/public/browser/render_view_host.h" | 28 #include "content/public/browser/render_view_host.h" |
| 27 #include "content/public/common/content_switches.h" | 29 #include "content/public/common/content_switches.h" |
| 30 #include "media/audio/audio_device_name.h" | |
| 28 #include "media/audio/audio_manager_base.h" | 31 #include "media/audio/audio_manager_base.h" |
| 29 #include "media/base/audio_bus.h" | 32 #include "media/base/audio_bus.h" |
| 30 #include "media/base/limits.h" | 33 #include "media/base/limits.h" |
| 31 | 34 |
| 32 using media::AudioBus; | 35 using media::AudioBus; |
| 33 using media::AudioManager; | 36 using media::AudioManager; |
| 34 | 37 |
| 35 namespace content { | 38 namespace content { |
| 36 | 39 |
| 37 namespace { | 40 namespace { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 AudioRendererHost::AudioEntry::~AudioEntry() {} | 142 AudioRendererHost::AudioEntry::~AudioEntry() {} |
| 140 | 143 |
| 141 /////////////////////////////////////////////////////////////////////////////// | 144 /////////////////////////////////////////////////////////////////////////////// |
| 142 // AudioRendererHost implementations. | 145 // AudioRendererHost implementations. |
| 143 | 146 |
| 144 AudioRendererHost::AudioRendererHost( | 147 AudioRendererHost::AudioRendererHost( |
| 145 int render_process_id, | 148 int render_process_id, |
| 146 media::AudioManager* audio_manager, | 149 media::AudioManager* audio_manager, |
| 147 AudioMirroringManager* mirroring_manager, | 150 AudioMirroringManager* mirroring_manager, |
| 148 MediaInternals* media_internals, | 151 MediaInternals* media_internals, |
| 149 MediaStreamManager* media_stream_manager) | 152 MediaStreamManager* media_stream_manager, |
| 153 const ResourceContext::SaltCallback& salt_callback) | |
| 150 : BrowserMessageFilter(AudioMsgStart), | 154 : BrowserMessageFilter(AudioMsgStart), |
| 151 render_process_id_(render_process_id), | 155 render_process_id_(render_process_id), |
| 152 audio_manager_(audio_manager), | 156 audio_manager_(audio_manager), |
| 153 mirroring_manager_(mirroring_manager), | 157 mirroring_manager_(mirroring_manager), |
| 154 audio_log_(media_internals->CreateAudioLog( | 158 audio_log_(media_internals->CreateAudioLog( |
| 155 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)), | 159 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)), |
| 156 media_stream_manager_(media_stream_manager), | 160 media_stream_manager_(media_stream_manager), |
| 157 num_playing_streams_(0) { | 161 num_playing_streams_(0), |
| 162 salt_callback_(salt_callback) { | |
| 158 DCHECK(audio_manager_); | 163 DCHECK(audio_manager_); |
| 159 DCHECK(media_stream_manager_); | 164 DCHECK(media_stream_manager_); |
| 160 } | 165 } |
| 161 | 166 |
| 162 AudioRendererHost::~AudioRendererHost() { | 167 AudioRendererHost::~AudioRendererHost() { |
| 163 DCHECK(audio_entries_.empty()); | 168 DCHECK(audio_entries_.empty()); |
| 164 } | 169 } |
| 165 | 170 |
| 166 void AudioRendererHost::GetOutputControllers( | 171 void AudioRendererHost::GetOutputControllers( |
| 167 const RenderProcessHost::GetAudioOutputControllersCallback& | 172 const RenderProcessHost::GetAudioOutputControllersCallback& |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 /////////////////////////////////////////////////////////////////////////////// | 308 /////////////////////////////////////////////////////////////////////////////// |
| 304 // IPC Messages handler | 309 // IPC Messages handler |
| 305 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { | 310 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { |
| 306 bool handled = true; | 311 bool handled = true; |
| 307 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) | 312 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) |
| 308 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) | 313 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) |
| 309 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) | 314 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) |
| 310 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) | 315 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) |
| 311 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | 316 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) |
| 312 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | 317 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
| 318 IPC_MESSAGE_HANDLER(AudioHostMsg_SwitchOutputDevice, OnSwitchOutputDevice) | |
| 313 IPC_MESSAGE_UNHANDLED(handled = false) | 319 IPC_MESSAGE_UNHANDLED(handled = false) |
| 314 IPC_END_MESSAGE_MAP() | 320 IPC_END_MESSAGE_MAP() |
| 315 | 321 |
| 316 return handled; | 322 return handled; |
| 317 } | 323 } |
| 318 | 324 |
| 319 void AudioRendererHost::OnCreateStream(int stream_id, | 325 void AudioRendererHost::OnCreateStream(int stream_id, |
| 320 int render_frame_id, | 326 int render_frame_id, |
| 321 int session_id, | 327 int session_id, |
| 322 const media::AudioParameters& params) { | 328 const media::AudioParameters& params) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 return; | 421 return; |
| 416 } | 422 } |
| 417 | 423 |
| 418 // Make sure the volume is valid. | 424 // Make sure the volume is valid. |
| 419 if (volume < 0 || volume > 1.0) | 425 if (volume < 0 || volume > 1.0) |
| 420 return; | 426 return; |
| 421 entry->controller()->SetVolume(volume); | 427 entry->controller()->SetVolume(volume); |
| 422 audio_log_->OnSetVolume(stream_id, volume); | 428 audio_log_->OnSetVolume(stream_id, volume); |
| 423 } | 429 } |
| 424 | 430 |
| 431 void AudioRendererHost::OnSwitchOutputDevice( | |
| 432 int stream_id, | |
| 433 const std::string& device_id, | |
| 434 const GURL& security_origin, | |
| 435 int render_frame_id, | |
| 436 int request_id) { | |
| 437 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 438 DVLOG(1) << "AudioRendererHost@" << this | |
| 439 << "::OnSwitchOutputDevice(stream_id=" << stream_id | |
| 440 << ", device_id=" << device_id | |
| 441 << ", security_origin=" << security_origin | |
| 442 << ", render_frame_id=" << render_frame_id | |
| 443 << ", request_id=" << request_id | |
| 444 << ")"; | |
| 445 | |
| 446 if (device_id.empty()) { | |
| 447 DVLOG(1) << __FUNCTION__ << ": default output device requested. " | |
| 448 <<"No permissions check or device translation/validation needed."; | |
| 449 DoSwitchOutputDevice(stream_id, device_id, request_id); | |
| 450 } else { | |
| 451 // We want to check that MediaStream device permissions have been granted, | |
|
miu
2015/06/03 21:01:01
nit: Please rewrite all code comments in this CL w
| |
| 452 // hence the use of a MediaStreamUIProxy. | |
| 453 scoped_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create(); | |
| 454 | |
| 455 // We use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT | |
| 456 // because MediaStreamUIProxy::CheckAccess does not currently support | |
| 457 // MEDIA_DEVICE_AUDIO_OUTPUT. | |
| 458 ui_proxy->CheckAccess(security_origin, | |
| 459 MEDIA_DEVICE_AUDIO_CAPTURE, | |
| 460 render_process_id_, | |
| 461 render_frame_id, | |
| 462 base::Bind( | |
| 463 &AudioRendererHost::OutputDeviceAccessChecked, | |
| 464 this, | |
| 465 base::Passed(&ui_proxy), | |
| 466 stream_id, | |
| 467 device_id, | |
| 468 security_origin, | |
| 469 render_frame_id, | |
| 470 request_id)); | |
| 471 } | |
| 472 } | |
| 473 | |
| 474 void AudioRendererHost::OutputDeviceAccessChecked( | |
| 475 scoped_ptr<MediaStreamUIProxy> ui_proxy, | |
| 476 int stream_id, | |
| 477 const std::string& device_id, | |
| 478 const GURL& security_origin, | |
| 479 int render_frame_id, | |
| 480 int request_id, | |
| 481 bool have_access) { | |
| 482 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 483 DVLOG(1) << __FUNCTION__; | |
| 484 if (!have_access) { | |
| 485 DVLOG(0) << __FUNCTION__ | |
| 486 << ": Have no access to media devices. Not switching device."; | |
| 487 Send(new AudioMsg_NotifyOutputDeviceSwitched( | |
| 488 stream_id, request_id, media::AudioOutputIPCDelegate::kSecurityError)); | |
| 489 return; | |
| 490 } | |
| 491 | |
| 492 scoped_refptr<base::SingleThreadTaskRunner> audio_worker_runner = | |
| 493 AudioManager::Get()->GetWorkerTaskRunner(); | |
| 494 audio_worker_runner->PostTask(FROM_HERE, base::Bind( | |
| 495 &AudioRendererHost::StartTranslateOutputDeviceName, | |
| 496 this, | |
| 497 stream_id, | |
| 498 device_id, | |
| 499 security_origin, | |
| 500 request_id)); | |
| 501 } | |
| 502 | |
| 503 void AudioRendererHost::StartTranslateOutputDeviceName( | |
| 504 int stream_id, | |
| 505 const std::string& device_id, | |
| 506 const GURL& security_origin, | |
| 507 int request_id) { | |
| 508 DCHECK(AudioManager::Get()->GetWorkerTaskRunner()->BelongsToCurrentThread()); | |
| 509 DCHECK(!device_id.empty()); | |
| 510 DVLOG(1) << __FUNCTION__; | |
| 511 | |
| 512 media::AudioDeviceNames* device_names = new media::AudioDeviceNames; | |
| 513 AudioManager::Get()->GetAudioOutputDeviceNames(device_names); | |
| 514 | |
| 515 BrowserThread::PostTask( | |
| 516 BrowserThread::IO, FROM_HERE, | |
| 517 base::Bind(&AudioRendererHost::FinishTranslateOutputDeviceName, | |
| 518 this, | |
| 519 stream_id, | |
| 520 device_id, | |
| 521 security_origin, | |
| 522 request_id, | |
| 523 base::Owned(device_names))); | |
| 524 } | |
| 525 | |
| 526 void AudioRendererHost::FinishTranslateOutputDeviceName( | |
| 527 int stream_id, | |
| 528 const std::string& device_id, | |
| 529 const GURL& security_origin, | |
| 530 int request_id, | |
| 531 media::AudioDeviceNames* device_names) { | |
| 532 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 533 DCHECK(!device_id.empty()); | |
| 534 DVLOG(1) << __FUNCTION__; | |
| 535 | |
| 536 std::string raw_device_id = ""; | |
| 537 // We process the enumeration here because |salt_callback_| can run | |
| 538 // only on the IO thread | |
| 539 for (const auto &device_name : *device_names) { | |
| 540 const std::string candidate_device_id = | |
| 541 content::GetHMACForMediaDeviceID(salt_callback_, | |
| 542 security_origin, | |
| 543 device_name.unique_id); | |
| 544 if (candidate_device_id == device_id) { | |
| 545 DVLOG(1) << "Requested device " << device_name.unique_id << " - " | |
| 546 << device_name.device_name; | |
| 547 raw_device_id = device_name.unique_id; | |
| 548 } | |
| 549 } | |
| 550 | |
| 551 if (raw_device_id.empty()) { | |
| 552 DVLOG(1) << "Requested device " << device_id << " could not be found."; | |
| 553 Send(new AudioMsg_NotifyOutputDeviceSwitched( | |
| 554 stream_id, request_id, media::AudioOutputIPCDelegate::kNotFound)); | |
| 555 return; | |
| 556 } | |
| 557 | |
| 558 DoSwitchOutputDevice(stream_id, raw_device_id, request_id); | |
| 559 } | |
| 560 | |
| 561 void AudioRendererHost::DoSwitchOutputDevice( | |
| 562 int stream_id, const std::string& raw_device_id, int request_id) { | |
| 563 DVLOG(1) << __FUNCTION__ << "(" << stream_id << ", " << raw_device_id << ", " | |
|
miu
2015/06/03 21:01:01
nit: Add DCHECK_CURRENTLY_ON(...)
| |
| 564 << request_id << ")"; | |
| 565 AudioEntry* entry = LookupById(stream_id); | |
| 566 if (!entry) { | |
| 567 Send(new AudioMsg_NotifyOutputDeviceSwitched( | |
| 568 stream_id, request_id, media::AudioOutputIPCDelegate::kOtherError)); | |
| 569 return; | |
| 570 } | |
| 571 | |
| 572 entry->controller()->SwitchOutputDevice( | |
| 573 raw_device_id, | |
| 574 base::Bind(&AudioRendererHost::DoOutputDeviceSwitched, | |
| 575 this, | |
| 576 stream_id, | |
| 577 request_id)); | |
| 578 audio_log_->OnSwitchOutputDevice(entry->stream_id(), raw_device_id); | |
| 579 } | |
| 580 | |
| 581 void AudioRendererHost::DoOutputDeviceSwitched(int stream_id, int request_id) { | |
| 582 DVLOG(1) << __FUNCTION__ << "(" << stream_id << ", " << request_id << ")"; | |
|
miu
2015/06/03 21:01:01
nit: Add DCHECK_CURRENTLY_ON(...)
| |
| 583 Send(new AudioMsg_NotifyOutputDeviceSwitched( | |
| 584 stream_id, request_id, media::AudioOutputIPCDelegate::kSuccess)); | |
| 585 } | |
| 586 | |
| 425 void AudioRendererHost::SendErrorMessage(int stream_id) { | 587 void AudioRendererHost::SendErrorMessage(int stream_id) { |
| 426 Send(new AudioMsg_NotifyStreamStateChanged( | 588 Send(new AudioMsg_NotifyStreamStateChanged( |
| 427 stream_id, media::AudioOutputIPCDelegate::kError)); | 589 stream_id, media::AudioOutputIPCDelegate::kError)); |
| 428 } | 590 } |
| 429 | 591 |
| 430 void AudioRendererHost::OnCloseStream(int stream_id) { | 592 void AudioRendererHost::OnCloseStream(int stream_id) { |
| 431 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 593 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 432 | 594 |
| 433 // Prevent oustanding callbacks from attempting to close/delete the same | 595 // Prevent oustanding callbacks from attempting to close/delete the same |
| 434 // AudioEntry twice. | 596 // AudioEntry twice. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 it != audio_entries_.end(); | 675 it != audio_entries_.end(); |
| 514 ++it) { | 676 ++it) { |
| 515 AudioEntry* entry = it->second; | 677 AudioEntry* entry = it->second; |
| 516 if (entry->render_frame_id() == render_frame_id && entry->playing()) | 678 if (entry->render_frame_id() == render_frame_id && entry->playing()) |
| 517 return true; | 679 return true; |
| 518 } | 680 } |
| 519 return false; | 681 return false; |
| 520 } | 682 } |
| 521 | 683 |
| 522 } // namespace content | 684 } // namespace content |
| OLD | NEW |