android jni 调用audiorecord,android 6.0 AudioRecord 录音流程分析(二)

本文详细分析了Android 6.0中AudioRecord录音流程,从JNI调用到AudioRecord的startRecording,深入探讨RecordThread的工作原理,包括线程同步、AudioPolicy管理和AudioPatch。通过对AudioFlinger核心函数的解析,揭示了录音数据的获取过程及内存共享机制。
摘要由CSDN通过智能技术生成

AudioRecord的开始录音 startRecording和 RecordThread

start录音流程走到(Android 应用阶段)

Jni android_media_AudioRecord_start ---> mAudioRecord->start ---> (AudioFlinger阶段开始跨进程)RecordHandle->start ---> RecordTrack->start --->RecordThread->start ---> (录音线程阶段)RecordThread-->threadLoop 走一轮还是来到了RecordThread,直奔解析RecordThread的start。

status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,

AudioSystem::sync_event_t event,

int triggerSession)

{

ALOGV("RecordThread::start event %d, triggerSession %d", event, triggerSession);

sp strongMe = this;

status_t status = NO_ERROR;

/* 基本默认都用SYNC_EVENT_NONE */

if (event == AudioSystem::SYNC_EVENT_NONE) {

recordTrack->clearSyncStartEvent();

} else if (event != AudioSystem::SYNC_EVENT_SAME) {

......

}

{

// This section is a rendezvous between binder thread executing start() and RecordThread

AutoMutex lock(mLock);

if (mActiveTracks.indexOf(recordTrack) >= 0) {

/**这里做判断,如果当前recordTrack已经start过了的,但是在暂停状态的话,

直接调整为ACTIVE状态,并且返回。

*/

if (recordTrack->mState == TrackBase::PAUSING) {

ALOGV("active record track PAUSING -> ACTIVE");

recordTrack->mState = TrackBase::ACTIVE;

} else {

ALOGV("active record track state %d", 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); //当前recordTrack存起来

mActiveTracksGen++;

status_t status = NO_ERROR;

if (recordTrack->isExternalTrack()) {

mLock.unlock();

status = AudioSystem::startInput(mId, (audio_session_t)recordTrack->sessionId());

mLock.lock();

// FIXME should verify that recordTrack is still in mActiveTracks

if (status != NO_ERROR) {

mActiveTracks.remove(recordTrack);

mActiveTracksGen++;

recordTrack->clearSyncStartEvent();

ALOGV("RecordThread::start error %d", status);

return status;

}

}

// 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.

/* reset一下mResamplerBufferProvider 和mRecordBufferConverter*/

recordTrack->mResamplerBufferProvider->reset();

// clear any converter state as new data will be discontinuous

recordTrack->mRecordBufferConverter->reset();

recordTrack->mState = TrackBase::STARTING_2;

// signal thread to start

mWaitWorkCV.broadcast();

if (mActiveTracks.indexOf(recordTrack) < 0) {

ALOGV("Record failed to start");

status = BAD_VALUE;

goto startError;

}

return status;

}

startError:

if (recordTrack->isExternalTrack()) {

AudioSystem::stopInput(mId, (audio_session_t)recordTrack->sessionId());

}

recordTrack->clearSyncStartEvent();

// FIXME I wonder why we do not reset the state here?

return status;

}

AudioSystem::startInput 基本上涉及到AudioSystem都是和AudioPolicy有关的,依然是由AudioPolicyManager::startInput(audio_io_handle_t input,

audio_session_t session)来处理这档事,。现在这里又要绕一圈audioPolicy 到 audioFlinger createAudioPatch创建AuioPatch来连接Source和sink端?不太懂这个AudioPatch概念。AudioPatch连接开始后和状态更新后唤醒录音线程mWaitWorkCV.broadcast(); 到这一步可以看RecordThread->threadLoop了。

bool AudioFlinger::RecordThread::threadLoop()

{

nsecs_t lastWarning = 0;

/* 暂停快速截取和让AudioStreamIn 输入流待机状态*/

inputStandBy();

reacquire_wakelock:

sp activeTrack;

int activeTracksGen;

{

Mutex::Autolock _l(mLock);

size_t size = mActiveTracks.size();

activeTracksGen = mActiveTracksGen;

if (size > 0) {

// FIXME an arbitrary choice

activeTrack = mActiveTracks[0];

acquireWakeLock_l(activeTrack->uid());

if (size > 1) {

SortedVector tmp;

for (size_t i = 0; i < size; i++) {

tmp.add(mActiveTracks[i]->uid());

}

updateWakeLockUids_l

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值