http://linuxtv.org/downloads/v4l-dvb-apis/pixfmt.html
第二節:圖像格式
V4L2 API首先是被設計成讓設備與應用程序交換圖像數據,struct v4l2_pix_format和v4l2_pix_format_mplane結構體定義了內存中圖片的格式和佈局。早期用作單平面API,後期就用作了多平面版本。圖片格式通過VIDIOC_S_FMT ioctl進行協商(這裏是對視頻捕捉設備和視頻輸出設備,對於overlay設備的幀緩衝格式見VIDIOC_G_FBUF)。
單平面格式結構體
struct v4l2_pix_format
類型 | 成員名 | 描述 |
---|---|---|
__u32 | width | 圖片寬度(像素) |
__u32 | height | 圖片高度(像素),若field是V4L2_FIELD_TOP、V4L2_FIELD_BOTTOM、V4L2_FIELD_ALTERNATE之一那麼高度指的是此區域的行數,否則的話指的是此幀的行數(是區域高度的兩倍,因爲是隔行掃描) |
__u32 | pixelformat | 像素格式或壓縮類型,由應用程序設定 |
enum v4l2_field | field | 視頻圖像通常是隔行掃描,應用程序可以請求只捕捉或輸出頂部或底部區域,或者都是交錯/連續的放置在一個緩存中,又或是連續的放置在不同的緩存中。驅動返回實際所選的區域順序 |
__u32 | bytesperline | 兩個相鄰線最左邊的像素相隔幾個字節 |
__u32 | sizeimage | 驅動設置的一張完整圖片在緩存中佔用多少個字節,通常等於bytesperline乘以height。若圖像由多種長度壓縮數據組成,這個值就是處理一張圖片的最大字節數 |
enum v4l2_colorspace | colorspace | 這是pixelformat的補充,驅動必須爲捕捉流進行設置,輸出流要被應用程序設置 |
__u32 | priv | 關於格式的自定義保留位,若驅動和應用程序都不使用必須將其設置爲0 |
多平面格式結構體
結構體v4l2_plane_pix_format定義了多面格式中每個面的尺寸和佈局,v4l2_pix_format_mplane結構體是v4l2_plane_pix_format結構體的集合,包含了所有面的信息。
struct v4l2_plane_pix_format
類型 | 成員名 | 描述 |
---|---|---|
__u32 | sizeimage | 一面的圖像數據最大多少個字節 |
__u16 | bytesperline | 兩相鄰線最左邊像素字節距離 |
__u16 | reserved[7] | 保留位,應置0 |
struct v4l2_pix_format_mplane
類型 | 成員名 | 描述 |
---|---|---|
__u32 | width | 圖像寬度,像素單位 |
__u32 | height | 圖像高度,像素單位 |
__u32 | pixelformat | 像素格式,單平面和多平面的FourCC都可以 |
enum v4l2_field | field | 見struct v4l2_pix_format |
enum v4l2_colorspace | colorspace | 見struct v4l2_pix_format |
struct v4l2_plane_pix_format | plane_fmt[VIDEO_MAX_PLANES | 描述每個平面的結構體集合,有效數量放在num_planes中 |
__u8 | num_planes | 平面數量 |
__u8 | reserved[11] | 保留位,應用應將其置0 |
標準圖片格式
爲了在驅動和應用程序之間交換圖像數據,在兩邊都有標準圖像數據是很有必要的。V4L2包含了一些格式,這一章節就來清晰的介紹一下V4L2中支持的標準圖像格式。
V4L2驅動並不限於這些格式,驅動自定義特殊格式是有可能的。既然如此,那麼應用程序可能就要在依賴於解碼器來將圖片轉換成需要的標準格式,但數據依然可以被保存及恢復成專有格式。比如,一個設備可能支持一個專有的壓縮格式。應用程序能夠將數據捕捉及保存在壓縮格式中,保存在硬盤空間上,然後當視頻需要顯示的時候使用解碼器將其轉換成顯示器的格式。
儘管如此,最終還是需要一些標準格式的,所以V4L2需要兼容一些較好的標準格式。
V4L2標準主要是非壓縮格式,在內存中,像素通常是以從左到右,從上到下的方式進行排列的。圖片緩存的第一個字節數據一般在最上邊的最左的像素中,然後依次向右,直到最定行的最後一個像素。行中最右邊的像素可能是0,或是填充數據以爲了保證每行像素數據都對齊。在對齊數據後,若有的話,是第二行最左側的像素數據,依此類推。最後一行也像其他行一樣有一些填充數據。
在V4L2中每個格式都是PIX_FMT_XXX的格式,他們定義在videodev.h頭文件中。同樣也列舉除了FourCC的定義,但是他們卻與Windows世界的不同。
對於一些格式來說,數據被存儲在隔開的、不連續的內存緩衝中。這些格式有些是FourCC,以及多平面格式。比如,YUV422幀通常存儲在一個內存緩衝中,但是還可以放到兩個或三個分開的緩衝中,2平面版本中Y部分一個緩衝,CbCr部分在另一個,或3平面版本中每個部分一個緩衝。這些自緩存就被視作“面”。
顏色空間
介紹
伽馬校正(顏色灰度校正)
E'R = f(R)
E'G = f(G)
E'B = f(B)
亮度構造和顏色差異信號
E'Y = CoeffR E'R + CoeffG E'G + CoeffB E'B
(E'R - E'Y) = E'R - CoeffR E'R - CoeffG E'G - CoeffB E'B
(E'B - E'Y) = E'B - CoeffR E'R - CoeffG E'G - CoeffB E'B
規範化顏色差異信號
顏色差異信號縮減範圍[-0.5;+0.5]
KB = 0.5 / (1 - CoeffB)
KR = 0.5 / (1 - CoeffR)
PB = KB (E'B - E'Y) = 0.5 (CoeffR / CoeffB) E'R + 0.5 (CoeffG / CoeffB) E'G + 0.5 E'B
PR = KR (E'R - E'Y) = 0.5 E'R + 0.5 (CoeffG / CoeffR) E'G + 0.5 (CoeffB / CoeffR) E'B
量化
Y' = (Lum. Levels - 1) · E'Y + Lum. Offset
CB = (Chrom. Levels - 1) · PB + Chrom. Offset
CR = (Chrom. Levels - 1) · PR + Chrom. Offset
在[0;255]範圍內舍入爲最接近的整數,最終形成YUV圖片的Y'CbCr格式。
例2.1 ITU-R Rec. BT.601顏色轉換
to YUV
int ER, EG, EB; /* gamma corrected RGB input [0;255] */
int Y1, Cb, Cr; /* output [0;255] */
double r, g, b; /* temporaries */
double y1, pb, pr;
int
clamp (double x)
{
int r = x; /* round to nearest */
if (r < 0) return 0;
else if (r > 255) return 255;
else return r;
}
r = ER / 255.0;
g = EG / 255.0;
b = EB / 255.0;
y1 = 0.299 * r + 0.587 * g + 0.114 * b;
pb = -0.169 * r - 0.331 * g + 0.5 * b;
pr = 0.5 * r - 0.419 * g - 0.081 * b;
Y1 = clamp (219 * y1 + 16);
Cb = clamp (224 * pb + 128);
Cr = clamp (224 * pr + 128);
或更簡短些
y1 = 0.299 * ER + 0.587 * EG + 0.114 * EB;
Y1 = clamp ( (219 / 255.0) * y1 + 16);
Cb = clamp (((224 / 255.0) / (2 - 2 * 0.114)) * (EB - y1) + 128);
Cr = clamp (((224 / 255.0) / (2 - 2 * 0.299)) * (ER - y1) + 128);
反向轉換
int Y1, Cb, Cr; /* gamma pre-corrected input [0;255] */
int ER, EG, EB; /* output [0;255] */
double r, g, b; /* temporaries */
double y1, pb, pr;
int
clamp (double x)
{
int r = x; /* round to nearest */
if (r < 0) return 0;
else if (r > 255) return 255;
else return r;
}
y1 = (Y1 - 16) / 219.0;
pb = (Cb - 128) / 224.0;
pr = (Cr - 128) / 224.0;
r = 1.0 * y1 + 0 * pb + 1.402 * pr;
g = 1.0 * y1 - 0.344 * pb - 0.714 * pr;
b = 1.0 * y1 + 1.772 * pb + 0 * pr;
ER = clamp (r * 255); /* [ok? one should prob. limit y1,pb,pr] */
EG = clamp (g * 255);
EB = clamp (b * 255);
索引格式
每個像素格式在256 ARGB調色板中有一個8位的索引,這只是爲視頻Overlay輸出準備的。沒有與調色板相關的ioctl,必須通過Linux framebuffer的API ioctl處理好。
表2.5 索引圖片格式
定義 | 碼 | Byte 0 |
---|---|---|
V4L2_PIX_FMT_PAL8 | "PAL8" | i7 i6 i5 i4 i3 i2 i1 i0 |