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 |