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

《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启动视频采集命令后,视频设备驱动程序开始采集视频数据,并把采集到的视频数   据   保存到视频驱动的视频缓冲区中。
*****************************
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值