YUV420介紹:
YUV420格式是指,每個像素都保留一個Y(亮度)分量,而在水平方向上,不是每行都取U和V分量,而是一行只取U分量,則其接着一行就只取V分量,以此重復(即4:2:0, 4:0:2, 4:2:0, 4:0:2 .......),所以420不是指沒有V,而是指一行采樣只取U,另一行采樣只取V。在取U和V時,每兩個Y之間取一個U或V。但從4x4矩陣列來看,每4個矩陣點Y區域中,只有一個U和V,所以它們的比值是4:1。所以對於一個像素,RGB需要8 * 3 = 24位,即占3個字節;而YUV420P,8 + 8/4 + 8/4 = 12位,即占2個字節,其中8指Y分量,8/4指U和V分量。
從這里也可以看出,YUV要比RGB節省存儲空間。
這里為什么一個分量是8位呢?
不管是R G B還是 Y U V他們每個分量的取值都是0-255,而計算機都是用二進制來存儲的。巧了,一個字節(8bit)剛好可以記錄0-255的數,
yuv420又分為yuv420p和yuv420sp.
yuv420P格式如下:
yuv420sp格式如下:
還是圖像比較直觀,從上面的圖片中就能看出來yuv420sp和yuv420p的區別了。
對於所有YUV420圖像,它們的Y值排列是完全相同的,因為只有Y的圖像就是灰度圖像。YUV420sp與YUV420p的數據格式它們的UV排列在原理上是完全不同的。420p它是先把U存放完后,再存放V,也就是說UV它們是連續的。而420sp它是UV、UV這樣交替存放的。(記得結合上圖查看)
有了上面的理論,就可以准確的計算出一個YUV420在內存中存放的大小。
Y = width * hight (總和)
U = Y / 4
V = Y / 4
所以一張YUV圖像他的存儲空間就是:
width * height + width * height / 4 + width * height / 4
化簡后就是 width * height *3 /2
看來數學還是有點用的
YUV420P內存中的存儲方式:
YUV格式通常有兩大類:打包(packed)格式和平面(planar)格式。
前者將YUV分量存放在同一個數組中,通常是幾個相鄰的像素組成一個宏像素(macro-pixel);
而后者使用三個數組分開存放YUV三個分量
YUV420P(planar格式)在ffmpeg中存儲是在struct AVFrame的data[]數組中
data[0]-------Y分量
data[1]------U分量
data[2]-------V分量
現在回過頭看一下,我們前面保存yuv420圖像的代碼:
int y_size=pCodecCtx->width*pCodecCtx->height;
fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y
fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U
fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V