和菜鸟一起学linux之V4L2摄像头应用流程

V4L2 编程

  1. 定义

V4L2(Video ForLinux Two) 是内核提供给应用程序访问音、视频驱动的统一接口。

  1. 工作流程:

打开设备-> 检查和设置设备属性->设置帧格式-> 设置一种输入输出方法(缓冲区管理)-> 循环获取数据-> 关闭设备。

  1. 设备的打开和关闭:

#include<fcntl.h>

int open(constchar *device_name, int flags);

#include <unistd.h>

int close(intfd);

例:

int fd=open(“/dev/video0”,O_RDWR);// 打开设备
close(fd);// 关闭设备

注意:V4L2 的相关定义包含在头文件<linux/videodev2.h>中.

  1. 查询设备属性: VIDIOC_QUERYCAP

相关函数:

int ioctl(intfd, int request, struct v4l2_capability *argp);

相关结构体:

structv4l2_capability
{
__u8 driver[16];     // 驱动名字
__u8 card[32];       // 设备名字
__u8bus_info[32]; // 设备在系统中的位置
__u32 version;       // 驱动版本号
__u32capabilities;  // 设备支持的操作
__u32reserved[4]; // 保留字段
};
capabilities 常用值:
V4L2_CAP_VIDEO_CAPTURE    // 是否支持图像获取
 

例:显示设备信息

structv4l2_capability cap;
ioctl(fd,VIDIOC_QUERYCAP,&cap);
printf(“DriverName:%s/nCard Name:%s/nBus info:%s/nDriverVersion:%u.%u.%u/n”,cap.driver,cap.card,cap.bus_info,(cap.version>>16)&0XFF,(cap.version>>8)&0XFF,cap.version&OXFF);

  1. 帧格式:
VIDIOC_ENUM_FMT// 显示所有支持的格式
int ioctl(intfd, int request, struct v4l2_fmtdesc *argp);
structv4l2_fmtdesc
{
__u32 index;   // 要查询的格式序号,应用程序设置
enumv4l2_buf_type type;     // 帧类型,应用程序设置
__u32 flags;    // 是否为压缩格式
__u8       description[32];      // 格式名称
__u32pixelformat; // 格式
__u32reserved[4]; // 保留
};

例:显示所有支持的格式

structv4l2_fmtdesc fmtdesc;
fmtdesc.index=0;
fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Supportformat:/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(intfd, int request, struct v4l2_format *argp);
structv4l2_format
{
enumv4l2_buf_type type;// 帧类型,应用程序设置
union fmt
{
structv4l2_pix_format pix;// 视频设备使用
structv4l2_window win;
structv4l2_vbi_format vbi;
structv4l2_sliced_vbi_format sliced;
__u8raw_data[200];
};
};

structv4l2_pix_format
{
__u32 width;  // 帧宽,单位像素
__u32 height;  // 帧高,单位像素
__u32pixelformat; // 帧格式
enum v4l2_fieldfield;
__u32bytesperline;
__u32 sizeimage;
enumv4l2_colorspace colorspace;
__u32 priv;
};

例:显示当前帧的相关信息

structv4l2_format fmt;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd,VIDIOC_G_FMT,&fmt);
printf(“Currentdata format information:
/n/twidth:%d/n/theight:%d/n”,fmt.fmt.width,fmt.fmt.height);
structv4l2_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++;
}

例:检查是否支持某种帧格式

structv4l2_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(“notsupport format RGB32!/n”);

  1. 图像的缩放
VIDIOC_CROPCAP
int ioctl(int fd,int request, struct v4l2_cropcap *argp);
structv4l2_cropcap
{
enumv4l2_buf_type type;// 应用程序设置
struct v4l2_rectbounds;//     最大边界
struct v4l2_rectdefrect;// 默认值
structv4l2_fract pixelaspect;
};

// 设置缩放

VIDIOC_G_CROP,VIDIOC_S_CROP
int ioctl(intfd, int request, struct v4l2_crop *argp);
int ioctl(intfd, int request, const struct v4l2_crop *argp);
struct v4l2_crop
{
enumv4l2_buf_type type;// 应用程序设置
struct v4l2_rectc;
}
  1. 申请和管理缓冲区,应用程序和设备有三种交换数据的方法,直接read/write ,内存映射(memorymapping) ,用户指针。这里只讨论 memorymapping.

// 向设备申请缓冲区

VIDIOC_REQBUFS
int ioctl(intfd, int request, struct v4l2_requestbuffers *argp);
structv4l2_requestbuffers
{
__u32 count;  // 缓冲区内缓冲帧的数目
enumv4l2_buf_type type;     // 缓冲帧数据格式
enum v4l2_memorymemory;       // 区别是内存映射还是用户指针方式
__u32 reserved[2];
};
 
enum v4l2_memoy{V4L2_MEMORY_MMAP,V4L2_MEMORY_USERPTR};
//count,type,memory都要应用程序设置

例:申请一个拥有四个缓冲帧的缓冲区

structv4l2_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(intfd, int request, struct v4l2_buffer *argp);

structv4l2_buffer
{
__u32 index;   //buffer 序号
enumv4l2_buf_type type;     //buffer 类型
__u32 byteused;     //buffer 中已使用的字节数
__u32 flags;    // 区分是MMAP 还是USERPTR
enum v4l2_fieldfield;
struct timevaltimestamp;// 获取第一个字节时的系统时间
structv4l2_timecode timecode;
__u32 sequence;// 队列中的序号
enum v4l2_memorymemory;//IO 方式,被应用程序设置
union m
{
__u32 offset;// 缓冲帧地址,只对MMAP 有效
unsigned longuserptr;
};
__u32 length;// 缓冲帧长度
__u32 input;
__u32 reserved;
};

MMAP ,定义一个结构体来映射每个缓冲帧。

Struct buffer
{
void* start;
unsigned intlength;
}*buffers;

为了做好运维面试路上的助攻手,特整理了上百道 【运维技术栈面试题集锦】 ,让你面试不慌心不跳,高薪offer怀里抱!

这次整理的面试题,小到shell、MySQL,大到K8s等云原生技术栈,不仅适合运维新人入行面试需要,还适用于想提升进阶跳槽加薪的运维朋友。

本份面试集锦涵盖了

  • 174 道运维工程师面试题
  • 128道k8s面试题
  • 108道shell脚本面试题
  • 200道Linux面试题
  • 51道docker面试题
  • 35道Jenkis面试题
  • 78道MongoDB面试题
  • 17道ansible面试题
  • 60道dubbo面试题
  • 53道kafka面试
  • 18道mysql面试题
  • 40道nginx面试题
  • 77道redis面试题
  • 28道zookeeper

总计 1000+ 道面试题, 内容 又全含金量又高

  • 174道运维工程师面试题

1、什么是运维?

2、在工作中,运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的?

3、现在给你三百台服务器,你怎么对他们进行管理?

4、简述raid0 raid1raid5二种工作模式的工作原理及特点

5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?

6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择?

7、Tomcat和Resin有什么区别,工作中你怎么选择?

8、什么是中间件?什么是jdk?

9、讲述一下Tomcat8005、8009、8080三个端口的含义?

10、什么叫CDN?

11、什么叫网站灰度发布?

12、简述DNS进行域名解析的过程?

13、RabbitMQ是什么东西?

14、讲一下Keepalived的工作原理?

15、讲述一下LVS三种模式的工作过程?

16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?

运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的?

3、现在给你三百台服务器,你怎么对他们进行管理?

4、简述raid0 raid1raid5二种工作模式的工作原理及特点

5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?

6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择?

7、Tomcat和Resin有什么区别,工作中你怎么选择?

8、什么是中间件?什么是jdk?

9、讲述一下Tomcat8005、8009、8080三个端口的含义?

10、什么叫CDN?

11、什么叫网站灰度发布?

12、简述DNS进行域名解析的过程?

13、RabbitMQ是什么东西?

14、讲一下Keepalived的工作原理?

15、讲述一下LVS三种模式的工作过程?

16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?

17、如何重置mysql root密码?

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值