颜色与格式这是不定期发布的关于写视频驱动程序的LWN系统文章的第五篇.没有看过介绍篇的,也许想从
这里开始.
应用在可以使视频设备工作之前,它必须与驱动达成了解,知道视频数据是何种格式的。这种协商将是一个非常复杂的过程,其原因有二:1、视频硬件所支持的视频格互不相同。2、在内核的格式转换是令人难以接受的。所以应用在找出一种硬件支持的格式,并做出一种大家都可以接受的配置。这篇文章将会讲述格式的基本描述方式;下期文章则会讲述V4L2驱动与应用协商格式时所实现的API。
色域
色域在广义上来讲,就是系统在描述色彩时所使用的坐标。V4L2规范中定义了好几个,但只有两个使用最为广泛。它们是:
注意:YUV和YCbCr并非完成一样,虽然有时他们的名字会替代使用。
密集存储和平面存储[p=21, null, left]如汝所见,像素值是以数组的方式表示的,通常由RGB或YUV值组成。要把这数组组织成图像,通常有两种常用的方法。
四字符码(four Charactor Code:FourCC)[p=21, null, left]V4L2 API中表示色彩格式采用的是广受好评的四字符码(fourcc)机制。这些编码都是32位的值,由四个ASCII码产生。如此一来,它就有一个优点就是,易于传递,对人可读。当一个色彩格式读作,例如,”RGB4″就没有必要去查表了。
[p=21, null, left]注意:四字符码在很不同的设定中都会使用,有些还是早于linux的.Mplayer中内部使用它们,然而,fourcc只是说明一种编码机制,并不说明使用何种编码。Mplayer有一个转换函数,用于在它自己的fourcc码和v4l2用的fourcc码之间做出转换。
RGB格式[p=21, null, left]在下面的格式描述中,字节是按存储顺序列出的。在小端模式下,LSByte在前面。每字节的LSbit在右侧。每种色域中,轻阴影位是最高有效的。
当使用有空位(上图中灰色部分)的格式 , 应用可以使用空位作alpha(透明度)值.
上面的最后一个格式是”Bayer(人名好像是)”格式,此格式与多数摄像机感光器所得到的真实数据非常接近。每个像素都有绿色分量,但蓝和红只是隔一个像素才有分量。本质上讲,绿色带有更重的强度信息,而蓝红色则在丢失时以相隔像素的内插值替换。这种模式我们交在YUV格式中再次见到。
YUV格式[p=21, null, left]YUV的紧密型模式在下面首先展示,看表的关键处如下:
也有几中平面型的YUV格式在用,但把它们全画出来并没有什么大的帮助,所以我们只是在下面举一下例子,常用”YUV 4:2:2″(V4L2_PIX_FMT_YUV422, fourcc422P)格式使用三组阵列,一幅4X4的图片将如下表示:
对于Bayer格式, YUV 4:2:2 每隔一个Y值有一个U和一个V值,展示图像需要以内插值替换的丢失的值。其他的平面YUV格式有:
还存在一些其他的YUV格式,但他们的使用极用少。想要了解的话请看这里。
其他格式[p=21, null, left]还有一些可能对驱动有用的格式如下:
[p=21, null, left]还有一些其他的混杂的格式,其中一些还是有传利保护的; 这里 有一张列表.
格式的描述[p=21, null, left]现在我们己经了解了颜色的格式,下面将要看看下V4L2 API中是如何描述图像格式的了。这里的主要的结构体是struct v4l2_pix_format (定义于<linux/videodev2.h>),它包含如下字段:
应用在可以使视频设备工作之前,它必须与驱动达成了解,知道视频数据是何种格式的。这种协商将是一个非常复杂的过程,其原因有二:1、视频硬件所支持的视频格互不相同。2、在内核的格式转换是令人难以接受的。所以应用在找出一种硬件支持的格式,并做出一种大家都可以接受的配置。这篇文章将会讲述格式的基本描述方式;下期文章则会讲述V4L2驱动与应用协商格式时所实现的API。
色域
色域在广义上来讲,就是系统在描述色彩时所使用的坐标。V4L2规范中定义了好几个,但只有两个使用最为广泛。它们是:
- V4L2_COLORSPACE_SRGB.多数开发者所熟悉的[red,green,blue]数组包含在这个色域之中。它为每一种颜色提供了一个简单的强度值,把它们混合在一起,从而产生了一种广泛的颜色的效果。表示RGB值的方法有很多,我们在下面将会有所介绍。
注意:YUV和YCbCr并非完成一样,虽然有时他们的名字会替代使用。
- V4L2_COLORSPACE_SMPTE170M 这个是NTSC或PAL等电视信号的模拟色彩表示方法,电视调谐器通常产生的色域都属于这个色域。
密集存储和平面存储[p=21, null, left]如汝所见,像素值是以数组的方式表示的,通常由RGB或YUV值组成。要把这数组组织成图像,通常有两种常用的方法。
- Packed格式把一个像素的所有值存领教在一起.
- Planar 格式把每一个分量单独存储成一个阵列,这样在YUV格式中,所有Y值都连续地一起存储在一个阵列中,U值存储在另一个中,V值存在第三个中.这些平面常常都存储在一个缓冲区中,但并不一定非要这样.
四字符码(four Charactor Code:FourCC)[p=21, null, left]V4L2 API中表示色彩格式采用的是广受好评的四字符码(fourcc)机制。这些编码都是32位的值,由四个ASCII码产生。如此一来,它就有一个优点就是,易于传递,对人可读。当一个色彩格式读作,例如,”RGB4″就没有必要去查表了。
[p=21, null, left]注意:四字符码在很不同的设定中都会使用,有些还是早于linux的.Mplayer中内部使用它们,然而,fourcc只是说明一种编码机制,并不说明使用何种编码。Mplayer有一个转换函数,用于在它自己的fourcc码和v4l2用的fourcc码之间做出转换。
RGB格式[p=21, null, left]在下面的格式描述中,字节是按存储顺序列出的。在小端模式下,LSByte在前面。每字节的LSbit在右侧。每种色域中,轻阴影位是最高有效的。
Name | fourcc | Byte 0 | Byte 1 | Byte 2 | Byte 3 | ||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB332 | RGB1 |
| |||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB444 | R444 |
|
| ||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB555 | RGB0 |
|
| ||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB565 | RGBP |
|
| ||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB555X | RGBQ |
|
| ||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB565X | RGBR |
|
| ||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_BGR24 | BGR3 |
|
|
| |||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB24 | RGB3 |
|
|
| |||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_BGR32 | BGR4 |
|
|
|
| ||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_RGB32 | RGB4 |
|
|
|
| ||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_SBGGR8 | BA81 |
|
|
|
| ||||||||||||||||||||||||||||||||
|
|
|
|
上面的最后一个格式是”Bayer(人名好像是)”格式,此格式与多数摄像机感光器所得到的真实数据非常接近。每个像素都有绿色分量,但蓝和红只是隔一个像素才有分量。本质上讲,绿色带有更重的强度信息,而蓝红色则在丢失时以相隔像素的内插值替换。这种模式我们交在YUV格式中再次见到。
YUV格式[p=21, null, left]YUV的紧密型模式在下面首先展示,看表的关键处如下:
-
= Y (intensity)
-
= U (Cb)
-
= V (Cr)
Name | fourcc | Byte 0 | Byte 1 | Byte 2 | Byte 3 | ||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_GREY | GREY |
| |||||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_YUYV | YUYV |
|
|
|
| ||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_UYVY | UYVY |
|
|
|
| ||||||||||||||||||||||||||||||||
V4L2_PIX_FORMAT_Y41P | Y41P |
|
|
|
| ||||||||||||||||||||||||||||||||
|
|
|
| ||||||||||||||||||||||||||||||||||
|
|
|
|
Y plane: |
|
|
|
| ||||||||||||||||||||||||||||||||
|
|
|
| |||||||||||||||||||||||||||||||||
|
|
|
| |||||||||||||||||||||||||||||||||
|
|
|
| |||||||||||||||||||||||||||||||||
U plane: |
|
|
|
| ||||||||||||||||||||||||||||||||
|
|
|
| |||||||||||||||||||||||||||||||||
V plane: |
|
|
|
| ||||||||||||||||||||||||||||||||
|
|
|
|
- V4L2_PIX_FMT_YUV420: YUV 4:2:0格式,每四个Y值才有一个U值一个V值.U和V都要在水平和垂直两个方向上都以内插值替换.平面是以Y-U-V的顺序存储的,与上面的例子一致.
- V4L2_PIX_FMT_YVU420: 与YUV 4:2:0格式类似,只是U,V值调换了位置.
- V4L2_PIX_FMT_YUV410: 每16个Y值才有一个U值和V值.阵列的顺序是 Y-U-V.
- V4L2_PIX_FMT_YVU410: 每16个Y 值才有一个U值和V值.阵列的顺序是Y-V-U.
还存在一些其他的YUV格式,但他们的使用极用少。想要了解的话请看这里。
其他格式[p=21, null, left]还有一些可能对驱动有用的格式如下:
- V4L2_PIX_FMT_JPEG: 一种定义模糊的JPEG流;更多信息请看这里.
- V4L2_PIX_FMT_MPEG: MPEG流.还有一些MPEG流格式的变种;未来的文章中将讨论流的控制.
[p=21, null, left]还有一些其他的混杂的格式,其中一些还是有传利保护的; 这里 有一张列表.
格式的描述[p=21, null, left]现在我们己经了解了颜色的格式,下面将要看看下V4L2 API中是如何描述图像格式的了。这里的主要的结构体是struct v4l2_pix_format (定义于<linux/videodev2.h>),它包含如下字段:
- __u32 width: 图片宽度,以像素为单位.
- __u32 height:图片高度,以像素为单位.
- __u32 pixelformat: 描述图片格式的四字符码.
- enum v4l2_field field:很多图片的源会使数据交错 -先传输奇数行,然后是偶到行.真正的摄像头设备是不会做数据的交错的。 V4L2 API 允许应用使用很多种方式交错字段.常用的值为V4L2_FIELD_NONE (字段不交错),V4l2_FIELD_TOP (只交错顶部字面),或V4L2_FIELD_ANY (无所谓). 详情见这里.
- __u32 bytesperline: 相临扫描行之间的字节数.这包括各种设备可能会加入的填充字节.对于平面格式,这个值描述的是最大的 (Y) 平面.
- __u32 sizeimage: 存储图片所需的缓冲区的大小.
- enum v4l2_colorspace colorspace: 使用的色域.