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 "ppapi/shared_impl/ppb_audio_config_shared.h" 6 #include "ppapi/thunk/enter.h" 7 #include "ppapi/thunk/ppb_instance_api.h" 8 9 namespace ppapi { 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 19 PPB_AudioConfig_Shared::PPB_AudioConfig_Shared(ResourceObjectType type, 20 PP_Instance instance) 21 : Resource(type, instance), 22 sample_rate_(PP_AUDIOSAMPLERATE_NONE), 23 sample_frame_count_(0) { 24 } 25 26 PPB_AudioConfig_Shared::~PPB_AudioConfig_Shared() { 27 } 28 29 PP_Resource PPB_AudioConfig_Shared::Create( 30 ResourceObjectType type, 31 PP_Instance instance, 32 PP_AudioSampleRate sample_rate, 33 uint32_t sample_frame_count) { 34 scoped_refptr<PPB_AudioConfig_Shared> object( 35 new PPB_AudioConfig_Shared(type, instance)); 36 if (!object->Init(sample_rate, sample_frame_count)) 37 return 0; 38 return object->GetReference(); 39 } 40 41 // static 42 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_0( 43 PP_AudioSampleRate sample_rate, 44 uint32_t requested_sample_frame_count) { 45 // Version 1.0: Don't actually query to get a value from the 46 // hardware; instead return the input for in-range values. 47 if (requested_sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) 48 return PP_AUDIOMINSAMPLEFRAMECOUNT; 49 if (requested_sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT) 50 return PP_AUDIOMAXSAMPLEFRAMECOUNT; 51 return requested_sample_frame_count; 52 } 53 54 // static 55 uint32_t PPB_AudioConfig_Shared::RecommendSampleFrameCount_1_1( 56 PP_Instance instance, 57 PP_AudioSampleRate sample_rate, 58 uint32_t sample_frame_count) { 59 // Version 1.1: Query the back-end hardware for sample rate and buffer size, 60 // and recommend a best fit based on request. 61 thunk::EnterInstanceNoLock enter(instance); 62 if (enter.failed()) 63 return 0; 64 65 // Get the hardware config. 66 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( 67 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); 68 uint32_t hardware_sample_frame_count = 69 enter.functions()->GetAudioHardwareOutputBufferSize(instance); 70 if (sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) 71 sample_frame_count = PP_AUDIOMINSAMPLEFRAMECOUNT; 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 84 // If client is using same sample rate as audio hardware, then recommend a 85 // multiple of the audio hardware's sample frame count. 86 if (hardware_sample_rate == sample_rate) { 87 return CalculateMultipleOfSampleFrameCount( 88 hardware_sample_frame_count, sample_frame_count); 89 } 90 91 // Should track the value reported by XP and ALSA backends. 92 const uint32_t kHighLatencySampleFrameCount = 2048; 93 94 // If the hardware requires a high latency buffer or we're at a low sample 95 // rate w/ a buffer that's larger than 10ms, choose the nearest multiple of 96 // the high latency sample frame count. An example of too low and too large 97 // is 16kHz and a sample frame count greater than 160 frames. 98 if (hardware_sample_frame_count >= kHighLatencySampleFrameCount || 99 (hardware_sample_rate < 44100 && 100 hardware_sample_frame_count > hardware_sample_rate / 100u)) { 101 return CalculateMultipleOfSampleFrameCount( 102 sample_frame_count, 103 std::max(kHighLatencySampleFrameCount, hardware_sample_frame_count)); 104 } 105 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); 124 } 125 126 // static 127 PP_AudioSampleRate PPB_AudioConfig_Shared::RecommendSampleRate( 128 PP_Instance instance) { 129 thunk::EnterInstanceNoLock enter(instance); 130 if (enter.failed()) 131 return PP_AUDIOSAMPLERATE_NONE; 132 PP_AudioSampleRate hardware_sample_rate = static_cast<PP_AudioSampleRate>( 133 enter.functions()->GetAudioHardwareOutputSampleRate(instance)); 134 return hardware_sample_rate; 135 } 136 137 thunk::PPB_AudioConfig_API* PPB_AudioConfig_Shared::AsPPB_AudioConfig_API() { 138 return this; 139 } 140 141 PP_AudioSampleRate PPB_AudioConfig_Shared::GetSampleRate() { 142 return sample_rate_; 143 } 144 145 uint32_t PPB_AudioConfig_Shared::GetSampleFrameCount() { 146 return sample_frame_count_; 147 } 148 149 bool PPB_AudioConfig_Shared::Init(PP_AudioSampleRate sample_rate, 150 uint32_t sample_frame_count) { 151 // TODO(brettw): Currently we don't actually check what the hardware 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. 155 if (sample_rate != PP_AUDIOSAMPLERATE_44100 && 156 sample_rate != PP_AUDIOSAMPLERATE_48000) 157 return false; 158 159 // TODO(brettw): Currently we don't actually query to get a value from the 160 // hardware, so just validate the range. 161 if (sample_frame_count > PP_AUDIOMAXSAMPLEFRAMECOUNT || 162 sample_frame_count < PP_AUDIOMINSAMPLEFRAMECOUNT) 163 return false; 164 165 sample_rate_ = sample_rate; 166 sample_frame_count_ = sample_frame_count; 167 return true; 168 } 169 170 } // namespace ppapi 171