携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、音频流数据传输通道创建
- AudioTrack在set函数中通过IAudioFlinger(binder机制)调用 AudioFlinger的createTrack接口进行设备选择(设备选择详细流程参考AudioTrack创建流程、输出设备选择),音频数据共享内存创建;
- 在PlayBackThread中创建Track,Track继承TrackBase,在TrackBase中创建audio_track_cblk_t以及分配用于跨进程音频数据传输的共享内存缓存,并且将音频信息和共享内存指针封装在audio_track_cblk_t中;
- 在Track中将audio_track_cblk_t和共享内存封装到AudioTrackServerProxy,同时将Track再次封装进TrackHandle(IAudioTrack服务端),传递回给AudioTrack;
- AudioTrack 通过 IAudioTrack获取共享内存地址和 audio_track_cblk_t 封装进AudioTrackClientProxy中;
- AudioTrack 通过 IAudioTrack接口start触发将Track加入到PlaybackThread激活Track列表(mActiveTracks)中,PlaybackThread从激活Track列表中取音频数据。
二、音频数据传输
- 应用通过AudioTrack::write中调用ClientProxy::obtainBuffer获取空闲的共享内存,再将音频数据拷贝到共享内存中,标记共享内存数据中有效音频数据启示位置和结束位置;
- MixerThread 内部封装 AudioMixer类,AudioMixer中封装的Track和AudioFlinger::PlaybackThread::Track::Track一一对应;
- AudioFlinger::PlaybackThread::Track::Track类实现AudioBufferProvider接口,并且分别实现getNextBuffer和releaseBuffer接口;
- AudioMixer内部封装了一个AudioMixer::mHook(函数指针)钩子函数,用于不同采样率等参数不同待用不同的接口,其接口函数如下:
void process__validate();
void process__nop();
void process__genericNoResampling();
void process__genericResampling();
void process__oneTrack16BitsStereoNoResampling();
template <int MIXTYPE, typename TO, typename TI, typename TA>
void process__noResampleOneTrack();
- 在 AudioMixer::invalidate 中对 AudioMixer::mHook进行赋值(mHook= &AudioMixer::process__validate),在AudioMixer::process__validate中根据是否静音重采样等参数选择对应的钩子函数;
- 同样在AudioMixer::Track中也有一个钩子函数,会根据音频采样位来选择对应的钩子函数,如下:
// hooks
void track__genericResample(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
void track__16BitsStereo(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
void track__16BitsMono(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
void volumeRampStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
void volumeStereo(int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
// multi-format track hooks
template <int MIXTYPE, typename TO, typename TI, typename TA>
void track__Resample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
template <int MIXTYPE, typename TO, typename TI, typename TA>
void track__NoResample(TO* out, size_t frameCount, TO* temp __unused, TA* aux);
- 最终AudioMixer::Track调用AudioFlinger::PlaybackThread::Track::getNextBuffer接口,而AudioFlinger::PlaybackThread::Track::getNextBuffer会调用ServerProxy::obtainBuffer获取已经填充音频数据的共享内存,并且将数据拷贝到本地内存中,在通过ServerProxy::releaseBuffer将取出数据的共享内存重置为无效(AudioTrack重复使用数据传输);