Android13 AudioFlinger RecordHandle start流程分析

我们还是从RecordHandle开始,它是IAudioRecord的服务端:

//frameworks/av/services/audioflinger/AudioFlinger.h
// server side of the client's IAudioRecord
class RecordHandle : public android::media::BnAudioRecord {
public:
    explicit RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
    virtual             ~RecordHandle();
    virtual binder::Status    start(int /*AudioSystem::sync_event_t*/ event,
            int /*audio_session_t*/ triggerSession);
    virtual binder::Status   stop();
    virtual binder::Status   getActiveMicrophones(
            std::vector<media::MicrophoneInfoData>* activeMicrophones);
    virtual binder::Status   setPreferredMicrophoneDirection(
            int /*audio_microphone_direction_t*/ direction);
    virtual binder::Status   setPreferredMicrophoneFieldDimension(float zoom);
    virtual binder::Status   shareAudioHistory(const std::string& sharedAudioPackageName,
                                               int64_t sharedAudioStartMs);


private:
    const sp<RecordThread::RecordTrack> mRecordTrack;


    // for use from destructor
    void                stop_nonvirtual();
};


//frameworks/av/services/audioflinger/Tracks.cpp
binder::Status AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
        int /*audio_session_t*/ triggerSession) {
    ALOGV("%s()", __func__);
    return binderStatusFromStatusT(
        mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession)); //调用RecordTrack的start函数
}

在RecordHandle的start函数中会调用mRecordTrack->start,也就是RecordTrack的start函数:

//frameworks/av/services/audioflinger/Threads.h
ActiveTracks<RecordTrack>           mActiveTracks;


//frameworks/av/services/audioflinger/Tracks.cpp
status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
                                                        audio_session_t triggerSession)
{
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
        RecordThread *recordThread = (RecordThread *)thread.get(); //获取RecordThread 
        return recordThread->start(this, event, triggerSession); //RecordThread 的start函数
    } else {
        ALOGW("%s track %d: thread was destroyed", __func__, portId());
        return DEAD_OBJECT;
    }
}


status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
                                           AudioSystem::sync_event_t event,
                                           audio_session_t triggerSession)
{
    ALOGV("RecordThread::start event %d, triggerSession %d", event, triggerSession);
    sp<ThreadBase> strongMe = this;
    status_t status = NO_ERROR;


    if (event == AudioSystem::SYNC_EVENT_NONE) {
        recordTrack->clearSyncStartEvent();
    } else if (event != AudioSystem::SYNC_EVENT_SAME) {
        recordTrack->mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
                                       triggerSession,
                                       recordTrack->sessionId(),
                                       syncStartEventCallback,
                                       recordTrack);
        // Sync event can be cancelled by the trigger session if the track is not in a
        // compatible state in which case we start record immediately
        if (recordTrack->mSyncStartEvent->isCancelled()) {
            recordTrack->clearSyncStartEvent();
        } else {
            // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs
            recordTrack->mFramesToDrop = -(ssize_t)
                    ((AudioSystem::kSyncRecordStartTimeOutMs * recordTrack->mSampleRate) / 1000);
        }
    }


    {
        // This section is a rendezvous between binder thread executing start() and RecordThread
        AutoMutex lock(mLock);
        if (recordTrack->isInvalid()) {
            recordTrack->clearSyncStartEvent();
            ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
            return DEAD_OBJECT;
        }
        if (mActiveTracks.indexOf(recordTrack) >= 0) {
            if (recordTrack->mState == TrackBase::PAUSING) {
                // We haven't stopped yet (moved to PAUSED and not in mActiveTracks)
                // so no need to startInput().
                ALOGV("active record track PAUSING -> ACTIVE");
                recordTrack->mState = TrackBase::ACTIVE;
            } else {
                ALOGV("active record track state %d", (int)recordTrack->mState);
            }
            return status;
        }


        // TODO consider other ways of handling this, such as changing the state to :STARTING and
        //      adding the track to mActiveTracks after returning from AudioSystem::startInput(),
        //      or using a separate command thread
        recordTrack->mState = TrackBase::STARTING_1;
        mActiveTracks.add(recordTrack);  //mActiveTracks在RecordTrack中是RecordTrack,将当前recordTrack加入到RecordTrack中
        status_t status = NO_ERROR;
        if (recordTrack->isExternalTrack()) {
            mLock.unlock();
            status = AudioSystem::startInput(recordTrack->portId()); 
            mLock.lock();
            if (recordTrack->isInvalid()) {
                recordTrack->clearSyncStartEvent();
                if (status == NO_ERROR && recordTrack->mState == TrackBase::STARTING_1) {
                    recordTrack->mState = TrackBase::STARTING_2;
                    // STARTING_2 forces destroy to call stopInput.
                }
                ALOGW("%s track %d: invalidated after startInput", __func__, recordTrack->portId());
                return DEAD_OBJECT;
            }
            if (recordTrack->mState != TrackBase::STARTING_1) {
                ALOGW("%s(%d): unsynchronized mState:%d change",
                    __func__, recordTrack->id(), (int)recordTrack->mState);
                // Someone else has changed state, let them take over,
                // leave mState in the new state.
                recordTrack->clearSyncStartEvent();
                return INVALID_OPERATION;
            }
            // we're ok, but perhaps startInput has failed
            if (status != NO_ERROR) {
                ALOGW("%s(%d): startInput failed, status %d",
                    __func__, recordTrack->id(), status);
                // We are in ActiveTracks if STARTING_1 and valid, so remove from ActiveTracks,
                // leave in STARTING_1, so destroy() will not call stopInput.
                mActiveTracks.remove(recordTrack);
                recordTrack->clearSyncStartEvent();
                return status;
            }
            sendIoConfigEvent_l(
                AUDIO_CLIENT_STARTED, recordTrack->creatorPid(), recordTrack->portId()); //发送音频客户端已启动消息
        }


        recordTrack->logBeginInterval(patchSourcesToString(&mPatch)); // log to MediaMetrics


        // Catch up with current buffer indices if thread is already running.
        // This is what makes a new client discard all buffered data.  If the track's mRsmpInFront
        // was initialized to some value closer to the thread's mRsmpInFront, then the track could
        // see previously buffered data before it called start(), but with greater risk of overrun.


        recordTrack->mResamplerBufferProvider->reset(); //reset 接收缓冲区
        if (!recordTrack->isDirect()) {
            // clear any converter state as new data will be discontinuous
            recordTrack->mRecordBufferConverter->reset(); //reset重采样器
        }
        recordTrack->mState = TrackBase::STARTING_2;
        // signal thread to start
        mWaitWorkCV.broadcast(); //唤醒recordThread
        return status;
    }
}

这里重要的处理有四步,分别是:

  • 调用mActiveTracks.add(recordTrack); 将当前recordTrack加入到RecordTrack中。

  • 调用recordTrack->mResamplerBufferProvider->reset();函数,reset 接收缓冲区。

  • 调用recordTrack->mRecordBufferConverter->reset();函数,reset 重采样器。

  • 调用mWaitWorkCV.broadcast()函数,唤醒recordThread.

AudioFlinger RecordThread threadLoop

唤醒recordThread后,recordThread就会开始它自己的工作,thread_loop会动起来,不停的从AudioHAL读取数据,然后通过共享内存传给AudioRecord:

Android13 AudioFlinger RecordThread threadLoop分析-CSDN博客

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值