V4L2 编程

Jun 07, 2016 pm 03:43 PM
for l video 定义 编程

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,“内存不足/n”); 

退出(EXIT_FAILURE); 


// 地图

for (unsigned int n_buffers = 0; n_buffers
结构体v4l2_buffer buf; 

memset(&buf,0,sizeof(buf)); 

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

buf.内存 = V4L2_MEMORY_MMAP; 

buf.index = n_buffers; 

// 查询序号为n_buffers的坐标,获取其起始物理地址和大小

if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf))

退出(-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) 

退出(-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); 

例:把四个缓冲帧队列,并启动数据流

无符号整型 i; 

枚举 v4l2_buf_type 类型; 

// 将缓冲队列队列

for (i = 0; i { 

结构体v4l2_buffer buf; 

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

buf.内存 = V4L2_MEMORY_MMAP; 

buf.index = i; 

ioctl (fd, VIDIOC_QBUF, &buf); 



类型= V4L2_BUF_TYPE_VIDEO_CAPTURE; 

ioctl (fd, VIDIOC_STREAMON, &type); 

// 这有问题,这些buf看起来和前面申请的buf没什么关系,为什么呢? 


例如:获取一帧并处理

结构体v4l2_buffer buf; 

清除(buf); 

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

buf.内存 = V4L2_MEMORY_MMAP; 

// 从动脉抽取一个缓冲帧

ioctl(fd, VIDIOC_DQBUF, &buf); 

// 图像处理

process_image(buffers[buf.index].start); 

// 将取出的缓冲帧放回瀑布

ioctl (fd, VIDIOC_QBUF, &buf); 

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

摩托罗拉 Razr 50 Ultra 出现在泄露的预告视频中,配有防水外壳和巨大的副显示屏 摩托罗拉 Razr 50 Ultra 出现在泄露的预告视频中,配有防水外壳和巨大的副显示屏 Jun 20, 2024 pm 09:31 PM

过去几周,摩托罗拉 Razr 50 和 Razr 50 Ultra 最重要的规格和欧元价格已经泄露。现在,极其可靠的泄密者 @MysteryLupin 能够发布下面嵌入的预告视频,其中

使用正则表达式去除 PHP 数组中的重复值 使用正则表达式去除 PHP 数组中的重复值 Apr 26, 2024 pm 04:33 PM

使用正则表达式从PHP数组中去除重复值的方法:使用正则表达式/(.*)(.+)/i匹配并替换重复项。遍历数组元素,使用preg_match检查匹配情况。如果匹配,跳过值;否则,将其添加到无重复值的新数组中。

Pixel 9 Pro XL 与 iPhone 15 Pro Max 相机比较显示谷歌在视频和变焦性能方面取得了令人惊讶的胜利 Pixel 9 Pro XL 与 iPhone 15 Pro Max 相机比较显示谷歌在视频和变焦性能方面取得了令人惊讶的胜利 Aug 24, 2024 pm 12:32 PM

谷歌 Pixel 9 Pro 和 Pro XL 是谷歌对三星 Galaxy S24 Ultra 和苹果 iPhone 15 Pro 和 Pro Max 等产品的回应。 YouTube 上的 Daniel Sin(请观看下文)将 Google Pixel 9 Pro XL 与 iPhone 15 Pro Max 进行了一些比较

松下 Lumix S9 供应短缺,尽管有负面报道,但仍完成富士 X100VI 的冒充行为 松下 Lumix S9 供应短缺,尽管有负面报道,但仍完成富士 X100VI 的冒充行为 Jun 14, 2024 am 09:36 AM

自从今年早些时候推出以来,松下 Lumix S9 就一直陷入争议。在松下切入小机身和 YouTube 上某些相机评论家的大惊小怪之间,看起来 Lumix S9 已经完蛋了。

在 Vivobook S15 基准测试中,Snapdragon X Elite CPU 的电池性能和插入性能几乎相同 在 Vivobook S15 基准测试中,Snapdragon X Elite CPU 的电池性能和插入性能几乎相同 Jun 20, 2024 pm 03:59 PM

尽管围绕高通 Snapdragon X Elite 进行了大肆宣传,但它的发布却相当平庸。在我们的评测中,我们发现搭载 Qualcomm Snapdragon X Elite X1E-78-100 的华硕 Vivobook S 15 最令人印象深刻的部分是无缝连接

编程是干啥的,学了有什么用 编程是干啥的,学了有什么用 Apr 28, 2024 pm 01:34 PM

1、编程可以用于开发各种软件和应用程序,包括网站、手机应用、游戏和数据分析工具等。它的应用领域非常广泛,覆盖了几乎所有行业,包括科学研究、医疗保健、金融、教育、娱乐等。2、学习编程可以帮助我们提高问题解决能力和逻辑思维能力。编程过程中,我们需要分析和理解问题,找出解决方案,并将其转化为代码。这种思维方式能够培养我们的分析和抽象能力,提高我们解决实际问题的能力。

使用 Python 解决问题:作为初学者,解锁强大的解决方案 使用 Python 解决问题:作为初学者,解锁强大的解决方案 Oct 11, 2024 pm 08:58 PM

Python 使初学者能够解决问题。其用户友好的语法、广泛的库以及变量、条件语句和循环等功能可实现高效的代码开发。从管理数据到控制程序流程和执行重复任务,Python 提供了

在 Vivobook S15 基准测试中,Snapdragon X Elite CPU 的电池性能与交流电源性能几乎相同 在 Vivobook S15 基准测试中,Snapdragon X Elite CPU 的电池性能与交流电源性能几乎相同 Jun 21, 2024 am 06:50 AM

尽管围绕高通 Snapdragon X Elite 进行了大肆宣传,但它的发布却相当平庸。在我们的评测中,我们发现搭载 Qualcomm Snapdragon X Elite X1E-78-100 的华硕 Vivobook S 15 最令人印象深刻的部分是无缝连接

See all articles