




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Linux之V4L2基础编程之内存映射:一、槪述Linux1!1操作一个设备一般都是打开(open),读取(read)和关闭(close)。使用Read的大多是一些字符型设备,然而对于显示屏或者摄像头这种字符设备而已,挨个字的读写将使得系统调用变得频繁,众所周之,系统调用对于系统而已是个不小的开销。于是有内存映射(mmap)等物,木例中将讲述在Linux下开发摄像头的一般过程以及使用Qt进行界面开发的实例。V4L2支持内存映射方式(mmap)和直接读取方式(read)來采集数据,前者一般用于连续视频数据的采集.后者常用于静态图片数据的采集。二、使用mmap方式获取摄像头数据的方式过程一般为:V
2、4L2采集视频操作基木按照打开视频设备、设宜视频格式、启动视频采集.循环处理视频数据、停止视频采集.关闭视频设备.具体操作通过ioctl等函数來实现。一般操作流程如下:L打开视频设备文件intfd=open(*/dev/videoO*O.RDWR);査询视频设备的能力,比如是否具有视频输入,或者音频输入输出等。ioctl(fd_v41,VIDIOC_QUERYCAP,4cP)设置视频釆集的参数:设置视频的制式.制式包括PAL/NTSC.使用VIDIOC.S.STD,&std.id)设置视频图像的采集窗口的大小,使用ioctl(fd41,VIDIOC.S.CROP,ftcrop)设置视频幀格式,
3、包括恢的点阵格式,宽度和高度等,使用ioctl(fd_v41,VIDIOC.SJVT,4fmt)设置视频的帧率,使用ioctl(fd.v41,VIDIOC.S.PARM,iparm)设置视频的旋转方式,使用ioctl(fLv41,VIDIOC.S.CTRL,4ctrl)向驱动申请视频流数据的帧缓冲区请求/申请若干个祯缓冲区,一般为不少于3个,使用ioctl(fd_v41,VIDIOC.REQBUFS,fareq),査询帧缓冲区在内核空间中的长度和偵移址ioctl(fd_v41,VIDIOC.QUERYBUF,4buf)应用程序通过内存映射,将帧缓冲区的地址映射到用户空间,这样就可以直接操作采集
4、到的帧了,而不必去复制.buffersi,start=mmap(NULL,buffersi.length,PROT.READ|PROT.WRITE,MAP-SHARED,fv41,buffersi.offset);&将申诸到的祯缓冲全部放入视频釆集输出队列,以便存放采集的数据.ioctl(fLv41,VIDIOC_QBUF,&buf)7.开始视频流数据的采集.ioctl(fd_v41,VIDIOC.STREAMON,Atype)&驱动将采集到的一帧视频数据存入输入队列第一个帧缓冲区,存完后将该帧缓冲区移至视频采集输出队列.应用程序从视频采集输出队列中取出已含有采集数据的祯缓冲区.ioctl(f
5、d_v41,VIDIOCJXJBUF,4buf),应用程序处理该帧缓冲区的原始视频数据.处理完后.应用程序的将该帧缓冲区重新排入输入队列,这样便可以循环采集数据ioctl(fLv41,VWIOC.QBUF,4buf)M复上述步骤8到10,直到停止采集数据。停止视频的采集。ioctl(fd_v41,VIDIOCSTREAMOFF,itype)释放申请的视频祯缓冲区unnap,关闭视频设备文件close(fd_v41)以上的程序流程,包含了视频设备采集连续的视频数据的逻辑关系。而在实际运用中往往还要加入对视频数据进行处理(如圧缩编码)的工作.否则.视频流数据虽相当大,需要很大的存储空间和传输带宽。
6、Mmap就是所谓内存映射。很多设备带有自己的数据缓冲区,或者驱动木身在内核空间中维护一片内存区域.为了让用户空间程序安全地访问,内核往往要从设备内存或者内核空间内存复制数据到用户空间。这样一來便多了复制内存这个环节,浪费了时间。因此mmap就将目标存储区域映射到一个用户空间的一片内存.这样用户进程访问这片内存时,内孩将自动转换为访问这个目标存储区。这种转换往往是地址的线性变化而已(很参设备的存储空间在所谓外闌总线地址空间(X86)或者总的地址空间(ARM)上都是连续的),所以不必担心其转换的效率。三、打开设备并进行错误检査staticintopen_cam(void)intfd=-1;stru
7、ctstatst:if(-1=stat(cam_name&st)fprintf(stderr,Cannotidentify弔s:策d,%sn:cam_name,errno,strerror(errno):exit(EXIT.FAILURE):if(!S_ISCHR(st.st.mode)fprintf(stderr,%sisnodevicen,cam_name):exit(EXIT.FAILURE):fd=open(cam_name,O_RDWR/*required/0_NONBL0CK0):if(-l=fd)fprintf(stderr,Cannotopen飞s:%d,%sn*,cam_na
8、meterrno,strerror(errno):returnfd:四、获取设备信息/*衬*ioctl(fd,VIDIOCQUERYCAP,&cap),这个ioctl函数用來确认这个设备是否和内核驱动相兼容.如果不兼容则返回EINVAL,并且获収这个摄像头的相关性能参数。if(!(cap.capabilities&V4L2_CAPJrIDEO_CAPTURE),获取摄像头参数后判断这个设备是否是videocapturedevice。if(!(cap.capabilities&V4L2_CAP_STREAMING)判断这个设备是否支持视频流方式。*/structv412_capabilityca
9、pif(ioctl(fd,VIDIOC.QUERYCAP,&cap)=FAILURE)printf(ErrorinVIDIOC.QUERYCAPofdevice%snz;CAPTURE.DEVICE):elseif(!(cap.capabilities&V4L2_CAP_VIDEO_CAPTVRE)printf(z,%sisnovideocapturedevicenzCAPTURE_DEVICE):elseprintfC%sisavideocapturedevicen*,CAPTURE_DEVICE);if(!(cap.capab订ities&V1L2_CAP_READWRITE)printf
10、(z,Itcannotreadn):elseprintfCltcanreadn*):if(!(cap.capabilities&V4L2_CAP_STREAMING)printf(Itcannotstreamingn);elseprintfCltcanstreamingn);)五.査询或设置视频的制式或者帧格式/*衬*设迢视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。査询并显示所有支持的格式:VIDIOC_ENUM_FMT査看或设迢出前格式:VIDIOC_G_FMT,VIDIOC.S.FMT检査是否支持某种格式:VIDIOC_TRY_FMT衬*衬*衬*申*申*衬*申
11、*衬*衬*衬*衬*枠*衬*衬*衬*衬*衬*申*衬/structv412_formatfmt:memset(&fmt,0,sizoef(fmt);fmt.type=Y4L2_BUF_TYPE_VIDEO_CAPTl;RE;fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_NOW;/采样灸刘,如YUV1:2:2fmt.fmt.pix.field=V4L2_FIELD_N0NE;/采样区域,如隔行采样;fmt.fmt.pix.width=D1_WIDTH;fmt.fmt.pix.height=Dl.HEIGHT;printf(VIDIOC.S.FMT:setformattob
12、eVlL2_PIX_FMT_UYVYn);if(ioctl(fd,VIDIOC.S.FMT,&fmt)=FAILURE)printf(ErrorinVIDIOC_S_FMTn);returnFAILURE;elseprintf(width=%dn,fmtfmtpixwidth);printf(height=%dn,fmtfnrtpixheight);if(fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_N0W)printf(Format=WL2_PIX_FMT_RGB565n);elseprintf(Nottherightformatn);Ax设置视频采集的帧率结构体
13、v412_streamparm來描述视频流的属性,它由type和共用体pann构成。type同上,由于选的是V4L2_BUF_TYPE_VIOEO_CAPTURE.所以仅需设定parm中的v412_capturepann型结构体capture即可。在其中,v412_fract型结构体timeperframe表示平均每一帧所占的时间,由其元素numerator和denominator共同抉定,该时长为numerator/denominator分母是需要设定的帧率,而分子是1。而capturemode则表示采集模式.采集高质量图片值为般设为0。賦值之后,用ioctl函数通过这个结构体对fd_v41
14、2进行设苣nstructv412_streamparmenumv412_buf_typetype;unionstructv412_captureparmcapture;structv412_outputparmoutput;_u8raw_data200;/*user-defined*/;parm;注:这里补充一点streamparam方面的spec:一般來说当前的帧率是由当前的视频标准來决定的,如果默认采用视频标准的帧率就不需要设宜流参数,但是如果想获得或者设定自己的帧率就需要使用VIDIOC.G.PARM,VIDIOC_S_PARM:intioctl(intfd,intrequest,v41
15、2_streamparm*argp);structv412_stramparam包含以下主要成员:enumv412_buf_typetypeunionparamstructv412_captureparmcapturestructv412outputparamoutput婆注总的是在这里.不管是overaly还是capture,这里的buffertype都是选择的V4L2_BUF_TYPE_VIDE0_CAPTURE.structv412captureparam包含以下主要成员:_u32capturemode/是否支持高质址图像捕捉structv412fracttimeperframe/设宜帧
16、率.通过分母分子实现这里要注意的是,通过VIDIOC.S.PARM设置帧率不一定成功.driver会根据锁件限制來设置这些参数,所以一般设置以后可以通过VIDIOC_G_PARM來看设定是否成功。/*衬*设迢视频采集的帧率及采集模式*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬/structv412_streamparmparm;parm.type=V4L2_BUF_TYPE_VIDE0_CAPTURE:parmparm.capture.timeperframe.numerator=1;parm.parm.capture.timeperframe.denominato
17、r=30;parm.parm.capturecapturemode=1:if(ioctl(fd,VIDIOC.S.PARM,&parm)0)printfCVIDIOC.S.PARMfailedJ;returnFAILURE;if(ioctl(fd,VIDIOC.G.PARM,&parm)0)printf(ErrorVIDIOC_S_PARMn):returnFAILURE;printf(streamparm:ntnumeratordXnXtdenominatoridXnXtcapturemodeidXnXn,parm.parmcapturetimeperframenumerator,parm.
18、parmcapturetimeperframedenominator,parm.parmcapturecapturemode);七、向驱动申请帧缓冲(一)向设备驱动申请缓冲区VIDIOCJ(EQBUFS/*请求一定数:的缓冲区。但是不一定能请求到那么多。据体还得看返回的数址。这里请求了NUM_BUFS_CAP块缓存区.并将其类空设为MMAP型。向驱动申请帧缓冲区的请求,里面包含申请的个数:*/structv412requestbuffersreq;memset(&req,0,sizeof(req);reqbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuf.m
19、emory=V4L2JEMORY.MMAP;reqbuf.count=NUM_BUFS_CAP;f(FAILURE=ioctl(fd,VIDIOC.REQBUFS,&reqbuf)/VIDIOC_REQBUFS:分配内存if(errno=EINVAL)printf(Videocapturingormmapstrearningisnotsupportedn):elseperror(VIDIOC.REQBUFS);returnFAILURE;printf(successinVIDEO_REQBUFSn);if(reqbufcount1)printf(NotenoughbuffermemoryXn)
20、;returnFAILURE;”printf(reqbufcountisbiggerthan1);获取缓冲帧的地址及长度/*函数:void*calloc(unsignedn,unsignedsize):功能:在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针:如果分配不成功,返回NULL。获取缓冲区的信息在操作之前,我们必须婆能记录下我们申请的缓存区,并在最后使用munmap释放它们。这里使用结构体:typedefstructImgBuffer_u8*start;size_tlength;ImgBuffer;以及buffer数虽intnumBufs來表示*
21、衬*衬*衬*申*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬*衬/imgBuffers=(ImgBuffer*)calloc(reqbufcount,_ieof(*imgBuffers):if(imgBuffers=NULL)printf(Failedincallocn);returnFAILURE;”printf(successincallocn);/*获取缓冲帧的地址,长度:VIDIOC.QUERYBUF功能:査询已经分配的V4L2的视频缓冲区的相关信息,包括视频缓冲区的使用状态.在内核空间的偏移地址、缓冲区长度等。在应用程序设计中通过调VIDIOC.QUERYBUF來获取内孩空间的
22、视频缓冲区信息,然后调用函数mmap把内核空间地址映射到用户空间.这样应用程序才能够访问位于内核空间的视频缓冲区。参数说明:参数类型为V4L2缓冲区数据结构类型structv412_buffer:返回值:执行成功时,函数返回值为0:structv412_buffer结构体变:fi中保存了指令的缓冲区的相关信息:一般情况下,应用程序中调用VIDIOC.QUERYBUF取得了内核缓冲区信息后,紧接着调用mmap函数把内核空间地址映射到用户空间.方便用户空间应用程序的访问。*/structv412_bufferbuffer;/structv412_buffer:代表驱动中的一帧for(numBufs
23、=0;numBufsreqbufcount:numBufs+)memset(&buffer,0,sizeof(buffer);buffer.type=reqbuftype;buffer,memory=V4L2_MEM0RY_MMAP;bufferindex=numBufs;bufferisinthekernelspace,imgBuffersintheuserspaceif(FAILURE=ioctl(fd,VIDIOC.QUERYBUF,buffer)perror(VIDIOC.QUERYBUF);returnFAILURE;printf(successinVIDEOQUERYBUFnzz);printf(bufferlength=%dn,bufferlen
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 基于人工智能的初中信息技术课程改革研究论文
- 艺术治疗师管理制度
- 芳烃油安全管理制度
- 茶叶溯源码管理制度
- 院校培训部管理制度
- 设备安装方案
- 保险公司保险销售营销渠道风险管理策略模板课件演示文档资料-早会分享激励专题培训资料
- 财务会计与流动资产管理知识分析记录(一)
- 自动化软件质量保证
- 褐色国风汉族民歌宣传介绍教育课件
- 【模板】纯化水微生物限度检查法验证报告
- 样品管理程序检验科程序文件
- 04D701-3 电缆桥架安装
- 叉车操作安全规范(图片版)课件
- 前置胎盘临床诊断与处理指南课件
- 《Python程序设计(第3版)》完整版PDF
- 15D501建筑物防雷设施安装图集
- 房屋安全简易鉴定表
- 《水产养殖前沿讲座》课程教学大纲
- 渔业成品油价格补助专项资金管理暂行办法
- 卵巢交界性肿瘤课件
评论
0/150
提交评论