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 "media/audio/mac/audio_manager_mac.h" | 5 #include "media/audio/mac/audio_manager_mac.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 | 363 |
364 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); | 364 DISALLOW_COPY_AND_ASSIGN(AudioPowerObserver); |
365 }; | 365 }; |
366 | 366 |
367 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) | 367 AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory) |
368 : AudioManagerBase(audio_log_factory), | 368 : AudioManagerBase(audio_log_factory), |
369 current_sample_rate_(0), | 369 current_sample_rate_(0), |
370 current_output_device_(kAudioDeviceUnknown) { | 370 current_output_device_(kAudioDeviceUnknown) { |
371 SetMaxOutputStreamsAllowed(kMaxOutputStreams); | 371 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
372 | 372 |
373 // CoreAudio calls must occur on the main thread of the process, which in our | |
374 // case is sadly the browser UI thread. Failure to execute calls on the right | |
375 // thread leads to crashes and odd behavior. See http://crbug.com/158170. | |
376 // TODO(dalecurtis): We should require the message loop to be passed in. | |
377 CHECK(base::MessageLoopForUI::IsCurrent()); | |
378 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | |
379 | |
373 // Task must be posted last to avoid races from handing out "this" to the | 380 // Task must be posted last to avoid races from handing out "this" to the |
374 // audio thread. Always PostTask even if we're on the right thread since | 381 // audio thread. Always PostTask even if we're on the right thread since |
375 // AudioManager creation is on the startup path and this may be slow. | 382 // AudioManager creation is on the startup path and this may be slow. |
376 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 383 task_runner_->PostTask(FROM_HERE, |
377 &AudioManagerMac::InitializeOnAudioThread, base::Unretained(this))); | 384 base::Bind(&AudioManagerMac::InitializeOnAudioThread, |
385 base::Unretained(this))); | |
378 } | 386 } |
379 | 387 |
380 AudioManagerMac::~AudioManagerMac() { | 388 AudioManagerMac::~AudioManagerMac() { |
381 if (GetTaskRunner()->BelongsToCurrentThread()) { | 389 if (GetTaskRunner()->BelongsToCurrentThread()) { |
382 ShutdownOnAudioThread(); | 390 ShutdownOnAudioThread(); |
383 } else { | 391 } else { |
384 // It's safe to post a task here since Shutdown() will wait for all tasks to | 392 // It's safe to post a task here since Shutdown() will wait for all tasks to |
385 // complete before returning. | 393 // complete before returning. |
386 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( | 394 GetTaskRunner()->PostTask(FROM_HERE, base::Bind( |
387 &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this))); | 395 &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this))); |
388 } | 396 } |
389 | 397 |
390 Shutdown(); | 398 Shutdown(); |
391 } | 399 } |
392 | 400 |
401 scoped_refptr<base::SingleThreadTaskRunner> AudioManagerMac::GetTaskRunner() { | |
402 return task_runner_; | |
403 } | |
404 | |
405 scoped_refptr<base::SingleThreadTaskRunner> | |
406 AudioManagerMac::GetWorkerTaskRunner() { | |
407 if (!worker_thread_) { | |
408 worker_thread_.reset(new base::Thread("AudioWorkerThread")); | |
409 CHECK(worker_thread_->Start()); | |
410 } | |
411 return worker_thread_->task_runner(); | |
412 } | |
413 | |
393 bool AudioManagerMac::HasAudioOutputDevices() { | 414 bool AudioManagerMac::HasAudioOutputDevices() { |
394 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); | 415 return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice); |
395 } | 416 } |
396 | 417 |
397 bool AudioManagerMac::HasAudioInputDevices() { | 418 bool AudioManagerMac::HasAudioInputDevices() { |
398 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); | 419 return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); |
399 } | 420 } |
400 | 421 |
401 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device, | 422 bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device, |
402 AudioObjectPropertyScope scope, | 423 AudioObjectPropertyScope scope, |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
517 const int buffer_size = ChooseBufferSize(true, sample_rate); | 538 const int buffer_size = ChooseBufferSize(true, sample_rate); |
518 | 539 |
519 // TODO(xians): query the native channel layout for the specific device. | 540 // TODO(xians): query the native channel layout for the specific device. |
520 return AudioParameters( | 541 return AudioParameters( |
521 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, | 542 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, |
522 sample_rate, 16, buffer_size); | 543 sample_rate, 16, buffer_size); |
523 } | 544 } |
524 | 545 |
525 std::string AudioManagerMac::GetAssociatedOutputDeviceID( | 546 std::string AudioManagerMac::GetAssociatedOutputDeviceID( |
526 const std::string& input_device_id) { | 547 const std::string& input_device_id) { |
527 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 548 DCHECK(task_runner_->BelongsToCurrentThread()); |
DaleCurtis
2016/03/14 21:46:09
Why this change? Seems better to use the GetTaskRu
alokp
2016/03/14 22:07:17
reverted in the new patch.
| |
528 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); | 549 AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id); |
529 if (device == kAudioObjectUnknown) | 550 if (device == kAudioObjectUnknown) |
530 return std::string(); | 551 return std::string(); |
531 | 552 |
532 UInt32 size = 0; | 553 UInt32 size = 0; |
533 AudioObjectPropertyAddress pa = { | 554 AudioObjectPropertyAddress pa = { |
534 kAudioDevicePropertyRelatedDevices, | 555 kAudioDevicePropertyRelatedDevices, |
535 kAudioDevicePropertyScopeOutput, | 556 kAudioDevicePropertyScopeOutput, |
536 kAudioObjectPropertyElementMaster | 557 kAudioObjectPropertyElementMaster |
537 }; | 558 }; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 // rates on OSX. | 653 // rates on OSX. |
633 current_sample_rate_ = params.sample_rate(); | 654 current_sample_rate_ = params.sample_rate(); |
634 } | 655 } |
635 | 656 |
636 AUHALStream* stream = new AUHALStream(this, params, device); | 657 AUHALStream* stream = new AUHALStream(this, params, device); |
637 output_streams_.push_back(stream); | 658 output_streams_.push_back(stream); |
638 return stream; | 659 return stream; |
639 } | 660 } |
640 | 661 |
641 std::string AudioManagerMac::GetDefaultOutputDeviceID() { | 662 std::string AudioManagerMac::GetDefaultOutputDeviceID() { |
642 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 663 DCHECK(task_runner_->BelongsToCurrentThread()); |
643 AudioDeviceID device_id = kAudioObjectUnknown; | 664 AudioDeviceID device_id = kAudioObjectUnknown; |
644 if (!GetDefaultOutputDevice(&device_id)) | 665 if (!GetDefaultOutputDevice(&device_id)) |
645 return std::string(); | 666 return std::string(); |
646 | 667 |
647 const AudioObjectPropertyAddress property_address = { | 668 const AudioObjectPropertyAddress property_address = { |
648 kAudioDevicePropertyDeviceUID, | 669 kAudioDevicePropertyDeviceUID, |
649 kAudioObjectPropertyScopeGlobal, | 670 kAudioObjectPropertyScopeGlobal, |
650 kAudioObjectPropertyElementMaster | 671 kAudioObjectPropertyElementMaster |
651 }; | 672 }; |
652 CFStringRef device_uid = NULL; | 673 CFStringRef device_uid = NULL; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
731 channel_layout = CHANNEL_LAYOUT_DISCRETE; | 752 channel_layout = CHANNEL_LAYOUT_DISCRETE; |
732 } | 753 } |
733 | 754 |
734 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, | 755 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, |
735 hardware_sample_rate, 16, buffer_size); | 756 hardware_sample_rate, 16, buffer_size); |
736 params.set_channels_for_discrete(output_channels); | 757 params.set_channels_for_discrete(output_channels); |
737 return params; | 758 return params; |
738 } | 759 } |
739 | 760 |
740 void AudioManagerMac::InitializeOnAudioThread() { | 761 void AudioManagerMac::InitializeOnAudioThread() { |
741 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 762 DCHECK(task_runner_->BelongsToCurrentThread()); |
742 power_observer_.reset(new AudioPowerObserver()); | 763 power_observer_.reset(new AudioPowerObserver()); |
743 } | 764 } |
744 | 765 |
745 void AudioManagerMac::ShutdownOnAudioThread() { | 766 void AudioManagerMac::ShutdownOnAudioThread() { |
746 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 767 DCHECK(task_runner_->BelongsToCurrentThread()); |
747 output_device_listener_.reset(); | 768 output_device_listener_.reset(); |
748 power_observer_.reset(); | 769 power_observer_.reset(); |
749 | 770 |
750 // Since CoreAudio calls have to run on the UI thread and browser shutdown | 771 // Since CoreAudio calls have to run on the UI thread and browser shutdown |
751 // doesn't wait for outstanding tasks to complete, we may have input/output | 772 // doesn't wait for outstanding tasks to complete, we may have input/output |
752 // streams still running at shutdown. | 773 // streams still running at shutdown. |
753 // | 774 // |
754 // To avoid calls into destructed classes, we need to stop the OS callbacks | 775 // To avoid calls into destructed classes, we need to stop the OS callbacks |
755 // by stopping the streams. Note: The streams are leaked since process | 776 // by stopping the streams. Note: The streams are leaked since process |
756 // destruction is imminent. | 777 // destruction is imminent. |
757 // | 778 // |
758 // See http://crbug.com/354139 for crash details. | 779 // See http://crbug.com/354139 for crash details. |
759 StopStreams(&basic_input_streams_); | 780 StopStreams(&basic_input_streams_); |
760 StopStreams(&low_latency_input_streams_); | 781 StopStreams(&low_latency_input_streams_); |
761 StopStreams(&output_streams_); | 782 StopStreams(&output_streams_); |
762 } | 783 } |
763 | 784 |
764 void AudioManagerMac::HandleDeviceChanges() { | 785 void AudioManagerMac::HandleDeviceChanges() { |
765 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 786 DCHECK(task_runner_->BelongsToCurrentThread()); |
766 const int new_sample_rate = HardwareSampleRate(); | 787 const int new_sample_rate = HardwareSampleRate(); |
767 AudioDeviceID new_output_device; | 788 AudioDeviceID new_output_device; |
768 GetDefaultOutputDevice(&new_output_device); | 789 GetDefaultOutputDevice(&new_output_device); |
769 | 790 |
770 if (current_sample_rate_ == new_sample_rate && | 791 if (current_sample_rate_ == new_sample_rate && |
771 current_output_device_ == new_output_device) { | 792 current_output_device_ == new_output_device) { |
772 return; | 793 return; |
773 } | 794 } |
774 | 795 |
775 current_sample_rate_ = new_sample_rate; | 796 current_sample_rate_ = new_sample_rate; |
(...skipping 21 matching lines...) Expand all Loading... | |
797 if (sample_rate <= 96000) | 818 if (sample_rate <= 96000) |
798 buffer_size = 2 * kMinimumInputOutputBufferSize; | 819 buffer_size = 2 * kMinimumInputOutputBufferSize; |
799 else if (sample_rate <= 192000) | 820 else if (sample_rate <= 192000) |
800 buffer_size = 4 * kMinimumInputOutputBufferSize; | 821 buffer_size = 4 * kMinimumInputOutputBufferSize; |
801 } | 822 } |
802 | 823 |
803 return buffer_size; | 824 return buffer_size; |
804 } | 825 } |
805 | 826 |
806 bool AudioManagerMac::ShouldDeferStreamStart() const { | 827 bool AudioManagerMac::ShouldDeferStreamStart() const { |
807 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 828 DCHECK(task_runner_->BelongsToCurrentThread()); |
808 return power_observer_->ShouldDeferStreamStart(); | 829 return power_observer_->ShouldDeferStreamStart(); |
809 } | 830 } |
810 | 831 |
811 bool AudioManagerMac::IsOnBatteryPower() const { | 832 bool AudioManagerMac::IsOnBatteryPower() const { |
812 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 833 DCHECK(task_runner_->BelongsToCurrentThread()); |
813 return power_observer_->IsOnBatteryPower(); | 834 return power_observer_->IsOnBatteryPower(); |
814 } | 835 } |
815 | 836 |
816 size_t AudioManagerMac::GetNumberOfResumeNotifications() const { | 837 size_t AudioManagerMac::GetNumberOfResumeNotifications() const { |
817 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 838 DCHECK(task_runner_->BelongsToCurrentThread()); |
818 return power_observer_->num_resume_notifications(); | 839 return power_observer_->num_resume_notifications(); |
819 } | 840 } |
820 | 841 |
821 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, | 842 bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id, |
822 AudioUnit audio_unit, | 843 AudioUnit audio_unit, |
823 AudioUnitElement element, | 844 AudioUnitElement element, |
824 size_t desired_buffer_size, | 845 size_t desired_buffer_size, |
825 bool* size_was_changed, | 846 bool* size_was_changed, |
826 size_t* io_buffer_frame_size) { | 847 size_t* io_buffer_frame_size) { |
827 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 848 DCHECK(task_runner_->BelongsToCurrentThread()); |
828 const bool is_input = (element == 1); | 849 const bool is_input = (element == 1); |
829 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id | 850 DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id |
830 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec | 851 << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec |
831 << desired_buffer_size << ")"; | 852 << desired_buffer_size << ")"; |
832 | 853 |
833 *size_was_changed = false; | 854 *size_was_changed = false; |
834 *io_buffer_frame_size = 0; | 855 *io_buffer_frame_size = 0; |
835 | 856 |
836 // Log the device name (and id) for debugging purposes. | 857 // Log the device name (and id) for debugging purposes. |
837 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input); | 858 std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
942 basic_input_streams_.erase(stream_it); | 963 basic_input_streams_.erase(stream_it); |
943 | 964 |
944 AudioManagerBase::ReleaseInputStream(stream); | 965 AudioManagerBase::ReleaseInputStream(stream); |
945 } | 966 } |
946 | 967 |
947 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 968 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
948 return new AudioManagerMac(audio_log_factory); | 969 return new AudioManagerMac(audio_log_factory); |
949 } | 970 } |
950 | 971 |
951 } // namespace media | 972 } // namespace media |
OLD | NEW |