Android 音频源码分析——Thread Track分析
Posted VNanyesheshou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 音频源码分析——Thread Track分析相关的知识,希望对你有一定的参考价值。
基于Andorid9.0源码
分析下AudioRecord、AudioTrack对应 audioserver中的关键类。
一.ThreadBase
ThreadBase,线程类对音频数据处理(混音、音效),从Hal层读数据、写数据
分析AudioRecord和AudioTrack源码,发现有多种Thread,都继承ThreadBase。其结构如下图
-
RecordThread:录音线程
-
PlaybackThread:播放线程,包括多个子类,对应不同的播放模式;
MixerThread:混音线程
DuplicatingThread:混音线程子类,特殊在于音频数据复制成两份分别输出
DirectOutputThread:直接输出,软件层不需要mixer混音,直接交给hal层数据
OffloadThread:压缩的音频数据,直接输出到hal层,由音频DSP进行解码处理;
-
MmapThread:映射线程,AAudio使用,后续研究。。。
MixerThread
以MixerThread为例分析下其内部使用
MixerThread由AudioFlinger openOutput创建,其父类PlaybackThread重写了Thread的threadLoop,onFirstRef方法,MixerThread没有重写.
void AudioFlinger::PlaybackThread::onFirstRef()
run(mThreadName, android_PRIORITY_URGENT_AUDIO);
MixerThread对象创建时会调用onFirstRef函数,run 方法启动线程循环体threadLoop
bool AudioFlinger::PlaybackThread::threadLoop()
while (!exitPending())
//....
processConfigEvents_l();
mMixerStatus = prepareTracks_l(&tracksToRemove);
if (mMixerStatus == MIXER_TRACKS_READY)
threadLoop_mix();
else if ((mMixerStatus != MIXER_DRAIN_TRACK)
&& (mMixerStatus != MIXER_DRAIN_ALL))
threadLoop_sleepTime();
for (size_t i = 0; i < effectChains.size(); i ++)
effectChains[i]->process_l();
ret = threadLoop_write();
- processConfigEvents_l处理event,包括:PRIO、IO、set_parameter、CREATE_AUDIO_PATCH、RELEASE_AUDIO_PATCH
- prepareTracks_l 准备工作,管理Track状态,添加、删除,设置参数到AudioMixer
- threadLoop_mix调用mAudioMixer->process()进行混音处理
- threadLoop_write输出音频数据
ssize_t AudioFlinger::MixerThread::threadLoop_write()
if (mFastMixer != 0)
return PlaybackThread::threadLoop_write();
// shared by MIXER and DIRECT, overridden by DUPLICATING
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
// If an NBAIO sink is present, use it to write the normal mixer's submix
if (mNormalSink != 0)
// otherwise use the HAL / AudioStreamOut directly
else
// Direct output and offload threads
// FIXME We should have an implementation of timestamps for direct output threads.
// They are used e.g for multichannel PCM playback over HDMI.
bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
mNumWrites++;
mInWrite = false;
mStandby = false;
return bytesWritten;
MixerThread threadLoop_write函数调用PlaybackThread write函数,mOutput->write 将音频数据写到hal层
二.TrackBase
音频管理类,创建共享内存,控制音频流状态。TrackBase继承关系如下图所示:
- RecordTrack:录音track
- Track:播放track
OutputTrack:播放Track子类,对应Duplicat 音频模式
PatchTrack:未知。。。 - MmapTrack:映射模式,对应MMapThread
应用创建一个录音实列(AudioRecord、MediaRecorder),AudioFlinger中对应创建RecordTrack;
应用创建一个播放实列(AudioTrack、MediaPlayer、SoundPool等),AudioFlinger中对应创建播放Track;
AudioFlinger::ThreadBase::TrackBase::TrackBase()
if (client != 0)
mCblkMemory = client->heap()->allocate(size);
if (mCblkMemory == 0 ||
(mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer())) == NULL)
ALOGE("not enough memory for AudioTrack size=%zu", size);
client->heap()->dump("AudioTrack");
mCblkMemory.clear();
return;
else
mCblk = (audio_track_cblk_t *) malloc(size);
if (mCblk == NULL)
ALOGE("not enough memory for AudioTrack size=%zu", size);
return;
//......
TrackBase初始化会创建共享内存mCblkMemory,与app交互音频数据。
以上是关于Android 音频源码分析——Thread Track分析的主要内容,如果未能解决你的问题,请参考以下文章
Android 音频源码分析——AudioTrack设备选择