V4L2 编程
V4L2 编程 1. 定义 V4L2(Video For Linux Two) 是内核提供给应用程序访问音、视频驱动的统一接口。 2. 工作流程: 打开设备- 检查和设置设备属性- 设置帧式- 设置一种输入输出方法(缓冲区管理)- 循环获取数据- 关闭设备。 3. 设备的打开和关闭: #inc
V4L2 编程
1. 定义
V4L2(Video For Linux Two) 是内核提供给应用程序访问音、视频驱动的统一接口。
2. 工作流程:
打开设备-> 检查和设置设备属性-> 设置帧格式-> 设置一种输入输出方法(缓冲区管理)-> 循环获取数据-> 关闭设备。
3. 设备的打开和关闭:
#include
int open(const char *device_name, int flags);
#include
int close(int fd);
例:
int fd=open(“/dev/video0”,O_RDWR);// 打开设备
close(fd);// 关闭设备
注意:V4L2 的相关定义包含在头文件
4. 查询设备属性: VIDIOC_QUERYCAP
相关函数:
int ioctl(int fd, int request, struct v4l2_capability *argp);
相关结构体:
struct v4l2_capability
{
__u8 driver[16]; // 驱动名字
__u8 card[32]; // 设备名字
__u8 bus_info[32]; // 设备在系统中的位置
__u32 version; // 驱动版本号
__u32 capabilities; // 设备支持的操作
__u32 reserved[4]; // 保留字段
};
capabilities 常用值:
V4L2_CAP_VIDEO_CAPTURE // 是否支持图像获取
例:显示设备信息
struct v4l2_capability cap;
ioctl(fd,VIDIOC_QUERYCAP,&cap);
printf(“Driver Name:%s/nCard Name:%s/nBus info:%s/nDriver Version:%u.%u.%u/n”,cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0XFF, (cap.version>>8)&0XFF,cap.version&OXFF);
5. 帧格式:
VIDIOC_ENUM_FMT // 显示所有支持的格式
int ioctl(int fd, int request, struct v4l2_fmtdesc *argp);
struct v4l2_fmtdesc
{
__u32 index; // 要查询的格式序号,应用程序设置
enum v4l2_buf_type type; // 帧类型,应用程序设置
__u32 flags; // 是否为压缩格式
__u8 description[32]; // 格式名称
__u32 pixelformat; // 格式
__u32 reserved[4]; // 保留
};
例:显示所有支持的格式
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index=0;
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Support format:/n");
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
{
printf("/t%d.%s/n",fmtdesc.index+1,fmtdesc.description);
fmtdesc.index++;
}
// 查看或设置当前格式
VIDIOC_G_FMT, VIDIOC_S_FMT
// 检查是否支持某种格式
VIDIOC_TRY_FMT
int ioctl(int fd, int request, struct v4l2_format *argp);
struct v4l2_format
{
enum v4l2_buf_type type;// 帧类型,应用程序设置
union fmt
{
struct v4l2_pix_format pix;// 视频设备使用
struct v4l2_window win;
struct v4l2_vbi_format vbi;
struct v4l2_sliced_vbi_format sliced;
__u8 raw_data[200];
};
};
struct v4l2_pix_format
{
__u32 width; // 帧宽,单位像素
__u32 height; // 帧高,单位像素
__u32 pixelformat; // 帧格式
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};
例:显示当前帧的相关信息
struct v4l2_format fmt;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd,VIDIOC_G_FMT,&fmt);
printf(“Current data format information:/n/twidth:%d/n/theight:%d/n”,fmt.fmt.width,fmt.fmt.height);
struct v4l2_fmtdesc fmtdesc;
fmtdesc.index=0;
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)
{
if(fmtdesc.pixelformat & fmt.fmt.pixelformat)
{
printf(“/tformat:%s/n”,fmtdesc.description);
break;
}
fmtdesc.index++;
}
例:检查是否支持某种帧格式
struct v4l2_format fmt;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_RGB32;
if(ioctl(fd,VIDIOC_TRY_FMT,&fmt)==-1)
if(errno==EINVAL)
printf(“not support format RGB32!/n”);
6. 图像的缩放
VIDIOC_CROPCAP
int ioctl(int fd, int request, struct v4l2_cropcap *argp);
struct v4l2_cropcap
{
enum v4l2_buf_type type;// 应用程序设置
struct v4l2_rect bounds;// 最大边界
struct v4l2_rect defrect;// 默认值
struct v4l2_fract pixelaspect;
};
// 设置缩放
VIDIOC_G_CROP,VIDIOC_S_CROP
int ioctl(int fd, int request, struct v4l2_crop *argp);
int ioctl(int fd, int request, const struct v4l2_crop *argp);
struct v4l2_crop
{
enum v4l2_buf_type type;// 应用程序设置
struct v4l2_rect c;
} ;
7. 申请和管理缓冲区,应用程序和设备有三种交换数据的方法,直接 read/write ,内存映射 (memory mapping) ,用户指针。这里只讨论 memory mapping.
// 向设备申请缓冲区
VIDIOC_REQBUFS
int ioctl(int fd, int request, struct v4l2_requestbuffers *argp);
struct v4l2_requestbuffers
{
__u32 count; // 缓冲区内缓冲帧的数目
enum v4l2_buf_type type; // 缓冲帧数据格式
enum v4l2_memory memory; // 区别是内存映射还是用户指针方式
__u32 reserved[2];
};
enum v4l2_memoy {V4L2_MEMORY_MMAP,V4L2_MEMORY_USERPTR};
//count,type,memory 都要应用程序设置
例:申请一个拥有四个缓冲帧的缓冲区
struct v4l2_requestbuffers req;
req.count=4;
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory=V4L2_MEMORY_MMAP;
ioctl(fd,VIDIOC_REQBUFS,&req);
获取缓冲帧的地址,长度:
VIDIOC_QUERYBUF
int ioctl(int fd, int request, struct v4l2_buffer *argp);
struct v4l2_buffer
{
__u32 index; //buffer 序号
enum v4l2_buf_type type; //buffer 类型
__u32 byteused; //buffer 中已使用的字节数
__u32 flags; // 区分是MMAP 还是USERPTR
enum v4l2_field field;
struct timeval timestamp;// 获取第一个字节时的系统时间
struct v4l2_timecode timecode;
__u32 sequence; // 队列中的序号
enum v4l2_memory memory;//IO 方式,被应用程序设置
union m
{
__u32 offset;// 缓冲帧地址,只对MMAP 有效
unsigned long userptr;
};
__u32 length;// 缓冲帧长度
__u32 input;
__u32 reserved;
};
MMAP ,定义一个结构体来映射每个缓冲帧。
Struct buffer
{
void* start;
unsigned int length;
}*buffers;
#include
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);// 断开映射
//addr 为映射后的地址,length 为映射后的内存长度
例:将四个已申请到的缓冲帧映射到应用程序,用buffers 指针记录。
buffers = (buffer*)calloc (req.count, sizeof (*buffers));
if (!buffers) {
fprintf (stderr, "Out of memory/n");
exit (EXIT_FAILURE);
}
// 映射
for (unsigned int n_buffers = 0; n_buffers
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
// 查询序号为n_buffers 的缓冲区,得到其起始物理地址和大小
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf))
exit(-1);
buffers[n_buffers].length = buf.length;
// 映射内存
buffers[n_buffers].start =mmap (NULL,buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED,fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
exit(-1);
}
8. 缓冲区处理好之后,就可以开始获取数据了
// 启动/ 停止数据流
VIDIOC_STREAMON,VIDIOC_STREAMOFF
int ioctl(int fd, int request, const int *argp);
//argp 为流类型指针,如V4L2_BUF_TYPE_VIDEO_CAPTURE.
在开始之前,还应当把缓冲帧放入缓冲队列:
VIDIOC_QBUF// 把帧放入队列
VIDIOC_DQBUF// 从队列中取出帧
int ioctl(int fd, int request, struct v4l2_buffer *argp);
例:把四个缓冲帧放入队列,并启动数据流
unsigned int i;
enum v4l2_buf_type type;
// 将缓冲帧放入队列
for (i = 0; i
{
struct v4l2_buffer buf;
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);
// 这有个问题,这些buf 看起来和前面申请的buf 没什么关系,为什么呢?
例:获取一帧并处理
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
// 从缓冲区取出一个缓冲帧
ioctl (fd, VIDIOC_DQBUF, &buf);
// 图像处理
process_image (buffers[buf.index].start);
// 将取出的缓冲帧放回缓冲区
ioctl (fd, VIDIOC_QBUF, &buf);

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

How to remove duplicate values from PHP array using regular expressions: Use regular expression /(.*)(.+)/i to match and replace duplicates. Iterate through the array elements and check for matches using preg_match. If it matches, skip the value; otherwise, add it to a new array with no duplicate values.

Over the past few weeks, the most important specifications and the euro prices of the Motorola Razr 50 and the Razr 50 Ultra have been leaked. Now the enormously reliable leaker @MysteryLupin was able to publish the teaser video embedded below, which

Despite the hype surrounding the Qualcomm Snapdragon X Elite, it has been a rather mediocre launch. In our review, we found that the most impressive part of the new Qualcomm Snapdragon X Elite X1E-78-100-powered Asus Vivobook S 15 was the seamlessnes

Despite the hype surrounding the Qualcomm Snapdragon X Elite, it has been a rather mediocre launch. In our review, we found that the most impressive part of the new Qualcomm Snapdragon X Elite X1E-78-100-powered Asus Vivobook S 15 was the seamlessnes

The GoPro Hero12 Black launched in September 2023 with a number of upgrades over its predecessor, including support for HDR in video and photos and updated image stabilisation algorithms. The normal price of the GoPro Hero12 Black is $399.99, but for

The Google Pixel 9 Pro and Pro XL are Google's answers to the likes of the Samsung Galaxy S24 Ultra and the Apple iPhone 15 Pro and Pro Max. Daniel Sin on YouTube(watch below) has compared the Google Pixel 9 Pro XL to the iPhone 15 Pro Max with some

1. Programming can be used to develop various software and applications, including websites, mobile applications, games, and data analysis tools. Its application fields are very wide, covering almost all industries, including scientific research, health care, finance, education, entertainment, etc. 2. Learning programming can help us improve our problem-solving skills and logical thinking skills. During programming, we need to analyze and understand problems, find solutions, and translate them into code. This way of thinking can cultivate our analytical and abstract abilities and improve our ability to solve practical problems.

Sinceitslaunchearlierthisyear,thePanasonicLumixS9hasbeenembroiledincontroversy.BetweenthecornersPanasoniccuttoarriveatsuchasmallbodyandthefusscertaincamerareviewerskickeduponYouTube,itseemedliketheLumixS9wasdoom
