V4L2超详细讲解_第1页
V4L2超详细讲解_第2页
V4L2超详细讲解_第3页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、内文内容主要来源于网络定义V4L2(VideoForLinuxTwo)是内核提供给应用程序访问音、视频驱动的统一接口。1. 工作流程:打开设备一检查和设置设备属性一设置帧格式一设置一种输入输出方法(缓冲区管理)循环获取数据关闭设备。2. 设备的打开和关闭:#includeintopen(constchar*device_name,intflags);#includeintclose(intfd);例:intfd=open(/dev/video0”,O_RDWR);/打开设备close(fd);/关闭设备注意:V4L2的相关定义包含在头文件中.查询设备属性:VIDIOC_QUERYCAP相关函数

2、:intioctl(intfd,intrequest,structv4l2_capability*argp);相关结构体:structv4l2_capabilityu8driver16;/驱动名字u8card32;/设备名字u8bus_info32;/设备在系统中的位置u32version;/驱动版本号u32capabilities;/设备支持的操作u32reserved4;/保留字段;capabilities常用值:V4L2_CAP_VIDEO_CAPTURE/是否支持图像获取例:显示设备信息structv4l2_capabilitycap;ioctl(fd,VIDIOC_QUERYCAP,

3、&cap);printf(“DriverName:%snCardName:%snBusinfo:%snDriverVersion:%u.%u.%un,cap.driver,cap.card,cap.bus_info,(cap.version6)&0XFF(cap.version8)&0XFFcap.version&0XFF;设置视频的制式和帧格式制式包括PAL,NTSC相关函数:intioctl(帧的格式个包括宽度和高度等。intfd,intrequest,structv4l2_fmtdesc*argp);intioctl(相关结构体:v4l2_cropcapv4l2_cropcapv4l2_

4、cropcapintfd,intrequest,structv4l2_format*argp);结构体用来设置摄像头的捕捉能力,在捕捉上视频时应先先设置的type域,再通过VIDIO_CROPCAP操作命令获取设备捕捉能力的参数,结构体中,包括bounds(最大捕捉方框的左上角坐标和宽高),defrect保存于(默认捕捉方框的左上角坐标和宽高)等。v4l2_format结构体用来设置摄像头的视频制式、帧格式等,在设置这个参数时应先填v4l2_format的各个域,如type(传输流类型),fmt.pix.width(宽),fmt.pix.heigth(高),fmt.pix.field(采样区域

5、,如隔行采样),fmt.pix.pixelformat(样类型,如YUV4:2:2),然后通过VIDIO_S_FMT操作命令设置视频捕捉格式。如下图所示:5.1查询并显示所有支持的格式:VIDIOCENUMFMT相关函数:intioctl(intfd,intrequest,structv4l2_fmtdesc*argp);相关结构体:structv4l2fmtdesc(u32index;/要查询的格式序号,应用程序设置enumv4l2_buf_typetype;/帧类型,应用程序设置u32flags;/是否为压缩格式u8description32;/格式名称u32pixelformat;/格式

6、u32reserved4;/保留;例:显示所有支持的格式structv4l2_fmtdescfmtdesc;fmtdesc.index=0;fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTUFpEi;ntf(Supportformat:n);while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)(printf(t%d.%sn,fmtdesc.index+1,fmtdesc.description);fmtdesc.index+;5.2查看或设置当前格式:VIDIOC_G_FMT,VIDIOC_S_FMT检查是否支持某种格式:VIDI

7、OC_TRY_FMT相关函数:intioctl(intfd,intrequest,structv4l2_format*argp);相关结构体:structv4l2_formatenumv4l2_buf_typetype;/帧类型,应用程序设置unionfmtstructv4l2_pix_formatpix;/视频设备使用structv4l2_windowwin;structv4l2_vbi_formatvbi;structv4l2_sliced_vbi_formatsliced;u8raw_data200;一;structv4l2_pix_formatu32width;/帧宽,单位像素u32h

8、eight;/帧高,单位像素u32pixelformat;/帧格式enumv4l2_fieldfield;u32bytesperline;u32sizeimage;enumv4l2_colorspacecolorspace;u32priv;例:显示当前帧的相关信息structv4l2_formatfmt;fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURoctl(fd,VIDIOC_G_FMT,&fmt);printf(“Currentdataformatinformation:ntwidth:%dntheight:%dnfmt.fmt.pix.width,fmt.fmt.

9、pix.height);structv4l2_fmtdescfmtdesc;fmtdesc.index=0;fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)if(fmtdesc.pixelformat&fmt.fmt.pix.pixelformat)printf(tformat:%sn”,fmtdesc.description);break;fmtdesc.index+;例:检查是否支持某种帧格式structv4l2_formatfmt;fmt.type=V4L2_BUF

10、_TYPE_VIDEO_CAPTURE;fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_RGB32;if(ioctl(fd,VIDIOC_TRY_FMT,&fmt)=-1)if(errno=EINVAL)printf(“notsupportformatRGB32!n”);6.图像的缩放VIDIOC_CROPCAP相关函数:intioctl(intfd,intrequest,structv4l2_cropcap*argp);intioctl(intfd,intrequest,structv4l2_crop*argp);intioctl(intfd,intrequest,

11、conststructv4l2_crop*argp);相关结构体:Cropping和scaling主要指的是图像的取景范围及图片的比例缩放的支持。Crop就是把得到的数据作一定的裁剪和伸缩,裁剪可以只取样我们可以得到的图像大小的一部分,剪裁的主要参数是位置、长度、宽度。而scale的设置是通过VIDIOC_G_FMT和VIDIOC_S_FMT来获得和设置当前的image的长度,宽度来实现的。看下图我们可以假设bounds是sensor最大能捕捉到的图像范围,而defrect是设备默认的最大取样范围,这个可以通过VIDIOC_CROPCAP的ioctl来获得设备的crap相关的属性v4l2_cr

12、opcap,其中的bounds就是这个bounds,其实就是上限。每个设备都有个默认的取样范围,就是defrect,就是defaultrect的意思,它比bounds要小一些。这个范围也是通过VIDIOC_CROPCAP的ioctl来获得的v4l2_cropcap结构中的defrect来表示的,我们可以通过VIDIOC_G_CROP和VIDIOC_S_CROP来获取和设置设备当前的crop设置。6.1设置设备捕捉能力的参数相关函数:intioctl(intfd,intrequest,structv4l2_cropcap*argp);相关结构体:structv4l2_cropcapenumv4l

13、2_buf_typetype;/数据流的类型,应用程序设置structv4l2_rectbounds;/这是camera的镜头能捕捉到的窗口大小的局限structv4l2_rectdefrect;/定义默认窗口大小,包括起点位置及长,宽的大小,大小以像素为单位structv4l2_fractpixelaspect;/定义了图片的宽高比;6.2设置窗口取景参数VIDIOC_G_CROPffiVIDIOC_S_CROP相关函数:intioctl(intfd,intrequest,structv4l2_crop*argp);intioctl(intfd,intrequest,conststructv

14、4l2_crop*argp);相关结构体:structv4l2_crop(enumv4l2_buf_typetype;/应用程序设置structv4l2_rectc;videoInputsandOutputsVIDIOC_G_INPUT和VIDIOC_S_INPUT用来查询和选则当前的input,一个video设备节点可能对应多个视频源,比如saf7113可以最多支持四路cvbs输入,如果上层想在四个cvbs视频输入间切换,那么就要调用ioctl(fd,VIDIOC_S_INPUT,&input)来切换。VIDIOC_G_INPUTandVIDIOC_G_OUTPUT返回当前的videoinp

15、ut和output的index.相关函数:intioctl(intfd,intrequest,structv4l2_input*argp);相关结构体:structv4l2_input(_u32index;/*Whichinput*/_u8name32;/*Label*/_u32type;/*Typeofinput*/_u32audioset;/*Associatedaudios(bitfield)*/_u32tuner;/*Associatedtuner*/v4l2_std_idstd;_u32status;_u32reserved4;T我们可以通过VIDIOC_ENUMINPUTandVI

16、DIOC_ENUMOUTPUT别列举一个input或者output的信息,我们使用一个v4l2_input结构体来存放查询结果,这个结构体中有一个index域用来指定你索要查询的是第几个input/ouput,如果你所查询的这个input是当前正在使用的,那么在v4l2_input还会包含一些当前的状态信息,如果所查询的input/output不存在,那么回返回EINVAL错误,所以,我们通过循环查找,直到返回错误来遍历所有的input/output.VIDIOC_G_INPUTandVIDIOC_G_OUTPUT返回当前的videoinput和output的index.例:列举当前输入视频所

17、支持的视频格式structv4l2_inputinput;structv4l2_standardstandard;memset(&input,0,sizeof(input);/首先获得当前输入的index,注意只是index,要获得具体的信息,就的调用列举操作if(-1=ioctl(fd,VIDIOC_G_INPUT,&input.index)perror(”VIDIOC_G_INPUT);exit(EXIT_FAILURE);/调用歹0举操作,获得input.index对应的输入的具体信息if(-1=ioctl(fd,VIDIOC_ENUMINPUT,&input)perror(”VIDIO

18、C_ENUM_INPUT;exit(EXIT_FAILURE);printf(”Currentinput%ssupports:n”,);memset(&standard,0,sizeof(standard);standard.index=0;/歹0举所有的所支持的standard,如果standard.id与当前input的input.std有共同的bitflag,意味着当前的输入支持这个standard,这样将所有驱动所支持的standard歹U举一个遍,就可以找到该输入所支持的所有standard了。while(0=ioctl(fd,VIDIOC_ENUMSTD,&st

19、andard)if(standard.id&input.std)printf(”sn”,);standard.index+;/*EINVALindicatestheendoftheenumeration,whichcannotbeemptyunlessthisdevicefallsundertheUSBexception.*/if(errno!=EINVAL|standard.index=0)perror(”VIDIOC_ENUMSTD;exit(EXIT_FAILURE);Videostandards相关函数:v4l2_std_idstd_id;/这个就是个64bi

20、t得数intioctl(intfd,intrequest,structv4l2_standard*argp);相关结构体:typedefu64v4l2_std_id;structv4l2_standardu32index;v4l2_std_idid;u8name24;structv4l2_fractframeperiod;/*Frames,notfields*/u32framelines;u32reserved4;当然世界上现在有多个视频标准,如NTSCPAL他们又细分为好多种,那么我们的设备输入/输出究竟支持什么样的标准呢?我们的当前在使用的输入和输出正在使用的是哪个标准呢?index,然后

21、查出它的属性,的信息进行个集合,而这个我们怎么设置我们的某个输入输出使用的标准呢?这都是有方法的。查询我们的输入支持什么标准,首先就得找到当前的这个输入的在其属性里面可以得到该输入所支持的标准,将它所支持的各个标准与所有的标准比较,就可以获知所支持的各个标准的属性。一个输入所支持的标准应该是一集合是用bit与的方式用一个64位数字表示。因此我们所查到的是一个数字。这个就Example:Informationaboutthecurrentvideostandardv4l2_std_idstd_id;/是个64bit得数structv4l2_standardstandard;/VIDIOC_G_S

22、T就是获得当前输入使用的standard,不过这里只是得到了该标准的id/即flag,还没有得到其具体的届性信息,具体的届性信息要通过列举操作来得到。if(-1=ioctl(fd,VIDIOC_G_STD,&std_id)/获得了当前输入使用的standard/NotewhenVIDIOC_ENUMSTDWaysreturnsEINVALthisisnovideodevice/oritfallsundertheUSBexception,andVIDIOC_G_STDeturningEINVAL/isnoerror.perror(”VIDIOC_G_STD);exit(EXIT_FAILURE)

23、;memset(&standard,0,sizeof(standard);standard.index=0;/从第一个开始歹U举/VIDIOC_ENUMSTffi来列举所支持的所有的video标准的信息,不过要先给standard/结构的index域制定一个数值,所歹U举的标准的信息届性包含在standard里面,/如果我们所列举的标准和std_id有共同的bit,那么就意味着这个标准就是当前输/入所使用的标准,这样我们就得到了当前输入使用的标准的届性信息while(0=ioctl(fd,VIDIOC_ENUMSTD,&standard)if(standard.id&std_id)printf

24、(”Currentvideostandard:%sn”,);exit(EXIT_SUCCESS);standard.index+;/*EINVALindicatestheendoftheenumeration,whichcannotbeemptyunlessthisdevicefallsundertheUSBexception.*/if(errno=EINVAL|standard.index=0)perror(”VIDIOC_ENUMSTD;exit(EXIT_FAILURE);申请和管理缓冲区应用程序和设备有三种交换数据的方法,直接read/write、内存映射(m

25、emorymapping)和用户指针。这里只讨论内存映射(memorymapping)。9.1向设备申请缓冲区VIDIOC_REQBUFS相关函数:intioctl(intfd,intrequest,structv4l2_requestbuffers*argp);相关结构体:structv4l2_requestbuffersu32count;/缓冲区内缓冲帧的数目enumv4l2_buf_typetype;/缓冲帧数据格式enumv4l2_memorymemory;/区别是内存映射还是用户指针方式u32reserved2;注:enumv4l2_memoyV4L2_MEMORY_MMAP,V4L

26、2_MEMORY_USERPTR);/count,type,memory都要应用程序设置例:申请一个拥有四个缓冲帧的缓冲区structv4l2_requestbuffersreq;req.count=4;req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory=V4L2_MEMORY_MMAP;ioctl(fd,VIDIOC_REQBUFS,&req);9.2获取缓冲帧的地址,长度:VIDIOC_QUERYBUF相关函数:intioctl(intfd,intrequest,structv4l2_buffer*argp);相关结构体:structv4l2_b

27、ufferu32index;/buffer序号enumv4l2_buf_typetype;/buffer类型u32byteused;/buffer中已使用的字节数u32flags;/区分是MMAF是USERPTRenumv4l2_fieldfield;structtimevaltimestamp;/获取第一个字节时的系统时间structv4l2_timecodetimecode;u32sequence;/队歹U中的序号enumv4l2_memorymemory;/IO方式,被应用程序设置unionmu32offset;/缓冲帧地址,只对MMAPt效unsignedlonguserptr;u32

28、length;/缓冲帧长度u32input;u32reserved;;9.3内存映射MMAP及定义一个结构体来映射每个缓冲帧。相关结构体:structbuffervoid*start;unsignedintlength;*buffers;相关函数:#includevoid*mmapVoid*addr,size_tlength,intprot,intflags,intfd,off_toffset)/addr映射起始地址,一般为NULL,让内核自动选择/length被映射内存块的长度/prot标志映射后能否被读写,其值为PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NON

29、E/flags确定此内存映射能否被其他进程共享,MAP_SHARED,MAP_PRIVATE/fd,offset,确定被映射的内存地址返回成功映射后的地址,不成功返回MAP_FAILED(void*)-1)相关函数:intmunmap(void*addr,size_tlength);/断开映射/addr为映射后的地址,length为映射后的内存长度例:将四个已申请到的缓冲帧映射到应用程序,用buffers指针记录。buffers=(buffer*)calloc(req.count,sizeof(*buffers);if(!buffers)/映射fprintf(stderr,Outofmemory/n);exit(EXIT_FAILURE);for(unsignedintn_buffers=0;n_buffersreq.count;+n_buffers)(structv4l2_bufferbuf;memset(&buf,0,sizeof(buf);buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory=V4L2_MEMORY_MMAP;buf.index=n_buffers;/查询序号为n_buffers的缓冲区,得到其起始物理地址和大小if(-

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论