| 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 <stdint.h> | 7 #include <stdint.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 // better to report a valid value if this is the only problem. | 102 // better to report a valid value if this is the only problem. |
| 103 if (params->channels() > media::limits::kMaxChannels) | 103 if (params->channels() > media::limits::kMaxChannels) |
| 104 params->set_channels_for_discrete(media::limits::kMaxChannels); | 104 params->set_channels_for_discrete(media::limits::kMaxChannels); |
| 105 | 105 |
| 106 // If hardware parameters are still invalid, use dummy parameters with | 106 // If hardware parameters are still invalid, use dummy parameters with |
| 107 // fake audio path and let the client handle the error. | 107 // fake audio path and let the client handle the error. |
| 108 if (!params->IsValid()) | 108 if (!params->IsValid()) |
| 109 *params = media::AudioParameters::UnavailableDeviceParams(); | 109 *params = media::AudioParameters::UnavailableDeviceParams(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) { |
| 113 UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime", |
| 114 base::TimeTicks::Now() - auth_start_time, |
| 115 base::TimeDelta::FromMilliseconds(1), |
| 116 base::TimeDelta::FromMilliseconds(5000), 50); |
| 117 } |
| 118 |
| 112 } // namespace | 119 } // namespace |
| 113 | 120 |
| 114 class AudioRendererHost::AudioEntry | 121 class AudioRendererHost::AudioEntry |
| 115 : public media::AudioOutputController::EventHandler { | 122 : public media::AudioOutputController::EventHandler { |
| 116 public: | 123 public: |
| 117 AudioEntry(AudioRendererHost* host, | 124 AudioEntry(AudioRendererHost* host, |
| 118 int stream_id, | 125 int stream_id, |
| 119 int render_frame_id, | 126 int render_frame_id, |
| 120 const media::AudioParameters& params, | 127 const media::AudioParameters& params, |
| 121 const std::string& output_device_id, | 128 const std::string& output_device_id, |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 return handled; | 398 return handled; |
| 392 } | 399 } |
| 393 | 400 |
| 394 void AudioRendererHost::OnRequestDeviceAuthorization( | 401 void AudioRendererHost::OnRequestDeviceAuthorization( |
| 395 int stream_id, | 402 int stream_id, |
| 396 int render_frame_id, | 403 int render_frame_id, |
| 397 int session_id, | 404 int session_id, |
| 398 const std::string& device_id, | 405 const std::string& device_id, |
| 399 const url::Origin& security_origin) { | 406 const url::Origin& security_origin) { |
| 400 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 407 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 408 const base::TimeTicks auth_start_time = base::TimeTicks::Now(); |
| 409 |
| 401 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization" | 410 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization" |
| 402 << "(stream_id=" << stream_id | 411 << "(stream_id=" << stream_id |
| 403 << ", render_frame_id=" << render_frame_id | 412 << ", render_frame_id=" << render_frame_id |
| 404 << ", session_id=" << session_id << ", device_id=" << device_id | 413 << ", session_id=" << session_id << ", device_id=" << device_id |
| 405 << ", security_origin=" << security_origin << ")"; | 414 << ", security_origin=" << security_origin << ")"; |
| 406 | 415 |
| 407 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id)) | 416 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id)) |
| 408 return; | 417 return; |
| 409 | 418 |
| 410 if (!IsValidDeviceId(device_id)) { | 419 if (!IsValidDeviceId(device_id)) { |
| 420 UMALogDeviceAuthorizationTime(auth_start_time); |
| 411 Send(new AudioMsg_NotifyDeviceAuthorized( | 421 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 412 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, | 422 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, |
| 413 media::AudioParameters::UnavailableDeviceParams(), std::string())); | 423 media::AudioParameters::UnavailableDeviceParams(), std::string())); |
| 414 return; | 424 return; |
| 415 } | 425 } |
| 416 | 426 |
| 417 // If |session_id should be used for output device selection and such output | 427 // If |session_id should be used for output device selection and such output |
| 418 // device is found, reuse the input device permissions. | 428 // device is found, reuse the input device permissions. |
| 419 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, | 429 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, |
| 420 device_id)) { | 430 device_id)) { |
| 421 const StreamDeviceInfo* info = | 431 const StreamDeviceInfo* info = |
| 422 media_stream_manager_->audio_input_device_manager() | 432 media_stream_manager_->audio_input_device_manager() |
| 423 ->GetOpenedDeviceInfoById(session_id); | 433 ->GetOpenedDeviceInfoById(session_id); |
| 424 if (info) { | 434 if (info) { |
| 425 media::AudioParameters output_params( | 435 media::AudioParameters output_params( |
| 426 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 436 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 427 static_cast<media::ChannelLayout>( | 437 static_cast<media::ChannelLayout>( |
| 428 info->device.matched_output.channel_layout), | 438 info->device.matched_output.channel_layout), |
| 429 info->device.matched_output.sample_rate, 16, | 439 info->device.matched_output.sample_rate, 16, |
| 430 info->device.matched_output.frames_per_buffer); | 440 info->device.matched_output.frames_per_buffer); |
| 431 output_params.set_effects(info->device.matched_output.effects); | 441 output_params.set_effects(info->device.matched_output.effects); |
| 432 authorizations_.insert(MakeAuthorizationData( | 442 authorizations_.insert(MakeAuthorizationData( |
| 433 stream_id, true, info->device.matched_output_device_id)); | 443 stream_id, true, info->device.matched_output_device_id)); |
| 434 MaybeFixAudioParameters(&output_params); | 444 MaybeFixAudioParameters(&output_params); |
| 445 UMALogDeviceAuthorizationTime(auth_start_time); |
| 435 // Hash matched device id and pass it to the renderer | 446 // Hash matched device id and pass it to the renderer |
| 436 Send(new AudioMsg_NotifyDeviceAuthorized( | 447 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 437 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, | 448 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, |
| 438 GetHMACForMediaDeviceID(salt_, security_origin, | 449 GetHMACForMediaDeviceID(salt_, security_origin, |
| 439 info->device.matched_output_device_id))); | 450 info->device.matched_output_device_id))); |
| 440 return; | 451 return; |
| 441 } | 452 } |
| 442 } | 453 } |
| 443 | 454 |
| 444 authorizations_.insert( | 455 authorizations_.insert( |
| 445 MakeAuthorizationData(stream_id, false, std::string())); | 456 MakeAuthorizationData(stream_id, false, std::string())); |
| 446 CheckOutputDeviceAccess( | 457 CheckOutputDeviceAccess( |
| 447 render_frame_id, device_id, security_origin, | 458 render_frame_id, device_id, security_origin, |
| 448 base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id, | 459 base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id, |
| 449 device_id, security_origin)); | 460 device_id, security_origin, auth_start_time)); |
| 450 } | 461 } |
| 451 | 462 |
| 452 void AudioRendererHost::OnDeviceAuthorized(int stream_id, | 463 void AudioRendererHost::OnDeviceAuthorized(int stream_id, |
| 453 const std::string& device_id, | 464 const std::string& device_id, |
| 454 const url::Origin& security_origin, | 465 const url::Origin& security_origin, |
| 466 base::TimeTicks auth_start_time, |
| 455 bool have_access) { | 467 bool have_access) { |
| 456 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 468 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 457 const auto& auth_data = authorizations_.find(stream_id); | 469 const auto& auth_data = authorizations_.find(stream_id); |
| 458 | 470 |
| 459 // A close request was received while access check was in progress. | 471 // A close request was received while access check was in progress. |
| 460 if (auth_data == authorizations_.end()) | 472 if (auth_data == authorizations_.end()) { |
| 473 UMALogDeviceAuthorizationTime(auth_start_time); |
| 461 return; | 474 return; |
| 475 } |
| 462 | 476 |
| 463 if (!have_access) { | 477 if (!have_access) { |
| 464 authorizations_.erase(auth_data); | 478 authorizations_.erase(auth_data); |
| 479 UMALogDeviceAuthorizationTime(auth_start_time); |
| 465 Send(new AudioMsg_NotifyDeviceAuthorized( | 480 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 466 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED, | 481 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED, |
| 467 media::AudioParameters::UnavailableDeviceParams(), std::string())); | 482 media::AudioParameters::UnavailableDeviceParams(), std::string())); |
| 468 return; | 483 return; |
| 469 } | 484 } |
| 470 | 485 |
| 471 // If enumerator caching is disabled, avoid the enumeration if the default | 486 // If enumerator caching is disabled, avoid the enumeration if the default |
| 472 // device is requested, since no device ID translation is needed. | 487 // device is requested, since no device ID translation is needed. |
| 473 // If enumerator caching is enabled, it is better to use its cache, even | 488 // If enumerator caching is enabled, it is better to use its cache, even |
| 474 // for the default device. | 489 // for the default device. |
| 475 if (media::AudioDeviceDescription::IsDefaultDevice(device_id) && | 490 if (media::AudioDeviceDescription::IsDefaultDevice(device_id) && |
| 476 !media_stream_manager_->audio_output_device_enumerator() | 491 !media_stream_manager_->audio_output_device_enumerator() |
| 477 ->IsCacheEnabled()) { | 492 ->IsCacheEnabled()) { |
| 478 base::PostTaskAndReplyWithResult( | 493 base::PostTaskAndReplyWithResult( |
| 479 audio_manager_->GetTaskRunner(), FROM_HERE, | 494 audio_manager_->GetTaskRunner(), FROM_HERE, |
| 480 base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_), | 495 base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_), |
| 481 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id, | 496 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id, |
| 482 true)); | 497 auth_start_time, true)); |
| 483 } else { | 498 } else { |
| 484 media_stream_manager_->audio_output_device_enumerator()->Enumerate( | 499 media_stream_manager_->audio_output_device_enumerator()->Enumerate( |
| 485 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id, | 500 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id, |
| 486 security_origin, | 501 security_origin, |
| 487 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, | 502 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, |
| 488 stream_id))); | 503 stream_id, auth_start_time))); |
| 489 } | 504 } |
| 490 } | 505 } |
| 491 | 506 |
| 492 void AudioRendererHost::OnDeviceIDTranslated( | 507 void AudioRendererHost::OnDeviceIDTranslated( |
| 493 int stream_id, | 508 int stream_id, |
| 509 base::TimeTicks auth_start_time, |
| 494 bool device_found, | 510 bool device_found, |
| 495 const AudioOutputDeviceInfo& device_info) { | 511 const AudioOutputDeviceInfo& device_info) { |
| 496 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 512 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 497 const auto& auth_data = authorizations_.find(stream_id); | 513 const auto& auth_data = authorizations_.find(stream_id); |
| 498 | 514 |
| 499 // A close request was received while translation was in progress | 515 // A close request was received while translation was in progress |
| 500 if (auth_data == authorizations_.end()) | 516 if (auth_data == authorizations_.end()) { |
| 517 UMALogDeviceAuthorizationTime(auth_start_time); |
| 501 return; | 518 return; |
| 519 } |
| 502 | 520 |
| 503 if (!device_found) { | 521 if (!device_found) { |
| 504 authorizations_.erase(auth_data); | 522 authorizations_.erase(auth_data); |
| 523 UMALogDeviceAuthorizationTime(auth_start_time); |
| 505 Send(new AudioMsg_NotifyDeviceAuthorized( | 524 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 506 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, | 525 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, |
| 507 media::AudioParameters::UnavailableDeviceParams(), std::string())); | 526 media::AudioParameters::UnavailableDeviceParams(), std::string())); |
| 508 return; | 527 return; |
| 509 } | 528 } |
| 510 | 529 |
| 511 auth_data->second.first = true; | 530 auth_data->second.first = true; |
| 512 auth_data->second.second = device_info.unique_id; | 531 auth_data->second.second = device_info.unique_id; |
| 513 | 532 |
| 514 media::AudioParameters output_params = device_info.output_params; | 533 media::AudioParameters output_params = device_info.output_params; |
| 515 MaybeFixAudioParameters(&output_params); | 534 MaybeFixAudioParameters(&output_params); |
| 535 UMALogDeviceAuthorizationTime(auth_start_time); |
| 516 Send(new AudioMsg_NotifyDeviceAuthorized( | 536 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 517 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); | 537 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); |
| 518 } | 538 } |
| 519 | 539 |
| 520 void AudioRendererHost::OnCreateStream(int stream_id, | 540 void AudioRendererHost::OnCreateStream(int stream_id, |
| 521 int render_frame_id, | 541 int render_frame_id, |
| 522 const media::AudioParameters& params) { | 542 const media::AudioParameters& params) { |
| 523 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 543 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 524 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" | 544 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" |
| 525 << "(stream_id=" << stream_id << ")"; | 545 << "(stream_id=" << stream_id << ")"; |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 callback.Run(false, device_info); | 827 callback.Run(false, device_info); |
| 808 } | 828 } |
| 809 | 829 |
| 810 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { | 830 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { |
| 811 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 831 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 812 const auto& i = authorizations_.find(stream_id); | 832 const auto& i = authorizations_.find(stream_id); |
| 813 return i != authorizations_.end(); | 833 return i != authorizations_.end(); |
| 814 } | 834 } |
| 815 | 835 |
| 816 } // namespace content | 836 } // namespace content |
| OLD | NEW |