V4L2应用程序详解

合集下载

v4l2框架流程

v4l2框架流程

v4l2框架流程
v4l2(Video For Linux 2)框架是Linux系统中用于处理视频设备的框架,包括了视频设备的控制、图像采集、图像输出等功能。

v4l2框架的流程如下:
1. 驱动初始化:在Linux系统启动时,v4l2框架会初始化其对于视频设备的驱动程序,包括找到设备、设备的分配和配置等。

2. 应用程序打开设备:应用程序需要使用摄像头或其他视频设备时,会使用v4l2的API打开设备进行访问。

3. 设备控制:应用程序对于视频设备进行管控,包括设备的各种设置,如视频格式、帧率等。

4. 图像采集:当视频设备开始采集图像时,v4l2框架会将图像数据传输到应用程序缓冲区。

5. 应用程序处理数据:应用程序从缓冲区中读取图像数据,可以对图像数据进行处理、展示或保存等。

6. 图像输出:当应用程序想要将图像数据输出到设备上,v4l2框架会将图像数据传送到设备的缓冲区。

7. 设备关闭:应用程序使用完设备后,会关闭设备以释放资源。

总的来说,v4l2框架主要涉及到设备的初始化、控制、数据传输等过程,通过对不同视频设备的控制,获取和处理设备所采集的图像数据,并在需要的时候进行输出。

v4l2controller 用法

v4l2controller 用法

v4l2controller 是一个用于控制视瓶设备的命令行工具,可以通过该工具来设置视瓶设备的参数、捕获视瓶数据、控制视瓶设备的属性等。

v4l2controller 主要用于 Linux 系统下的视瓶设备,如摄像头、视瓶采集卡等。

一、安装 v4l2controller1. 在终端中输入以下命令安装 v4l2controller:```sudo apt-get install v4l2-ctl```2. 安装完成后,可以通过以下命令来验证 v4l2controller 是否安装成功:```v4l2-ctl --version```二、查看视瓶设备的信息1. 使用以下命令可以列出系统中所有的视瓶设备:```v4l2-ctl --list-devices```2. 通过以下命令可以查看指定视瓶设备的详细信息:```v4l2-ctl -d /dev/video0 --all```三、设置视瓶设备的参数1. 设置视瓶设备的分辨率:```v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=1 ```2. 设置视瓶设备的帧率:```v4l2-ctl -d /dev/video0 --set-parm=30```3. 设置视瓶设备的曝光模式:```v4l2-ctl -d /dev/video0 --set-ctrl=exposure=100```四、捕获视瓶数据1. 使用以下命令可以捕获视瓶设备的实时视瓶数据,并保存为文件:```v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=100 --stream-to=test.yuv```2. 查看捕获的视瓶数据的详细信息:```v4l2-ctl --stream-to=test.yuv --stream-status```五、控制视瓶设备的属性1. 设置视瓶设备的亮度值:```v4l2-ctl -d /dev/video0 --set-ctrl=brightness=50 ```2. 调整视瓶设备的对比度:```v4l2-ctl -d /dev/video0 --set-ctrl=contrast=80 ```3. 关闭视瓶设备的自动白平衡:```v4l2-ctl -d /dev/video0 --set-ctrl=white_balance_temperature_auto=0```六、其他常用命令1. 查看视瓶设备支持的视瓶格式:```v4l2-ctl -d /dev/video0 --list-formats```2. 查看视瓶设备支持的帧率范围:```v4l2-ctl -d /dev/video0 --list-framesizes```3. 重置视瓶设备的所有参数为默认值:```v4l2-ctl -d /dev/video0 --all=default```通过上述介绍,相信读者已经对 v4l2controller 的用法有了初步的了解。

V4L2驱动的移植与应用(三)

V4L2驱动的移植与应用(三)

三、V4L2的democapture.c是官方示例程序。

capture.c 程序中的process_image 函数:capture.c 程序主要是用来演示怎样使用v4l2 接口,并没有对采集到的视频帧数据做任何实际的处理,仅仅用process_image 函数表示了处理图像的代码位置。

process_image 函数只有一个参数,就是存储视频帧的内存的地址指针,但是在真正的应用中,通常还需要知道该指针指向的数据的大小。

因此可以修改函数,改成void process_image ( const void * p, int len ) ,但是每次调用process_image 的时候,第 2 个参数该传递什么值?考虑到程序中对buffer 的定义struct buffer {void * start;size_t length};如果将buffer.length 作为第 2 个参数传递到修改后的process_image 函数中,这样做是不正确的。

process_image 需要的第二个参数应该是每帧图像的大小,仔细阅读代码后会发现,buffer.length 并不一定就等于图像帧的大小。

(buffer 的大小,还需要考虑其他的一些因素,比如内存对齐等)。

capture.c只是一个示例程序,仅仅是演示怎样使用v4l2中最基本的接口。

尤其是在main函数中的那几个函数调用,表明了在使用v4l2时的最基本的一个流程,包括open_device,init_device,start_capturing,mainloop,stop_capturing,uninit_device,close_device。

在写程序的时候,可以充分的利用这几个基本模块,把他们分散在不同的代码位置上,灵活的调用,有兴趣的可以看一下gstreamer 中v4l2src的源代码或者其他的大型程序的相关部分。

总之一句话,capture.c仅仅是一个演示程序,不要局限于它的代码结构,要灵活的使用。

v4l2loopback-ctl用法

v4l2loopback-ctl用法

文章标题:深度探讨v4l2loopback-ctl的用法及应用在今天的文章中,我们将更深入地探讨v4l2loopback-ctl的用法及应用。

v4l2loopback-ctl是一个非常有用的工具,它可以帮助我们在Linux系统下创建虚拟视频设备,并且可以对这些虚拟设备进行一些配置和控制。

通过对v4l2loopback-ctl的深入了解,我们可以更好地利用它为我们的工作和学习带来便利。

下面,让我们一起来深入探讨v4l2loopback-ctl的用法及应用。

1. v4l2loopback-ctl的基本概念让我们回顾一下v4l2loopback-ctl的基本概念。

v4l2loopback-ctl是一个基于V4L2(Video for Linux 2)框架的工具,它可以用来创建虚拟视频设备,并且可以通过命令行对这些虚拟设备进行配置和控制。

通过v4l2loopback-ctl,我们可以模拟出多个虚拟摄像头,这些虚拟摄像头可以被应用于视频会议、视频录制、视频流等各种场景中。

2. v4l2loopback-ctl的安装和基本用法接下来,让我们来了解一下v4l2loopback-ctl的安装和基本用法。

我们需要在Linux系统中安装v4l2loopback-ctl的相关软件包,可以通过apt-get或者yum等包管理工具进行安装。

安装完成后,我们可以使用v4l2loopback-ctl命令来创建虚拟视频设备,并且可以通过参数来配置这些虚拟设备的分辨率、帧率、格式等属性。

3. v4l2loopback-ctl的高级用法及应用场景除了基本的用法之外,v4l2loopback-ctl还有一些高级的用法和应用场景。

我们可以通过v4l2loopback-ctl将实际摄像头的视频流导入到虚拟设备中,从而实现视频流的转发和分发。

另外,我们还可以通过v4l2loopback-ctl将虚拟设备的视频流导出到网络,实现远程视频监控的功能。

V4L2(video 4 linux 2)视频采集接口使用说明

V4L2(video 4 linux 2)视频采集接口使用说明

V4L2(video 4 linux 2)视频采集接口使用说明主要功能:使程序有发觉设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频格式和图像像参数等等(在我写的FM驱动中就主要是设置频率,设置音量等)可以支持多种设备,它可以有以下几种接口: 1. 视频采集接口(veo capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的. 2. 视频输出接口(video output interface):可以驱动计算机的外围视频图像设备--像可以输出电视信号格式的设备. 3. 挺直传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号挺直输出到输出设备之上,而不用经过系统的CPU.4. 视频间隔消隐信号接口(VBI interface):它可以使应用可以拜访传输消隐期的视频信号. 5. 收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流.(因为只写过FM 的驱动所以下面着重讲解这种应用.)一,什么是video4linuxVideo4linux(简称V4L),是linux中关于视频设备的内核驱动,现在已有Video4linux2,还未加入linux内核,用法需自己下载补丁。

在Linux中,视频设备是设备文件,可以像拜访一般文件一样对其举行读写,摄像头在/dev/videoN下,N可能为0,1,2,3... 普通0. 另,推举一个用于播放从摄像头采集到的raw数据的播放器RawPlayer,只需要把采集的数据保存到文件***.yuv就OK了。

二,V4L2采集视频流程 1. 打开设备文件。

int fd=open(”/dev/video0″,O_RDWR);2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。

V4L2讲解学习

V4L2讲解学习

一,功能参考目录V4L2 close()- 关闭一个V4L2设备V4L2 ioctl()- 创建的V4L2设备ioctl VIDIOC_CROPCAP - 视频裁剪和缩放功能信息ioctl VIDIOC_DBG_G_REGISTER,VIDIOC_DBG_S_REGISTER - 读或写硬件注册表ioctl VIDIOC_ENCODER_CMD,VIDIOC_TRY_ENCODER_CMD - 执行编码器命令ioctl VIDIOC_ENUMAUDIO - 枚举音频输入ioctl VIDIOC_ENUMAUDOUT - 枚举音频输出ioctl VIDIOC_ENUM_FMT - 枚举图像格式ioctl VIDIOC_ENUM_FRAMESIZES - 枚举外形尺寸ioctl VIDIOC_ENUM_FRAMEINTERVALS - 枚举帧间隔ioctl VIDIOC_ENUMINPUT - 枚举视频输入ioctl VIDIOC_ENUMOUTPUT - 枚举视频输出ioctl VIDIOC_ENUMSTD - 枚举支持的视频标准ioctl VIDIOC_G_AUDIO,VIDIOC_S_AUDIO - 查询或选择当前的音频输入和它的属性ioctl VIDIOC_G_AUDOUT,VIDIOC_S_AUDOUT - 查询或选择当前的音频输出ioctl VIDIOC_G_CHIP_IDENT –识别电视卡的芯片ioctl VIDIOC_G_CROP,VIDIOC_S_CROP - 获取或设置当前裁剪矩形ioctl VIDIOC_G_CTRL,VIDIOC_S_CTRL - 获取或设置控件的值ioctl VIDIOC_G_ENC_INDEX - 获取关于压缩视频流的元数据ioctl VIDIOC_G_EXT_CTRLS,VIDIOC_S_EXT_CTRLS,VIDIOC_TRY_EXT_CTRLS - 获取或设置控件的值数,尽量控制值ioctl VIDIOC_G_FBUF,VIDIOC_S_FBUF - 获取或设置参数帧缓冲区覆盖ioctl VIDIOC_G_FMT,VIDIOC_S_FMT,VIDIOC_TRY_FMT - 获取或设置数据格式,试验格式ioctl VIDIOC_G_FREQUENCY,VIDIOC_S_FREQUENCY - 获取或设置调谐器或射频调制器ioctl VIDIOC_G_INPUT,VIDIOC_S_INPUT - 查询或选择当前视频输入ioctl VIDIOC_G_JPEGCOMP,VIDIOC_S_JPEGCOMP -ioctl VIDIOC_G_MODULATOR,VIDIOC_S_MODULATOR - 调制器,获取或设置属性ioctl VIDIOC_G_OUTPUT,VIDIOC_S_OUTPUT - 查询或选择当前视频输出ioctl VIDIOC_G_PARM,VIDIOC_S_PARM - 获取或设置流参数ioctl VIDIOC_G_PRIORITY,VIDIOC_S_PRIORITY - 查询或要求访问的优先级与文件描述符关联ioctl VIDIOC_G_SLICED_VBI_CAP - 查询切片的VBI功能ioctl VIDIOC_G_STD,VIDIOC_S_STD - 查询或选择当前输入视频标准ioctl VIDIOC_G_TUNER,VIDIOC_S_TUNER - 获取或设置调谐器属性ioctl VIDIOC_LOG_STATUS - 记录驱动程序的状态信息ioctl VIDIOC_OVERLAY - 启动或停止视频覆盖ioctl VIDIOC_QBUF,VIDIOC_DQBUF - 交流与驱动程序缓冲区ioctl VIDIOC_QUERYBUF - 查询一个缓冲区的状态ioctl VIDIOC_QUERYCAP - 查询设备的功能ioctl VIDIOC_QUERYCTRL,VIDIOC_QUERYMENU - 枚举控制和菜单控制项目ioctl VIDIOC_QUERYSTD –识别由目前的输入接收的视频标准ioctl VIDIOC_REQBUFS - 启动用户指针或内存映射的I / Oioctl VIDIOC_STREAMON,VIDIOC_STREAMOFF - 启动或停止流I / OV4L2 mmap()- 映射设备内存到应用程序的地址空间V4L2 munmap()- 取消映射设备内存V4L2 open()- 打开的V4L2设备V4L2调查()- 等待某些事件对一个文件描述符V4L2阅读()- 读取V4L2设备V4L2选择()- 同步I / O复用V4L2写()- 写入V4L2设备V4L2 close()名称V4L2 的关闭- 关闭一个V4L2设备概要#include <unistd.h>int close(int fd);fd打开()返回的文件描述符。

V4L2视频采集程序框架

V4L2视频采集程序框架

V4L2应用程序框架V4L2较V4L有较大的改动,并已成为2.6的标准接口,函盖video\dvb\FM...,多数驱动都在向V4l2迁移。

更好地了解V4L2先从应用入手,然后再深入到内核中结合物理设备/接口的规范实现相应的驱动。

本文先就V4L2在视频捕捉或camera方面的应用框架。

V4L2采用流水线的方式,操作更简单直观,基本遵循打开视频设备、设置格式、处理数据、关闭设备,更多的具体操作通过ioct l函数来实现。

1.打开视频设备在V4L2中,视频设备被看做一个文件。

使用open函数打开这个设备:// 用非阻塞模式打开摄像头设备int cameraFd;cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);// 如果用阻塞模式打开摄像头设备,上述代码变为://cameraFd = open("/dev/video0", O_RDWR, 0);应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。

2. 设定属性及采集方式打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。

这一步是可选的。

在Linux编程中,一般使用ioctl 函数来对设备的I/O通道进行管理:int ioctl (int __fd, unsigned long int __request, .../*args*/) ;在进行V4L2开发中,常用的命令标志符如下(some are optional):∙VIDIOC_REQBUF S:分配内存∙VIDIOC_QUERYBUF:把VIDIOC_REQBUF S中分配的数据缓存转换成物理地址∙VIDIOC_QUERYCAP:查询驱动功能∙VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式∙VIDIOC_S_FMT:设置当前驱动的频捕获格式∙VIDIOC_G_FMT:读取当前驱动的频捕获格式∙VIDIOC_TRY_FMT:验证当前驱动的显示格式∙VIDIOC_CROPCAP:查询驱动的修剪能力∙VIDIOC_S_CROP:设置视频信号的边框∙VIDIOC_G_CROP:读取视频信号的边框∙VIDIOC_QBUF:把数据从缓存中读取出来∙VIDIOC_DQBUF:把数据放回缓存队列∙VIDIOC_STREAMON:开始视频显示函数∙VIDIOC_STREAMOFF:结束视频显示函数∙VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。

Linux摄像头V4L2编程

Linux摄像头V4L2编程

一、摘要在Linux操作系统下,摄像头的工作都要遵循V4L2的机制,下面介绍如何从无到有,编写代码去使能摄像头拍照。

使用V4L2基本上就是使用内核提供的函数接口,填充相应的函数,主要依靠ioctl()函数填充函数域,然后按照一定操作顺序(工作流程),就能拍照了。

二、操作顺序(工作流程)前奏:1、打开USB摄像头设备文件2、获取驱动信息(VIDIOC_QUERYCAP)3、设置图像格式(VIDIOC_S_FMT)帧缓冲:4、申请帧缓冲(VIDIOC_REQBUFS)5、获取帧缓冲地址长度信息(VIDIOC_QUERYBUF)6、使用mmap吧内核空间的帧缓冲映射到用户空间7、帧缓冲入队列8、开始采集图像(VIDIOC_STREAMON)9、取出帧缓冲(VIDIOC_DQBUF)10、访问帧缓冲(可以读写操作等等)11、帧缓冲入队列,重新入队(VIDIOC_QBUF)写代码的时候按照这个编写就行了。

如果用在嵌入式板子上,只用交叉编译以后就能用了#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <getopt.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <malloc.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <asm/types.h>#include <linux/videodev2.h>struct buffer {void * start;size_t length;};struct buffer *buffers;unsigned long n_buffers;unsigned long file_length;int file_fd;char *dev_name = "/dev/video3"; //这是我摄像头节点,根据自己的节点填写int fd;static int read_frame (void){struct v4l2_buffer buf;/*帧出列*/buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;ioctl (fd, VIDIOC_DQBUF, &buf);write(file_fd,buffers[buf.index].start,buffers[buf.index].length);/*buf入列*/ioctl(fd, VIDIOC_QBUF, &buf);return 1;}int main (int argc,char ** argv){struct v4l2_capability cap;struct v4l2_format fmt;struct v4l2_requestbuffers req;struct v4l2_buffer buf;unsigned int i;enum v4l2_buf_type type;file_fd = open("test.jpg", O_RDWR | O_CREAT, 0777); //用来保存图片 fd = open (dev_name, O_RDWR | O_NONBLOCK, 0);/*获取驱动信息*/ioctl (fd, VIDIOC_QUERYCAP, &cap); //驱动信息保存在cap结构体printf("Driver Name:%s/n Card Name:%s/n Businfo:%s/n/n",cap.driver,cap.card,cap.bus_info);/*设置图像格式*/fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //这是设置传输流类型fmt.fmt.pix.width = 320; //设置分辨率fmt.fmt.pix.height = 240;fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; //图像格式,此处是jpg ioctl (fd, VIDIOC_S_FMT, &fmt) ;/*申请图像缓冲区*/req.count = 4;req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;req.memory = V4L2_MEMORY_MMAP;ioctl (fd, VIDIOC_REQBUFS, &req);buffers = calloc (req.count, sizeof (*buffers));for (n_buffers = 0; n_buffers < req.count; ++n_buffers){/*获取图像缓冲区的信息*/buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = n_buffers;ioctl (fd, VIDIOC_QUERYBUF, &buf);buffers[n_buffers].length = buf.length;// 把内核空间中的图像缓冲区映射到用户空间buffers[n_buffers].start = mmap (NULL , //通过mmap建立映射关系buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED ,fd,buf.m.offset);}/*图像缓冲入队*/for (i = 0; i < n_buffers; ++i){buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;ioctl (fd, VIDIOC_QBUF, &buf);}//开始捕捉图像数据type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ioctl (fd, VIDIOC_STREAMON, &type);fd_set fds;FD_ZERO (&fds);FD_SET (fd, &fds);select(fd + 1, &fds, NULL, NULL, NULL);/*读取一幅图像*/read_frame();for (i = 0; i < n_buffers; ++i)munmap (buffers[i].start, buffers[i].length);close (fd);close (file_fd);printf("Camera Done./n");return 0;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/** V4L2 video capture example** This program can be used and distributed without restrictions.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <getopt.h> /* getopt_long() */#include <fcntl.h> /* low-level i/o */#include <unistd.h> /*getpid()*/#include <error.h>#include <errno.h>#include <malloc.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <asm/types.h> /* for videodev2.h */#include <linux/videodev2.h>#define CLEAR(x) memset(&(x), 0, sizeof (x))typedef enum {IO_METHOD_READ,IO_METHOD_MMAP,IO_METHOD_USERPTR,} io_method;struct buffer {void *start;size_t length;};static char * dev_name = NULL;static io_method io = IO_METHOD_MMAP; static int fd = -1;struct buffer * buffers = NULL;static unsigned int n_buffers = 0;static void errno_exit(const char *s){fprintf(stderr, "%s error %d, %s\n",s, errno, strerror(errno));exit(EXIT_FAILURE);}static int xioctl(int fd,int request,void *arg){int r;do r = ioctl(fd, request, arg);while (-1 == r && EINTR == errno);return r;}static void process_image(const void *p){FILE* fp;fp = fopen("test","w+"); //w+:打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。

若文件不存在则建立该文件。

fputs(p, fp); //成功,返回一个非负整数;出错,返回EOF。

fputs(const char *s,FILE *stream)作用:向指定文件写入一个字符串,缓冲区S中保存的是以‘/0’结尾的字符串,fputs将该字符串写入stream,但不写入结尾的’/0’。

fclose(fp);// fflush(stdout); // fflush(stdout):清空输出缓冲区,并把缓冲区内容输出}static int read_frame(void)//用来读取一帧数据{struct v4l2_buffer buf;unsigned int i;switch (io){case IO_METHOD_READ:if (-1 == read(fd, buffers[0].start, buffers[0].length)){switch (errno){case EAGAIN: //当使用不可阻断(O_NONBLOCK)打开文件后,read呼叫无可读取的数据return 0;case EIO: //设备文件读取文件时发生输出输入错误/* Could ignore EIO, see spec. *//* fall through */default:errno_exit("read");}}process_image(buffers[0].start); //保存读到的数据break;/* V4L2有一个数据缓存,存放req.count数量的缓存数据。

数据缓存采用FIFO的方式,当应用程序调用缓存数据时,缓存队列将最先采集到的视频数据缓存送出,并重新采集一张视频数据。

这个过程需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF*/ case IO_METHOD_MMAP:CLEAR (buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;/*出队列以取得采集数据的帧缓冲,取得原始的采集数据*/if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)){switch (errno){case EAGAIN:return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit("VIDIOC_DQBUF");}}assert(buf.index < n_buffers); //assert的作用是计算括号内的表达式,如果其值为0,就先向stderr打印一条出错信息,然后通过abort来终止程序运行process_image(buffers[buf.index].start);if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) //重新放入缓存队列errno_exit("VIDIOC_QBUF");break;case IO_METHOD_USERPTR:CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_USERPTR;if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)){switch (errno){case EAGAIN:return 0;case EIO:/* Could ignore EIO, see spec. *//* fall through */default:errno_exit("VIDIOC_DQBUF");}}for (i = 0; i < n_buffers; ++i)if (erptr == (unsigned long) buffers[i].start&& buf.length == buffers[i].length)break;assert(i < n_buffers);process_image((void *) erptr);if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");break;}return 1;}/*完成图像的连续采集*/4. static void mainloop(void){unsigned int count;count = 100;while (count-- > 0){for (;;){fd_set fds;struct timeval tv;int r;FD_ZERO(&fds); //初始化fd_set结构体变量FD_SET(fd, &fds);//在fd_set结构体上注册文件描述/* Timeout. */_sec = 2; //时间“2S”_usec = 0;r = select (fd + 1, &fds, NULL, NULL, &tv); //判断是否可读(即摄像头是否准备好)tv是定时if (-1 == r) {if (EINTR == errno)continue;errno_exit("select");}if (0 == r) { //时间到,返回0fprintf(stderr, "select timeout\n");exit(EXIT_FAILURE);}if (read_frame()) //如果可读,执行read_frame函数,并跳出循环break;/* EAGAIN - continue select loop. */}}}5. static void stop_capturing(void)//停止视频的采集{enum v4l2_buf_type type;switch (io){case IO_METHOD_READ:/* Nothing to do. */break;case IO_METHOD_MMAP:case IO_METHOD_USERPTR:type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))errno_exit("VIDIOC_STREAMOFF");break;}}3. static void start_capturing(void) //开始视频采集{unsigned int i;enum v4l2_buf_type type;switch (io){case IO_METHOD_READ:/* Nothing to do. */break;case IO_METHOD_MMAP:for (i = 0; i < n_buffers; ++i){struct v4l2_buffer buf;CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) //申请到的缓冲进入列队errno_exit("VIDIOC_QBUF");}/*for循环的作用是:将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer*/type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) //开始捕捉图像数据errno_exit("VIDIOC_STREAMON");break;case IO_METHOD_USERPTR:for (i = 0; i < n_buffers; ++i){struct v4l2_buffer buf;CLEAR(buf);buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_USERPTR;buf.index = i;erptr = (unsigned long) buffers[i].start;buf.length = buffers[i].length;if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))errno_exit("VIDIOC_QBUF");}type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))errno_exit("VIDIOC_STREAMON");break;}}6. static void uninit_device(void)//注销设备文件{unsigned int i;switch (io) {case IO_METHOD_READ:free(buffers[0].start); //原型void free(void *ptr);参数ptr为指向先前由malloc()、calloc()或realloc()所返回的内存指针。

相关文档
最新文档