音視訊程式設計基本概念梳理
本文梳理了音視訊程式設計開發者需要了解的基本概念
訪問
我的部落格
瞭解更多
前言
本文梳理了音視訊程式設計開發者需要了解的基本概念,當然,有的人一開始看著乾巴巴的理論,感到睏乏,卻是一個喜歡動手實踐的開發者,那麼先實踐 ffmpeg的C語言程式設計入門 ,然後再來看理論篇更好了。
音訊的基本概念
音訊技術是為了取樣、儲存、播放"聲學現象"而存在的,詳細一點,是模擬訊號與數字訊號轉換;在人耳可聽的時域與頻域的範圍內,進行壓縮、轉碼,在資料大小與音質的取捨中儲存音訊檔案;播放時解讀檔案的音訊引數,進行轉碼。
聲學的物理知識
聲音是有物體振動而產生的,是一種壓力波。
聲音的振動會引起空氣有節奏的振動,是周圍的空氣發生疏密變化,形成疏密相間的縱波
通過上一句話,容易理解聲波三要素:
- 頻率,音階的高低,頻率越高,波長越短,而低頻聲音的波長較長,更容易繞過阻礙物。
- 振幅,響度,使用分貝描述響度的大小,
- 波形,音色
人耳的生物知識
回聲的區分:兩道聲音傳入人耳的時差小於 80 毫秒,人耳便無法區分這兩道聲音。
人耳可接收的頻率範圍:20Hz~20kHz
聲音的數字化
數字音訊的三個要素: 取樣、量化、編碼
- 取樣,在時間軸上對訊號進行數字化,根據取樣定理(奈奎斯特定理),按比聲音最高頻率高兩倍以上的頻率對聲音進行取樣(AD轉換),根據人耳可聽頻率,高質量的取樣頻率為 44.1kHz,即一秒取樣44100次
- 量化,在幅度軸上對訊號進行數字化,例如使用 short (16 bit) 儲存空間表示一個聲音取樣,共有 2^16 個可能取值,於是模擬的音訊訊號在幅度上分為了 65536 層
- 編碼,按照一定的格式記錄取樣和量化後的數字資料,比如順序儲存,壓縮儲存等
音訊檔案的原始格式,PCM, WAV
PCM + WAV header (44 bit) = WAV
PCM 全稱 Pulse Code Modulation,脈衝編碼調製,是音訊的裸資料,PCM 檔案缺少描述引數,一般需要 WAV header 來描述,如:量化格式(sampleFormat)、取樣率(sampleRate)、聲道數(channel)。
描述音訊檔案的大小、質量
- 位元率,對於聲音格式,一個常見的描述大小的概念是,資料位元率,描述一秒時間內的位元數目,可以作為衡量音訊質量的依據。
- 取樣格式,比如用16 bit,即 4 位元組來描述一個取樣,儲存空間越大,聲音在頻域上描述越精細。
- 取樣率,比如 48kHz,取樣率越大,聲音在時域上描述越精細。
計算位元率的公式: 取樣率 × 取樣格式 × 聲道數 = 位元率
聲音的大小單位——分貝
什麼是分貝,為什麼使用分貝作單位?
若以聲壓值來表示聲音大小,變化範圍太大,可以達到六個數量級以上,另外,人耳對聲音訊號的強弱刺激的反應不是線性的,而是呈對數比例關係,於是採用分貝的概念:
分貝是指兩個物理量之比除以 10 為底的對數並乘以 10,中文描述有點繞,看簡潔的公式
N = 10 * lg(A1/A0)
分貝符號:dB, 它是無量綱的,式中 A0 是基準量,A1是"被量度"量
音訊的編碼
CD 音質的格式是 WAV,完整地儲存取樣資料。但是儲存空間較大,計算一下,CD的音質引數:量化格式16 bit,取樣率 44100,聲道數 2,計算一秒的位元數:
44100 16 2 = 1378.125 kbps (千位元每秒) = 176400 位元組每秒
一分鐘的 CD 音質的儲存空間約為 10.09 MB。儲存空間太大,不適合在 4G 以下的網路中線上播放音訊。
在實際應用中,需要對資料進行壓縮,有效的壓縮方法是從兩個維度上進行壓縮,分別是頻域與時域。
提供給人類播放的音訊,只需儲存人耳聽覺範圍內的訊號,於是音訊壓縮編碼的原理實際上是壓縮掉冗餘訊號,冗餘訊號包括人耳聽覺範圍之外的音訊訊號以及被掩蔽掉的音訊訊號等,被掩蔽掉的音訊訊號主要是因為人耳的掩蔽效應,主要表現為頻域掩蔽效應與時域掩蔽效應,無論是時域上還是頻域上,被掩蔽掉的聲音訊號都被認為是冗餘資訊,不進行編碼處理。
介紹常見的音訊格式:
- MP3,具有不錯的壓縮比,MP3其中一種實現編碼格式 LAME 是中高位元速率的,聽感接近源 WAV 檔案。MP3適用於在高位元率下有相容要求的音樂欣賞。
- ACC,新一代音訊有失真壓縮技術,在小於 128 Kbit/s的位元速率下表現優異,多用於視訊中音訊軌的編碼。
- Ogg,開源免費,在各種位元速率下都有比較優秀的表現,表現優於 MP3,缺點是相容性不夠好,不支援流媒體特性,適用於語音聊天的音訊訊息場景。
視訊的基本概念
表示方式
常見兩種表示方式為: RGB, YUV
RGB 概念
RGB的概念,很多人都瞭解,三種原色來描述一個畫素點,還有 RGBA 格式,A 是透明度。
畫素的取值範圍有幾種:
- 浮點數,取值範圍 0.0 ~ 1.0,例如 OpenGL ES
- 整數,子畫素的取值範圍 0~255,或 00 ~ FF, 這是計算機上的 8 bit, RGBA 四個子畫素即佔用 32 bit,即 4 個位元組,這是 RGBA_8888,也有特別的表示方法,比如安卓平臺上的 RGB_565,16 bit 表示一個畫素,R=5 bit, G=6 bit, B=5 bit
一張圖片的裸資料是 bitmap,記憶體很大,也浪費空間,於是有壓縮演算法:
JPEG 是靜態影象壓縮標準,有良好的壓縮效能,然而,對於視訊來說還不夠,視訊還需要在時域上進行壓縮,後面講到。
YUV 概念
如果你未理解過 YUV 概念,來看這一張熟悉的圖片:
90年代彩色電視或黑白電視,測試畫面使用的圖片,圖片的色塊直接地反映了 YUV 的色彩空間,再來看下一張埠圖:
以上埠中,老式的黑白電視使用 Y C 埠,彩色電視採用 YUV 埠,以前在家接過電視盒、DVD埠的童鞋是不是很熟悉。其中 Y 代表明亮度/灰階值 (Luma);U 和 V 代表色度(chroma),指定畫素的顏色。
概括而言,YUV 主要應用於優化彩色視訊訊號的傳輸,使其向後相容老式黑白電視。
與直觀的 RGB 不同,YUV 的表示方式是差分的:
- Y 亮度,是 RGB 訊號的特定部分疊加到一起的值
- U V 色度,分別是色調 Cr 與飽和度 Cb,Cr 表示 RGB 紅色部分與亮度值的差異,Cb表示 RGB 藍色部分與亮度值的差異
看下一張圖片反映 YUV 與 RGB 的差異
YUV 最常見的取樣格式是 4:2:0,其中 0 不代表其中一個輸入為0,而是交錯的 4:2:0 與 4:0:2,左右兩列的色度是共享的,如下圖片
不考慮時域壓縮,YUV的一幀圖片比RGB的一幀圖片的位元量化要大,比如 RGB 用 8 bit 表示一個畫素,YUV 需要用 12 bit 表示一個畫素。
瞭解 YUV 的概念,對於音視訊程式設計中的客戶端開發,是必要的。在IOS或安卓,攝像頭採集到的裸資料格式是 YUV,然後需要呼叫相關API使其轉換成 RGB 格式,詳細暫且打住。
視訊編碼
音視訊的編碼通常是去除冗餘資訊,從而實現資料量的壓縮。對於視訊,可以從空間與時間維度上進行壓縮,而且,視訊資料有極強的相關性,有著大量的冗餘資訊。
從時間維度上去除冗餘資訊的方法:
- 運動補償,通過先前的區域性影象來預測、補償當前的區域性影象
- 運動表示,不同區域的影象需要使用不同的運動向量來描述運動資訊
- 運動估計,從視訊序列中抽取運動資訊的一整套技術
從空間維度上,運用幀內編碼技術,例如,靜態影象編碼標準 JPEG,在視訊上,ISO 制定了 Motion JPEG,即 MPEG,MPEG演算法是適用於動態視訊的壓縮演算法,除了對單幅影象進行編碼外,還利用影象序列中相關原則去除冗餘,大大提高壓縮比。MPEG版本一直在不斷更新,如:Mpeg1(用於VCD),Mpeg2(用於DVD),Mpeg4 AVC(流媒體的主力演算法)
獨立於 ISO 制定的 MPEG 視訊壓縮標準,ITU-T制定了 H.261~H.264一系列視訊標準,其中H.264吸取了眾多標準的經驗,採取簡約設計,比起 Mpeg4更容易推廣。
H.264使用了新的壓縮技術,例如:多參考幀,多塊型別,整數變換,幀內預測等,使用了更精細的分畫素運動向量(1/4,1/8)和新一代的環路濾波器。
編碼的細節概念
IPB 幀,是最常見的幀間編碼技術型別,在GOP(Group Of Pictures)中有以下三種幀:
- I 幀,intra picture,幀內編碼幀,I幀通常是每個 GOP 的第一個幀,進過適度壓縮,作為隨機訪問的參考點,可以當做靜態影象。I幀壓縮可以去掉視訊的空間冗餘資訊。
- P 幀,predictive picture,前向預測編碼幀,通過將影象序列中前面已編碼幀的時間冗餘資訊充分去除壓縮傳播數量的編碼影象,簡稱預測幀。
- B 幀,bi-directional interpolated prediction frame,雙向預測內插編碼幀,與P幀不同的是,它同時參考影象序列前面與後面的已編碼幀的時間冗餘資訊。
gop_size,代表兩個 I 幀之間的幀數目。理論上,在儲存空間固定的條件下,gop_size越大,畫面質量越好,因為可以留下更多的空間儲存畫質更高的 I 幀。
壓縮比,一般而言,I幀的壓縮率是 7 (與 JPG 差不多),P幀是20,B幀是50
PTS 與DTS
- DTS, decode timestamp,資料壓縮包 packet 的解碼時間
- PTS, presentation timestamp,視訊幀 frame 的展示時間
一般來說,如果視訊的各幀編碼是按輸入順序依次進行的,那麼解碼時間與顯示時間應該一致,然而事實上,大多數編解碼標準(如H.264),編碼順序與顯示順序並不一致,於是需要 PTS 與 DTS 兩種時間戳。
Tip: 在 FFmpeg 工具中,AVPacket結構體是描述解碼前或編碼後的壓縮資料,AVFrame是描述視訊的一幀影象,而 DTS 是 AVPacket 結構體的一個成員屬性,PTS 是 AVFrame 的一個成員屬性。另外,FFmpeg 中還有一個屬性,基準時間 time_base ,即每 1 pts 的時間間隔,單位秒
Reference
本文的文字摘抄於《音視訊開發進階指南》,即是我閱讀後將知識內化的再輸出
圖片均來自網際網路