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 3 // found in the LICENSE file. 4 5 #include "build/build_config.h" 6 #include "ppapi/shared_impl/ppb_audio_config_shared.h" 7 #include "ppapi/thunk/enter.h" 8 #include "ppapi/thunk/ppb_instance_api.h" 9 10 namespace ppapi { 11 12 // Rounds up requested_size to the nearest multiple of minimum_size. 13 static uint32_t CalculateMultipleOfSampleFrameCount(uint32_t minimum_size, 14 uint32_t requested_size) { 15 const uint32_t multiple = (requested_size + minimum_size - 1) / minimum_size; 16 return std::min(minimum_size * multiple, 17 static_cast<uint32_t>(PP_AUDIOMAXSAMPLEFRAMECOUNT)); 18 } 19 20 PPB_AudioConfig_Shared::PPB_AudioConfig_Shared(ResourceObjectType type, 21 PP_Instance instance) 22 : Resource(type, instance), 23 sample_rate_(PP_AUDIOSAMPLERATE_NONE), 24 sample_frame_count_(0) {} 25 26 PPB_AudioConfig_Shared::~PPB_AudioConfig_Shared() {} 27 28 PP_Resource PPB_AudioConfig_Shared::Create(ResourceObjectType type, 29 PP_Instance instance, 30 PP_AudioSampleRate sample_rate, 31 uint32_t sample_frame_count) { 32 scoped_refptr<PPB_AudioConfig_Shared> object( 33 new PPB_AudioConfig_Shared(type, instance)); 34 if (!object->Init(sample_rate, sample_frame_count)) 35 return 0; 36 return object->GetReference(); 37 } 38 39 // static 40 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_0( 41 PP_AudioSampleRate sample_rate, 42 uint32_t requested_sample_frame_count) { 43 // Version 1.0: Don't actually query to get a value from the 44 // hardware; instead return the input for in-range values. 45 if (requested_sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) 46 return PP_AUDIOMINSAMPLEFRAMECOUNT; 47 if (requested_sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT) 48 return PP_AUDIOMAXSAMPLEFRAMECOUNT; 49 return requested_sample_frame_count; 50 } 51 52 // static 53 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_1( 54 PP_Instance instance, 55 PP_AudioSampleRate sample_rate, 56 uint32_t sample_frame_count) { 57 // Version 1.1: Query the back-end hardware for sample rate and buffer size, 58 // and recommend a best fit based on request. 59 thunk::EnterInstanceNoLock enter(instance); 60 if (enter.failed()) 61 return 0; 62 63 // Get the hardware config. 64 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( 65 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); 66 uint32_t hardware_sample_frame_count = 67 enter.functions()->GetAudioHardwareOutputBufferSize(instance); 68 if (sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) 69 sample_frame_count = PP_AUDIOMINSAMPLEFRAMECOUNT; 70 71 // If hardware information isn't available we're connected to a fake audio 72 // output stream on the browser side, so we can use whatever sample count the 73 // client wants. 74 if (!hardware_sample_frame_count || !hardware_sample_rate) 75 return sample_frame_count; 76 77 // Note: All the values below were determined through experimentation to 78 // minimize jitter and back-to-back callbacks from the browser. Please take 79 // care when modifying these values as they impact a large number of users. 80 // TODO(dalecurtis): Land jitter test and add documentation for updating this. 81 82 // Should track the value reported by XP and ALSA backends. 83 const uint32_t kHighLatencySampleFrameCount = 2048; 84 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY) 85 // TODO(ihf): Remove this once ARM Chromebooks support low latency audio. For 86 // now we classify them as high latency. See crbug.com/289770. Note that 87 // Adobe Flash is affected but not HTML5, WebRTC and WebAudio (they are using 88 // real time threads). 89 const bool kHighLatencyDevice = true; 90 #else 91 const bool kHighLatencyDevice = false; 92 #endif 93 94 // If client is using same sample rate as audio hardware, then recommend a 95 // multiple of the audio hardware's sample frame count. 96 if (!kHighLatencyDevice && hardware_sample_rate == sample_rate) { 97 return CalculateMultipleOfSampleFrameCount(hardware_sample_frame_count, 98 sample_frame_count); 99 } 100 101 // If the hardware requires a high latency buffer or we're at a low sample 102 // rate w/ a buffer that's larger than 10ms, choose the nearest multiple of 103 // the high latency sample frame count. An example of too low and too large 104 // is 16kHz and a sample frame count greater than 160 frames. 105 if (kHighLatencyDevice || 106 hardware_sample_frame_count >= kHighLatencySampleFrameCount || 107 (hardware_sample_rate < 44100 && 108 hardware_sample_frame_count > hardware_sample_rate / 100u)) { 109 return CalculateMultipleOfSampleFrameCount( 110 sample_frame_count, 111 std::max(kHighLatencySampleFrameCount, hardware_sample_frame_count)); 112 } 113 114 // All low latency clients should be able to handle a 512 frame buffer with 115 // resampling from 44.1kHz and 48kHz to higher sample rates. 116 // TODO(dalecurtis): We may need to investigate making the callback thread 117 // high priority to handle buffers at the absolute minimum w/o glitching. 118 const uint32_t kLowLatencySampleFrameCount = 512; 119 120 // Special case for 48kHz -> 44.1kHz and buffer sizes greater than 10ms. In 121 // testing most buffer sizes > 10ms led to glitching, so we choose a size we 122 // know won't cause jitter. 123 int min_sample_frame_count = kLowLatencySampleFrameCount; 124 if (hardware_sample_rate == 44100 && sample_rate == 48000 && 125 hardware_sample_frame_count > hardware_sample_rate / 100u) { 126 min_sample_frame_count = 127 std::max(2 * kLowLatencySampleFrameCount, hardware_sample_frame_count); 128 } 129 130 return CalculateMultipleOfSampleFrameCount(min_sample_frame_count, 131 sample_frame_count); 132 } 133 134 // static 135 PP_AudioSampleRate PPB_AudioConfig_Shared::RecommendSampleRate( 136 PP_Instance instance) { 137 thunk::EnterInstanceNoLock enter(instance); 138 if (enter.failed()) 139 return PP_AUDIOSAMPLERATE_NONE; 140 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( 141 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); 142 return hardware_sample_rate; 143 } 144 145 thunk::PPB_AudioConfig_API* PPB_AudioConfig_Shared::AsPPB_AudioConfig_API() { 146 return this; 147 } 148 149 PP_AudioSampleRate PPB_AudioConfig_Shared::GetSampleRate() { 150 return sample_rate_; 151 } 152 153 uint32_t PPB_AudioConfig_Shared::GetSampleFrameCount() { 154 return sample_frame_count_; 155 } 156 157 bool PPB_AudioConfig_Shared::Init(PP_AudioSampleRate sample_rate, 158 uint32_t sample_frame_count) { 159 // TODO(brettw): Currently we don't actually check what the hardware 160 // supports, so just allow sample rates of the "guaranteed working" ones. 161 // TODO(dalecurtis): If sample rates are added RecommendSampleFrameCount_1_1() 162 // must be updated to account for the new rates. 163 if (sample_rate != PP_AUDIOSAMPLERATE_44100 && 164 sample_rate != PP_AUDIOSAMPLERATE_48000) 165 return false; 166 167 // TODO(brettw): Currently we don't actually query to get a value from the 168 // hardware, so just validate the range. 169 if (sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT || 170 sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) 171 return false; 172 173 sample_rate_ = sample_rate; 174 sample_frame_count_ = sample_frame_count; 175 return true; 176 } 177 178 } // namespace ppapi 179