前言
H264 視頻壓縮算法現在無疑是所有視頻壓縮技術中使用最廣泛,最流行的。隨着 x264/openh264 以及 ffmpeg 等開源庫的推出,大多數使用者無需再對H264的細節做過多的研究,這大降低了人們使用H264的成本。
但為了用好 H264,我們還是要對 H264 的基本原理弄清楚才行。今天我們就來看看H264 的基本原理。
H264概述

H264壓縮技術主要采用了以下幾種方法對視頻數據進行壓縮。包括:
- 幀內預測壓縮,解決的是空域數據冗余問題。
- 幀間預測壓縮(運動估計與補償),解決的是時域數據冗徐問題。
- 整數離散余弦變換(DCT),將空間上的相關性變為頻域上無關的數據然后進行量化。
- CABAC壓縮。
經過壓縮后的幀分為:I幀,P幀和B幀:
- I幀:關鍵幀,采用幀內壓縮技術。
- P幀:向前參考幀,在壓縮時,只參考前面已經處理的幀。采用幀音壓縮技術。
- B幀:雙向參考幀,在壓縮時,它即參考前而的幀,又參考它后面的幀。采用幀間壓縮技術。
除了I/P/B幀外,還有圖像序列GOP。
- GOP:兩個I幀之間是一個圖像序列,在一個圖像序列中只有一個I幀。如下圖所示:

下面我們就來詳細描述一下H264壓縮技術。
H264壓縮技術
H264的基本原理其實非常簡單,下我們就簡單的描述一下H264壓縮數據的過程。通過攝像頭采集到的視頻幀(按每秒 30 幀算),被送到 H264 編碼器的緩沖區中。編碼器先要為每一幅圖片划分宏塊。
以下面這張圖為例:

划分宏塊
H264默認是使用 16X16 大小的區域作為一個宏塊,也可以划分成 8X8 大小。

划分好宏塊后,計算宏塊的象素值。

以此類推,計算一幅圖像中每個宏塊的像素值,所有宏塊都處理完后如下面的樣子。

划分子塊
H264對比較平坦的圖像使用 16X16 大小的宏塊。但為了更高的壓縮率,還可以在 16X16 的宏塊上更划分出更小的子塊。子塊的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4非常的靈活。

上幅圖中,紅框內的 16X16 宏塊中大部分是藍色背景,而三只鷹的部分圖像被划在了該宏塊內,為了更好的處理三只鷹的部分圖像,H264就在 16X16 的宏塊內又划分出了多個子塊。

這樣再經過幀內壓縮,可以得到更高效的數據。下圖是分別使用mpeg-2和H264對上面宏塊進行壓縮后的結果。其中左半部分為MPEG-2子塊划分后壓縮的結果,右半部分為H264的子塊划壓縮后的結果,可以看出H264的划分方法更具優勢。

宏塊划分好后,就可以對H264編碼器緩存中的所有圖片進行分組了。
幀分組
對於視頻數據主要有兩類數據冗余,一類是時間上的數據冗余,另一類是空間上的數據冗余。其中時間上的數據冗余是最大的。下面我們就先來說說視頻數據時間上的冗余問題。
為什么說時間上的冗余是最大的呢?假設攝像頭每秒抓取30幀,這30幀的數據大部分情況下都是相關聯的。也有可能不止30幀的的數據,可能幾十幀,上百幀的數據都是關聯特別密切的。
對於這些關聯特別密切的幀,其實我們只需要保存一幀的數據,其它幀都可以通過這一幀再按某種規則預測出來,所以說視頻數據在時間上的冗余是最多的。
為了達到相關幀通過預測的方法來壓縮數據,就需要將視頻幀進行分組。那么如何判定某些幀關系密切,可以划為一組呢?我們來看一下例子,下面是捕獲的一組運動的台球的視頻幀,台球從右上角滾到了左下角。


H264編碼器會按順序,每次取出兩幅相鄰的幀進行宏塊比較,計算兩幀的相似度。如下圖:

通過宏塊掃描與宏塊搜索可以發現這兩個幀的關聯度是非常高的。進而發現這一組幀的關聯度都是非常高的。因此,上面這幾幀就可以划分為一組。其算法是:在相鄰幾幅圖像畫面中,一般有差別的像素只有10%以內的點,亮度差值變化不超過2%,而色度差值的變化只有1%以內,我們認為這樣的圖可以分到一組。
在這樣一組幀中,經過編碼后,我們只保留第一帖的完整數據,其它幀都通過參考上一幀計算出來。我們稱第一幀為IDR/I幀,其它幀我們稱為P/B幀,這樣編碼后的數據幀組我們稱為GOP。
運動估計與補償
在H264編碼器中將幀分組后,就要計算幀組內物體的運動矢量了。還以上面運動的台球視頻幀為例,我們來看一下它是如何計算運動矢量的。
H264編碼器首先按順序從緩沖區頭部取出兩幀視頻數據,然后進行宏塊掃描。當發現其中一幅圖片中有物體時,就在另一幅圖的鄰近位置(搜索窗口中)進行搜索。如果此時在另一幅圖中找到該物體,那么就可以計算出物體的運動矢量了。下面這幅圖就是搜索后的台球移動的位置。

通過上圖中台球位置相差,就可以計算出台圖運行的方向和距離。H264依次把每一幀中球移動的距離和方向都記錄下來就成了下面的樣子。

運動矢量計算出來后,將相同部分(也就是綠色部分)減去,就得到了補償數據。我們最終只需要將補償數據進行壓縮保存,以后在解碼時就可以恢復原圖了。壓縮補償后的數據只需要記錄很少的一點數據。如下所示:

我們把運動矢量與補償稱為幀間壓縮技術,它解決的是視頻幀在時間上的數據冗余。除了幀間壓縮,幀內也要進行數據壓縮,幀內數據壓縮解決的是空間上的數據冗余。下面我們就來介紹一下幀內壓縮技術。
幀內預測
人眼對圖象都有一個識別度,對低頻的亮度很敏感,對高頻的亮度不太敏感。所以基於一些研究,可以將一幅圖像中人眼不敏感的數據去除掉。這樣就提出了幀內預測技術。
H264的幀內壓縮與JPEG很相似。一幅圖像被划分好宏塊后,對每個宏塊可以進行 9 種模式的預測。找出與原圖最接近的一種預測模式。

下面這幅圖是對整幅圖中的每個宏塊進行預測的過程。

幀內預測后的圖像與原始圖像的對比如下:

然后,將原始圖像與幀內預測后的圖像相減得殘差值。

再將我們之前得到的預測模式信息一起保存起來,這樣我們就可以在解碼時恢復原圖了。效果如下:

經過幀內與幀間的壓縮后,雖然數據有大幅減少,但還有優化的空間。
對殘差數據做DCT
可以將殘差數據做整數離散余弦變換,去掉數據的相關性,進一步壓縮數據。如下圖所示,左側為原數據的宏塊,右側為計算出的殘差數據的宏塊。

將殘差數據宏塊數字化后如下圖所示:

將殘差數據宏塊進行 DCT 轉換。

去掉相關聯的數據后,我們可以看出數據被進一步壓縮了。

做完 DCT 后,還不夠,還要進行 CABAC 進行無損壓縮。
CABAC
上面的幀內壓縮是屬於有損壓縮技術。也就是說圖像被壓縮后,無法完全復原。而CABAC屬於無損壓縮技術。
無損壓縮技術大家最熟悉的可能就是哈夫曼編碼了,給高頻的詞一個短碼,給低頻詞一個長碼從而達到數據壓縮的目的。MPEG-2中使用的VLC就是這種算法,我們以 A-Z 作為例子,A屬於高頻數據,Z屬於低頻數據。看看它是如何做的。

CABAC也是給高頻數據短碼,給低頻數據長碼。同時還會根據上下文相關性進行壓縮,這種方式又比VLC高效很多。其效果如下:

現在將 A-Z 換成視頻幀,它就成了下面的樣子。

從上面這張圖中明顯可以看出采用 CACBA 的無損壓縮方案要比 VLC 高效的多。
小結
至此,我們就將H264的編碼原理講完了。本篇文章主要講了以下以點內容:
- 簡音介紹了H264中的一些基本概念。如I/P/B幀, GOP。
- 詳細講解了H264編碼的基本原理,包括:
- 宏塊的划分
- 圖像分組
- 幀內壓縮技術原理
- 幀間壓縮技術原理。
- DCT
- CABAC壓縮原理。
最后
大家都知道要入門音視頻要學習音視頻錄制,編碼,處理,但是具體不知道怎么做。我自己在入門的時候也一樣,靠着搜索引擎自己一點一點的積累,在這里當然要謝謝在該領域無私奉獻的大佬們。
下面是我整理的學習路線,相信我,如果你認真學完了,你一定會成為音視頻人才招聘市場的香餑餑~~
一、初級入門篇:
一、繪制圖片
-
ImageView 繪制圖片
-
SurfaceView 繪制圖片
-
自定義 View 繪制圖片

二、AudioRecord API詳解

三、使用 AudioRecord 實現錄音,並生成wav
- 創建一個AudioRecord對象
- 初始化一個buffer
- 開始錄音
- 創建一個數據流,一邊從AudioRecord中讀取聲音數據到初始化的buffer,一邊將buffer中數據導入數據流。
- 關閉數據流
- 停止錄音

四、用 AudioTrack 播放PCM音頻
1.AudioTrack 基本使用
- MODE_STATIC模式
- MODE_STREAM模式
2.AudioTrack 詳解
- 音頻流的類型
- Buffer分配和Frame的概念
- AudioTrack構造過程
- AudioTrack 與 MediaPlayer 的對比
- 區別
- 聯系
- SoundPool

五、使用 Camera API 采集視頻數據
1.預覽 Camera 數據
2.取到 NV21 的數據回調
六、使用 MediaExtractor 和 MediaMuxer API 解析和封裝 mp4 文件
1.MediaExtractor API介紹
2.MediaMuxer API介紹
3.使用情境

七、MediaCodec API 詳解
1.MediaCodec 介紹
2.MediaCodec API 說明
3.MediaCodec 流控
- 流控基本概念
- Android 硬編碼流控
- Android 流控策略選擇

由於文章篇幅受限,剩余內容過多,文中插圖有限,下文只能截圖目錄展示:
所有知識點詳細內容都整理在了開源項目【GitHub】,有需要的可以自取。
二、中級進階篇:
- Android OpenGL ES 開發(一): OpenGL ES 介紹
- Android OpenGL ES 開發(二): OpenGL ES 環境搭建
- Android OpenGL ES 開發(三): OpenGL ES 定義形狀
- Android OpenGL ES 開發(四): OpenGL ES 繪制形狀
- Android OpenGL ES 開發(五): OpenGL ES 使用投影和相機視圖
- Android OpenGL ES 開發(六): OpenGL ES 添加運動效果
- Android OpenGL ES 開發(七): OpenGL ES 響應觸摸事件
- Android OpenGL ES 開發(八): OpenGL ES 着色器語言GLSL
- Android OpenGL ES 開發(九): OpenGL ES 紋理貼圖
- Android OpenGL ES 開發(十): 通過GLES20與着色器交互
- 使用 OpenGL 顯示一張圖片
- GLSurfaceviw 繪制 Camera 預覽畫面及實現拍照
- 使用OpenGL ES 完成視頻的錄制,並實現視頻水印效果

高級探究篇:
- 深入學習音視頻編碼,如H.264,AAC,研究使用開源編解碼庫,如x.264,JM 等
- 深入研究音視頻相關的網絡協議,如 rtmp,hls,以及封包格式,如:flv,mp4
- 深入學習一些音視頻領域的開源項目,如 webrtc,ffmpeg,ijkplayer,librtmp 等等
- 將 ffmpeg 庫移植到 Android 平台,結合上面積累的經驗,編寫一款簡易的音視頻播放器
- 將 x264 庫移植到 Android 平台,結合上面積累的經驗,完成視頻數據 H264 軟編功能
- 將 librtmp 庫移植到 Android 平台,結合上面積累的經驗,完成 Android RTMP 推流功能
音視頻編解碼技術
- 音視頻編解碼技術(一):MPEG-4/H.264 AVC 編解碼標准
- 音視頻編解碼技術(二):AAC 音頻編碼技術
流媒體協議
- 流媒體協議(一):HLS 協議
- 流媒體協議(二):RTMP協議
多媒體文件格式
- 多媒體文件格式(一):MP4 格式
- 多媒體文件格式(二):FLV 格式
- 多媒體文件格式(三):M3U8 格式
- 多媒體文件格式(四):TS 格式
- 多媒體文件格式(五):PCM / WAV 格式


FFmpeg 學習記錄
- FFmpeg命令行工具學習(一):查看媒體文件頭信息工具ffprobe
- FFmpeg命令行工具學習(二):播放媒體文件的工具ffplay
- FFmpeg命令行工具學習(三):媒體文件轉換工具ffmpeg
- FFmpeg命令行工具學習(四):FFmpeg 采集設備
- FFmpeg命令行工具學習(五):FFmpeg 調整音視頻播放速度

- FFmpeg 學習(一):FFmpeg 簡介
- FFmpeg 學習(二):Mac下安裝FFmpeg
- FFmpeg 學習(三):將 FFmpeg 移植到 Android平台
- FFmpeg 學習(四):FFmpeg API 介紹與通用 API 分析
- FFmpeg 學習(五):FFmpeg 編解碼 API 分析
- FFmpeg 學習(六):FFmpeg 核心模塊 libavformat 與 libavcodec 分析

- FFmpeg 結構體學習(一): AVFormatContext 分析
- FFmpeg 結構體學習(二): AVStream 分析
- FFmpeg 結構體學習(三): AVPacket 分析
- FFmpeg 結構體學習(四): AVFrame 分析
- FFmpeg 結構體學習(五): AVCodec 分析
- FFmpeg 結構體學習(六): AVCodecContext 分析
- FFmpeg 結構體學習(七): AVIOContext 分析
- FFmpeg 結構體學習(八):FFMPEG中重要結構體之間的關系

更多目錄截圖:



總結:以上就是關於音視頻的資料最強整理和概括了(還有部分內容沒有截圖出來),相信應該是全網最全了,所有資料都是免費分享給大家的,也省去了對音視頻感興趣的小伙伴們四處找資料的時間,如果你正好需要可以點此處免費獲取
音視頻開發的前景,相信大家從相關的招聘網站上就可以看到,不管是流媒體開發還是音視頻處理開發,都是大量招人的,並且由於入門門檻相對較高,學習周期長,薪資也是居高不下。
另外:小編還收集整理一些音視頻相關配套視頻,相信能使大家學習起來更加快速有效:

文中所有資料都是免費分享給大家的,只需你動動手指點擊此處就可直達免費領取方式了。
Android架構師之路很漫長, 一起共勉吧!學習之路猶如逆水行舟,不進則退,如果你松懈了, 那么你就退步了,而在Android開發工作中沒有一門吃香獨特的技術,想拿高薪也只能是望塵莫及的。做個勤奮向上的人,加緊學習,抓住中心,寧精勿雜,寧專勿多。
如果你正好需要這份完整版Android音視頻開發,只需你多多支持我這篇文章。
整理不易,覺得有幫助的朋友可以幫忙點贊分享支持一下小編~
你的支持,我的動力;祝各位前程似錦,offer不斷!!!