Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17590
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-22 08:19
个人简介

平凡不平庸,自信不自负,人贵自知……

文章分类

全部博文(1)

分类: 嵌入式

2015-08-09 13:49:35

V4L2基础知识:

v4l2:是内核提供给应用程序访问音、视频驱动的统一接口。
基本的工作流程:打开摄像头->检查和设置设备属性->设置帧格式->设置输入输出方法->循环获取数据->关闭设备.
1、打开摄像头
在v4l2中,视频设备被看做一个文件。使用open函数打开这个设备:
可以用非阻塞方式打开摄像头设备
fd = open (“dev_name”, O_RDWR| O_NONBLOCK)
也可以用阻塞方式打开摄像头设备
fd = open (“dev_name”, O_RDWR)
如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
设置视频设备属性通过ioctl来进行设置,ioctl有三个参数,分别是fd, cmd,和parameter,表示设备描述符,控制命令和控制命令参数。
int ioctl(int fd, int cmd, ...);
2、查询设备属性:控制命令VIDIOC_QUERYCAP
功能:查询视频设备的功能 ;
参数:参数类型为v4l2的能力描述类型struct v4l2_capability ;
返回值:执行成功时,函数返回值为 0;函数执行成功后,struct v4l2_capability结构体变量中的返回当前视频设备所支持的功能;
3、设置视频的制式和帧格式:
制式包括PAL,NTSC,帧的格式包括宽度和高度。
v4l2_cropcap 结构体用来设置摄像头的捕捉能力。
v4l2_cropcap 的 type 域,再通过 VIDIO_CROPCAP 操作命令获取设备捕捉能力的参数,保存于 v4l2_cropcap 结构体中,包括 bounds(最大捕捉方框的左上角坐标和宽高),defrect(默认捕捉方框的左上角坐标和宽高)等。
v4l2_format 结构体用来设置摄像头的视频制式、帧格式等,在设置这个参数时应先填 好 v4l2_format 的各个域,如 type(传输流类型),fmt.pix.width(宽),fmt.pix.heigth(高),fmt.pix.field(采样区域,如隔行采样),fmt.pix.pixelformat(采样类型,如 YUV4:2:2),然后通过 VIDIO_S_FMT 操作命令设置视频捕捉格式。
控制命令VIDIOC_S_FMT        
功能: 设置视频设备的视频数据格式,例如设置视频图像数据的长、宽,图像格式(JPEG、YUYV格式);
参数:参数类型为v4l2的视频数据格式类型 struct v4l2_format  ;
返回值: 执行成功时,函数返回值为 0;
4、查询并显示所有支持的格式
控制命令 VIDIOC_ENUM_FMT     
功能: 获取当前视频设备支持的视频格式 。
参数:参数类型为v4l2的视频格式描述符类型 struct v4l2_fmtdesc
返回值: 执行成功时,函数返回值为 0;struct v4l2_fmtdesc 结构体中的 .pixelformat和 .description 成员返回当前视频设备所支持的视频格式;
5、图像的缩放 VIDIOC_CROPCAP
相关函数:
int ioctl(int fd, int request, struct v4l2_cropcap *argp);int ioctl(int fd, int request, struct v4l2_crop *argp);int ioctl(int fd, int request, const struct v4l2_crop *argp);
Cropping 和 scaling 主要指的是图像的取景范围及图片的比例缩放的支持。Crop就是把得到的数据作一定的裁剪和伸缩,裁剪可以只取样我们可以得到的图像大小的一部分,剪裁的主要参数是位置、长度、宽度。scale 的设置是通过VIDIOC_G_FMT 和 VIDIOC_S_FMT 来获得和设置当前的 image 的长度,宽度来实现的。
6、设置设备捕捉能力的参数
相关结构体:
struct v4l2_cropcap{enum v4l2_buf_type type; // 数据流的类型,应用程序设置struct v4l2_rect bounds; // 这是 camera 的镜头能捕捉到的窗口大小的局限struct v4l2_rect defrect; // 定义默认窗口大小,包括起点位置及长,宽的大小,大小以像素为单位struct v4l2_fract pixelaspect; // 定义了图片的宽高比};
7、设置窗口取景参数  VIDIOC_G_CROP 和 VIDIOC_S_CROP
struct v4l2_crop{
enum v4l2_buf_type type;// 应用程序设置struct v4l2_rect c;
}
8、设置输入输出:
VIDIOC_G_INPUT 和 VIDIOC_S_INPUT 用来查询和选则当前的 input,一个 video 设备 节点可能对应多个视频源,如果上层应用想在多个视频输入间切换,就会调用 ioctl(fd, VIDIOC_S_INPUT, &input) 来切换;
可以通过VIDIOC_ENUMINPUT and VIDIOC_ENUMOUTPUT 分别列举一个input或者 output的信息,我们使用一个v4l2_input结构体来存放查询结果,这个结构体中有一个 index域用来指定你索要查询的是第几个input/ouput,如果你所查询的这个input是当前正 在使用的,那么在v4l2_input还会包含一些当前的状态信息,如果所 查询的input/output 不存在,那么回返回EINVAL错误,所以,我们通过循环查找,直到返回错误来遍历所有的 input/output. VIDIOC_G_INPUT and VIDIOC_G_OUTPUT 返回当前的video input和output 的index.
9、申请和管理缓冲区
应用程序和设备有三种交换数据的方法,直接 read/write、内存映射(memory mapping)和用户指针,这里采用内存映射(memory mapping);
1、向设备申请缓冲区 
控制命令VIDIOC_REQBUFS    
功能: 请求v4l2驱动分配视频缓冲区(申请v4l2视频驱动分配内存),v4l2是视频设备的驱动层,位于内核空间,所以通过VIDIOC_REQBUFS控制命令字申请的内存位于内核空间,应用程序不能直接访问,需要通过调用mmap内存映射函数把内核空间内存映射到用户空间后,应用程序通过访问用户空间地址来访问内核空间。
参数:参数类型为v4l2的申请缓冲区数据结构体类型struct v4l2_requestbuffers  ;
返回值: 执行成功时,函数返回值为 0;v4l2驱动层分配好了视频缓冲区;
2、获取缓冲帧的地址,长度:VIDIOC_QUERYBUF
功能:查询已经分配的v4l2的视频缓冲区的相关信息,包括视频缓冲区的使用状态、在内核空间的偏移地址、缓冲区长度等。在应用程序设计中通过调VIDIOC_QUERYBUF来获取内核空间的视频缓冲区信息,然后调用函数mmap把内核空间地址映射到用户空间,这样应用程序才能够访问位于内核空间的视频缓冲区。
参数:参数类型为v4l2缓冲区数据结构类型 struct v4l2_buffer  ;
返回值: 执行成功时,函数返回值为 0;struct v4l2_buffer结构体变量中保存了指令的缓冲区的相关信息;
一般情况下,应用程序中调用VIDIOC_QUERYBUF取得了内核缓冲区信息后,紧接着调用mmap函数把内核空间地址映射到用户空间,方便用户空间应用程序的访问。
3、内存映射MMAP 及定义一个结构体来映射每个缓冲帧
相关结构体:
struct buffer{void* start;
unsigned int length;
}*buffers;
相关函数:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
//addr 映射起始地址,一般为NULL ,让内核自动选择
//length 被映射内存块的长度
//prot 标志映射后能否被读写,其值为PROT_EXEC,PROT_READ,PROT_WRITE, PROT_NONE
//flags 确定此内存映射能否被其他进程共享,MAP_SHARED,MAP_PRIVATE
//fd,offset, 确定被映射的内存地址 返回成功映射后的地址,不成功返回MAP_FAILED ((void*)-1)
int munmap(void *addr, size_t length);// 断开映射
将申请到的缓冲帧映射到应用程序,用buffers 指针记录。
10、循环获取数据
启动数据流,控制命令VIDIOC_STREAMON
功能: 启动视频采集命令,应用程序调用VIDIOC_STREAMON启动视频采集命令后,视频设备驱动程序开始采集视频数据,并把采集到的视频数据保存到视频驱动的视频缓冲区中。
参数:参数类型为v4l2的视频缓冲区类型 enum v4l2_buf_type ;
返回值: 执行成功时,函数返回值为 0;函数执行成功后,视频设备驱动程序开始采集视频数据,此时应用程序一般通过调用select函数来判断一帧视频数据是否采集完成,当视频设备驱动完成一帧视频数据采集并保存到视频缓冲区中时,select函数返回,应用程序接着可以读取视频数据;否则select函数阻塞直到视频数据采集完成。
停止数据流:控制命令VIDIOC_STREAMOFF
功能:停止视频采集命令,应用程序调用VIDIOC_ STREAMOFF停止视频采集命令后,视频设备驱动程序不在采集视频数据。
参数:参数类型为v4l2的视频缓冲区类型 enum v4l2_buf_type ;
返回值:执行成功时,函数返回值为 0;函数执行成功后,视频设备停止采集视频数据。

11、关闭设备;close(fd);

参考:http://blog.chinaunix.net/uid-26851094-id-3356224.html



阅读(585) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~