Camera的可设置项极多,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_QUERYCAP

struct 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_CAPTURE 0x00000001     The device supports the Video    Capture interface.

V4L2_CAP_VIDEO_OUTPUT   0x00000002     The device supports the Video    Output interface.

V4L2_CAP_VIDEO_OVERLAY 0x00000004     The device supports the Video    Overlay interface.

A video overlay device typically stores captured images directly in the video memory   of a graphics card,with hardware clipping and scaling.

V4L2_CAP_VBI_CAPTURE     0x00000010 The device supports the Raw  VBI Capture interface, providing Teletext and Closed Caption   data.

V4L2_CAP_VBI_OUTPUT     0x00000020      The device supports the Raw  VBI Output interface.

V4L2_CAP_SLICED_VBI_CAPTURE  0x00000040 The device supports the Sliced VBI Capture interface.

V4L2_CAP_SLICED_VBI_OUTPUT   0x00000080 The device supports the Sliced VBI Output interface.

V4L2_CAP_RDS_CAPTURE    0x00000100          [to be 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_STREAMING 0x04000000  



看起来非常熟悉吧。事实上就是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_FMT

struct 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会填充结构体struct v4l2_fmtdesc的其他内容。假设index超出范围,则返回-1。

struct 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];         // image format的描写叙述,如:YUV 4:2:2 (YUYV)

 __u32 pixelformat;        //所支持的格式。如:V4L2_PIX_FMT_UYVY

 __u32 reserved[4];

}; 



这样。则知道当前硬件支持什么样的image format. 下一步,则能够设置image 了。当然。设置之前,还能够读取当前缺省设置。

3. 得到和设置Image Format: VIDIOC_G_FMT, VIDIOC_S_FMT:

3.1: 得到当前Image Format:

struct v4l2_format Format;

memset(&Format, 0, sizeof(struct v4l2_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;    // used by 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;    //Image width in pixels.

 __u32 height;   // Image Height 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;  //This information supplements the pixelformat and must 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_PARM

Stream信息,主要是设置帧数。

4.1:得到Stream信息:

struct v4l2_streamparm Stream_Parm;



memset(&Stream_Parm, 0, sizeof(struct v4l2_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就会把结构体中其他部分填充好。

struct v4l2_streamparm

{

 enum v4l2_buf_type type;

 union

 {

 struct v4l2_captureparm capture;

 struct v4l2_outputparm output;

 __u8 raw_data[200];

 } parm;

};



由于是Camera, 所以使用capture. 它是 struct v4l2_captureparm



struct 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];

};

struct v4l2_fract timeperframe;  //帧数。

struct v4l2_fract {

 __u32 numerator;  // 分子。例:1

 __u32 denominator; //分母。 例:30

};



4.2:设置帧数:

struct v4l2_streamparm Stream_Parm;

memset(&Stream_Parm, 0, sizeof(struct v4l2_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得到一些设置:

一些详细的设置,如曝光模式(Exposure Type),曝光值(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来设置:

非常easy,设置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_field field; 具体解释:

9.设定分辨率:

struct v4l2_control control;

memset(&control, 0, sizeof(control));

control.id = V4L2_CID_AUTO_WHITE_BALANCE;

control.value = 1;

if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 

{

printf("Couldn't set auto white balance!\n");


//return -1;


}



memset(&control, 0, sizeof(control));

control.id = V4L2_CID_EXPOSURE_AUTO;

control.value = 1;



if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 

{

printf("Couldn't set auto exposure!\n");


//return -1;


}



memset(&control, 0, sizeof(control));

control.id = V4L2_CID_HFLIP;

control.value = 1;

if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 

{

printf("Couldn't set h flip!\n");


//return -1;


}





memset(&control, 0, sizeof(control));

control.id = V4L2_CID_VFLIP;

control.value = 1;

if (ioctl(fd, VIDIOC_S_CTRL, &control) < 0) 

{

printf("Couldn't set v flip!\n");


//return -1;


}

Linux下实现视频读取(二)---camera參数设定的更多相关文章

  1. Linux下实现视频读取(三)---Buffer的准备和数据读取

    前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度.曝光时间,帧数,增益.白平衡等.今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取. 1. 初始化 Memory ...

  2. Linux下实现视频读取

    V4L(video4linux是一些视频系统,视频软件.音频软件的基础,经常时候在需要采集图像的场合,如视频监控,webcam,可视电话,经常使用在embedded linux中是linux嵌入式开发 ...

  3. 嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍

    **************************************************************************************************** ...

  4. Linux下的视频字幕编辑

    一.Linux下的字幕编辑软件 常用的有subtitleeditor, gnome-subtitles, gaupol 1.gnome-subtitles:不支持多字幕文件批量处理2.gaupol:全 ...

  5. Linux下从视频提取音频的方法

    Linux下可以利用mencoder将视频里的音频提取出来.方法如下: 1.首先安装mencoder.对于Ubuntu来说,软件仓库里就有mencoder,可直接输入如下命令安装 sudo apt-g ...

  6. linux下动态链接库解决方案(二)

    以前写过一个关于linux下用c++写动态链接库无法通过的解决方案,今天看到<linux C程序设计-王者归来>这本书,书中有个更容易的解决方案,特此记录下来 书中使用的是c语言,我改用c ...

  7. Linux下修改当前用户的最大线程数和 open files

    1 查看当前用户的线程 ulimit -a 2 修改配置文件 vi /etc/security/limits.d/90-nproc.conf 3 改完即可生效 4 修改可打开的最大文件数 vi  /e ...

  8. Linux 下 Bash配置文件读取

    Linux安装时可能要修改的配置文件:/etc/profile./etc/bashrc(ubuntu没有这个文件,对应地,其有/etc/bash.bashrc文件.我用的是ubuntu系统,所以下面将 ...

  9. linux 下shell程序(二)

    输入和输出 输入指的是Shell程序读入数据.有从文件读取.从用户输入读取等方式读入数据.输出指的是Shell程序的运行 结果的处理,可以显示到屏幕或保存到文件. 用ceho命令输出结果 echo $ ...

随机推荐

  1. 数据指令MOV

    MOV分成三类,第一类不需要拓展(MOV),第二类做符号拓展(MOVS),第三类做零拓展(MOVZ),拓展类型根据源操作数决定. 这三类根据操作的数据类型其后可加l,w,b. MOV操作的操作数可以是 ...

  2. Linux常用C函数---内存控制篇

    函数讲解部分参考http://net.pku.edu.cn/~yhf/linux_c/ calloc(配置内存空间) 相关函数 malloc,free,realloc,brk 表头文件 #includ ...

  3. C与C++动态分配二维数组

    C: C中使用函数malloc和free两个函数. //动态分配M*N维 int **a=(int **)malloc(sizeof(int*)*M); ;i<M;i++) a[i]=(int ...

  4. 窥探 kernel --- 进程调度的目标,nice值,静态优先级,动态优先级,实时优先级

    http://blog.chinaunix.net/uid-24227137-id-3595610.html 窥探 kernel --- 进程调度的目标,nice值,静态优先级,动态优先级,实时优先级 ...

  5. MD5和SHA512Managed ——哈希算法

    本文来自:http://www.cnblogs.com/chuncn/archive/2008/02/26/1082418.html C#的哈希 哈希算法是啥?哈希英文hash,是一种数学算法,它能把 ...

  6. 关于AndroidManifest.xml

    一.关于AndroidManifest.xml http://themeforest.net/item/metro-vibes-showcase-html-theme/full_screen_prev ...

  7. HDOJ3374 String Problem 【KMP】+【最小表示法】

    String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. Basic Concepts of Block Media Recovery

    Basic Concepts of Block Media Recovery Whenever block corruption has been automatically detected, yo ...

  9. nginx添加需要代理的域名 配置

    dap.cns.360buy.com为需要nginx代理的域名,被代理的端口为:8089,配置需要在${nginx_home}/conf/nginx.conf的文件中加入如下配置即可 upstream ...

  10. oracle 定义数据完整性

    1. 定义主键约束 1.1 在创建表时定义主键约束 create table student(name varchar2(8),studentid varchar2(10) primary key,s ...