1.ffmpeg簡介
ffmpeg是一個開源免費跨平台的視頻和音頻流方案,屬於自由軟體,採用LGPL/GPL許可證。它提供了錄製、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼品質,libavcodec裡很多codec都是從頭開發的。ffmpeg是一套可以用來記錄、轉換數字音頻、視頻,並能將其轉化為流的開源電腦程式。它包括了目前領先的音/視頻編碼庫libavcodec。 ffmpeg是在Linux下開發出來的,但它可以在包括Windows在內的大多數作業系統中編譯。
----------------------
ffmpeg的一些基本概念
----------------------
Container:在音視頻中的“容器”,一般指的是一種特定格式的多媒體檔案,裡面指明了所包含的音視頻、字幕等相關資訊;
Stream:可以理解為分解開的、單純的音頻資料流或視頻資料流或字幕流等;
Frame:指的是Stream中的一個未經壓縮的完整資料單元;
Packet:是儲存壓縮資料的結構,視頻流中通常是壓縮的一個Frame的,而在音頻流中則可能是壓縮的多個Frame;
Codec:轉碼器;
採樣率:每秒鐘記錄多少個採樣點;
----------------------
ffmpeg的組成結構
----------------------
ffmpeg主要由以下幾個庫組成:
· libavcodec: encoding/decoding library (編解碼庫)
· libavfilter: graph-based frame editing library(濾波器庫,類似DShow的“可組裝”的特點,但要求filter的輸入/輸出介面是匹配的)
· libavformat: I/O and muxing/demuxing library(IO及分解/合并流)
· libavdevice: special devices muxing/demuxing library(例如開啟網路攝影機,螢幕錄製等)
· libavutil: common utility library(小型函數庫,記憶體配置、釋放)
· libswresample: audio resampling, format conversion and mixing
· libpostproc: post processing library(後期處理。尚不清楚)
· libswscale: color conversion and scaling library(轉碼及尺度變換)
ffmpeg軟體包經編譯過後將產生三個可執行檔(可通過命令列運行):
· ffmpeg:ffmpeg用於對媒體檔案進行處理;
· ffserver:ffserver是一個http的流媒體伺服器;
· ffplay:ffplay是一個基於SDL的簡單播放器。 2.視頻YUV格式簡介
YUV格式,一般用Y,U,V三者的比率來表示不同格式,比如YUV444 表示三者是比值此是 4:4:4,即一個點資料點,Y,U,V的空間都是一樣大小。目前主要有如下比例,注意所有格式中Y比值都是4,佔一個位元組,表示沒有減少採樣。不同格式中,減小隻是UV的採樣值.
4:4:4:表示色度值(UV)沒有減少採樣。即Y,U,V各佔一個位元組,總共佔3位元組。
4:2:2:表示UV分量採樣減半,比如第一個像素採樣Y,U,第二個像素採樣Y,V,依次類推,這樣每個點佔用2個位元組。二個像素組成一個宏像素.
4:2:0:這種採樣並不意味著只有Y,Cb而沒有Cr分量,這裡的0說的U,V分量隔行才採樣一次。比如第一行採樣 4:2:0,第二行採樣 4:0:2 ,依次類推……在這種採樣方式下,平均每一個像素佔用1.5位元組.
4:2:2樣本
如果未經處理資料三個像素是 [Y0 U0 V0] ,[Y1 U1 V1],[Y2 U2 V2],[Y3 U3 V3]
經過4:2:2採樣後,資料變成了 Y0 U0 ,Y1 V1 ,Y2 U2,Y3 V3
如果還原後,因為某一些資料丟失就補成 [Y0 U0 V1],[Y1 U0 V1],[Y2 U2 V3] ,[Y3 U3 V2]
4:2:0樣本
下面八個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3] [Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
存放的碼流為: Y0 U0, Y1, Y2 U2, Y3,Y5 V5, Y6,Y7 V7, Y8
映射出的像素點為:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7] [Y5 U0 V5] [Y6 U0 V5] [Y7 U2 V7] [Y8 U2 V7]
除了4:4:4採樣,其餘採樣後訊號重新還原顯示後,會丟失部分UV資料,只能用相臨的資料補齊,但人眼對UV不敏感,因此總體感覺損失不大。
圖1 YUV420sp儲存格式
圖2 YUV420p儲存格式
ps: ffmpeg中,映像未經處理資料包括兩種:planar和packed。planar就是將幾個分量分開存,比如YUV420中,data[0]專門存Y,data[1]專門存U,data[2]專門存V。而packed則是打包存,所有資料都存在data[0]中. 3.YUV格式樣本【順時針旋轉90°YUV420映像】:
public static void rotateYUV420(byte[] src,byte[] des,int width,int height, String type){// 原圖按行序儲存int wh = width * height;int k = 0;//旋轉Y分量(按原圖的列序儲存)for(int i=0;i<width;i++) {for(int j=0;j<height;j++) { des[k] = src[width*j + i]; k++;}}if(type.equals(“YUV420SP”)){// YUV420SP是UV分量交錯依次儲存的情況// 旋轉UV分量(按原圖的列序儲存)for(int i=0;i<width;i+=2) {for(int j=0;j<height/2;j++) { des[k] = src[wh+ width*j + i]; des[k+1]=src[wh + width*j + i+1]; k+=2;}}}else if(type.equals(“YUV420P”)){// YUV420P是UV分量分開儲存的情況// 旋轉U分量(按原圖的列序儲存)for(int i=0;i<width;i++) {for(int j=0;j<height/4;j++) { des[k] = src[wh + width*j + i]; k++;}}// 旋轉V分量(按原圖的列序儲存)for(int i=0;i<width;i++) {for(int j=0;j<height/4;j++) { des[k] = src[(1+1/4.0f)*wh + width*j + i]; k++; } }}}
ps: ffmpeg庫的介面都是c函數,在cpp檔案裡調用ffmpeg函數要注意了,由於C++語言支援函數重載,C語言不支援函數重載,函數被C++編譯器編譯後在庫中的名字與C語言的不同(mangled name),一個用C寫成的庫如果想被C/C++同時可以使用,那在標頭檔應該加上以下代碼 #ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}
#endif