Android Audio - 音頻子系統框架簡析
關鍵的類對象
AudioSystem
AudioFlinger
AudioPolicy
AudioStreamIn
AudioResampler
Threads
RecordThread
MixerThread
PlaybackThread
TrackBase
RecordTrack
Track (playback track)
TimedTrack
OutputTrack
mRecord = new AudioRecord() 時
set
openRecord
AudioSystem::getInput
// 只有 openInput 纔回去創建新的 RecordThread.
// 這裏做了處理, 當本次錄音的 Profile 文件與已經打開的
// mInput Profile 一樣的話, 表示希望打開同一設備. 僅返回 audio_io_handle_t 即可.
mpClientInterface->openInput
AudioFlinger::openInput
// 創建一個新的 audio_io_handle_t 號碼.
audio_io_handle_t id = nextUniqueId();
// 建立與 so 庫的連接, 注意: 此時還沒有 open 底層驅動.
inHwHal->open_input_stream(inHwHal, id, *pDevices, &config, &inStream);
ladev->hwif->openInputStream
// 創建 speex_resampler_init 重採樣器.
new AudioHardware::DownSampler
// 創建一個 RecordThread 錄音線程
thread = new RecordThread();
// 將 audio_io_handle_t 綁定 RecordThread.
mRecordThreads.add(id, thread);
record = audioFlinger->openRecord
// 從 mRecordThreads 裏面根據 input(id) 獲取一個 RecordThread.
thread = checkRecordThread_l(input);
// 創建一個 RecordTrack.
recordTrack = thread->createRecordTrack_l();
new RecordTrack()
// 將 recordTrack 綁定 RecordHandle
recordHandle = new RecordHandle(recordTrack);
return recordHandle;
mAudioRecord = record;
mRecord.start() 時
start
mAudioRecord->start(event, triggerSession);
RecordHandle->start()
RecordThread::start(recordTrack)
// 在此處加入 mActiveTracks 數組
mActiveTracks.add(recordTrack);
// 置位 recordTrack != TrackBase::IDLE 狀態.
recordTrack->mState = TrackBase::STARTING_2;
// 釋放 RecordThread::threadLoop() 的鎖.
mWaitWorkCV.broadcast();
mRecord.read() 時
待填充
mRecord.stop() 時
// 停止只是將 recordTrack = TrackBase::PAUSING 的狀態
// 不在 memcpy 底層獲得到的 buffer 而已.
stop
mRecordTrack->stop();
AudioSystem::stopInput(recordThread->id());
mRecord 對象被釋放時
// 當 RecordHandle 析構時, 也就是持有它的 AudioRecord 對象析構時才調用.
~RecordHandle
RecordTrack::destroy
AudioSystem::releaseInput
mpClientInterface->closeInput
AudioFlinger::closeInput
thread = checkRecordThread_l(input);
mRecordThreads.removeItem(input);
in->hwDev()->close_input_stream(in->hwDev(), in->stream);
recordThread->destroyTrack_l
// 僅僅是指移除了在 mTracks 裏面的 recordTrack. 沒有移除 mActiveTracks 裏面的 recordTrack.
mTracks.remove(track);
待整理流程
// 從 APP 錄音角度分析
AudioRecord.java
create/set(設備(BT, DEFUALT), 通道數, 採樣速率, 數據深度)
start
AudioRecord.cpp
1. set: new AudioRecordThread 讀 RecordTrack.
2. openRecord_l:
// 用於標誌從哪個聲卡c / p設備獲取.
audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
AudioPolicy->openInput -> 調用到了 AudioFlinger -> openInput()
audioFlinger->openRecord
thread->createRecordTrack_l
3. start
RecordHandle->start
mRecordTrack->start
recordThread->start
AudioFlinger //
openInput()
AudioStreamIn *input = stream_in.
new RecordThread
Threads // 線程
RecordThreads // 錄音線程(單例), 在第一次被 sp -> run() -> 由於錄音狀態是 PAUSING. 休眠.
createRecordTrack_l
RecordTrack. app 讀 buffer. 採集.
start
AudioSystem::startInput(mId);
mpClientInterface->setParameters(input, param.toString());
mActiveTrack->RESUMING
if (mActiveTrack == RESUMING)
threadLoop往下走了.
1. 讀一次.
2. mInput->stream->read(mInput->stream, readInto, mBufferSize);
AudioPolicy //向下管理so庫. 向上提供 Read / Write / set 接口.
AudioHAL // ALSA PCM_XXX 操作聲卡
set
read
open_l -> pcm_open().
pcm_read()
Dev // 驅動
// 從系統啓動角度
libmeida.so
init.rc media
AudioFlinger 首先啓動.
1. 初始化 so 庫列表.
mAudioHwDevs = dopen(xxx.so).
AudioPolicy
getProfile 解析 audio_policy.xml
mAudioHwDevs
與之相關
Android Audio - 支持多應用同時錄音_Android4.4修改方法
Android Audio - 支持多應用同時錄音_Android5.1 & Android6.0 修改方法
Android Audio - 支持多應用同時錄音_Android8.1修改方法