[RK3288][Android6.0] Audio中的混音过程小结
2017-06-14 10:55
429 查看
Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
所以核心流程就是:
1. 睡眠, threadLoop_standby()
2. 混音前做准备工作, prepareTracks_l()
3. 混音, threadLoop_mix()
4. 音频输出, threadLoop_write()
prepareTracks_l():
threadLoop_mix():
hook在之前会根据采样率来选择不同的处理函数,假如不需要resample,那么调用process__genericNoResampling()
threadLoop_write():
参考:
http://www.cnblogs.com/TaigaCon/p/4827227.html
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); ...... }
参考:
http://www.cnblogs.com/TaigaCon/p/4827227.html
相关文章推荐
- [RK3288][Android6.0] Audio的音量计算过程小结
- [RK3288][Android6.0] USB 枚举过程小结
- [RK3288][Android6.0] 系统关机调用过程小结
- [RK3288][Android6.0] Audio的音量设置流程小结
- [RK3288][Android6.0] Audio录音frame rate设置流程小结
- [RK3288][Android6.0] WiFi的驱动初始化过程小结
- [RK3288][Android6.0] Apk设置显示旋转过程小结
- [RK3288][Android6.0] Audio中的单声道到双声道的转换处理过程
- [RK3288][Android6.0] Audio中的录音重采样小结
- [RK3288][Android6.0] WiFi在Setting中的开启过程小结
- [RK3288][Android6.0] MediaCodec的configure配置过程小结
- [RK3288][Android6.0] MediaCodec初始化过程小结
- [RK3288][Android6.0] WIFI接入过程的加密和认证方式小结
- [RK3288][Android6.0] WiFi之Framework连接过程小结
- [RK3288][Android6.0] USB 枚举过程小结
- [RK3288][Android6.0] Audio中的放音重采样小结
- [RK3288][Android6.0] 系统重启调用过程小结
- [RK3288][Android6.0] 有线耳机插拔事件监听小结
- [RK3288][Android6.0] Camera HAL流程小结
- [RK3288][Android6.0] Audio中的HW Params设置流程