Home | History | Annotate | Download | only in shared_impl
      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