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 "ppapi/shared_impl/ppb_audio_config_shared.h" | 5 #include "ppapi/shared_impl/ppb_audio_config_shared.h" |
6 #include "ppapi/thunk/enter.h" | 6 #include "ppapi/thunk/enter.h" |
7 #include "ppapi/thunk/ppb_instance_api.h" | 7 #include "ppapi/thunk/ppb_instance_api.h" |
8 | 8 |
9 namespace ppapi { | 9 namespace ppapi { |
10 | 10 |
| 11 // Rounds up requested_size to the nearest multiple of minimum_size. |
| 12 static uint32_t CalculateMultipleOfSampleFrameCount(uint32_t minimum_size, |
| 13 uint32_t requested_size) { |
| 14 const uint32_t multiple = (requested_size + minimum_size - 1) / minimum_size; |
| 15 return std::min(minimum_size * multiple, |
| 16 static_cast<uint32_t>(PP_AUDIOMAXSAMPLEFRAMECOUNT)); |
| 17 } |
| 18 |
11 PPB_AudioConfig_Shared::PPB_AudioConfig_Shared(ResourceObjectType type, | 19 PPB_AudioConfig_Shared::PPB_AudioConfig_Shared(ResourceObjectType type, |
12 PP_Instance instance) | 20 PP_Instance instance) |
13 : Resource(type, instance), | 21 : Resource(type, instance), |
14 sample_rate_(PP_AUDIOSAMPLERATE_NONE), | 22 sample_rate_(PP_AUDIOSAMPLERATE_NONE), |
15 sample_frame_count_(0) { | 23 sample_frame_count_(0) { |
16 } | 24 } |
17 | 25 |
18 PPB_AudioConfig_Shared::~PPB_AudioConfig_Shared() { | 26 PPB_AudioConfig_Shared::~PPB_AudioConfig_Shared() { |
19 } | 27 } |
20 | 28 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 return 0; | 63 return 0; |
56 | 64 |
57 // Get the hardware config. | 65 // Get the hardware config. |
58 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( | 66 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( |
59 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); | 67 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); |
60 uint32_t hardware_sample_frame_count = | 68 uint32_t hardware_sample_frame_count = |
61 enter.functions()->GetAudioHardwareOutputBufferSize(instance); | 69 enter.functions()->GetAudioHardwareOutputBufferSize(instance); |
62 if (sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) | 70 if (sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) |
63 sample_frame_count = PP_AUDIOMINSAMPLEFRAMECOUNT; | 71 sample_frame_count = PP_AUDIOMINSAMPLEFRAMECOUNT; |
64 | 72 |
| 73 // If hardware information isn't available we're connected to a fake audio |
| 74 // output stream on the browser side, so we can use whatever sample count the |
| 75 // client wants. |
| 76 if (!hardware_sample_frame_count || !hardware_sample_rate) |
| 77 return sample_frame_count; |
| 78 |
| 79 // Note: All the values below were determined through experimentation to |
| 80 // minimize jitter and back-to-back callbacks from the browser. Please take |
| 81 // care when modifying these values as they impact a large number of users. |
| 82 // TODO(dalecurtis): Land jitter test and add documentation for updating this. |
| 83 |
65 // If client is using same sample rate as audio hardware, then recommend a | 84 // If client is using same sample rate as audio hardware, then recommend a |
66 // multiple of the audio hardware's sample frame count. | 85 // multiple of the audio hardware's sample frame count. |
67 if (hardware_sample_rate == sample_rate && hardware_sample_frame_count > 0) { | 86 if (hardware_sample_rate == sample_rate) { |
68 // Round up input sample_frame_count to nearest multiple. | 87 return CalculateMultipleOfSampleFrameCount( |
69 uint32_t multiple = (sample_frame_count + hardware_sample_frame_count - 1) / | 88 hardware_sample_frame_count, sample_frame_count); |
70 hardware_sample_frame_count; | |
71 uint32_t recommendation = hardware_sample_frame_count * multiple; | |
72 if (recommendation > PP_AUDIOMAXSAMPLEFRAMECOUNT) | |
73 recommendation = PP_AUDIOMAXSAMPLEFRAMECOUNT; | |
74 return recommendation; | |
75 } | 89 } |
76 | 90 |
77 // Otherwise, recommend a conservative 50ms buffer based on sample rate. | 91 // Should track the value reported by XP and ALSA backends. |
78 const uint32_t kDefault50msAt44100kHz = 2205; | 92 const uint32_t kHighLatencySampleFrameCount = 2048; |
79 const uint32_t kDefault50msAt48000kHz = 2400; | 93 |
80 switch (sample_rate) { | 94 // If the hardware requires a high latency buffer or we're at a low sample |
81 case PP_AUDIOSAMPLERATE_44100: | 95 // rate w/ a buffer that's larger than 10ms, choose the nearest multiple of |
82 return kDefault50msAt44100kHz; | 96 // the high latency sample frame count. An example of too low and too large |
83 case PP_AUDIOSAMPLERATE_48000: | 97 // is 16kHz and a sample frame count greater than 160 frames. |
84 return kDefault50msAt48000kHz; | 98 if (hardware_sample_frame_count >= kHighLatencySampleFrameCount || |
85 case PP_AUDIOSAMPLERATE_NONE: | 99 (hardware_sample_rate < 44100 && |
86 return 0; | 100 hardware_sample_frame_count > hardware_sample_rate / 100u)) { |
| 101 return CalculateMultipleOfSampleFrameCount( |
| 102 sample_frame_count, |
| 103 std::max(kHighLatencySampleFrameCount, hardware_sample_frame_count)); |
87 } | 104 } |
88 // Unable to make a recommendation. | 105 |
89 return 0; | 106 // All low latency clients should be able to handle a 512 frame buffer with |
| 107 // resampling from 44.1kHz and 48kHz to higher sample rates. |
| 108 // TODO(dalecurtis): We may need to investigate making the callback thread |
| 109 // high priority to handle buffers at the absolute minimum w/o glitching. |
| 110 const uint32_t kLowLatencySampleFrameCount = 512; |
| 111 |
| 112 // Special case for 48kHz -> 44.1kHz and buffer sizes greater than 10ms. In |
| 113 // testing most buffer sizes > 10ms led to glitching, so we choose a size we |
| 114 // know won't cause jitter. |
| 115 int min_sample_frame_count = kLowLatencySampleFrameCount; |
| 116 if (hardware_sample_rate == 44100 && sample_rate == 48000 && |
| 117 hardware_sample_frame_count > hardware_sample_rate / 100u) { |
| 118 min_sample_frame_count = std::max( |
| 119 2 * kLowLatencySampleFrameCount, hardware_sample_frame_count); |
| 120 } |
| 121 |
| 122 return CalculateMultipleOfSampleFrameCount( |
| 123 min_sample_frame_count, sample_frame_count); |
90 } | 124 } |
91 | 125 |
92 // static | 126 // static |
93 PP_AudioSampleRate PPB_AudioConfig_Shared::RecommendSampleRate( | 127 PP_AudioSampleRate PPB_AudioConfig_Shared::RecommendSampleRate( |
94 PP_Instance instance) { | 128 PP_Instance instance) { |
95 thunk::EnterInstanceNoLock enter(instance); | 129 thunk::EnterInstanceNoLock enter(instance); |
96 if (enter.failed()) | 130 if (enter.failed()) |
97 return PP_AUDIOSAMPLERATE_NONE; | 131 return PP_AUDIOSAMPLERATE_NONE; |
98 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( | 132 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( |
99 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); | 133 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); |
100 return hardware_sample_rate; | 134 return hardware_sample_rate; |
101 } | 135 } |
102 | 136 |
103 thunk::PPB_AudioConfig_API* PPB_AudioConfig_Shared::AsPPB_AudioConfig_API() { | 137 thunk::PPB_AudioConfig_API* PPB_AudioConfig_Shared::AsPPB_AudioConfig_API() { |
104 return this; | 138 return this; |
105 } | 139 } |
106 | 140 |
107 PP_AudioSampleRate PPB_AudioConfig_Shared::GetSampleRate() { | 141 PP_AudioSampleRate PPB_AudioConfig_Shared::GetSampleRate() { |
108 return sample_rate_; | 142 return sample_rate_; |
109 } | 143 } |
110 | 144 |
111 uint32_t PPB_AudioConfig_Shared::GetSampleFrameCount() { | 145 uint32_t PPB_AudioConfig_Shared::GetSampleFrameCount() { |
112 return sample_frame_count_; | 146 return sample_frame_count_; |
113 } | 147 } |
114 | 148 |
115 bool PPB_AudioConfig_Shared::Init(PP_AudioSampleRate sample_rate, | 149 bool PPB_AudioConfig_Shared::Init(PP_AudioSampleRate sample_rate, |
116 uint32_t sample_frame_count) { | 150 uint32_t sample_frame_count) { |
117 // TODO(brettw): Currently we don't actually check what the hardware | 151 // TODO(brettw): Currently we don't actually check what the hardware |
118 // supports, so just allow sample rates of the "guaranteed working" ones. | 152 // supports, so just allow sample rates of the "guaranteed working" ones. |
| 153 // TODO(dalecurtis): If sample rates are added RecommendSampleFrameCount_1_1() |
| 154 // must be updated to account for the new rates. |
119 if (sample_rate != PP_AUDIOSAMPLERATE_44100 && | 155 if (sample_rate != PP_AUDIOSAMPLERATE_44100 && |
120 sample_rate != PP_AUDIOSAMPLERATE_48000) | 156 sample_rate != PP_AUDIOSAMPLERATE_48000) |
121 return false; | 157 return false; |
122 | 158 |
123 // TODO(brettw): Currently we don't actually query to get a value from the | 159 // TODO(brettw): Currently we don't actually query to get a value from the |
124 // hardware, so just validate the range. | 160 // hardware, so just validate the range. |
125 if (sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT || | 161 if (sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT || |
126 sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) | 162 sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) |
127 return false; | 163 return false; |
128 | 164 |
129 sample_rate_ = sample_rate; | 165 sample_rate_ = sample_rate; |
130 sample_frame_count_ = sample_frame_count; | 166 sample_frame_count_ = sample_frame_count; |
131 return true; | 167 return true; |
132 } | 168 } |
133 | 169 |
134 } // namespace ppapi | 170 } // namespace ppapi |
OLD | NEW |