什么是AudioBufferProvider?
顧名思義,Audio音頻數據緩沖提供,就是提供音頻數據的緩沖類,而且這個AudioBufferProvider派生出許多子類,每個子類有不同的用途,至關重要;那它在Android哪個地方使用呢?
在PlaybackTread中,接收應用層傳遞而來的數據,那為什么要專門用這么多Provider類來處理呢?而不只是簡單的轉發,將應用層的數據轉發到PlaybackThread就行了;
No、No、No!因為PlaybackThread負責接收應用層諸多應用的音頻數據,每個音源的數據format、channel等不同,需要進行不同format轉換、channel擴張/裁剪、down/upMix等,甚至會對其數據做一些音頻特性如變速等操作,這就要對數據進行預處理,每一個provider的派生類就是用來做這些的
AudioBufferProvider類派生關系圖
整體框架圖如上,類的大致用途在圖片中已簡單標識,簡而言之,右側SourceAudioBufferProvider是專用于數據提供,而左側的BufferProvider則是對數據進行一些特殊處理,那系統是如何串聯這些對象呢?那就和父類的virtual函數有關系,重點關注AudioBufferProvider和PassthruBufferProvider這兩個祖先類
AudioBufferProvider
class AudioBufferProvider
{
public:// FIXME merge with AudioTrackShared::Buffer, AudioTrack::Buffer, and AudioRecord::Buffer// and rename getNextBuffer() to obtainBuffer()struct Buffer {Buffer() : raw(NULL), frameCount(0) { }//聯合體所有成員共用一個空間union {void* raw;short* i16;int8_t* i8;};size_t frameCount;};// On entry:// buffer != NULL// buffer->raw unused// buffer->frameCount maximum number of desired frames// On successful return:// status NO_ERROR// buffer->raw non-NULL pointer to buffer->frameCount contiguous available frames// buffer->frameCount number of contiguous available frames at buffer->raw,// 0 < buffer->frameCount <= entry value// On error return:// status != NO_ERROR// buffer->raw NULL// buffer->frameCount 0//buffer.raw地址 buffer.frameCount長度,也就是數據是讀出來,讀到buffer中去virtual status_t getNextBuffer(Buffer* buffer) = 0;
始祖類AudioBufferProvider定義了數據Buffer結構體,而getNextBuffer就是獲取音頻數據的,調用此方法后數據會存到buffer參數中去;
PassthruBufferProvider工作模式—責任鏈模式
class PassthruBufferProvider : public AudioBufferProvider {virtual void setBufferProvider(AudioBufferProvider *p) {mTrackBufferProvider = p;}protected:AudioBufferProvider *mTrackBufferProvider;
}
上面是定義,可以按如下偽代碼使用:
std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider = AdjustChannelsBufferProvider();
std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider = ReformatBufferProvider().setsetBufferProvider(mAdjustChannelsBufferProvider);
std::unique_ptr<PassthruBufferProvider> mTimestretchBufferProvider = TimestretchBufferProvider().setsetBufferProvider(mReformatBufferProvider);
這樣mAdjustChannelsBufferProvider處理完了,就交給mReformatBufferProvider處理,在交給mTimestretchBufferProvider處理,直至處理完成;
在Android中哪個地方使用?
哈哈,據我所知,目前在2個地方看到:
/framework/av/services/audioflinger/threads.cpp
/frameworks/av/media/libaudioprocessing/AudioMixer.cpp
在threads里面的threadLoop_write方法里面,通常寫入到sink對象,如下:
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{.....ssize_t framesWritten = mNormalSink->write((char *)mSinkBuffer + offset, count);....
}
這里就是接收應用層的數據,通常是寫入到SourceBufferProvider中去;mNormalSink是MonoPipe類型,而MonoPipe怎么又和SourceBufferProvider扯上關系了呢?見下圖:
當write寫入到MonoPipe中去了以后,在SourceBufferProvider中,虛函數使用getNextBuffer拉去數據即可
而在AudioMixer中,在混音時通常會創建許多BufferProvider,對音頻數據進行預處理,如下: