您的位置:首页 > 其它

《基于GTK的USB视频采集程序》

2015-09-09 21:39 274 查看
《V4L2驱动的移植与应用(一)》

vivi.c中的头文件包含:

vivi.c包含头文件v4l2-device.h和v4l2-ioctl.h,其中v4l2-device.h中包含了v4l2-subdev.h,v4l2-subdev.h

中又包含了v4l2-common.h,v4l2-common.h中包含了v4l2-dev.h。vivi.h

在v4l2-dev.h中定义了结构体video_device和v4l2_file_operations;

在v4l2-ioctl.h中定义了结构体v4l2_ioctl_ops;

在v4l2-device.h中定义了结构体v4l2_device、v4l2_file_operation结构;

struct v4l2_capability/v4l2_cropcap/v4l2_crop在/include/linux/videodev2.h定义

其中cap为struct v4l2_capability;

/include/linux/videodev2.h定义,v4l2_cropcap/v4l2_crop也在其中有定义。

struct v4l2_capability

{

__u8 driver[16];

__u8 card[32];

__u8 bus_info[32];

__u32 version;

__u32 capabilities;

__u32 device_caps;

__u32 reserved[3];

}

video_capability在videodev.h中定义的,在linux-3.4.2中已经没有这个文件了!!!

struct video_capability

{

char name[32];

int type;

int channels;

int audios;

int maxwidth;

int maxheight;

int minwidth;

int minheight;

}

结构体包含关系

struct video_device

->vivi_fops (v4l2_file_operations)

->vivi_ioctl_ops(v4l2_ioctl_ops)

《基于GTK的USB视频采集程序》

本测试程序包括两部分:

一是视频采集部分,主要通过v4l2接口操作摄像头,将采集的视频帧存放在内存缓冲区。

二是显示部分,将视频缓冲区的数据显示到屏幕上。因为摄像头采集回来的数据帧为YUV格式,不能直接显示,需要转

换成RGB格式才可以显示在屏幕上。

**********程序主要参考了v4l2视频采集例程capture.c,以及开源软件Camorama-0.16的源代码。***************

知识点补充:

Linux下对视频音频设备操作的接口叫video4linux,现在内核中是它的第二个版本video4linux2(v4l2)。他是内核中的一个模块,就像input模块一样。

(1)v4l2对应用程序抽象了操作音频视频设备的细节。应用程序只需要调用v4l2接口函数就可以操作设备,无须关心是什么样的设备,比如在应用程序层面上,USB摄像头与其他类型的摄像头没有分别。

(2)与此同时v4l2简化了音视频驱动程序的编写,底层驱动只需要实现很少一部分功能,把其他的工作交给video4linux层

就可以了。

程序结构:

程序主要分为三个部分:视频采集,格式转换,视频显示。

1.视频采集部分主要是操作v4l2的接口函数,对应v4l2.c以及v4l2.h文件。

2.视频转换,主要是将yuv格式转换成rgb格式,对应于yuv422_rgb.c,以及yuv422_rgb.h文件。

3.视频显示,主要是利用GTK图形库构建图形界面,以及将视频数据显示在窗口上,对应与main.c文件。

注意v4l2读取视频数据有三种方式:

一个就是通过普通的read操作,这个比较慢。

另外一个就是使用mmap,速度比较块。

第三种方式是用户指针,在capeture.c中,可以选择这三种方式,而我的程序中只用了mmap的方式。

设置视频设备属性通过ioctl来进行设置,ioctl有三个参数,分别是fd, cmd,和parameter,表示设备描述符,控制命令和控制命令参数。

ioctl(fd_usbcam, VIDIOC_QUERYCAP, &cap);

功能: 获取当前视频设备支持的视频格式 。

ioctl(dev, VIDIOC_ENUM_FMT, &fmt)

(1)init_camera(cam):

->xioctrl(cam->fd,VIDIOC_QUERYCAP,cap) //执行VIDIOC_QUERYCAP该命令后,cap中capabilities获 取到视频设备的所支持功能。

->if(!(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)); //通过这些宏定义与cap比较来判断设备的功能。

->if(!(cap->capabilities & V4L2_CAP_STREAMING));

->xioctl (cam->fd, VIDIOC_CROPCAP, cropcap) //通过VIDIOC_CROPCAP的ioctl来获得设备的crap相关属性

//v4l2_cropcap

->xioctl (cam->fd, VIDIOC_S_CROP, &crop)) //通过VIDIOC_S_CROP来设置设备当前的crop设置。

Cropping 和 scaling 主要指的是图像的取景范围及图片的比例缩放的支持。Crop 就 是把得到的数据作一定的裁剪和伸缩,裁剪可以只取样我们可以得到的图像大小的一部分, 剪裁的主要参数是位置、长度、宽度。而 scale 的设置是通过 VIDIOC_G_FMT 和 VIDIOC_S_FMT 来获得和设置当前的 image 的长度,宽度来实现的。

(http://www.cnblogs.com/emouse/archive/2013/03/04/2943243.html)

->xioctl (cam->fd, VIDIOC_S_FMT, fmt)) //scale 的设置是通过 VIDIOC_G_FMT 和 VIDIOC_S_FMT 来获得和设置当前的 image 的长度,宽度来实现的

(2)init_mmap(cam):

->xioctl (cam->fd, VIDIOC_REQBUFS, &req)

******************************

控制命令VIDIOC_REQBUFS:

功能: 请求V4L2驱动分配视频缓冲区(申请V4L2视频驱动分配内存),V4L2是视频设备的驱动层, 位于内核空间,所以通过VIDIOC_REQBUFS控制 命令字申请的内存位于内核空间,应用程序不能直接访问,需要通过调用mmap内存映射函数把内核空间内存映射到用户空间后,应用程序 通 过访问用户空间地址来访问内核空间。

******************************

cam->buffers = calloc (req.count, sizeof (*(cam->buffers)));

-> for (n_buffers = 0; n_buffers < req.count; ++(n_buffers)) //查询空buffer

{

...

xioctl (cam->fd, VIDIOC_QUERYBUF, &buf))

*********************************

控制命令VIDIOC_QUERYBUF:

功能: 查询已经分配的V4L2的视频缓冲区的相关信息,包括视频缓冲区的使用状态、在内核空间的偏移地址、缓冲区长度等。在应用程序 设计中通过调用VIDIOC_QUERYBUF来获取内核空间的视频缓冲区信息,然后调用函数mmap把内核空间地址映射到用户空间,这样
应用程序才能够访问位于内核空间的视频缓冲区。

**********************************

....

mmap (NULL ,buf.length,PROT_READ | PROT_WRITE , MAP_SHARED,cam->fd, buf.m.offset);

**********************************

通过调用VIDIOC_QUERYBUF取得内核空间的缓冲区信息后,接着调用mmap函数把内核空间缓冲区映射到用户空间;

**********************************

}

(3)start_capturing(cam)

-> xioctl (cam->fd, VIDIOC_QBUF, &buf))

*****************************

控制命令VIDIOC_QBUF:

功能: 投放一个空的视频缓冲区到视频缓冲区输入队列中 ;

参数说明:参数类型为V4L2缓冲区数据结构类型 struct v4l2_buffer;

返回值说明: 执行成功时,函数返回值为 0;

函数执行成功后,指令(指定)的视频缓冲区进入视频输入队列,在启动视频设备拍摄图像时,相应的视频数据被

保存到视频输入队列相应的视频缓冲区中。

struct v4l2_buffer tV4L2buf;

memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer));

tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

tV4L2buf.memory = V4L2_MEMORY_MMAP;

tV4L2buf.index = i; //指令(指定)要投放到视频输入队列中的内核空间视频缓冲区的编号;

iret = ioctl(fd_usbcam, VIDIOC_QBUF, &tV4L2buf);

*****************************

-> xioctl (cam->fd, VIDIOC_STREAMON, &type)

*****************************

控制命令VIDIOC_STREAMON:

功能: 启动视频采集命令,应用程序调用VIDIOC_STREAMON启动视频采集命令后,视频设备驱动程序开始采集视频数据,并把采集到的视频数 据 保存到视频驱动的视频缓冲区中。

*****************************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: