上一篇 中介紹了音視頻開發中的基礎知識,本篇介紹音頻幀、視頻幀的主要參數和分析方法以及音視頻的同步等,主要內容如下:
- 音頻幀
- 視頻幀
- PTS 與 DTS
- 音視頻同步
音頻幀#
音頻幀的概念沒有視頻幀那麼清晰,幾乎所有視頻編碼格式都可以簡單的認為一幀就是編碼後的一副圖像,而音頻幀會因編碼格式的不同而不同,如 PCM 音頻流可以直接進行播放,下面以 MPEG 音頻幀格式為例介紹音頻幀。
幀大小#
幀大小指每幀的採樣數,這個值是恆定的,具體如下:
MPEG 1 | MPEG 2 | MPEG 2.5 | |
---|---|---|---|
Layer Ⅰ | 384 | 384 | 384 |
Layer Ⅱ | 1152 | 1152 | 1152 |
Layer Ⅲ | 1152 | 576 | 576 |
幀長度#
幀長度指壓縮時每一幀的長度,包括幀頭及填充位,由於有填充和比特率變換,所以幀長度不是恆定的,這個填充位具體從幀頭中第 9 位獲取,如果是 0 則無填充位,如果是 1 則有填充位,來看下關於填充位的說明:
Padding is used to fit the bit rates exactly. For an example: 128k 44.1kHz layer II uses a lot of 418 bytes and some of 417 bytes long frames to get the exact 128k bitrate. For Layer I slot is 32 bits long, for Layer II and Layer III slot is 8 bits long.
可知,Layer Ⅰ 的填充位是 4 字節,Layer Ⅱ 和 Layer Ⅲ 的填充位是 1 字節,當讀取 MPEG 文件時必須計算該值以便找到相鄰的幀,幀長度的計算公式如下:
// Layer I(SampleSize = 384) 單位:byte
FrameLengthInBytes = SampleSize / 8 * BitRate / SampleRate + Padding * 4
FrameLengthInBytes = 48 * BitRate / SampleRate + Padding * 4
// Layer II & III(SampleSize = 1152) 單位:byte
FrameLengthInBytes = SampleSize / 8 / SampleRate + Padding
FrameLengthInBytes = 144 * BitRate / SampleRate + Padding
其中 SampleSize 表示每幀採樣數,其值是固定的,可在幀大小小節中查看,Padding 表示填充位,BitRate 表示比特率,SampleRate 表示採樣率,比特率和採樣率的值可在幀頭中獲取。
如果一個 MP3 音頻文件比特率為 320kbps、採樣率為 44.1KHz、無填充位,則該文件的幀長度為 144 x 320 / 44.1 ≈ 1044 字節。
波特率#
可以從 MPEG 音頻幀頭 12~15 位獲取波特率,單位 kbps,參考如下:
bits | V1,L1 | V1,L2 | V1,L3 | V2,L1 | V2,L2 & L3 |
---|---|---|---|---|---|
0000 | free | free | free | free | free |
0001 | 32 | 32 | 32 | 32 | 8 |
0010 | 64 | 48 | 40 | 48 | 16 |
0011 | 96 | 56 | 48 | 56 | 24 |
0100 | 128 | 64 | 56 | 64 | 32 |
0101 | 160 | 80 | 64 | 80 | 40 |
0110 | 192 | 96 | 80 | 96 | 48 |
0111 | 224 | 112 | 96 | 112 | 56 |
1000 | 256 | 128 | 112 | 128 | 64 |
1001 | 288 | 160 | 128 | 144 | 80 |
1010 | 320 | 192 | 160 | 160 | 96 |
1011 | 352 | 224 | 192 | 176 | 112 |
1100 | 384 | 256 | 224 | 192 | 128 |
1101 | 416 | 320 | 256 | 224 | 144 |
1110 | 448 | 384 | 320 | 256 | 160 |
1111 | bad | bad | bad | bad | bad |
針對表格中的說明:
- V1:MPEG Version 1
- V2:MPEG Version 2 and Version 2.5
- L1:Layer Ⅰ
- L2:Layer Ⅱ
- L3:Layer Ⅲ
MPEG 文件可能具有可變的比特率,意味著比特率會發生變化,這裡知道比特率的獲取即可。
採樣率#
可以從 MPEG 音頻幀頭 10~11 位獲取採樣率,單位 Hz,參考如下:
bits | MPEG1 | MPEG2 | MPEG2.5 |
---|---|---|---|
00 | 44100 | 22050 | 11025 |
01 | 48000 | 24000 | 12000 |
10 | 32000 | 16000 | 8000 |
11 | reserv. | reserv. | reserv. |
每幀的持續時間#
一幀持續時間計算公式如下:
// 單位 ms
FrameTime = SampleSize / SampleRate * 1000
其中 SampleSize 表示採樣數,也就是幀大小,SampleRate 表示採樣率。
如採樣率為 44.1KHz 的 MP3 音頻文件每幀的持續時間為 1152 / 44100 * 1000 ≈ 26 ms,這就是經常聽到的 mp3 每幀播放時間固定為 26ms 的由來。
視頻幀#
在視頻壓縮技術中,視頻幀採用不同的壓縮算法來減少數據量,通常只編碼圖像之間的差異之處,相同的元素信息則不必重複發送,視頻幀的不同算法一般稱之為圖片類型(picture types)或者幀類型(frame types),主要的三種圖片類型分別是 I、P 和 B,其特徵如下:
- I 幀:幀內編碼幀,通常是每個 GOP(下文介紹)的第一幀,可壓縮性最低,無需其他視頻幀即可解碼,可以說是一張完整的圖片,通常,I 幀用於隨機訪問,並用作其他圖片解碼的參考。
- P 幀:前向預測幀,表示與前一幀(I 或 P 幀)之間的差別,需要參考前面的 I 幀或 P 幀才能生成完整的圖片,相較 I 幀更具壓縮性,節省了空間,所以 P 幀也成為增量幀。
- B 幀:雙向預測編碼幀,表示與前後兩幀的差異,需要參考前面的 I 幀或 P 幀及後面的 P 幀來生成一張完成的圖片,壓縮性最大。
上面說的幀或圖片通常會分為幾個宏塊(Macroblock),宏塊是運動預測的基本單位,一個完整的圖像通常被分為幾個宏塊,如 MPEG-2 和較早期的編解碼器定義宏塊都是 8×8 像素,以宏塊為基準選擇特定的預測類型,而非整個圖像都使用相同的預測類型,具體如下:
- I 幀:只包含節點宏塊。
- P 幀:可含有節點宏區塊或預測宏區塊。
- B 幀:可含有節點、預測和前後預測宏區塊。
下面來看下 I 幀、P 幀、B 幀的示意圖如下:
在 H.264 / MPEG-4 AVC 標準中,預測類型的粒度降低到切片(Slice)級別,切片是幀的空間上不同的區域,該區域與同一幀中的任何其他區域分開進行編碼,I 切片,P 切片和 B 切片取代了 I、P 和 B 幀,這部分內容暫時了解這麼多。
前面提到了 GOP,它是 Group of pictures 的縮寫,可譯為圖片組,每個 GOP 都以 I 幀為起始點,其他為 P 幀和 B 幀,如下圖所示:
上圖中顯示的順序為:
I1、B2、B3、B4、P5、B6、B7、B8、P9、B10、B11、B12、I13
編解碼順序為:
I1、P5、B2、B3、B4、P9、B6、B7、B8、I13、B10、B11、B12
其中下標數字表示在原始幀數據中 PTS,這裡可以理解為 GOP 中的位置。
DTS 與 PTS#
- DTS (Decoding Time Stamp):解碼時間戳,表示壓縮幀的解碼時間,相當於告訴播放器什麼時候解碼這一幀的數據
- PTS (Presentation Time Stamp):顯示時間戳,表示將壓縮幀解碼後得到的原始幀的顯示時間,相當於告訴播放時什麼時候顯示這一陣的數據。
對於音頻來說,DTS 和 PTS 是相同的,對於視頻來說,由於 B 幀是雙向預測幀,這就導致 DTS 與 PTS 不同,如果每個 GOP 沒有 B 幀,則 DTS 和 PTS 相同,反之則 DTS 與 PTS 不同,舉例如下:
I | B | B | P | B | P | |
---|---|---|---|---|---|---|
顯示順序 | I1 | B2 | B3 | P4 | B5 | P6 |
編解碼順序 | I1 | P4 | B2 | B3 | P6 | B5 |
PTS | 1 | 2 | 3 | 4 | 5 | 6 |
DTS | 1 | 4 | 2 | 3 | 6 | 5 |
當接收端接收到碼流進行解碼後的幀的順序顯然不是正確的順序,需要根據 PTS 進行重新排序再顯示。
音視頻同步#
先大概介紹一下視頻播放的過程,麥克風和攝像頭採集數據後,分別通過音頻、視頻編碼,再通過復用,也就是將音視頻進行格式封裝生成媒體文件,當收到一個媒體文件,需要解復用將音視頻分開,再分別通過音頻、視頻解碼,然後音視頻獨立播放,由於播放速率的差異就會出現音視頻不同的問題,音頻和視頻播放對應的兩個指標如下:
- 音頻:採樣率
- 視頻:幀率
聲卡和顯卡一般是按照每幀數據進行播放的,所以要計算音頻和視頻每幀的播放時長,還是這樣,舉個例子:
從上文中已知採樣率為 44.1KHz 的 MP3 音頻文件的每幀持續時長為 26 ms,如果此時視頻的幀率為 30fps,則視頻幀的每幀持續時長為 1000 / 30 ≈ 33ms,如果在理想情況下能夠按照計算出的數值進行播放,則音視頻可以看做是同步的。
實際情況是因為各種原因導致音視頻不同步,如每幀解碼和渲染的時長有差別,色彩豐富的視頻幀可能就比色彩單一的視頻幀解碼渲染更慢以及計算的誤差等,音視頻同步方式主要有三種:
- 視頻同步到音頻
- 音頻同步到視頻
- 音視頻同步到外部時鐘
一般是把視頻同步到音頻時鐘,主要是因為,對於延遲以及卡頓,人的聽覺較視覺更為敏感,需盡量保持音頻正常輸出,這裡說的音視頻同步是允許一定延遲的,即延遲要在可接收的延遲範圍內,相當於一個反饋機制,當視頻慢於音頻就要加快視頻的播放速度,可以適當丟幀彌補追上音頻,如果已經有延遲減小延遲也可以,反之則減小視頻的播放速度。