Android 音频源码分析——AndroidRecord音频数据传输流程

本文详细分析了AndroidRecord的音频数据传输流程,包括AudioFlinger如何从AudioHal读取数据,RecordThread的处理,以及AudioRecord如何通过共享内存获取数据。重点探讨了RecordThread的read、getNextBuffer和convert步骤,以及AudioRecord客户端的读取过程。
摘要由CSDN通过智能技术生成

Android 音频源码分析——AndroidRecord录音(一)
Android 音频源码分析——AndroidRecord录音(二)
Android 音频源码分析——AndroidRecord音频数据传输流程

这篇主要分析一下AudioRecord录音过程中的 数据传输流程。
流程图:
音频传输流程

部分数据传输的流程已在前两篇文章中分析了。
这里主要分析一下:

  • AudioFlinger 从Hal 读取数据。
  • AudioRecord从AudioFlinger获取数据。

AudioHal -> AudioFlinger

AudioFlinger服务通过RecordThread读取数据。
直接来看RecordThread循环体。

bool AudioFlinger::RecordThread::threadLoop()
{
   
    nsecs_t lastWarning = 0;
    inputStandBy();

reacquire_wakelock:
    sp<RecordTrack> activeTrack;
    {
   
        Mutex::Autolock _l(mLock);
        acquireWakeLock_l();
    }

    // used to request a deferred sleep, to be executed later while mutex is unlocked
    uint32_t sleepUs = 0;
    // loop while there is work to do
    for (;;) {
   
        Vector< sp<EffectChain> > effectChains;
        // activeTracks accumulates a copy of a subset of mActiveTracks
        Vector< sp<RecordTrack> > activeTracks;
        // reference to the (first and only) active fast track
        sp<RecordTrack> fastTrack;
        // reference to a fast track which is about to be removed
        sp<RecordTrack> fastTrackToRemove;
        {
    // scope for mLock
            Mutex::Autolock _l(mLock);
            processConfigEvents_l();
            // check exitPending here because checkForNewParameters_l() and
            // checkForNewParameters_l() can temporarily release mLock
            if (exitPending()) {
   
                break;
            }
            // sleep with mutex unlocked
            if (sleepUs > 0) {
   
                ATRACE_BEGIN("sleepC");
                mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)sleepUs));
                ATRACE_END();
                sleepUs = 0;
                continue;
            }

            // if no active track(s), then standby and release wakelock
            size_t size = mActiveTracks.size();
            if (size == 0) {
   
                standbyIfNotAlreadyInStandby();
                // exitPending() can't become true here
                releaseWakeLock_l();
                ALOGV("RecordThread: loop stopping");
                // go to sleep
                mWaitWorkCV.wait(mLock);
                ALOGV("RecordThread: loop starting");
                goto reacquire_wakelock;
            }

            bool doBroadcast = false;
            bool allStopped = true;
            for (size_t i = 0; i < size; ) {
   
                activeTrack = mActiveTracks[i];
                if (activeTrack->isTerminated()) {
   
                    if (activeTrack->isFastTrack()) {
   
                        ALOG_ASSERT(fastTrackToRemove == 0);
                        fastTrackToRemove = activeTrack;
                    }
                    removeTrack_l(activeTrack);
                    mActiveTracks.remove(activeTrack);
                    size--;
                    continue;
                }

                TrackBase::track_state activeTrackState = activeTrack->mState;
                switch (activeTrackState) {
   
                case TrackBase::PAUSING:
                    mActiveTracks.remove(activeTrack);
                    doBroadcast = true;
                    size--;
                    continue;
                case TrackBase::STARTING_1:
                    sleepUs = 10000;
                    i++;
                    allStopped = false;
                    continue;
                case TrackBase::STARTING_2:
                    doBroadcast = true;
                    mStandby = false;
                    activeTrack->mState = TrackBase::ACTIVE;
                    allStopped = false;
                    break;
                case TrackBase::ACTIVE:
                    allStopped = false;
                    break;
                case TrackBase::IDLE:
                    i++;
                    continue;
                default:
                    LOG_ALWAYS_FATAL("Unexpected activeTrackState %d", activeTrackState);
                }
                activeTracks.add(activeTrack);
                i++;
                if (activeTrack->isFastTrack()) {
   
                    ALOG_ASSERT(!mFastTrackAvail);
                    ALOG_ASSERT(fastTrack == 0);
                    fastTrack = activeTrack;
                }
            }
            mActiveTracks.updatePowerState(this);
            updateMetadata_l();
            if (allStopped) {
   
                standbyIfNotAlreadyInStandby();
            }
            if (doBroadcast) {
   
                mStartStopCond.broadcast();
            }
            // sleep if there are no active tracks to process
            if (activeTracks.size() == 0) {
   
                if (sleepUs == 0) {
   
                    sleepUs = kRecordThreadSleepUs;
                }
                continue;
            }
            sleepUs = 0;

            lockEffectChains_l(effectChains);
        }

        // thread mutex is now unlocked, mActiveTracks unknown, activeTracks.size() > 0

        size_t size = effectChains.size();
        for (size_t i = 0; i < size; i++) {
   
            // thread mutex is not locked, but effect chain is locked
            effectChains[i]->process_l();
        }

        // Push a new fast capture state if fast capture is not already running, or cblk change
        if (mFastCapture != 0) {
   
            FastCaptureStateQueue *sq = mFastCapture->sq();
            FastCaptureState *state = sq->begin();
            bool didModify = false;
            FastCaptureStateQueue::block_t block = FastCaptureStateQueue::BLOCK_UNTIL_PUSHED;
            if (state->mCommand != FastCaptureState::READ_WRITE /* FIXME &&
                    (kUseFastMixer != FastMixer_Dynamic || state->mTrackMask > 1)*/) {
   
                if (state->mCommand == FastCaptureState::COLD_IDLE) {
   
                    int32_t old = android_atomic_inc(&mFastCaptureFutex);
                    if (old == -1) {
   
                        (void) syscall(
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值