一、v412-概述
V4L2(Video For Linux Two)是内核提供给应用程序访问音、视频驱动的统一接口。V412可以支持多种设备,它可以有以下几种接口:
- 视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头,V4L2的最初设计就是应用于这种功能的。
- 视频输出接口(video output interface):可以驱动计算机的外围视频图像设备,如可以输出电视信号格式的设备。
- 直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU.
- 视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号。
- 收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流。
二、v412-框架结构
Linux系统中视频输入设备主要包括以下四个部分:
- 字符设备驱动程序核心:V4L2本身就是一个字符设备,具有字符设备所有的特性,暴露接口给用户空间;
- V4L2驱动核心:主要是构建一个内核中标准视频设备驱动的框架,为视频操作提供统一的接口函数;
- 平台V4L2设备驱动:在V4L2框架下,根据平台自身的特性实现与平台相关的V4L2驱动部分,包括注册video_device和v412_dev。
- 具体的sensor驱动:主要上电、提供工作时钟、视频图像裁剪、流IO开启等,实现各种设备控制方法供上层调用并注册v412_subdev。
三、v412-应用程序读取图像的流程
1.打开设备(xawtv,cheese)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
// 1.打开设备
int fd = open("/dev/video0", O_RDWR);
if (fd < 0)
{
perror("open video0 faild");
return -1;
}
//关闭设备
close(fd);
return 0;
}
2.获取设备支持格式
使用的函数:
int ioctl(int __fd,unsigned long int __request,...)
获取摄像头格式VIDIOC_ENUM_FMT–对应存储格式的结构体struct v4l2_fmtdesc
#define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc)
struct v4l2_fmtdesc {
__u32 index; //要查询的格式序号,应用程序设置
__u32 type; //帧类型,应用程序设置
__u32 flags; //是否为压缩格式
__u8 description[32]; //格式名称
__u32 pixelformat; //听支持的格式
__u32 mbus_code;
__u32 reserved[3]; //保留
};
enum v4l2_buf_type:
enum v4l2_buf_type {
V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, //捕获采集
V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, //输出
V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, //覆盖
};
查看支持的格式
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h> //命令码
int main(int argc, const char *argv[])
{
// 1.打开设备
int fd = open("/dev/video0", O_RDWR);
if (fd < 0)
{
perror("open video0 faild");
return -1;
}
// 2.获取摄像头支持的格式ioctl
struct v4l2_fmtdesc v4fmt;
v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //类型为输出
// v4fmt.index = 0;
int i = 0;
while (1)
{
v4fmt.index = i++;
int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt);
if (ret < 0)
{
perror("itctl get fmt faild");
break;
}
printf("index = %d\n", v4fmt.index);
printf("flags = %d\n", v4fmt.flags);
printf("description = %s\n", v4fmt.description);
unsigned char *p = (unsigned char *)&v4fmt.pixelformat;
printf("pixelformat = %c%c%c%c\n",p[0],p