类AudioTrack的函数getMinFrameCount(java侧为getMinBufferSize)

来源:互联网 发布:深圳淘宝客服工资多少 编辑:程序博客网 时间:2024/05/17 02:53

http://blog.csdn.net/njuitjf/article/details/7638579


以前看这个函数的时候,对min frame是如何计算得来的,并不是很了解。

今天又看了看,终于有点头绪了。

[cpp] view plain copy
  1. status_t AudioTrack::getMinFrameCount(  
  2.         int* frameCount,  
  3.         int streamType,  
  4.         uint32_t sampleRate)  
  5. {  
  6.     int afSampleRate;  
  7.     if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {  
  8.         return NO_INIT;  
  9.     }  
  10.     int afFrameCount;  
  11.     if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {  
  12.         return NO_INIT;  
  13.     }  
  14.     uint32_t afLatency;  
  15.     if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {  
  16.         return NO_INIT;  
  17.     }  
  18.   
  19.     // Ensure that buffer depth covers at least audio hardware latency  
  20.     uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);  
  21.     if (minBufCount < 2) minBufCount = 2;  
  22.   
  23.     *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :  
  24.               afFrameCount * minBufCount * sampleRate / afSampleRate;  
  25.     return NO_ERROR;  
  26. }  

先看看下面这一段代码:

[cpp] view plain copy
  1. int afSampleRate;  
  2. if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {  
  3.     return NO_INIT;  
  4. }  

从字面意思上,也基本上可以看出来,是去获取output 设备的sampling rate的。
如何获取到的呢?
一步一步来吧。


函数AudioSystem::getOutputSamplingRate中会首先根据stream type获取对应的output,然后尝试获取output的描述。
若获取成功,取output描述的samplerate:

[cpp] view plain copy
  1. *samplingRate = outputDesc->samplingRate;  

否则,取AudioFlinger的sample rate:

[cpp] view plain copy
  1. *samplingRate = af->sampleRate(output);  

先看audio flinger的sample rate是如何取得的。


函数AudioFlinger::sampleRate中,找到output对应的thread,取对应thread的sample rate。


函数AudioFlinger::ThreadBase::sampleRate中直接返回了成员变量mSampleRate。


mSampleRate是在函数AudioFlinger::PlaybackThread::readOutputParameters中被赋值:

[cpp] view plain copy
  1. mSampleRate = mOutput->sampleRate();  

mOutput->sampleRate,真正调用的是AudioStreamOutALSA对象的函数。
函数定义在其父类ALSAStreamOps中:

[cpp] view plain copy
  1. uint32_t ALSAStreamOps::sampleRate() const  
  2. {  
  3.     return mHandle->sampleRate;  
  4. }  

mHandle的赋值在ALSAStreamOps的构造函数中。使用的是构造函数参数handle。
AudioStreamOutALSA对象中函数AudioHardwareALSA::openOutputStream被创建:

[cpp] view plain copy
  1. out = new AudioStreamOutALSA(this, &(*it));  

其中it即为构造函数参数handle。
it的赋值:

[cpp] view plain copy
  1. ALSAHandleList::iterator it = mDeviceList.begin();  

mDeviceList的赋值在AudioHardwareALSA的构造函数中:

[cpp] view plain copy
  1. mALSADevice->init(mALSADevice, mDeviceList);  

init函数其实就是s_init函数:

[cpp] view plain copy
  1. static status_t s_init(alsa_device_t *module, ALSAHandleList &list)  
  2. {  
  3.     LOGD("Initializing devices for IMX51 ALSA module");  
  4.   
  5.     list.clear();  
  6.   
  7.     for (size_t i = 0; i < ARRAY_SIZE(_defaults); i++) {  
  8.   
  9.         _defaults[i].module = module;  
  10.         list.push_back(_defaults[i]);  
  11.     }  
  12.   
  13.     return NO_ERROR;  
  14. }  

_defaults的定义:

[cpp] view plain copy
  1. static alsa_handle_t _defaults[] = {  
  2.     {  
  3.         module      : 0,  
  4.         devices     : IMX51_OUT_DEFAULT,  
  5.         curDev      : 0,  
  6.         curMode     : 0,  
  7.         handle      : 0,  
  8.         format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT  
  9.         channels    : 2,  
  10.         sampleRate  : DEFAULT_SAMPLE_RATE,  
  11.         latency     : 200000, // Desired Delay in usec  
  12.         bufferSize  : 6144, // Desired Number of samples  
  13.         modPrivate  : (void *)&setDefaultControls,  
  14.     },  
  15.     {  
  16.         module      : 0,  
  17.         devices     : IMX51_IN_DEFAULT,  
  18.         curDev      : 0,  
  19.         curMode     : 0,  
  20.         handle      : 0,  
  21.         format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT  
  22.         channels    : 2,  
  23.         sampleRate  : DEFAULT_SAMPLE_RATE,  
  24.         latency     : 250000, // Desired Delay in usec  
  25.         bufferSize  : 6144, // Desired Number of samples  
  26.         modPrivate  : (void *)&setDefaultControls,  
  27.     },  
  28. };  

sampleRate原来是在这儿指定的:

[cpp] view plain copy
  1. sampleRate  : DEFAULT_SAMPLE_RATE,  

DEFAULT_SAMPLE_RATE的定义为44100.


所以,afSampleRate的值其实就是44100.


回头看看,若是在函数AudioSystem::getOutputSamplingRate中找到了output的描述,情况又是怎样的呢?


output描述是在AudioPolicyManagerBase的构造函数中被创建。
其中,latency是通过调用函数mpClientInterface->openOutput取得:

[cpp] view plain copy
  1. mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,  
  2.                                 &outputDesc->mSamplingRate,  
  3.                                 &outputDesc->mFormat,  
  4.                                 &outputDesc->mChannels,  
  5.                                 &outputDesc->mLatency,  
  6.                                 outputDesc->mFlags);  

其实就是调用了函数AudioFlinger::openOutput。
其中对SamplingRate的赋值:

[cpp] view plain copy
  1. if (pSamplingRate) *pSamplingRate = samplingRate;  

samplingRate的来历:

[cpp] view plain copy
  1. AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,  
  2.                                                          (int *)&format,  
  3.                                                          &channels,  
  4.                                                          &samplingRate,  
  5.                                                          &status);  

函数AudioHardwareALSA::openOutputStream中对samplingRate的赋值:

[cpp] view plain copy
  1. err = out->set(format, channels, sampleRate);  

函数ALSAStreamOps::set中对sampleRate的处理:

[cpp] view plain copy
  1. if (rate && *rate > 0) {  
  2.     if (mHandle->sampleRate != *rate)  
  3.         return BAD_VALUE;  
  4. else if (rate)  
  5.     *rate = mHandle->sampleRate;  

与前面的那条河流汇合了。




FrameCount与sampleRate的流程类似,下面只说是其中不同的地方。
AudioFlinger::PlaybackThread::readOutputParameters函数中:

[cpp] view plain copy
  1. mFrameSize = (uint16_t)mOutput->frameSize();  
  2. mFrameCount = mOutput->bufferSize() / mFrameSize;  

函数frameSize来自于类AudioStreamOut:

[cpp] view plain copy
  1. /** 
  2.  * return the frame size (number of bytes per sample). 
  3.  */  
  4. uint32_t    frameSize() const { return AudioSystem::popCount(channels())*((format()==AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(int8_t)); }  

函数ALSAStreamOps::channels的实现:

[cpp] view plain copy
  1. uint32_t ALSAStreamOps::channels() const  
  2. {  
  3.     unsigned int count = mHandle->channels;  
  4.     uint32_t channels = 0;  
  5.   
  6.     if (mHandle->curDev & AudioSystem::DEVICE_OUT_ALL)  
  7.         switch(count) {  
  8.             case 4:  
  9.                 channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT;  
  10.                 channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT;  
  11.                 // Fall through...  
  12.             default:  
  13.             case 2:  
  14.                 channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT;  
  15.                 // Fall through...  
  16.             case 1:  
  17.                 channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT;  
  18.                 break;  
  19.         }  
  20.     else  
  21.         switch(count) {  
  22.             default:  
  23.             case 2:  
  24.                 channels |= AudioSystem::CHANNEL_IN_RIGHT;  
  25.                 // Fall through...  
  26.             case 1:  
  27.                 channels |= AudioSystem::CHANNEL_IN_LEFT;  
  28.                 break;  
  29.         }  
  30.   
  31.     return channels;  
  32. }  

看看channels在_defaults中的定义:

[cpp] view plain copy
  1. channels    : 2,  

函数ALSAStreamOps::format实现:

[cpp] view plain copy
  1. int ALSAStreamOps::format() const  
  2. {  
  3.     int pcmFormatBitWidth;  
  4.     int audioSystemFormat;  
  5.   
  6.     snd_pcm_format_t ALSAFormat = mHandle->format;  
  7.   
  8.     pcmFormatBitWidth = snd_pcm_format_physical_width(ALSAFormat);  
  9.     switch(pcmFormatBitWidth) {  
  10.         case 8:  
  11.             audioSystemFormat = AudioSystem::PCM_8_BIT;  
  12.             break;  
  13.   
  14.         default:  
  15.             LOG_FATAL("Unknown AudioSystem bit width %i!", pcmFormatBitWidth);  
  16.   
  17.         case 16:  
  18.             audioSystemFormat = AudioSystem::PCM_16_BIT;  
  19.             break;  
  20.     }  
  21.   
  22.     return audioSystemFormat;  
  23. }  

看看format在_defaults中的定义:

[cpp] view plain copy
  1. format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT  

PCM_8_BIT与PCM_16_BIT的定义:

[cpp] view plain copy
  1. // Audio sub formats (see AudioSystem::audio_format).  
  2. enum pcm_sub_format {  
  3.     PCM_SUB_16_BIT          = 0x1, // must be 1 for backward compatibility  
  4.     PCM_SUB_8_BIT           = 0x2, // must be 2 for backward compatibility  
  5. };  

所以,

[cpp] view plain copy
  1. mFrameSize = (uint16_t)mOutput->frameSize();  

的结果其实就是4.


函数ALSAStreamOps::bufferSize的实现:

[cpp] view plain copy
  1. size_t ALSAStreamOps::bufferSize() const  
  2. {  
  3.     snd_pcm_uframes_t bufferSize = mHandle->bufferSize;  
  4.     snd_pcm_uframes_t periodSize;  
  5.   
  6.     // 掉进了难缠的alsa lib,先不去看了。  
  7.     snd_pcm_get_params(mHandle->handle, &bufferSize, &periodSize);  
  8.   
  9.     size_t bytes = static_cast<size_t>(snd_pcm_frames_to_bytes(mHandle->handle, bufferSize));  
  10.   
  11.     // Not sure when this happened, but unfortunately it now  
  12.     // appears that the bufferSize must be reported as a  
  13.     // power of 2. This might be for OSS compatibility.  
  14.     for (size_t i = 1; (bytes & ~i) != 0; i<<=1)  
  15.         bytes &= ~i;  
  16.   
  17.     return bytes;  
  18. }  

看看bufferSize在_defaults中的定义:

[cpp] view plain copy
  1. bufferSize  : 6144, // Desired Number of samples  

所以,不考虑alsa lib,下面:

[cpp] view plain copy
  1. mFrameCount = mOutput->bufferSize() / mFrameSize;  

的运算结果为:6144 / 4 = 1536
即afFrameCount为1536.


关于latency的流程就不再看了。
在_defaults中,latency的定义为:

[cpp] view plain copy
  1. latency     : 200000, // Desired Delay in usec  

根据以下计算公式:

[cpp] view plain copy
  1. #define USEC_TO_MSEC(x) ((x + 999) / 1000)  

可以算得,afLatency的结果其实就是200.


变量的值都知道了,所以minBufCount也就可以算出来了:

[cpp] view plain copy
  1. // Ensure that buffer depth covers at least audio hardware latency  
  2. uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);  

minBufCount = 200 / ((1000×1536)/44100) = 5.


消化消化。
afFrameCount的意思是硬件buffer里能放多少frame,afFrameCount/afSampleRate的意思是,播放一次硬件buffer中的数据需要多少时间,算出来的单位是秒。
再乘以个1000,即将秒转为了毫秒。
这样就与afLatency的单位一致了。
这样算出来的结果,就是说,为了满足硬件延迟,软件侧的buffer大小只是要是硬件侧buffer大小的多少倍。


感觉还是没消化彻底。
什么是硬件延迟?为什么软件侧的buffer size需要这个倍数呢?
硬件延迟,就是说,硬件侧可能会延迟这么久,也就是说硬件可能有这么长的时间都没有从软件侧取数据。
而软件侧还在不停地写数据,为了保证软件侧的数据不被丢失,就需要软件侧的buffer足够大。
多大才是足够大呢?
就是在硬件允许的最大时间,不取数据的情况下,软件侧的buffer也不至于爆仓。
这样基本上消化彻底了。


frameCount的计算与传入参数sampleRate有关:

[cpp] view plain copy
  1. *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :  
  2.           afFrameCount * minBufCount * sampleRate / afSampleRate;  

如果sampleRate为0,frameCount为 7680.
如果sampleRate不为0,frameCount为7680×sampleRate/44100.


消化一下。
既然上面已经算出来了软件buffer 大小只是要是硬件的多少倍,而硬件buffer中包含的frame个数已经知道为afFrameCount,
算出软件buffer中包含多少frame也没什么困难了。
如果软件侧过来的数据与硬件侧的sampling rate未指定,或者与硬件侧的一样,软件侧的buffer能装的frame个数即为afFrameCount * minBufCount。
如果软件侧的sampling rate与硬件侧不一致,就拿上面的结果再乘以个sampleRate / afSampleRate即可。

0 0
原创粉丝点击