首页 > 代码库 > v4l2 Camera详细设置【转】

v4l2 Camera详细设置【转】

转自:http://blog.csdn.net/smilefyx/article/details/39555289

转载自:http://blog.sina.com.cn/s/blog_602f87700101bf36.htmlCamera的可设置项极多,V4L2支持了不少。但Sam之前对这些设置的用法和涵义都是在看videodev2.h中边看边理解,感觉非常生涩。直到写这篇blog时,才发现v4l2有专门的SPEC来说明:http://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html但也基本没有时间仔细看了。先把自己看头文件看出的一些东西记录在这里吧。以实际设置过程为顺序谈谈V4L2 设置。1. 查询V4L2 功能集:VIDIOC_QUERYCAPstruct v4l2_capability cap;int rel = 0;ioctl(Handle, VIDIOC_QUERYCAP, &cap);使用ioctl VIDIOC_QUERYCAP来查询当前driver是否合乎规范。因为V4L2要求所有driver 和Device都支持这个Ioctl。所以,可以通过这个ioctl是否成功来判断当前设备和dirver是否支持V4L2规范。当然,这样同时还能够得到设备足够的能力信息。struct v4l2_capability{ __u8 driver[16];  //驱动名。 __u8 card[32];    //Device名 __u8 bus_info[32]; //在Bus系统中存放位置 __u32 version;     //driver版本 __u32 capabilities; //能力集 __u32 reserved[4];};能力集中包含:V4L2_CAP_VIDEO_CAPTURE0x00000001     Thedevice supports the Video   Captureinterface.V4L2_CAP_VIDEO_OUTPUT  0x00000002     Thedevice supports the Video   Outputinterface.V4L2_CAP_VIDEO_OVERLAY0x00000004     Thedevice supports the Video   Overlayinterface.A video overlay device typically stores captured images directly inthe videomemory   ofa graphics card,with hardware clipping and scaling.V4L2_CAP_VBI_CAPTURE     0x00000010The device supports the Raw  VBI Captureinterface, providing Teletext and Closed Caption  data.V4L2_CAP_VBI_OUTPUT     0x00000020      Thedevice supports the Raw  VBI Outputinterface.V4L2_CAP_SLICED_VBI_CAPTURE  0x00000040The device supports the Sliced VBI Capture interface.V4L2_CAP_SLICED_VBI_OUTPUT   0x00000080The device supports the Sliced VBI Output interface.V4L2_CAP_RDS_CAPTURE   0x00000100          [tobe defined]#define V4L2_CAP_TUNER 0x00010000 #define V4L2_CAP_AUDIO 0x00020000 #define V4L2_CAP_RADIO 0x00040000 #define V4L2_CAP_READWRITE 0x01000000 #define V4L2_CAP_ASYNCIO 0x02000000 #define V4L2_CAP_STREAMING0x04000000  看起来很熟悉吧,其实就是Driver里面的Type。 __u8 driver[16]; driver名,通常为:uvcvideo __u8 card[32]; 设备名:厂商会填写。 __u8 bus_info[32]; bus,通常为:usb-hiusb-ehci-2.4 __u32 version; __u32 capabilities; 通常为:V4L2_CAP_VIDEO_CAPTURE| V4L2_CAP_STREAMING __u32 reserved[4];2. 枚举设备所支持的image format: VIDIOC_ENUM_FMTstruct v4l2_fmtdesc fmtdesc;fmtdesc.index = 0;fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(Handle, VIDIOC_ENUM_FMT,&fmtdesc);使用ioctl VIDIOC_ENUM_FMT依次询问,type为:V4L2_BUF_TYPE_VIDEO_CAPTURE。 index从0开始,依次增加,直到返回.Driver会填充结构体structv4l2_fmtdesc的其它内容,如果index超出范围,则返回-1struct v4l2_fmtdesc{ __u32 index;               // 需要填充,从0开始,依次上升。 enum v4l2_buf_type type;     //Camera,则填写V4L2_BUF_TYPE_VIDEO_CAPTURE __u32 flags;               // 如果压缩的,则Driver填写:V4L2_FMT_FLAG_COMPRESSED,否则为0  __u8 description[32];        // imageformat的描述,如:YUV 4:2:2 (YUYV) __u32 pixelformat;       //所支持的格式。如:V4L2_PIX_FMT_UYVY __u32 reserved[4];}; 这样,则知道当前硬件支持什么样的image format.下一步,则可以设置image 了。当然,设置之前,还可以读取当前缺省设置。3.得到和设置ImageFormat: VIDIOC_G_FMT, VIDIOC_S_FMT:3.1: 得到当前ImageFormat:struct v4l2_format Format;memset(&Format, 0, sizeof(structv4l2_format));Format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ioctl(Handle, VIDIOC_G_FMT, &Format);利用ioctl VIDIOC_G_FMT. 得到当前设置。因为Camera为CAPTURE设备,所以需要设置type为: V4L2_BUF_TYPE_VIDEO_CAPTURE然后Driver会填充其它内容。struct v4l2_format{ enum v4l2_buf_type type;  // Camera,则用户必须填写:V4L2_BUF_TYPE_VIDEO_CAPTURE union { struct v4l2_pix_format pix;   // usedby video capture and output devices struct v4l2_window win; struct v4l2_vbi_format vbi; struct v4l2_sliced_vbi_format sliced; __u8 raw_data[200]; } fmt;};因为是Camera, 所以采用pix. 现在分析如下:struct v4l2_pix_format{ __u32 width;   //Imagewidth in pixels. __u32 height;   // ImageHeight in pixels. __u32 pixelformat;  //Image格式,最常见的有:V4L2_PIX_FMT_YYUV enum v4l2_field field; //是否逐行扫描,是否隔行扫描.Sam通常采用V4L2_FIELD_NONE,逐行放置数据 (注1) __u32 bytesperline; //每行的byte数 __u32 sizeimage;    //总共的byte数,bytesperline* height enum v4l2_colorspace colorspace; //Thisinformation supplements the pixelformat andmust be set by the driver __u32 priv;};3.2:设置Image Format:VIDIOC_S_FMT之前通过VIDIOC_ENUM_FMT已经知道Device支持什么Format。所以就不用猜测了,直接设置吧。设置Image  Format ,利用 iocto VIDIOC_S_FMT.需要APPLICATION填写的Struct项目有:struct v4l2_format Format;Format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;Format.fmt.pix.width =  Width;Format.fmt.pix.height = Height;Format.fmt.pix.pixelformat=pixelformat;//V4L2_PIX_FMT_YUYV;Format.fmt.pix.field = field;io_rel = ioctl(Handle, VIDIOC_S_FMT,&Format);SamInfo:之前设置了Image Format,是指每一帧的数据格式,但Stream的行为呢,也需要设置,这就是下面所说的Stream 设置了。它就包含帧数设置和修改。4.得到和设置Stream信息:VIDIOC_G_PARM, VIDIOC_S_PARMStream信息,主要是设置帧数。4.1:得到Stream信息:struct v4l2_streamparm Stream_Parm;memset(&Stream_Parm, 0, sizeof(structv4l2_streamparm));Stream_Parm.type =V4L2_BUF_TYPE_VIDEO_CAPTURE; io_rel = ioctl(Handle, VIDIOC_G_PARM,&Stream_Parm);用户只需要填充type为V4L2_BUF_TYPE_VIDEO_CAPTURE。Driver就会把结构体中其它部分填充好。structv4l2_streamparm{ enum v4l2_buf_type type; union { struct v4l2_captureparmcapture; struct v4l2_outputparm output; __u8 raw_data[200]; } parm;};因为是Camera, 所以使用capture. 它是 structv4l2_captureparmstruct v4l2_captureparm{ __u32 capability;   //是否可以被timeperframe控制帧数。可以则:V4L2_CAP_TIMEPERFRAME __u32 capturemode;  //是否为高清模式。如果是:则设置为:V4L2_MODE_HIGHQUALITY。 高清模式会牺牲其它信息。通常设置为0。 struct v4l2_fract timeperframe; //帧数。 __u32 extendedmode; //定制的。如果不支持,设置为0 __u32 readbuffers; __u32 reserved[4];}; structv4l2_fract timeperframe;  //帧数。struct v4l2_fract { __u32 numerator;  // 分子。例:1 __u32 denominator; //分母。 例:30};4.2:设置帧数:struct v4l2_streamparm Stream_Parm;memset(&Stream_Parm, 0, sizeof(structv4l2_streamparm));Stream_Parm.type =V4L2_BUF_TYPE_VIDEO_CAPTURE; Stream_Parm.parm.capture.timeperframe.denominator=Denominator;;Stream_Parm.parm.capture.timeperframe.numerator =Numerator;io_rel = ioctl(Handle, VIDIOC_S_PARM,&Stream_Parm);请注意,哪怕ioctl返回0。也有可能没设置成功。所以需要再次Get。当然,哪怕Get发现设置成功。真正抓帧也可能没那么高。5.利用VIDIOC_G_CTRL得到一些设置:一些具体的设置,如曝光模式(ExposureType),曝光值(Exposure),增益(Gain),白平衡(WHITE_BALANCE),亮度(BRIGHTNESS),饱和度(SATURATION),对比度(CONTRAST)等信息。可以通过VIDIOC_G_CTRL得到当前值。用法:APP 填写结构体中的id. 通过调用VIDIOC_G_CTRL,driver会填写结构体中value项。struct v4l2_control ctrl;struct v4l2_control{ __u32 id; __s32 value;};以曝光模式,曝光,和增益为例; 曝光模式:struct v4l2_control ctrl;ctrl.id = V4L2_CID_EXPOSURE_AUTO;ret = ioctl(Handle, VIDIOC_G_CTRL,&ctrl);ctrl.value 则由Driver填写。告知当前曝光模式。有以下几个选择:enum  v4l2_exposure_auto_type {V4L2_EXPOSURE_AUTO = 0,V4L2_EXPOSURE_MANUAL = 1,V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,V4L2_EXPOSURE_APERTURE_PRIORITY = 3};曝光:struct v4l2_control ctrl;ctrl.id = V4L2_CID_EXPOSURE_ABSOLUTE;ret = ioctl(Handle, VIDIOC_G_CTRL,&ctrl);同样,driver填写ctrl.value. 内容为曝光值。增益:struct v4l2_control ctrl;ctrl.id = V4L2_CID_GAIN;ret = ioctl(Handle, VIDIOC_G_CTRL,&ctrl);同样,driver填写ctrl.value.内容为增益。6. 利用VIDIOC_QUERYCTRL得到设置具体信息:在很多情况下,我们并不知道如何设置一些信息,例如,曝光应该设置为多少?Driver能够接受的范围是多少?最大,最小值是多少?步长是多少?缺省值为多少?可以通过VIDIOC_QUERYCTRL得到。咱们还是以增益为例:struct v4l2_queryctrl  Setting;Setting.id = V4L2_CID_GAIN;ret = ioctl(Handle, VIDIOC_QUERYCTRL,&Setting);Driver就会填写结构体中所有信息。struct v4l2_queryctrl{ __u32 id; //用户设置。指定查找的是哪个ID。 enum v4l2_ctrl_type type; __u8 name[32]; //ID对应的名字。 __s32 minimum; __s32 maximum; __s32 step;   //步长 __s32 default_value; __u32 flags; __u32 reserved[2];};这样,就知道设置什么值是合法的了。那么,下一步就是设置了。7.利用VIDIOC_S_CTRL来设置:很简单,设置id和value.调用ioctl就好。还是以增益为例:struct v4l2_control ctrl;ctrl.id = V4L2_CID_GAIN;ctrl.value = Gain;ret = ioctl(Handle, VIDIOC_S_CTRL,&ctrl);有时候,硬件设置很奇怪,可以设置某个信息,却无法得到如何设置的信息。例如:HD-500可以设置增益。却无法得到该如何设置。8. 利用扩展Ctrl设置:焦距(FOUCE);注1:enum v4l2_fieldfield; 详解:

 

v4l2 Camera详细设置【转】