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 <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/mac/mac_logging.h" | 13 #include "base/mac/mac_logging.h" |
14 #include "base/mac/scoped_cftyperef.h" | 14 #include "base/mac/scoped_cftyperef.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/memory/free_deleter.h" | 16 #include "base/memory/free_deleter.h" |
17 #include "base/power_monitor/power_monitor.h" | 17 #include "base/power_monitor/power_monitor.h" |
18 #include "base/power_monitor/power_observer.h" | 18 #include "base/power_monitor/power_observer.h" |
19 #include "base/strings/sys_string_conversions.h" | 19 #include "base/strings/sys_string_conversions.h" |
20 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
21 #include "media/audio/audio_device_description.h" | 21 #include "media/audio/audio_device_description.h" |
22 #include "media/audio/mac/audio_auhal_mac.h" | 22 #include "media/audio/mac/audio_auhal_mac.h" |
23 #include "media/audio/mac/audio_input_mac.h" | 23 #include "media/audio/mac/audio_input_mac.h" |
24 #include "media/audio/mac/audio_low_latency_input_mac.h" | 24 #include "media/audio/mac/audio_low_latency_input_mac.h" |
25 #include "media/audio/mac/scoped_audio_unit.h" | 25 #include "media/audio/mac/scoped_audio_unit.h" |
26 #include "media/base/audio_parameters.h" | 26 #include "media/base/audio_parameters.h" |
27 #include "media/base/bind_to_current_loop.h" | 27 #include "media/base/bind_to_current_loop.h" |
28 #include "media/base/channel_layout.h" | 28 #include "media/base/channel_layout.h" |
29 #include "media/base/limits.h" | 29 #include "media/base/limits.h" |
30 #include "media/base/mac/audio_latency_mac.h" | |
31 #include "media/base/media_switches.h" | 30 #include "media/base/media_switches.h" |
32 | 31 |
33 namespace media { | 32 namespace media { |
34 | 33 |
35 // Maximum number of output streams that can be open simultaneously. | 34 // Maximum number of output streams that can be open simultaneously. |
36 static const int kMaxOutputStreams = 50; | 35 static const int kMaxOutputStreams = 50; |
37 | 36 |
| 37 // Define bounds for for low-latency input and output streams. |
| 38 static const int kMinimumInputOutputBufferSize = 128; |
| 39 static const int kMaximumInputOutputBufferSize = 4096; |
| 40 |
38 // Default sample-rate on most Apple hardware. | 41 // Default sample-rate on most Apple hardware. |
39 static const int kFallbackSampleRate = 44100; | 42 static const int kFallbackSampleRate = 44100; |
40 | 43 |
41 // Helper method to construct AudioObjectPropertyAddress structure given | 44 // Helper method to construct AudioObjectPropertyAddress structure given |
42 // property selector and scope. The property element is always set to | 45 // property selector and scope. The property element is always set to |
43 // kAudioObjectPropertyElementMaster. | 46 // kAudioObjectPropertyElementMaster. |
44 static AudioObjectPropertyAddress GetAudioObjectPropertyAddress( | 47 static AudioObjectPropertyAddress GetAudioObjectPropertyAddress( |
45 AudioObjectPropertySelector selector, | 48 AudioObjectPropertySelector selector, |
46 bool is_input) { | 49 bool is_input) { |
47 AudioObjectPropertyScope scope = is_input ? kAudioObjectPropertyScopeInput | 50 AudioObjectPropertyScope scope = is_input ? kAudioObjectPropertyScopeInput |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, | 829 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, |
827 kFallbackSampleRate, 16, ChooseBufferSize(false, kFallbackSampleRate)); | 830 kFallbackSampleRate, 16, ChooseBufferSize(false, kFallbackSampleRate)); |
828 } | 831 } |
829 | 832 |
830 const bool has_valid_input_params = input_params.IsValid(); | 833 const bool has_valid_input_params = input_params.IsValid(); |
831 const int hardware_sample_rate = HardwareSampleRateForDevice(device); | 834 const int hardware_sample_rate = HardwareSampleRateForDevice(device); |
832 | 835 |
833 // Allow pass through buffer sizes. If concurrent input and output streams | 836 // Allow pass through buffer sizes. If concurrent input and output streams |
834 // exist, they will use the smallest buffer size amongst them. As such, each | 837 // exist, they will use the smallest buffer size amongst them. As such, each |
835 // stream must be able to FIFO requests appropriately when this happens. | 838 // stream must be able to FIFO requests appropriately when this happens. |
836 int buffer_size; | 839 int buffer_size = ChooseBufferSize(false, hardware_sample_rate); |
837 if (has_valid_input_params) { | 840 if (has_valid_input_params) { |
838 // If passed in via the input_params we allow buffer sizes to go as | |
839 // low as the the kMinAudioBufferSize, ignoring what | |
840 // ChooseBufferSize() normally returns. | |
841 buffer_size = | 841 buffer_size = |
842 std::min(static_cast<int>(limits::kMaxAudioBufferSize), | 842 std::min(kMaximumInputOutputBufferSize, |
843 std::max(input_params.frames_per_buffer(), | 843 std::max(input_params.frames_per_buffer(), buffer_size)); |
844 static_cast<int>(limits::kMinAudioBufferSize))); | |
845 } else { | |
846 buffer_size = ChooseBufferSize(false, hardware_sample_rate); | |
847 } | 844 } |
848 | 845 |
849 int hardware_channels; | 846 int hardware_channels; |
850 if (!GetDeviceChannels(device, AUElement::OUTPUT, &hardware_channels)) | 847 if (!GetDeviceChannels(device, AUElement::OUTPUT, &hardware_channels)) |
851 hardware_channels = 2; | 848 hardware_channels = 2; |
852 | 849 |
853 // Use the input channel count and channel layout if possible. Let OSX take | 850 // Use the input channel count and channel layout if possible. Let OSX take |
854 // care of remapping the channels; this lets user specified channel layouts | 851 // care of remapping the channels; this lets user specified channel layouts |
855 // work correctly. | 852 // work correctly. |
856 int output_channels = input_params.channels(); | 853 int output_channels = input_params.channels(); |
(...skipping 26 matching lines...) Expand all Loading... |
883 current_output_device_ == new_output_device) { | 880 current_output_device_ == new_output_device) { |
884 return; | 881 return; |
885 } | 882 } |
886 | 883 |
887 current_sample_rate_ = new_sample_rate; | 884 current_sample_rate_ = new_sample_rate; |
888 current_output_device_ = new_output_device; | 885 current_output_device_ = new_output_device; |
889 NotifyAllOutputDeviceChangeListeners(); | 886 NotifyAllOutputDeviceChangeListeners(); |
890 } | 887 } |
891 | 888 |
892 int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) { | 889 int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) { |
893 // kMinAudioBufferSize is too small for the output side because | 890 // kMinimumInputOutputBufferSize is too small for the output side because |
894 // CoreAudio can get into under-run if the renderer fails delivering data | 891 // CoreAudio can get into under-run if the renderer fails delivering data |
895 // to the browser within the allowed time by the OS. The workaround is to | 892 // to the browser within the allowed time by the OS. The workaround is to |
896 // use 256 samples as the default output buffer size for sample rates | 893 // use 256 samples as the default output buffer size for sample rates |
897 // smaller than 96KHz. | 894 // smaller than 96KHz. |
898 // TODO(xians): Remove this workaround after WebAudio supports user defined | 895 // TODO(xians): Remove this workaround after WebAudio supports user defined |
899 // buffer size. See https://github.com/WebAudio/web-audio-api/issues/348 | 896 // buffer size. See https://github.com/WebAudio/web-audio-api/issues/348 |
900 // for details. | 897 // for details. |
901 int buffer_size = | 898 int buffer_size = is_input ? |
902 is_input ? limits::kMinAudioBufferSize : 2 * limits::kMinAudioBufferSize; | 899 kMinimumInputOutputBufferSize : 2 * kMinimumInputOutputBufferSize; |
903 const int user_buffer_size = GetUserBufferSize(); | 900 const int user_buffer_size = GetUserBufferSize(); |
904 buffer_size = user_buffer_size | 901 if (user_buffer_size) { |
905 ? user_buffer_size | 902 buffer_size = user_buffer_size; |
906 : GetMinAudioBufferSizeMacOS(buffer_size, sample_rate); | 903 } else if (sample_rate > 48000) { |
| 904 // The default buffer size is too small for higher sample rates and may lead |
| 905 // to glitching. Adjust upwards by multiples of the default size. |
| 906 if (sample_rate <= 96000) |
| 907 buffer_size = 2 * kMinimumInputOutputBufferSize; |
| 908 else if (sample_rate <= 192000) |
| 909 buffer_size = 4 * kMinimumInputOutputBufferSize; |
| 910 } |
| 911 |
907 return buffer_size; | 912 return buffer_size; |
908 } | 913 } |
909 | 914 |
910 bool AudioManagerMac::IsSuspending() const { | 915 bool AudioManagerMac::IsSuspending() const { |
911 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 916 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
912 return power_observer_->IsSuspending(); | 917 return power_observer_->IsSuspending(); |
913 } | 918 } |
914 | 919 |
915 bool AudioManagerMac::ShouldDeferStreamStart() const { | 920 bool AudioManagerMac::ShouldDeferStreamStart() const { |
916 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 921 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 } | 1183 } |
1179 | 1184 |
1180 std::unique_ptr<AudioManager> CreateAudioManager( | 1185 std::unique_ptr<AudioManager> CreateAudioManager( |
1181 std::unique_ptr<AudioThread> audio_thread, | 1186 std::unique_ptr<AudioThread> audio_thread, |
1182 AudioLogFactory* audio_log_factory) { | 1187 AudioLogFactory* audio_log_factory) { |
1183 return base::MakeUnique<AudioManagerMac>(std::move(audio_thread), | 1188 return base::MakeUnique<AudioManagerMac>(std::move(audio_thread), |
1184 audio_log_factory); | 1189 audio_log_factory); |
1185 } | 1190 } |
1186 | 1191 |
1187 } // namespace media | 1192 } // namespace media |
OLD | NEW |