[RK3288][Android6.0] Audio中的混音過程小結
阿新 • • 發佈:2019-02-05
Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
bool AudioFlinger::PlaybackThread::threadLoop()
{
......
while (!exitPending())
{
......
//如果目前沒有音訊需要處理,那麼進入睡眠。
if ((!mActiveTracks.size() && systemTime() > mStandbyTimeNs) ||
isSuspended()) {
// put audio hardware into standby after short delay
if (shouldStandby_l()) {
//進入睡眠待機
threadLoop_standby();
mStandby = true;
}
if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
.....
//等待被喚醒
mWaitWorkCV.wait(mLock);
......
}
}
// mMixerStatusIgnoringFastTracks is also updated internally
//喚醒後說明有active的trace,混音前做準備工作
mMixerStatus = prepareTracks_l(&tracksToRemove);
......
if (mBytesRemaining == 0) {
//開始混音
threadLoop_mix();
......
}
if (!waitingAsyncCallback()) {
......
if (mBytesRemaining) {
//混音後就可以寫資料到底層了
ret = threadLoop_write();
//處理underrun的情況
if ((now - lastWarning) > kWarningThrottleNs) {
ATRACE_NAME("underrun");
......
}
......
}
所以核心流程就是:
1. 睡眠, threadLoop_standby()
2. 混音前做準備工作, prepareTracks_l()
3. 混音, threadLoop_mix()
4. 音訊輸出, threadLoop_write()
prepareTracks_l():
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Vector< sp<Track> > *tracksToRemove)
{
......
//當前active的track做配置。
size_t count = mActiveTracks.size();
for (size_t i=0 ; i<count ; i++) {
......
// XXX: these things DON'T need to be done each time
//設定資料buffer,這個buffer可能會因為format,channel不一樣以及effect功能而被重新輸出到另一個buffer。
//可以參考reconfigureBufferProviders()
mAudioMixer->setBufferProvider(name, track);
mAudioMixer->enable(name);
//設定音量
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, &vlf);
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, &vrf);
mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, &vaf);
//設定format
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::FORMAT, (void *)track->format());
//設定通道數,可能會通道轉換
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask);
......
//設定取樣率,如果取樣率不一致,那麼要做重取樣的初始化工作。
mAudioMixer->setParameter(
name,
AudioMixer::RESAMPLE,
AudioMixer::SAMPLE_RATE,
(void *)(uintptr_t)reqSampleRate);
......
}
......
}
threadLoop_mix():
void AudioFlinger::MixerThread::threadLoop_mix()
{
......
// mix buffers...
mAudioMixer->process(pts);
......
}
void AudioMixer::process(int64_t pts)
{
mState.hook(&mState, pts);
}
hook在之前會根據取樣率來選擇不同的處理函式,假如不需要resample,那麼呼叫process__genericNoResampling()
void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
{
......
while (e0) {
const int i = 31 - __builtin_clz(e0);
e0 &= ~(1<<i);
track_t& t = state->tracks[i];
t.buffer.frameCount = state->frameCount;
//獲取可用buffer
t.bufferProvider->getNextBuffer(&t.buffer, pts);
t.frameCount = t.buffer.frameCount;
t.in = t.buffer.raw;
}
while (e0) {
track_t& t = state->tracks[i];
//函式的賦值也是在process__validate()中,選擇哪個處理函式可參考getTrackHook()
t.hook()
.....
}
......
}
threadLoop_write():
ssize_t AudioFlinger::MixerThread::threadLoop_write()
{
......
return PlaybackThread::threadLoop_write();
}
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{
......
mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
......
}