| 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 <CoreAudio/AudioHardware.h> | 7 #include <CoreAudio/AudioHardware.h> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "media/base/bind_to_current_loop.h" | 22 #include "media/base/bind_to_current_loop.h" |
| 23 #include "media/base/channel_layout.h" | 23 #include "media/base/channel_layout.h" |
| 24 #include "media/base/limits.h" | 24 #include "media/base/limits.h" |
| 25 #include "media/base/media_switches.h" | 25 #include "media/base/media_switches.h" |
| 26 | 26 |
| 27 namespace media { | 27 namespace media { |
| 28 | 28 |
| 29 // Maximum number of output streams that can be open simultaneously. | 29 // Maximum number of output streams that can be open simultaneously. |
| 30 static const int kMaxOutputStreams = 50; | 30 static const int kMaxOutputStreams = 50; |
| 31 | 31 |
| 32 // Default buffer size in samples for low-latency input and output streams. | 32 // Define bounds for for low-latency input and output streams. |
| 33 static const int kDefaultLowLatencyBufferSize = 128; | 33 static const int kMinimumInputOutputBufferSize = 128; |
| 34 static const int kMaximumInputOutputBufferSize = 4096; |
| 34 | 35 |
| 35 // Default sample-rate on most Apple hardware. | 36 // Default sample-rate on most Apple hardware. |
| 36 static const int kFallbackSampleRate = 44100; | 37 static const int kFallbackSampleRate = 44100; |
| 37 | 38 |
| 38 static bool HasAudioHardware(AudioObjectPropertySelector selector) { | 39 static bool HasAudioHardware(AudioObjectPropertySelector selector) { |
| 39 AudioDeviceID output_device_id = kAudioObjectUnknown; | 40 AudioDeviceID output_device_id = kAudioObjectUnknown; |
| 40 const AudioObjectPropertyAddress property_address = { | 41 const AudioObjectPropertyAddress property_address = { |
| 41 selector, | 42 selector, |
| 42 kAudioObjectPropertyScopeGlobal, // mScope | 43 kAudioObjectPropertyScopeGlobal, // mScope |
| 43 kAudioObjectPropertyElementMaster // mElement | 44 kAudioObjectPropertyElementMaster // mElement |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 const AudioDeviceID device = GetAudioDeviceIdByUId(false, output_device_id); | 666 const AudioDeviceID device = GetAudioDeviceIdByUId(false, output_device_id); |
| 666 if (device == kAudioObjectUnknown) { | 667 if (device == kAudioObjectUnknown) { |
| 667 DLOG(ERROR) << "Invalid output device " << output_device_id; | 668 DLOG(ERROR) << "Invalid output device " << output_device_id; |
| 668 return input_params.IsValid() ? input_params : AudioParameters( | 669 return input_params.IsValid() ? input_params : AudioParameters( |
| 669 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, | 670 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, |
| 670 kFallbackSampleRate, 16, ChooseBufferSize(kFallbackSampleRate)); | 671 kFallbackSampleRate, 16, ChooseBufferSize(kFallbackSampleRate)); |
| 671 } | 672 } |
| 672 | 673 |
| 673 const bool has_valid_input_params = input_params.IsValid(); | 674 const bool has_valid_input_params = input_params.IsValid(); |
| 674 const int hardware_sample_rate = HardwareSampleRateForDevice(device); | 675 const int hardware_sample_rate = HardwareSampleRateForDevice(device); |
| 675 const int buffer_size = ChooseBufferSize(hardware_sample_rate); | 676 |
| 677 // Allow pass through buffer sizes. If concurrent input and output streams |
| 678 // exist, they will use the smallest buffer size amongst them. As such, each |
| 679 // stream must be able to FIFO requests appropriately when this happens. |
| 680 int buffer_size = ChooseBufferSize(hardware_sample_rate); |
| 681 if (has_valid_input_params) { |
| 682 buffer_size = |
| 683 std::min(kMaximumInputOutputBufferSize, |
| 684 std::max(input_params.frames_per_buffer(), buffer_size)); |
| 685 } |
| 676 | 686 |
| 677 int hardware_channels; | 687 int hardware_channels; |
| 678 if (!GetDeviceChannels(device, kAudioDevicePropertyScopeOutput, | 688 if (!GetDeviceChannels(device, kAudioDevicePropertyScopeOutput, |
| 679 &hardware_channels)) { | 689 &hardware_channels)) { |
| 680 hardware_channels = 2; | 690 hardware_channels = 2; |
| 681 } | 691 } |
| 682 | 692 |
| 683 // Use the input channel count and channel layout if possible. Let OSX take | 693 // Use the input channel count and channel layout if possible. Let OSX take |
| 684 // care of remapping the channels; this lets user specified channel layouts | 694 // care of remapping the channels; this lets user specified channel layouts |
| 685 // work correctly. | 695 // work correctly. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 if (current_sample_rate_ == new_sample_rate && | 750 if (current_sample_rate_ == new_sample_rate && |
| 741 current_output_device_ == new_output_device) | 751 current_output_device_ == new_output_device) |
| 742 return; | 752 return; |
| 743 | 753 |
| 744 current_sample_rate_ = new_sample_rate; | 754 current_sample_rate_ = new_sample_rate; |
| 745 current_output_device_ = new_output_device; | 755 current_output_device_ = new_output_device; |
| 746 NotifyAllOutputDeviceChangeListeners(); | 756 NotifyAllOutputDeviceChangeListeners(); |
| 747 } | 757 } |
| 748 | 758 |
| 749 int AudioManagerMac::ChooseBufferSize(int output_sample_rate) { | 759 int AudioManagerMac::ChooseBufferSize(int output_sample_rate) { |
| 750 int buffer_size = kDefaultLowLatencyBufferSize; | 760 int buffer_size = kMinimumInputOutputBufferSize; |
| 751 const int user_buffer_size = GetUserBufferSize(); | 761 const int user_buffer_size = GetUserBufferSize(); |
| 752 if (user_buffer_size) { | 762 if (user_buffer_size) { |
| 753 buffer_size = user_buffer_size; | 763 buffer_size = user_buffer_size; |
| 754 } else if (output_sample_rate > 48000) { | 764 } else if (output_sample_rate > 48000) { |
| 755 // The default buffer size is too small for higher sample rates and may lead | 765 // The default buffer size is too small for higher sample rates and may lead |
| 756 // to glitching. Adjust upwards by multiples of the default size. | 766 // to glitching. Adjust upwards by multiples of the default size. |
| 757 if (output_sample_rate <= 96000) | 767 if (output_sample_rate <= 96000) |
| 758 buffer_size = 2 * kDefaultLowLatencyBufferSize; | 768 buffer_size = 2 * kMinimumInputOutputBufferSize; |
| 759 else if (output_sample_rate <= 192000) | 769 else if (output_sample_rate <= 192000) |
| 760 buffer_size = 4 * kDefaultLowLatencyBufferSize; | 770 buffer_size = 4 * kMinimumInputOutputBufferSize; |
| 761 } | 771 } |
| 762 | 772 |
| 763 return buffer_size; | 773 return buffer_size; |
| 764 } | 774 } |
| 765 | 775 |
| 766 bool AudioManagerMac::ShouldDeferStreamStart() { | 776 bool AudioManagerMac::ShouldDeferStreamStart() { |
| 767 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 777 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
| 768 return power_observer_->ShouldDeferStreamStart(); | 778 return power_observer_->ShouldDeferStreamStart(); |
| 769 } | 779 } |
| 770 | 780 |
| 771 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) { | 781 void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) { |
| 772 output_streams_.remove(stream); | 782 output_streams_.remove(stream); |
| 773 AudioManagerBase::ReleaseOutputStream(stream); | 783 AudioManagerBase::ReleaseOutputStream(stream); |
| 774 } | 784 } |
| 775 | 785 |
| 776 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { | 786 void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) { |
| 777 input_streams_.remove(stream); | 787 input_streams_.remove(stream); |
| 778 AudioManagerBase::ReleaseInputStream(stream); | 788 AudioManagerBase::ReleaseInputStream(stream); |
| 779 } | 789 } |
| 780 | 790 |
| 781 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { | 791 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { |
| 782 return new AudioManagerMac(audio_log_factory); | 792 return new AudioManagerMac(audio_log_factory); |
| 783 } | 793 } |
| 784 | 794 |
| 785 } // namespace media | 795 } // namespace media |
| OLD | NEW |