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修改方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章