其實老早就想寫一些關(guān)于音視頻學(xué)習(xí)的文章了,但由于各方面的原因遲遲都沒有開始。一個方面是因為筆者寫文章都是成系統(tǒng)的,音視頻需要大家有一定的 c/c++ 基礎(chǔ);還有一個方面是因為之前經(jīng)驗不足,這一塊涉及到的細(xì)節(jié)也比較多。我自己學(xué)習(xí)時看過大量的文章和資料,這里推薦 雷霄驊的專欄 ,雖然文章的更新永遠(yuǎn)停在了那一刻,但其無私分享的精神值得我們每一個開發(fā)者學(xué)習(xí)。音視頻這系列文章我們打算從基礎(chǔ)開始學(xué),然后結(jié)合移動端 NDK 來開發(fā)。因此如果你已經(jīng)是音視頻開發(fā)的老司機(jī),那么本文可能不太適合你,其次如果之前沒了解過 NDK 開發(fā),學(xué)習(xí)起來也可能會有些難度。
目前市面上我們所熟悉的音視頻開發(fā)大致有:視頻播放器、短視頻、視音頻直播 等等,他們之間有很多的共性像音視頻編解碼、視音頻同步等,因此我們首先來看下這些共性內(nèi)容。假設(shè)我們現(xiàn)在要播放一個本地視頻,需要經(jīng)過哪些步驟呢?大家不妨自己先思考一下,當(dāng)然這里不是說集成 ijkplayer 或者 ExoPlayer 等開源庫,目前只給一個 SurfaceView 和一個視頻文件,在此基礎(chǔ)上實現(xiàn)一個視頻播放。我們先來看一個簡單的流程圖:
上面這張圖我們務(wù)必得要記在心里,想必理解這么一張圖對于大家來說應(yīng)該 soEasy 。很多東西都是一通百通的,之前就講過怎么解析一張圖片,我們再渙散一下思維,假如去解析加載一個 dex/class 文件呢?基于上面這個圖,我們再來看一些具體的細(xì)節(jié):
解封裝
將輸入的封裝格式的數(shù)據(jù)(文件),分離成為音頻流壓縮編碼數(shù)據(jù)和視頻流壓縮編碼數(shù)據(jù)。封裝格式種類很多,具體可以參考下面這張表,它的作用就是將已經(jīng)壓縮編碼的視頻數(shù)據(jù)和音頻數(shù)據(jù)按照一定的格式放到一起。例如,F(xiàn)LV 格式的數(shù)據(jù),經(jīng)過解封裝操作后,輸出 H.264 編碼的視頻碼流和 AAC 編碼的音頻碼流。
名稱 | 推出機(jī)構(gòu) | 支持的視頻編碼 | 支持的音頻編碼 |
---|---|---|---|
AVI | Microsoft Inc. | 幾乎所有格式 | 幾乎所有格式 |
MP4 | MPEG | MPEG-2, MPEG-4, H.264, H.263等 | AAC, MPEG-1 Layers I, II, III, AC-3等 |
TS | MPEG | MPEG-1, MPEG-2, MPEG-4, H.264 | MPEG-1 Layers I, II, III, AAC, |
FLV | Adobe Inc. | Sorenson, VP6, H.264 | MP3, ADPCM, Linear PCM, AAC等 |
MKV | CoreCodec Inc. | 幾乎所有格式 | 幾乎所有格式 |
RMVB | Real Networks Inc. | RealVideo 8, 9, 10 | AAC, Cook Codec, RealAudio Lossless |
視音頻解碼
將視頻/音頻壓縮編碼數(shù)據(jù),解碼成為非壓縮的視頻/音頻原始數(shù)據(jù)。音頻的壓縮編碼標(biāo)準(zhǔn)包含 AAC,MP3,AC-3 等等,視頻的壓縮編碼標(biāo)準(zhǔn)則包含 H.264,MPEG2,VC-1 等等。解碼是整個系統(tǒng)中最重要也是最復(fù)雜的一個環(huán)節(jié)。通過解碼,壓縮編碼的視頻數(shù)據(jù)輸出成為非壓縮的顏色數(shù)據(jù),例如 YUV420P,RGB 等等;壓縮編碼的音頻數(shù)據(jù)輸出成為非壓縮的音頻抽樣數(shù)據(jù),例如 PCM 數(shù)據(jù)。
視頻編碼
視頻編碼的主要作用是將視頻像素數(shù)據(jù)(RGB,YUV等)壓縮成為視頻碼流,從而降低視頻的數(shù)據(jù)量。如果視頻不經(jīng)過壓縮編碼的話,體積通常是非常大的,一部電影可能就要上百G的空間。視頻編碼是視音頻技術(shù)中最重要的技術(shù)之一。視頻碼流的數(shù)據(jù)量占了視音頻總數(shù)據(jù)量的絕大部分。高效率的視頻編碼在同等的碼率下,可以獲得更高的視頻質(zhì)量。主要的編碼方式有 HEVC(H.265),H.264,MPEG4,MPEG2,VP9,VP8,VC-1 等等。
音頻編碼
音頻編碼的主要作用是將音頻采樣數(shù)據(jù)(PCM等)壓縮成為音頻碼流,從而降低音頻的數(shù)據(jù)量。音頻編碼也是互聯(lián)網(wǎng)視音頻技術(shù)中一個重要的技術(shù)。但是一般情況下音頻的數(shù)據(jù)量要遠(yuǎn)小于視頻的數(shù)據(jù)量,因而即使使用稍微落后的音頻編碼標(biāo)準(zhǔn),而導(dǎo)致音頻數(shù)據(jù)量有所增加,也不會對視音頻的總數(shù)據(jù)量產(chǎn)生太大的影響。高效率的音頻編碼在同等的碼率下,可以獲得更高的音質(zhì)。主要的編碼方式有 AAC,AC-3,MP3,WMA 等等。
FFmpeg
整個音視頻技術(shù)學(xué)習(xí)的核心就在協(xié)議和編解碼,其中最復(fù)雜重要的部分當(dāng)屬編解碼了,如果沒有基礎(chǔ)的話,我們可以買一些書看一下,實體書或電子書都行。如果真的只給大家一個文件和一個 SurfaceView ,第一步解封裝估計就得難倒一大部分人。因此如果是初學(xué)習(xí)音視頻技術(shù),還是建議大家基于一些第三方的開源庫來實現(xiàn)功能,等時機(jī)成熟了再去了解底層的源碼和算法。我選的是一個常用的同時也是大家比較熟悉的開源庫 FFmpeg。所以后面我們基于 FFmpeg + NDK 來開發(fā)音視頻,等有了一定的經(jīng)驗我們再去閱讀源碼學(xué)習(xí)算法。
準(zhǔn)備工作
首先我們得去編譯 FFmpeg 的 so 庫文件,而編譯 so 庫又涉及到 shell 腳本和 cmake 語法知識,所以我們又需要一個 linux 環(huán)境。我當(dāng)初在學(xué)習(xí)這些基礎(chǔ)知識時,買的是半年的云主機(jī)服務(wù),如果大家本來就是用的 linux 系統(tǒng)或 mac 系統(tǒng),那么就沒必要再去購買云主機(jī)了。考慮到 Android 底層本身也是基于 linux 內(nèi)核,趁著買了云主機(jī)的這個機(jī)會,我把 linux 內(nèi)核的基礎(chǔ)也學(xué)習(xí)了一遍。所以未來幾個月的文章和視頻,基本都是一些關(guān)于 shell 腳本,cmake 語法,linux 內(nèi)核,音視頻編解碼,音視頻通話,視頻直播 等知識。
視頻地址:https://pan.baidu.com/s/1Ib8NlaaqycmVY_FX9OmU2w
視頻密碼:6mmz