音視頻學習(七、初識YUV)

本來不想寫YUV的,不過再寫編碼程序的時候,老是編碼不成功,沒辦法,該還的總是要還的,還是來補補知識吧。

7.1 引入YUV

我們常見的視頻格式RGB888,不知道有沒有做過顯示屏的同學,我們在顯示屏顯示中,每個像素是使用RGB888或者RGRB565,這裏利用了三種基色可以組合成任意一種顏色,這樣我們人眼就可以看到任何顏色了。但是RGB這種存儲方式會帶來一個問題,我們用RGB888來舉例來計算視頻的大小:
一個像素就用3byte存儲,那如果是1280720的(低清通道)圖片,存儲一張需要:12807203=2.637MB,如果是視頻的話(應該都知道視頻其實就是好多張圖片連接起來的,這樣就可以看到是視頻了),如果是一個90分鐘的電影,每秒25幀,則一部電影的大小爲2.637M * 90分鐘 60秒 * 25幀 = 347.651G。看看一部視頻就300G,我們硬盤纔多少G,所以如果直接存儲RGB是存儲不下來的,所以需要壓縮編碼。
所以這時候YUV格式就出現了,(歷史怎麼來的,我們這裏不探討,有興趣的同學可以自己去查)。

YUV,是一種顏色編碼方法。常使用在各個視頻處理組件中。 YUV在對照片或視頻編碼時,考慮到人類的感知能力,允許降低色度的帶寬。YUV是編譯true-color顏色空間(color space)的種類,Y’UV, YUV, YCbCr,YPbPr等專有名詞都可以稱爲YUV,彼此有重疊。“
Y”表示明亮度(Luminance或Luma),也就是灰階值,
“U”和“V”表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用於指定像素的顏色。《百度百科》

概念的東西還是要抄抄百度百科的是吧。

7.2 採樣格式

像RGB是每個像素都要3個字節表示,所以不存在採樣。但是在YUV格式中,需要對UV分量的數據進行壓縮,在壓縮過後,其實對整體的質量影響不大,這樣YUV所佔用的空間就比RGB的要小。

YUV是怎麼壓縮的呢?其實就是把顏色分量的採樣調整了一下,所以我們平時表示YUV也用比率來表示不同的格式。比如YUV444 表示三者是比值此是 4:4:4,即一個點數據點,Y,U,V的空間都是一樣大小。
目前主要有如下比例,注意所有格式中Y比值都是4,佔一個字節,表示沒有減少採樣。不同格式中,減小隻是UV的採樣值。

  • 4:4:4 表示色度值(UV)沒有減少採樣。即Y,U,V各佔一個字節,加上Alpha通道一個字節,總共佔4字節.這個格式其實就是24bpp的RGB格式了。

  • 4:2:2 表示UV分量採樣減半,比如第一個像素採樣Y,U,第二個像素採樣Y,V,依次類推,這樣每個點佔用2個字節.二個像素組成一個宏像素.

  • 4:2:0 這種採樣並不意味着只有Y,Cb而沒有Cr分量,這裏的0說的U,V分量隔行才採樣一次。比如第一行採樣 4:2:0 ,第二行採樣 4:0:2 ,依次類推…在這種採樣方式下,每一個像素佔用16bits或10bits空間.

  • 4:1:1 可以參考4:2:2分量,是進一步壓縮,每隔四個點才採一次U和V分量。一般是第0點採Y,U,第1點採Y,第3點採YV,第四點採Y,依次類推。
    除了4:4:4採樣,其餘採樣後信號重新還原顯示後,會丟失部分UV數據,只能用相臨的數據補齊,但人眼對UV不敏感,因此總體感覺損失不大。

用三個圖來直觀地表示採集的方式吧,以黑點表示採樣該像素點的Y分量,以空心圓圈表示採用該像素點的UV分量。
在這裏插入圖片描述

先記住下面這段話,以後提取每個像素的YUV分量會用到。

YUV 4:4:4採樣,每一個Y對應一組UV分量。
YUV 4:2:2採樣,每兩個Y共用一組UV分量。
YUV 4:2:0採樣,每四個Y共用一組UV分量。

還是下面這個描述容易懂。

7.3 存儲格式

YUV的存儲和RGB最大的不同,就是RGB每個點的數據都是連續保存在一起的,而YUV數據爲了節省空間,UV分量會減少,像上面所說,幾個Y才共用一個UV分量,所以YUV的數據是不對等的。
YUV格式有兩大類:planar和packed
對於planar的YUV格式,先連續存儲所有像素點的Y,緊接着存儲所有像素點的U,隨後是所有像素點的V。
對於packed的YUV格式,每個像素點的Y,U,V是連續交叉存儲的。

7.3.1 YU12/I420

該格式屬於4:2:0類型,存儲方式上面已經說過,就是先存儲把全部的Y分量存完,再存U分量,最後存V分量,從網上找了一張很形象的圖:
在這裏插入圖片描述
可以看到,第一行的Y1Y2和第二行的Y7Y8共同使用一組UV分量U1V1。

7.3.2 YV12

該格式與YU12基本一樣,唯一的區別是先存儲V分量再存儲U分量,對應到上圖把第五行和第六行位置互換一下就是了。

以上兩種格式我們可以看到都是4:2:0的,因爲都是planar方式存儲,簡稱420p。

除了上面兩種,還有兩種4:2:0,NV12和NV21,這兩種是比較特殊的存儲格式,是planar和packed混合存儲的,分別看下:

7.3.3 NV12

該格式是先存儲全部的Y分量,然後UV分量交叉存儲,用圖像表示下:
在這裏插入圖片描述
很直觀,不多說了。

7.3.4 NV21

該格式與NV21的區別和上面YU12/YV12一樣,唯一的區別只是UV分量交叉的順序不同,NV12是U排前面,NV21是V排前面,用圖像表示如下:
在這裏插入圖片描述
上面兩種雖然也是4:2:0類型,但是並不是完全的planar格式,所以又稱爲420sp,與420p進行區分。

上面說的都是4:2:0類型的,下面說幾個4:2:2類型較常見的

7.3.5 YUV422P

名字中帶P表示是planar格式存儲,該格式存儲方式與I420是一樣的,唯一的區別是UV分量的數量不同,I420中四個Y共用一組UV,而該格式中兩個Y共用一組UV,也就是說UV分量相對於I420在數量上多了一倍,從網上找了一張圖,如下:
在這裏插入圖片描述
如上圖,在渲染時Y00與Y01會共用U00和V00.

7.3.6 YUYV/YUY2

該格式屬於4:2:2類型,且是用packed形式存儲的,上面也簡單的說過,存儲方式如下圖:
在這裏插入圖片描述
可以看到,每兩個Y分量共用一組UV分量,存儲順序是YUYV。

7.3.7 YVYU

該格式與YUYV相似,只是存儲時UV分量順序不同而已,爲YVYU。

7.3.8 UYVY

該格式也是4:2:2類型,與上面兩種方式並無大的不同,從網上找了一張圖如下:
在這裏插入圖片描述
可以看到存儲時YUV分量的順序如名字所示:UYVY。

7.4 計算

上面講過,90分鐘的1280720的電影,每秒25幀存儲的RGB格式大小:2.637M * 90分鐘 60秒 * 25幀 = 347.651G。現在我們用YUV420p的格式計算一下,YUV420p描述一個像素的大小爲:1(Y)+0.5(2/4 UV) = 1.5,一張1280720的圖片大小:1280720*1.5byte = 1.318MB,所以電影大小的話爲:1.318M * 90分鐘 * 60秒 * 25幀 = 173.76GB。

是不是感覺還是很大,雖然比RGB小了3倍,但是還是很大,所以壓縮到YUV格式還是不夠的,這時候還需要繼續壓縮,壓縮成h264格式,也就是上篇文章寫的h264格式解析,可以好好了解,就會發現之間的聯繫了。

7.5 YUV和RGB轉換

Y = 0.299R + 0.587G+ 0.114B
U = -0.147R -0.289G + 0.436B
V = 0.615R - 0.515G- 0.100B

R = Y + 1.14V
G = Y - 0.39U -0.58V
B = Y + 2.03U

網上找到的,我也還沒試過。

YUV420p的 YUV分量大小:
即YUV數據的0--720×480字節是Y分量值,
720×480--720×480×5/4字節是U分量
720×480×5/4 --720×480×3/2字節是V分量。

7.6 舉例

下一節實現編碼的話,就是讀取這個YUV的文件,一幀一幀進行編碼,編碼之後,就可以利用我們之前的推流,進行推,就是實現這個編碼的時候,一直編碼不成功,所以纔來複習一下YUV格式,把原來的編碼文章往後推了一章。
在這裏插入圖片描述
既然學習了YUV格式,我們就知道存儲一幀720480的420P的視頻總大小=720480*1.5=518400,然後我們在上面的視頻中截取第一幀,也就是518400字節大小,可以用dd命令截取,這個比較好用,

dd if=720x480_25fps_420p.yuv of=1.yuv count=1 bs=518400

截取出來的圖片,使用yuv的軟件打開
在這裏插入圖片描述
論證了上面的說法,我們就可以把這一幀的數據進行編碼了,下一節解析FFMPEF編碼。

7.7 其他

libyuv,Google開源的實現各種YUV與RGB之間相互轉換,旋轉,縮放的庫,比FFmpeg效率高,有興趣可以去看看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章