成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android Audio系統(tǒng)變化說(shuō)明

移動(dòng)開(kāi)發(fā) Android
Audio系統(tǒng)的難度相對(duì)4.0, 2.3, 2.2已經(jīng)非常非常大了。99%的情況下,在你沒(méi)有看到這個(gè)NB(這不是臟話,4.1 Audio系統(tǒng)中就有一個(gè)類(lèi)叫NBAIO,籃球控不要搞錯(cuò)成NBA了,原意是Non-block Audio I/O。

先從Java層AudioTrack類(lèi)說(shuō)起

一 AudioTrack Java類(lèi)變化說(shuō)明

  • 聲 道數(shù)上,以前只有單聲道(MONO)和立體聲(STEREO),現(xiàn)在拓展到最NB八聲道(7.1 HiFi啊)。參數(shù)名為CHANNEL_OUT_7POINT1_SURROUND。看到這個(gè)參數(shù),我下巴咣當(dāng)就掉下來(lái)了。這玩意,一時(shí)半會(huì)我還弄不明白 是個(gè)什么道理。有知曉的屌絲碼農(nóng)們不妨告訴大家。 當(dāng)然,最終的輸出還是雙聲道。多聲道(大于2)的時(shí)候會(huì)使用downmixer處理(下變換處理,同學(xué)們可搜索之)
  • 其他的變化也有,但不大了。我這里先挑一些吸引眼球的。BTW,放心,不會(huì)像那個(gè)瀧澤蘿拉首秀片子一樣只讓大家看見(jiàn)大鼻孔的。

二 AudioTrack JNI層變化說(shuō)明

這一層包括JNI層和AudioTrack本身

  • JNI層變化不大。
  • Audio Native核心代碼移到了framework/av下。對(duì),你沒(méi)看錯(cuò)。真的是av。這就是JB Audio一個(gè)比較大的變化。Audio Native核心代碼全部移到了frameworks/AV目錄下。
  • AudioTrack 增加了一個(gè)變量,用于控制使用它的進(jìn)程的調(diào)度優(yōu)先級(jí)(前文說(shuō)錯(cuò)了,這里確實(shí)設(shè)置的是nicer值)。如果處于播放狀態(tài)的話,將設(shè)置進(jìn)程調(diào)度優(yōu)先級(jí)為 ANDROID_PRIORITY_AUDIO。就像你們看到馬賽克時(shí)一定會(huì)嘟喃一樣。我這里也要特別啰嗦幾句。在單核CPU的情況下,設(shè)置優(yōu)先級(jí)是比較 愚蠢的(ANDROID_PRIORITY_AUDIO的值為-16,優(yōu)先級(jí)極高,單核設(shè)置個(gè)這么高的怪物,不知道其他app還怎么玩。如果你不知道我在 說(shuō)什么,先看看這篇文章吧,http://blog.csdn.net/innost/article/details/6940136)。 但現(xiàn)在2核,4核已經(jīng)比較常見(jiàn)了,這里就可以來(lái)玩玩調(diào)度方面的事情。對(duì)屌絲碼農(nóng)的真正考驗(yàn)是:多核并行編程,linux os的原理,需要各位屌絲同學(xué)努力掌握。Audio已經(jīng)不那么能輕易被你們?nèi)我怩遘k了。另外,低端手機(jī),求求你們別移植4.1了,這個(gè)真的不是低端能玩 的。
  • AudioTrack升級(jí)為父親了。JB為它定義了一個(gè)莫名其妙的的TimedAudioTrack子類(lèi)。這個(gè)類(lèi)在編解碼的 aah_rtp(我現(xiàn)在還不知道aah是什么)里邊用到了。從注釋上看,該類(lèi)是一個(gè)帶時(shí)間戳(有時(shí)間戳,就可以做同步了)的音頻輸出接口。詳細(xì)理解的話, 就需要結(jié)合具體應(yīng)用場(chǎng)景去分析了(主要是rtp這一塊)。搞編解碼的同學(xué)們,抓緊了!
  • 另外一個(gè)超級(jí)復(fù)雜的變化,是Audio定義了幾 個(gè)輸出flag(見(jiàn)audio.h的audio_output_flags_t枚舉定義)。根據(jù)注釋?zhuān)撝涤袃蓚€(gè)作用,一個(gè)是AT的使用者可以指明自己想 使用怎樣的outputDevice。另外一個(gè)是設(shè)備廠商可以通過(guò)它聲明自己支持的輸出設(shè)備(看來(lái),設(shè)備初始化的時(shí)候,又增添了參數(shù)讀取和配置這方面的工 作)。不過(guò),從該枚舉的定義來(lái)看,我還看不出它和硬件有什么關(guān)系。它定義的值如下:

typedef enum {

AUDIO_OUTPUT_FLAG_NONE = 0x0, // no attributes

AUDIO_OUTPUT_FLAG_DIRECT = 0x1, // this output directly connects a track

// to one output stream: no software mixer

AUDIO_OUTPUT_FLAG_PRIMARY = 0x2, // this output is the primary output of

// the device. It is unique and must be

// present. It is opened by default and

// receives routing, audio mode and volume

// controls related to voice calls.

AUDIO_OUTPUT_FLAG_FAST = 0x4, // output supports "fast tracks", 《==什么叫fast track?太難理解了!目前,java層的audiotrack只會(huì)使用第一個(gè)標(biāo)志。

// defined elsewhere

AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8 // use deep audio buffers 《==deep buffer是個(gè)什么玩意?這個(gè)馬賽克是不是太大了點(diǎn)?現(xiàn)在完全看不清楚啊??!

} audio_output_flags_t;

  • AudioTrack其他變化不大。AudioTrack.cpp總共才1600多行,so easy!

OK,上面有好幾個(gè)馬賽克,平常看看日本大片的時(shí)候也就擼過(guò)去了,但分析Audio可不行。把去馬賽克的希望寄托在下一步AudioFlinger的分析上吧!

三 AudioFlinger變化說(shuō)明

我們將根據(jù)AF工作的主要流程來(lái)介紹下變化情況:

  • AF創(chuàng)建,包括其onFirstRef函數(shù)
  • openOutput函數(shù)及MixerThread對(duì)象的創(chuàng)建
  • AudioTrack調(diào)用createTrack函數(shù)
  • AudioTrack調(diào)用start函數(shù)
  • AF混音,然后輸出

3.1 AF創(chuàng)建和onFirstRef

恩,沒(méi)什么太大變化。有三個(gè)點(diǎn):

  • 現(xiàn)在對(duì)Primary設(shè)備的音量有了更為細(xì)致的控制,例如有些設(shè)備能設(shè)音量,有些不能設(shè)置音量,所以定義了一個(gè)master_volume_support(AudioFlinger.h)枚舉,用來(lái)判斷Primary設(shè)備的音量控制能力。
  • 以 前播放過(guò)程的standby時(shí)間(就是為了節(jié)電而用)是寫(xiě)死的,現(xiàn)在可由ro.audio.flinger_standbytime_ms控制,如果沒(méi)有 這個(gè)屬性,則默認(rèn)是3秒。AF還增加了其他變量控制,例如有一個(gè)gScreenState變量,用來(lái)表示屏幕是開(kāi)還是關(guān)。可通過(guò) AudioSystem::setParameters來(lái)控制。另外還定義了一個(gè)和藍(lán)牙SCO相關(guān)的mBtNrecIsOff變量,是用于控制藍(lán)牙 SCO(錄音時(shí)用,藍(lán)牙上的一個(gè)專(zhuān)業(yè)術(shù)語(yǔ)叫,NREC。不知道是什么,用懂的人告訴我一下)時(shí)禁止AEC和NS特效的。請(qǐng)參考 AudioParameter.cpp

3.2 openOutput函數(shù)

openOutput 函數(shù)比較關(guān)鍵,其中會(huì)見(jiàn)到以前的老朋友MixerThread,AudioStreamOutput等。整個(gè)流程包括加載Audio相關(guān)的硬件so。這部 分工作在4.0的時(shí)候就有了,談不上太多的變化。但物是人非,老朋友已經(jīng)發(fā)生巨大變化了。先來(lái)看MixerThread家族。

 

圖1 PlaybackThread家族

圖1稍加解釋?zhuān)?/p>

  • ThreadBase 從Thread派生,所以它會(huì)運(yùn)行在一個(gè)單獨(dú)的線程中(啰嗦一句,線程和對(duì)象其實(shí)沒(méi)有關(guān)系的,不懂多線程編程的碼農(nóng)們請(qǐng)務(wù)必認(rèn)真學(xué)習(xí)多線程)。它定義了一 個(gè)枚舉type_t,用來(lái)表示子類(lèi)的類(lèi)型,這幾個(gè)類(lèi)型包括MIXER,DIRECT,RECORD,DUPLICATING等。這個(gè)應(yīng)該比較好懂吧?
  • ThreadBase的內(nèi)部類(lèi)TrackBase從ExtendedAudioBufferProvider派生,這個(gè)應(yīng)該是新增加的。TrackBase嘛,大家把它理解成一個(gè)Buffer Container就好了。

  • ThreadBase 的內(nèi)部類(lèi)PMDeathRecipient用來(lái)監(jiān)聽(tīng)PowerManagerService的死亡消息。這個(gè)設(shè)計(jì)有點(diǎn)搞,因?yàn)镻MS運(yùn)行在 SystemService中,只有SS掛了,PMS才會(huì)掛。而SS掛了,mediaserver也會(huì)被init.rc的規(guī)則給弄死,所以 AudioFlinger也會(huì)死。既然大家都一起死,速度很快。故,設(shè)置這個(gè)PMDeathRecipient有何大的意義呢?

再來(lái)看ThreadBase的一個(gè)重要子類(lèi)PlaybackThread,這個(gè)類(lèi)應(yīng)該是做過(guò)大整容了。

  • 其定義了一個(gè)枚舉mixer_state,用來(lái)反映當(dāng)前混音工作的狀態(tài),有MIXER_IDLE,MIXER_READY和MIXER_ENABLED

  • 定義了幾個(gè)虛函數(shù),需要子類(lèi)實(shí)現(xiàn),包括threadLoop_mix,prepareTracks_l等。這幾個(gè)函數(shù)的抽象工作做得還是可以。但變化之大讓人防不勝防啊。

  • Track類(lèi)增加了從VolumeProvider派生,這個(gè)VP是用來(lái)控制音量的。根據(jù)前面的介紹,在JB中,音量管理比以前來(lái)得細(xì)致

  • 新增定義了TimedTrack。這個(gè)類(lèi)的作用和前面提到的rtp aah有關(guān)。等同學(xué)們學(xué)完本篇,即可開(kāi)展相應(yīng)研究,打響殲滅戰(zhàn)!

接下來(lái)看圖2。

 

圖2 MixerThread和它的弟兄們

圖2,簡(jiǎn)單介紹一下:

  • MixerThread從PlaybackThread派生,這個(gè)關(guān)系至始至終不會(huì)變化,相信以后也不會(huì)。

  • MT最大的變化是其中幾個(gè)重要的成員變量。大家肯定認(rèn)識(shí)其中的AudioMixer,它是用來(lái)混音的。

  • 新 增一個(gè)Soaker對(duì)象(由編譯宏控制),它是一個(gè)線程。這個(gè)單詞的前綴soak在webster詞典(相信經(jīng)歷過(guò),那些年,我們一起GRE的日子 的人知道什么是webster)中最貼切的一條解釋是to cause to pay an exorbitant amount。還是不很明白是干嘛的?再一看代碼。原來(lái),soaker就是一個(gè)專(zhuān)職玩弄CPU的線程。它的工作就是不斷得做運(yùn)算,拉高CPU使用率。它的 存在應(yīng)該是為了測(cè)試新AF框架在多核CPU上的效率等等等的問(wèn)題。所以,低端智能機(jī)們,你們不要玩JB了。

  • 另外一條證明低端智能機(jī)不能隨便玩JB的鐵證就是:我們看到MT中新增了一個(gè)FastMixer,它也是一個(gè)線程。明白了?在JB中,多核智能機(jī)上,混音工作可以放到FastMixer所在的線程來(lái)做,當(dāng)然速度,效率會(huì)高了。

  • FastMixer 工作流程比較復(fù)雜,又牽扯到多線程同步。所以,這里定義了一個(gè)FastMixerStateQueue,它由typedef StateQueue<FastMixerState>得到。首先它是一個(gè)StateQueue(簡(jiǎn)單把它當(dāng)做數(shù)組吧)。其數(shù)組元素的類(lèi)型為 FastMixerState。一個(gè)StateQueue通過(guò)mStats變量保存4個(gè)FasetMixerState成員。

  • FasetMixerState類(lèi)似狀態(tài)機(jī),有一個(gè)enum Command,用來(lái)控制狀態(tài)的。FastMixerState中含有一個(gè)八元組的FastTracks數(shù)組。FastTrack是用來(lái)完成FastMixer的一個(gè)功能類(lèi)。

  • 每個(gè)FastTrack都有一個(gè)mBufferProvider,該成員類(lèi)型為SourceAudioBufferProvider。

以上的內(nèi)容已經(jīng)比較復(fù)雜了,下面來(lái)介紹下MixerThread對(duì)象創(chuàng)建中碰到的其他內(nèi)容:

#p#

3.3 MixerThread創(chuàng)建

通 過(guò)圖1和圖2,應(yīng)該對(duì)AF的幾個(gè)主要成員有了認(rèn)識(shí)。可惜啊,上面MixerThread中還有一個(gè)mOutputSink成員,沒(méi)看到吧?它就和我們前面 提到的NBAIO(Non-block Audio I/O )有重大關(guān)系。NBAIO的存在,是為了想實(shí)現(xiàn)非阻塞的音頻輸入輸出操作。下面是這個(gè)類(lèi)的注釋?zhuān)?/p>

NBAIO注釋?zhuān)?/p>

// This header file has the abstract interfaces only. Concrete implementation classes are declared

// elsewhere. Implementations _should_ be non-blocking for all methods, especially read() and

// write(), but this is not enforced. In general, implementations do not need to be multi-thread

// safe, and any exceptions are noted in the particular implementation.

NBAIO只是定義了一個(gè)接口,需要去實(shí)現(xiàn)具體的實(shí)現(xiàn)類(lèi)。當(dāng)然,它要求read/write函數(shù)是非阻塞的,真實(shí)實(shí)現(xiàn)到底是不是阻塞,由實(shí)現(xiàn)者去控制。

個(gè)人感覺(jué)這部分框架還沒(méi)有完全成熟,但NBIO的引入,需要同學(xué)們小心,相對(duì)而言,難度也比較大。下面我們通過(guò)圖3來(lái)看看NBAIO的一些內(nèi)容。

 

圖3 NBAIO相關(guān)內(nèi)容

圖3解釋如下:

  • NBAIO 包括三個(gè)主要類(lèi),一個(gè)是NBAIO_Port,代表I/O端點(diǎn),其中定義了一個(gè)negotiate函數(shù),用于調(diào)用者和I/O端點(diǎn)進(jìn)行參數(shù)協(xié)調(diào)。注意,并不 是為I/O端點(diǎn)設(shè)置參數(shù)。因?yàn)镮/O端點(diǎn)往往和硬件相關(guān),而硬件有些參數(shù)是不能像軟件一般隨意變化的。例如硬件只支持最多44.1KHZ的采樣率,而調(diào)用 者傳遞48KHz的采樣率,這直接就需要一個(gè)協(xié)商和匹配的過(guò)程。這個(gè)函數(shù)的比較難用,主要是規(guī)則較多。同學(xué)們可以參考其注釋說(shuō)明。
  • NBAIO_Sink對(duì)應(yīng)output端點(diǎn),其定義了write和writeVia函數(shù),writeVia函數(shù)需要傳遞一個(gè)回調(diào)函數(shù)via,其內(nèi)部將調(diào)用這個(gè)via函數(shù)獲取數(shù)據(jù)。類(lèi)似數(shù)據(jù)的推/拉兩種模式。

  • NBAIO_Source對(duì)應(yīng)input端點(diǎn),其定義了read和readVia函數(shù)。意義同NBAIO_Sink。

  • 定 義一個(gè)MonoPipe和MonoPipeReader。Pipe即管道,MonoPipe和LINUX中的IPC通信Pipe沒(méi)毛關(guān)系,只不過(guò)借用了這 個(gè)管道概念和思路。MonoPipe即只支持單個(gè)讀者的Pipe(AF中,它是MonoPipeReader)。這兩個(gè)Pipe,代表了Audio的 Output和Input端點(diǎn)。

  • MT中由mOutputSink指向 AudioStreamOutSink,此類(lèi)用NBAIO_Sink派生,用于普通的mixer的輸出。mPipeSink指向MonoPipe,本意是 用于FastMixer的。另外,還有一個(gè)變量mNormalSink,它將根據(jù)FastMixer的情況,指向mPipeSink,或者是 mOutputSink。這段控制的邏輯如下:

switch (kUseFastMixer) { //kUseFastMixer用于控制FastMixer的使用情況,一共4種:

case FastMixer_Never: //永遠(yuǎn)不使用FastMixer,這個(gè)選項(xiàng)用于調(diào)試,即關(guān)閉FastMixer的情況

case FastMixer_Dynamic: //根據(jù)情況,動(dòng)態(tài)使用。根據(jù)注釋?zhuān)@個(gè)功能似乎還沒(méi)有完全實(shí)現(xiàn)好

mNormalSink = mOutputSink;

break;

case FastMixer_Always: //永遠(yuǎn)使用FastMixer,調(diào)試用

mNormalSink = mPipeSink;

break;

case FastMixer_Static://靜態(tài)。默認(rèn)就是這個(gè)。但具體是否使用mPipeSink,將收到initFastMixer的控制

mNormalSink = initFastMixer ? mPipeSink : mOutputSink;

break;

}

由上所述,kUseFastMixer默認(rèn)是FastMixer_Static,但mNormalSink是否指向mPipeSink,還由initFastMixer控制。這個(gè)變量本身又有mFrameCount和

mNormalFrameCount的大小決定,只有mFrameCount小于mNormalFrameCount時(shí),initFastMixer才為真。暈了....這兩個(gè)frameCount由PlaybackThread的

readOutputParameters得到。請(qǐng)同學(xué)們自己研究這段代碼吧,就是一些簡(jiǎn)單的計(jì)算。想要搞明白的話,最好帶著參數(shù)進(jìn)去,把值都算出來(lái)。

好了,MixerThread的創(chuàng)建就分析到此,最好還是把這段代碼多研究研究。了解幾個(gè)兄弟對(duì)象是做什么的....

3.4 createTrack和start說(shuō)明

createTrack 中最大的變化就是新增了對(duì)MediaSyncEvent同步機(jī)制的處理。MediaSyncEvent的目的很簡(jiǎn)單,其Java API的解釋如下:startRecording(MediaSyncEvent) is used to start capture only when the playback on a particular audio session is complete. The audio session ID is retrieved from a player (e.g MediaPlayer, AudioTrack or ToneGenerator) by use of the getAudioSessionId() method. 簡(jiǎn)單點(diǎn)講,就是必須等上一個(gè)player工作完畢了,才能開(kāi)始下一個(gè)播放或者錄制。這個(gè)機(jī)制解決了Android長(zhǎng)久以來(lái)的聲音經(jīng)常混著出來(lái)的問(wèn)題(目前 一個(gè)惡心但卻實(shí)效的方法就是加一個(gè)sleep,以錯(cuò)開(kāi)多個(gè)player不同步的問(wèn)題。)。注意,iPhone上就沒(méi)有這個(gè)問(wèn)題。

另外,這個(gè)機(jī)制的潛在好處就是解放了做AudioPolicy AudioRoute工作的同學(xué)們,似乎(個(gè)人感覺(jué)是可以解決這個(gè)問(wèn)題的)可以不用再去琢磨到底sleep多少時(shí)間,在哪加sleep的問(wèn)題了

在AF中,MediaSyncEvent機(jī)制的代表是SyncEvent。大家自己看看就好。

start函數(shù)的變化不大,其中加了對(duì)SyncEvent的處理。

另外,createTrack中還涉及到FastMixer和TimedTrack處理。核心在PlaybackThread的createTrack_l和Track構(gòu)造函數(shù)中。尤其是和FastMixer的關(guān)系。

根據(jù)圖2,F(xiàn)M(FastMixer簡(jiǎn)寫(xiě))內(nèi)部用得數(shù)據(jù)結(jié)構(gòu)是FastTrack,而MT用得是Track,所以這里存在一一對(duì)應(yīng)的關(guān)系。FM的FastTrack是保存在數(shù)組中的,所以

使用FM的Track將通過(guò)mFastIndex來(lái)指向這個(gè)FastTrack。

現(xiàn)在搞清楚FastTrack和Track之間的關(guān)系即可,后續(xù)的數(shù)據(jù)流動(dòng)還需要詳細(xì)討論

下面來(lái)看看MixerThread的工作流程。這部分是重頭戲!

3.5 MixerThread的工作流程

這部分難的還是在FastMixer的工作原理上。不過(guò)這里提前和大家說(shuō):目前這個(gè)功能還沒(méi)有做完,代碼里邊一堆的FIXME...。但屌絲們不要happy太早了,

估計(jì)馬上、很快、必須得下個(gè)版本就好了。現(xiàn)在看看這個(gè)不成熟的東西,可以緩解以后看到成熟的東西的心理壓力。

MT是一個(gè)線程,其工作內(nèi)容主要在threadLoop中完成,而這個(gè)函數(shù)是由其基類(lèi)PlaybackThread定義的,大體變化如下:

  • PlaybackThread的threadLoop定義了整個(gè)音頻處理的大體流程,具體的細(xì)節(jié)通過(guò)幾個(gè)虛函數(shù)(如prepareTracks_l,threadLoop_mix,threadLoop_write)交給子類(lèi)去實(shí)現(xiàn)了

  • MT 變化大的首先是prepareTracks_l,首先處理的是FastMix類(lèi)型的Track,判斷標(biāo)準(zhǔn)是該Track是否設(shè)置了TRACK_FAST標(biāo) 志(爽了,目前JB中還沒(méi)有哪個(gè)地方使用了這個(gè)標(biāo)志)。這部分判斷比較復(fù)雜。首先FastMixer維護(hù)了一個(gè)狀態(tài)機(jī),另外,這個(gè)FastMixer運(yùn)行 在自己的線程里,所以線程同步是必須的。這里采用的是狀態(tài)來(lái)控制FastMixer的工作流程。由于涉及到多線程,所以音頻的 underrun,overrun狀態(tài)(不知道是什么嗎?看前面提到的參考書(shū)!)也是一個(gè)需要處理的棘手問(wèn)題。另外,一個(gè)MT是帶一個(gè) AudioMixer對(duì)象,這個(gè)對(duì)象將完成數(shù)據(jù)的混音,下變換等等超難度,數(shù)字音頻處理等方面的工作。也就是說(shuō),對(duì)于混音來(lái)說(shuō),前期的prepare工作 還是由MT線程來(lái)完成,因?yàn)檫@樣可以做到統(tǒng)一管理(有些Track并不需要使用FastMixer。但仔細(xì)一想,誰(shuí)都希望處理越快越好,在多核CPU上, 將混音工作交給多個(gè)線程處理是充分利用CPU資源的典范,這應(yīng)該是未來(lái)Android演化的趨勢(shì)。所以,我估計(jì)這個(gè)JB還沒(méi)完全長(zhǎng)大....)。對(duì) FastMixer感興趣的屌絲們,請(qǐng)務(wù)必認(rèn)真研究prepareTracks_l函數(shù)。

  • MT 下一個(gè)重要函數(shù)就是threadLoop_mix了,由于存在一個(gè)TimedTrack類(lèi),那么AudioMixer的process函數(shù)就帶上了一個(gè)時(shí) 間戳,PTS,presentation timestamp。從編解碼角度來(lái)說(shuō),還有一個(gè)DTS,Decode timestamp。這里要閑扯下PTS和DTS的區(qū)別了。DTS是解碼時(shí)間,但編碼的時(shí)候由于有可能會(huì)根據(jù)未來(lái)幀來(lái)編碼當(dāng)前幀。所以,解碼的時(shí)候會(huì)先解 未來(lái)幀,然后解出當(dāng)前幀,但是。你播放的時(shí)候可不能先播未來(lái)幀。只能老老實(shí)實(shí)得按播放順序來(lái)先播當(dāng)前幀,然后播未來(lái)幀(盡管先解出來(lái)的是未來(lái)幀)。關(guān)于 PTS/DTS,請(qǐng)屌絲們研究下IBP相關(guān)的知識(shí)吧。回到MT,這個(gè)PTS是從硬件hal對(duì)象取的,應(yīng)該是HAL內(nèi)部維護(hù)的時(shí)間戳。這個(gè)時(shí)間戳原則上會(huì)比 較準(zhǔn)確。

  • 混音完了,再做特效處理(和以前的版本差不多),然后調(diào)用 threadLoop_write。MT的threadLoop_write函數(shù)的輸出端點(diǎn)就是前面那個(gè)坑爹的mNormalSink,如果不為空,就調(diào) 用它的write函數(shù)。想著是調(diào)用NBAIO_Sink的非阻塞的write函數(shù)。根據(jù)圖2的分析,它有可能是那個(gè)MonoPipe,也有可能就是 AudioStreamOutputSink,這個(gè)sink節(jié)點(diǎn)用得就是以前的AudioStreamOutput。而MonoPipe的write其內(nèi) 部就是一個(gè)buffer。并沒(méi)有和真實(shí)的AUDIO HAL Output掛上關(guān)系。這.....咋整??(大膽假設(shè),小心求證。只能是FastMixer把這個(gè)buffer取出來(lái),然后再寫(xiě)到真實(shí)的Audio HAL中了。因?yàn)樵贛ixerThread構(gòu)造函數(shù)中,曾經(jīng)為FastTrack保存過(guò)mOutputSink,這個(gè)就是用來(lái)和 AudioStreamOutput聯(lián)系的)

另外,DulicatingThread,DirectOuptutThread沒(méi)有太大變化。

四 FastMixer工作原理簡(jiǎn)單說(shuō)明

我以前想得是:混音工作由FastMixer線程和MixerThread線程共同完成,但輸出工作依然在MixerThread做。從上面MonoPipe的分析來(lái)看,這個(gè)判斷可能不準(zhǔn)。

既 有可能是輸出工作也交給FastMixer來(lái)做,而MixerThread僅做一部分混音工作,然后把數(shù)據(jù)通過(guò)MonoPipe傳給FastMixer線 程。FastMixer線程將自己的FastTrack的混音結(jié)果和MT的混音結(jié)果再做一次混音,然后再由FastMixer輸出。

FM定義在FastMixer.cpp中,核心就是一個(gè)ThreadLoop。由于AF所有Track的預(yù)備工作由MT線程來(lái)做,所以FM的threadLoop基本上就是根據(jù)狀態(tài)來(lái)做對(duì)應(yīng)處理。

這 里的同步使用了LINUX中很底層的futex(Fast Userspace Mutex)。暈,futex是POSIX Mutex的實(shí)現(xiàn)基礎(chǔ)。不知道寫(xiě)這段代碼的人為何不直接用Mutex(估計(jì)還是嫌效率的問(wèn)題,但是 媽的,用了Mutex效率能差多少?代碼是寫(xiě)給人看的,太B4我們了...)。玩多線程玩到這種地步,佩服啊!不懂多線程編程的屌絲們,請(qǐng)仔細(xì)研究 Posix MultiThread Programming吧

  • FastMixer內(nèi)部還使用了一個(gè)AudioMixer,用于它的混音

  • 然后再write出去.....

這里是FM的簡(jiǎn)單說(shuō)明,詳細(xì)內(nèi)容,沒(méi)有拿個(gè)真機(jī)給我,我也沒(méi)法整啊....歡迎樂(lè)善好施的兄弟們刷個(gè)4.1的機(jī)器,然后借給我研究下...

(這玩意,個(gè)人感覺(jué)也不是太難。東西嘛,耐不住琢磨,總能搞透的)。兄弟們今天知道FM和MT的大體工作流程就可以了。

五 其他變化

其他變化包括:

  • 非常注重調(diào)試了,加了大量的XXXDump類(lèi)。看來(lái),Google自己開(kāi)發(fā)的時(shí)候也碰到不少問(wèn)題。簡(jiǎn)單的功能,誰(shuí)會(huì)想著去dump呢?
  • 增加AudioWatchdog類(lèi),用來(lái)監(jiān)控AF性能的,如CPU使用情況等。

六 總結(jié)

我記得在研究2.2 AF的時(shí)候,AudioFlinger才3k多行,而JB已經(jīng)有9K多行了。還沒(méi)算其他的輔助類(lèi)。從整體上看,JB變化趨勢(shì)為:

  • 要充分利用多核資源,所以FastMixer的出現(xiàn)是必然。還包括NBAIO接口。感覺(jué)對(duì)HAL編寫(xiě)會(huì)有大的挑戰(zhàn)。
  • 增加TimedTrack和SyncEvent,對(duì)于RTP或者多個(gè)player間的同步會(huì)帶來(lái)比較好的用戶體驗(yàn)。
  • 增加native層往java層通知的接口。

還有其他的東西.....今天先到這了。

責(zé)任編輯:張葉青
相關(guān)推薦

2010-02-07 13:55:39

Android圖形

2010-03-03 13:56:24

2010-02-06 15:53:55

2010-03-05 13:34:54

2010-03-02 14:04:44

Android手機(jī)系統(tǒng)

2010-03-03 14:16:53

Android操作系統(tǒng)

2010-03-05 10:31:33

Android OS

2010-02-05 17:34:37

Android 2.1

2010-02-06 16:57:43

Android操作系統(tǒng)

2010-03-03 10:55:39

2010-03-03 16:14:56

Android系統(tǒng)市場(chǎng)

2010-03-05 10:38:16

Android移動(dòng)操作

2010-03-04 17:27:04

Android 2.0

2010-03-05 15:58:11

操作系統(tǒng)Android

2010-03-02 14:46:03

Android核心系統(tǒng)

2010-03-04 15:04:35

2010-03-04 15:26:13

Android操作系統(tǒng)

2010-03-02 09:33:19

Android操作系統(tǒng)

2013-11-14 13:27:38

AndroidAudio

2015-10-28 13:29:21

音頻源碼audio
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 亚洲综合天堂 | 国产在线精品免费 | 91 在线 | 国产精品视频网 | 亚洲一区国产 | 亚洲欧美在线观看 | 狠狠操狠狠干 | 人人澡人人射 | 中文字幕视频一区二区 | 日韩1区| 国产精品高潮呻吟久久av野狼 | 精品国产99 | 久在线视频播放免费视频 | 国产免费一区二区 | 亚洲伦理自拍 | 日韩欧美一级片 | 欧美成人精品一区二区男人看 | 81精品国产乱码久久久久久 | 日本精品视频在线 | 国产成人在线一区二区 | 一级欧美一级日韩片 | 91精品中文字幕一区二区三区 | 9191av| 日韩在线电影 | 99久久婷婷 | 国产一区二区在线播放 | 欧美日韩综合精品 | 日日夜夜天天 | 激情一区 | 久久成人精品视频 | 日本不卡一区 | 成人午夜免费网站 | 一级久久久久久 | 欧美日韩一区在线观看 | 高清18麻豆 | 91 久久| 国产乱码精品一区二三赶尸艳谈 | 久操福利 | 青青草久久| 亚洲激情在线观看 | 久久久久久av |