前言
學(xué)習(xí)之前請容許我悼念下雷霄驊前輩,他的博客是我學(xué)習(xí)視頻編解碼資料的主要來源,雷霄驊前輩博客地址.我們主要是來學(xué)習(xí)FFmpeg和SDL,學(xué)習(xí)的第一階段我們要使用它們來做一款跨平臺的播放器,作者是從事iOS開發(fā)的,所以會將這個跨平臺播放器集成于iOS平臺,各位有什么好的建議可以在文章下方留言.FFmpeg主要是為了處理音視頻的編碼,而SDL則是為了展示畫面,至于具體的知識還是需要閱讀雷哥的博客去學(xué)習(xí).
- 視頻解碼器(FFmpeg)
主要掌握幾個常用的FFmpeg解碼的函數(shù),主要實現(xiàn)H.264->YUV的轉(zhuǎn)換
- 視頻顯示(SDL)
掌握SDL顯示視頻的函數(shù),實現(xiàn)YUV -> 設(shè)備屏幕
視頻播放器原理
-
這是雷哥的一張圖,簡單介紹了視頻播放器原理.我們?nèi)粘I钪?視頻,音頻的結(jié)尾都會有類似.MP4之類的字符,這里就是他們的封裝格式.我們拿到這個視頻文件如果想播放的話,會將它解封裝成音頻壓縮數(shù)據(jù)和視頻壓縮數(shù)據(jù),在對這兩個數(shù)據(jù)進行解碼,獲得音頻采樣數(shù)據(jù)和視頻像素數(shù)據(jù),他們分別會送到我們的聲卡和顯卡最終到達播放設(shè)備,這里需要注意的是我們需要解決聲畫同步的問題,這個我們以后再說.
封裝格式(MP4,RMVB评腺,TS,F(xiàn)LV朱浴,AVI)
- 上圖講的是比較形象的封裝格式,同時也列舉了一些封裝格式的推出機構(gòu)以及目前使用的主要領(lǐng)域.下圖舉例了兩種比較代表性的封裝格式,他們的具體區(qū)別圖上可以看出,MPEG2 - TS這種封裝格式在損壞了某個TS包時依舊可以繼續(xù)播放,而FLV若損壞了文件頭那么他將無法播放.
視頻編碼數(shù)據(jù)(H.264,MPEG2达椰,VC-1)
- 上圖主要講的幾種視頻編碼數(shù)據(jù),通俗的講視頻編碼其實就是將我們?nèi)庋劭吹降拿恳环鶊D進行壓縮,壓縮成流,當(dāng)然編碼和壓縮肯定是不能畫等號的.這些流中也有集中壓縮散發(fā)我們后面會講到,壓縮和不壓縮前后體積大概相差百倍,這就對傳輸和存儲帶來了巨大的壓力,所以我們才要對其進行視頻編碼,在我們的日常生活中H.264目前是最常見的,所以許多做視頻的公司招聘上都會要求了解FFmpeg,H.264等.下面我們主要對H.264中最常見的IPB壓縮算法來進行介紹.
IPB
視頻流中的每一張靜止的畫面其實都是一幀,在壓縮的算法中IPB算是一種比較常見的算法了.I幀是關(guān)鍵幀表示一副畫面的完整數(shù)據(jù),所以解碼的時候只需要自身就可以完成,P幀是差別幀表示當(dāng)前畫面和上一幅畫面的區(qū)別,上一幅畫面的數(shù)據(jù)IPB三種幀都有可能,他的解碼依賴于上一幀數(shù)據(jù),最終實際上還是要依賴I幀才能實現(xiàn)解碼.B幀是雙向關(guān)鍵幀,表示該畫面數(shù)據(jù)與上一幀和下一幀的區(qū)別,所以解碼的時候我們需要對他的前后幀都進行解碼,優(yōu)點是壓縮率高,但是處理起來計算機的處理負擔(dān)會比較大.
從上面的解釋看翰蠢,我們知道I和P的解碼算法比較簡單,資源占用也比較少砰碴,I只要自己完成就行了躏筏,P呢板丽,也只需要解碼器把前一個畫面緩存一下呈枉,遇到P時就使用之前緩存的畫面就好了,如果視頻流只有I和P埃碱,解碼器可以不管后面的數(shù)據(jù)猖辫,邊讀邊解碼,線性前進砚殿,大家很舒服啃憎。但網(wǎng)絡(luò)上的電影很多都采用了B幀,因為B幀記錄的是前后幀的差別似炎,比P幀能節(jié)約更多的空間辛萍,但這樣一來悯姊,文件小了,解碼器就麻煩了贩毕,因為在解碼時悯许,不僅要用之前緩存的畫面,還要知道下一個I或者P的畫面(也就是說要預(yù)讀預(yù)解碼)辉阶,而且先壕,B幀不能簡單地丟掉,因為B幀其實也包含了畫面信息谆甜,如果簡單丟掉垃僚,并用之前的畫面簡單重復(fù),就會造成畫面卡(其實就是丟幀了)规辱,并且由于網(wǎng)絡(luò)上的電影為了節(jié)約空間谆棺,往往使用相當(dāng)多的B幀,B幀用的多按摘,對不支持B幀的播放器就造成更大的困擾包券,畫面也就越卡。 一般平均來說炫贤,I的壓縮率是7(跟JPG差不多)溅固,P是20,B可以達到50兰珍,可見使用B幀能節(jié)省大量空間侍郭,節(jié)省出來的空間可以用來保存多一些I幀,這樣在相同碼率下掠河,可以提供更好的畫質(zhì)亮元。
上面這段話參考自CSDN Rachel-Zhang博主的一篇文章.
音頻編碼數(shù)據(jù)(AAC,MP3唠摹,AC-3)
- 一般音頻編碼的重要性遠不如視頻編碼重要,因為音頻數(shù)據(jù)就算不壓縮,他的體積我們也是可以接受的.音頻壓縮中最常用的AAC原始碼流他是由一個一個的ADTS frame組成的,每個ADTS的大小還不是固定的.其中每個ADTS frame之間通過syncword(同步字)進行分隔爆捞。同步字為0xFFF(二進制“111111111111”)。AAC碼流解析的步驟就是首先從碼流中搜索0x0FFF勾拉,分離出ADTS frame煮甥;然后再分析ADTS frame的首部各個字段。這就是AAC碼流解碼時的主要邏輯.
視頻像素數(shù)據(jù)(YUV420P藕赞,RGB)
- 我們生活中比較常見的像素數(shù)據(jù)主要有兩種,RGB個式和YUV格式,其中以后者的YUV420P居多.RGB格式的原理很簡單,使用RGB我們可以把一幅圖片的每個點上的顏色記錄下來,同時生活中所有的顏色都是由三原色組成的,差別為非就是三者的比例不同罷了.YUV的原理主要就是人眼對亮度敏感而對色度并不敏感,所以對色度進行了比較深的壓縮,可以看出對U和V分別壓縮到了Y的四分之一,也就是寬壓縮二分之一而長壓縮二分之一,YUV先從左上角到右下角一行行存儲了圖片的Y信息,再然后是U信息,最后才是V信息,我們播放YUV視頻時一般是無法直接播放的,因為他沒有文件頭所以我們要對視頻的一些基本信息(例如畫面寬高)進行設(shè)置才可以播放.
音頻采樣數(shù)據(jù)(PCM)
- 學(xué)習(xí)PCM前我們需要了解什么是采樣,這個在大學(xué)教材數(shù)字信號處理有講
聲波其實是一個連續(xù)的模擬信號,我們?nèi)绻朐谟嬎銠C中對他進行處理,那么必須要將他轉(zhuǎn)換為數(shù)字信號,我們對這個連續(xù)的模擬信號(類似正弦波)進行每隔一定的時間就進行取點,獲取到該點的縱坐標(biāo)值,然后將這些點用平滑的曲線連接起來,就能完成模擬信號轉(zhuǎn)數(shù)字信號,當(dāng)然我們還要對其中的噪聲等因素進行處理,這些都是后話,這個采樣的時間間隔越短我們所轉(zhuǎn)化的數(shù)字信號的還原程度就越高.采樣率我們一般根據(jù)人耳的識別頻率以及奈奎斯特定理設(shè)為44.1kHZ,PCM格式也是不包含文件頭的,所以我們直接播放時要將它的采樣率和采樣精度設(shè)置好,否則就會出問題.