2.5 Camera Control Reference

控制属性

class="table-box">
ID描述
VIDIOC_QUERYCTRL查询指定的control详细信息
VIDIOC_QUERYMENU查询menu
VIDIOC_G_CTRL获取设备指定control的当前信息
VIDIOC_S_CTRL设置设备指定的control

2.6 Image Format

图像格式

图像由多种格式YUV和RGB还有压缩格式等等,其中每种格式又分有多种格式,比如RGB:RGB565、RGB888…

所以在使用设备时,需要对格式进行设置

class="table-box">
ID描述
VIDIOC_ENUM_FMT枚举设备支持的图像格式
VIDIOC_G_FMT获取当前设备的图像格式
VIDIOC_S_FMT设置图像格式
VIDIOC_TRY_FMT测试设备是否支持此格式

2.7 Cropping, composing and scaling

图像裁剪、插入与缩放

class="table-box">
ID描述
VIDIOC_CROPCAP获取图像裁剪缩放能力
VIDIOC_G_CROP获取当前的裁剪矩阵
VIDIOC_S_CROP设置裁剪矩阵

2.8 Input/Output

数据的输入和输出

内核中使用缓存队列对图像数据进行管理,用户空间获取图像数据有两种方式,一种是通过read、write方式读取内核空间的缓存,一种是将内核空间的缓存映射到用户空间。在操作v4l2设备时,通过VIDIOC_QUERYCAP获取设备支持哪种方式

class="table-box">
ID描述
VIDIOC_REQBUFS申请缓存
VIDIOC_QUERYBUF获取缓存信息
VIDIOC_QBUF将缓存放入队列中
VIDIOC_DQBUF将缓存从队列中取出

ioctl API就先介绍到这里,还有非常多的接口这里就不一一介绍了,具体可以查看V4L2 Function Reference

下面来讲一讲如何使用这些接口

三、v4l2设备操作流程

V4L2支持多种接口:capture(捕获)output(输出)overlay(预览)等等

这里讲解如何使用capture功能,下面讲解操作流程

step1:打开设备

在Linux中,视频设备节点为/dev/videox,使用open函数将其打开

int fd = open(name, flag);
if(fd < 0)
{
    printf("ERR(%s):failed to open %s\n", __func__, name);
    return -1;
}

return fd;
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 2:查询设备功能

if (ioctl(fd, VIDIOC_QUERYCAP, cap) < 0)
{
    printf("ERR(%s):VIDIOC_QUERYCAP failed\n", __func__);
    return -1;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

看一看v4l2_capability

struct v4l2_capability {
	__u8	driver[16];	/* i.e. "bttv" */
	__u8	card[32];	/* i.e. "Hauppauge WinTV" */
	__u8	bus_info[32];	/* "PCI:" + pci_name(pci_dev) */
	__u32   version;        /* should use KERNEL_VERSION() */
	__u32	capabilities;	/* Device capabilities */
	__u32	reserved[4];
};
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

其中最重要的是capabilities字段,这个字段标记着v4l2设备的功能,capabilities有以下部分标记位

class="table-box">
ID描述符
V4L2_CAP_VIDEO_CAPTURE设备支持捕获功能
V4L2_CAP_VIDEO_OUTPUT设备支持输出功能
V4L2_CAP_VIDEO_OVERLAY设备支持预览功能
V4L2_CAP_STREAMING设备支持流读写
V4L2_CAP_READWRITE设备支持read、write方式读写

我们可以通过这样子去判断设备的功能


if(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
    printf("v4l2 dev support capture\n");

if(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
    printf("v4l2 dev support output\n");

if(cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
    printf("v4l2 dev support overlay\n");

if(cap.capabilities & V4L2_CAP_STREAMING)
    printf("v4l2 dev support streaming\n");

if(cap.capabilities & V4L2_CAP_READWRITE)
    printf("v4l2 dev support read write\n");
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 3:设置输入设备

一个设备可能有多个输入,比如:在芯片上,摄像头控制器和摄像头接口是分离的,需要选择哪一个摄像头接口作为摄像头控制器的输入源

当然,并不是所有的设备都需要设置输入,比如:uvc摄像头,一般只有一个输入,默认就会选择,不需要设置

下面介绍如何设置输入设备

step 4:设置图像格式

有的摄像头支持多种像素格式,有的摄像头只支持一种像素格式,在设置格式之前,要先枚举出所有的格式,看一看是否支持要设置的格式,然后再进一步设置

step 5:设置缓存

v4l2设备读取数据的方式有两种,一种是read方式,一种是streaming方式,具体需要看step 2的返回结果是支持V4L2_CAP_READWRITE还是V4L2_CAP_STREAMING

read方式很容易理解,就是通过read函数读取,那么streaming是什么意思呢?

streaming就是在内核空间中维护一个缓存队列,然后将内存映射到用户空间,应用读取图像数据就是一个不断地出队列入队列的过程,如下图所示

在这里插入图片描述

下面讲解如何去申请和映射缓存

step 6:打开设备

enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
    printf("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
    return -1;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 7:读取数据

获取图像数据其实就是一个不断地入队列和出队列地过程,在出队列前要调用poll等待数据准备完成

step 8:关闭设备

libv4l2

v4l2设备操作起来还是比较繁琐的,为此我对其进行了封装,写了一套库,使用起来更加方便,可以从这里libv4l2获取

其中附带一个实例example_cature,通过capture /dev/video0运行程序采集一张YUYV格式的图片,采集后得到了pic.yuv,可以通过ffplay查看ffplay -pixel_format yuyv422 -f rawvideo -video_size 640x480 pic.yuv,效果图如下

在这里插入图片描述

四、v4l2采集图像在frame buffer显示

如何将采集图像在frame buff上显示?

具体的实现过程这里就不详细说了,下面给出一个例子,点击这里example_video2lcd获取

执行make编译后可以得到video2lcd,执行video2lcd /dev/video0

运行效果如下

在这里插入图片描述

五、v4l2采集图像使用Qt显示

如何使用qt显示,道理跟在frame buff上显示是一样的,都是采集,转化格式,显示,只是在显示部分不同而已,这里给出一个例子,点击这里example_qt获取

运行效果如下

在这里插入图片描述

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"http://iyenn.com/rec/2146284.html","extend1":"pc","ab":"new"}">>
id="article_content" class="article_content clearfix"> id="content_views" class="markdown_views prism-atom-one-light">

深入学习Linux摄像头系列

深入学习Linux摄像头(一)v4l2应用编程

深入学习Linux摄像头(二)v4l2驱动框架

深入学习Linux摄像头(三)虚拟摄像头驱动分析

深入学习Linux摄像头(四)三星平台fimc驱动详解

深入学习Linux摄像头(一)v4l2应用编程

class="toc">

文章目录

一、什么是v4l2

vl42是video for Linux 2的缩写,是一套Linux内核视频设备的驱动框架,该驱动框架为应用层提供一套统一的操作接口(一系列的ioctl)

V4L2在设计时,是要支持很多广泛的设备的,它们之中只有一部分在本质上是真正的视频设备,可以支持多种设备,它可以有以下几种接口

video capture interface:视频采集接口,这种接口应用于摄像头,v4l2在最初设计的时候就是应用于这种功能

video output interface:视频输出接口,将静止图像或图像序列编码为模拟视频信号,通过此接口,应用程序可以控制编码过程并将图像从用户空间移动到驱动程序

video overlay interface:视频直接传输接口,可以将采集到的视频数据直接传输到显示设备,不需要cpu参与,这种方式的显示图像的效率比其他方式高得多

其他接口这里就不介绍了,下面来看一下v4l2的API

二、v4l2 API介绍

对V4L2设备进行编程包括以下步骤

其中大多数操作都是通过应用层调用ioctl实现的,可以将这些ioctl分为下面几类

2.1 Querying Capabilities

查询设备的功能

由于V4L2涵盖了各种各样的设备,因此并非API的所有方面都适用于所有类型的设备,在使用v4l2设备时,必须调用此API,获得设备支持的功能(capture、output、overlay…)

class="table-box">
ID描述
VIDIOC_QUERYCAP查询设备功能

:可以点击名称查看API讲解

2.2 Application Priority

应用优先级

当多个应用程序共享设备时,可能需要为它们分配不同的优先级。视频录制应用程序可以例如阻止其他应用程序改变视频控制或切换当前的电视频道。另一个目标是允许在后台工作的低优先级应用程序,这些应用程序可以被用户控制的应用程序抢占,并在以后自动重新获得对设备的控制

class="table-box">
ID描述
VIDIOC_G_PRIORITY获取优先级
VIDIOC_S_PRIORITY设置优先级

2.3 Device Inputs and Outputs

输入和输出设备

class="table-box">
ID描述
VIDIOC_ENUMINPUT枚举视频输入设备
VIDIOC_G_INPUT获取当前的视频输入设备
VIDIOC_S_INPUT设置视频输入设备
VIDIOC_ENUMOUTPUT枚举视频输出设备
VIDIOC_G_OUTPUT获取当前视频输出设备
VIDIOC_S_OUTPUT设置视频输出设备
VIDIOC_ENUMAUDIO枚举音频输入设备
VIDIOC_G_AUDIO获取当前音频输入设备
VIDIOC_S_AUDIO设置音频输入设备
VIDIOC_ENUMAUDOUT枚举音频输出设备
VIDIOC_G_OUTPUT获取音频输出设备
VIDIOC_S_AUDOUT设置音频输出设备

2.4 Video Standards

视频标准

class="table-box">
ID描述
VIDIOC_ENUMSTD枚举设备支持的所有标准
VIDIOC_G_STD获取当前正在使用的标准
VIDIOC_S_STD设置视频标准
VIDIOC_QUERYSTD有的设备支持自动侦测输入源的视频标准,此ioctl获取检测到的标准

2.5 Camera Control Reference

控制属性

class="table-box">
ID描述
VIDIOC_QUERYCTRL查询指定的control详细信息
VIDIOC_QUERYMENU查询menu
VIDIOC_G_CTRL获取设备指定control的当前信息
VIDIOC_S_CTRL设置设备指定的control

2.6 Image Format

图像格式

图像由多种格式YUV和RGB还有压缩格式等等,其中每种格式又分有多种格式,比如RGB:RGB565、RGB888…

所以在使用设备时,需要对格式进行设置

class="table-box">
ID描述
VIDIOC_ENUM_FMT枚举设备支持的图像格式
VIDIOC_G_FMT获取当前设备的图像格式
VIDIOC_S_FMT设置图像格式
VIDIOC_TRY_FMT测试设备是否支持此格式

2.7 Cropping, composing and scaling

图像裁剪、插入与缩放

class="table-box">
ID描述
VIDIOC_CROPCAP获取图像裁剪缩放能力
VIDIOC_G_CROP获取当前的裁剪矩阵
VIDIOC_S_CROP设置裁剪矩阵

2.8 Input/Output

数据的输入和输出

内核中使用缓存队列对图像数据进行管理,用户空间获取图像数据有两种方式,一种是通过read、write方式读取内核空间的缓存,一种是将内核空间的缓存映射到用户空间。在操作v4l2设备时,通过VIDIOC_QUERYCAP获取设备支持哪种方式

class="table-box">
ID描述
VIDIOC_REQBUFS申请缓存
VIDIOC_QUERYBUF获取缓存信息
VIDIOC_QBUF将缓存放入队列中
VIDIOC_DQBUF将缓存从队列中取出

ioctl API就先介绍到这里,还有非常多的接口这里就不一一介绍了,具体可以查看V4L2 Function Reference

下面来讲一讲如何使用这些接口

三、v4l2设备操作流程

V4L2支持多种接口:capture(捕获)output(输出)overlay(预览)等等

这里讲解如何使用capture功能,下面讲解操作流程

step1:打开设备

在Linux中,视频设备节点为/dev/videox,使用open函数将其打开

int fd = open(name, flag);
if(fd < 0)
{
    printf("ERR(%s):failed to open %s\n", __func__, name);
    return -1;
}

return fd;
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 2:查询设备功能

if (ioctl(fd, VIDIOC_QUERYCAP, cap) < 0)
{
    printf("ERR(%s):VIDIOC_QUERYCAP failed\n", __func__);
    return -1;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

看一看v4l2_capability

struct v4l2_capability {
	__u8	driver[16];	/* i.e. "bttv" */
	__u8	card[32];	/* i.e. "Hauppauge WinTV" */
	__u8	bus_info[32];	/* "PCI:" + pci_name(pci_dev) */
	__u32   version;        /* should use KERNEL_VERSION() */
	__u32	capabilities;	/* Device capabilities */
	__u32	reserved[4];
};
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

其中最重要的是capabilities字段,这个字段标记着v4l2设备的功能,capabilities有以下部分标记位

class="table-box">
ID描述符
V4L2_CAP_VIDEO_CAPTURE设备支持捕获功能
V4L2_CAP_VIDEO_OUTPUT设备支持输出功能
V4L2_CAP_VIDEO_OVERLAY设备支持预览功能
V4L2_CAP_STREAMING设备支持流读写
V4L2_CAP_READWRITE设备支持read、write方式读写

我们可以通过这样子去判断设备的功能


if(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
    printf("v4l2 dev support capture\n");

if(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
    printf("v4l2 dev support output\n");

if(cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
    printf("v4l2 dev support overlay\n");

if(cap.capabilities & V4L2_CAP_STREAMING)
    printf("v4l2 dev support streaming\n");

if(cap.capabilities & V4L2_CAP_READWRITE)
    printf("v4l2 dev support read write\n");
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 3:设置输入设备

一个设备可能有多个输入,比如:在芯片上,摄像头控制器和摄像头接口是分离的,需要选择哪一个摄像头接口作为摄像头控制器的输入源

当然,并不是所有的设备都需要设置输入,比如:uvc摄像头,一般只有一个输入,默认就会选择,不需要设置

下面介绍如何设置输入设备

step 4:设置图像格式

有的摄像头支持多种像素格式,有的摄像头只支持一种像素格式,在设置格式之前,要先枚举出所有的格式,看一看是否支持要设置的格式,然后再进一步设置

step 5:设置缓存

v4l2设备读取数据的方式有两种,一种是read方式,一种是streaming方式,具体需要看step 2的返回结果是支持V4L2_CAP_READWRITE还是V4L2_CAP_STREAMING

read方式很容易理解,就是通过read函数读取,那么streaming是什么意思呢?

streaming就是在内核空间中维护一个缓存队列,然后将内存映射到用户空间,应用读取图像数据就是一个不断地出队列入队列的过程,如下图所示

在这里插入图片描述

下面讲解如何去申请和映射缓存

step 6:打开设备

enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
    printf("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
    return -1;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 7:读取数据

获取图像数据其实就是一个不断地入队列和出队列地过程,在出队列前要调用poll等待数据准备完成

step 8:关闭设备

libv4l2

v4l2设备操作起来还是比较繁琐的,为此我对其进行了封装,写了一套库,使用起来更加方便,可以从这里libv4l2获取

其中附带一个实例example_cature,通过capture /dev/video0运行程序采集一张YUYV格式的图片,采集后得到了pic.yuv,可以通过ffplay查看ffplay -pixel_format yuyv422 -f rawvideo -video_size 640x480 pic.yuv,效果图如下

在这里插入图片描述

四、v4l2采集图像在frame buffer显示

如何将采集图像在frame buff上显示?

具体的实现过程这里就不详细说了,下面给出一个例子,点击这里example_video2lcd获取

执行make编译后可以得到video2lcd,执行video2lcd /dev/video0

运行效果如下

在这里插入图片描述

五、v4l2采集图像使用Qt显示

如何使用qt显示,道理跟在frame buff上显示是一样的,都是采集,转化格式,显示,只是在显示部分不同而已,这里给出一个例子,点击这里example_qt获取

运行效果如下

在这里插入图片描述

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"http://iyenn.com/rec/2146284.html","extend1":"pc","ab":"new"}">>
id="article_content" class="article_content clearfix"> id="content_views" class="markdown_views prism-atom-one-light">

深入学习Linux摄像头系列

深入学习Linux摄像头(一)v4l2应用编程

深入学习Linux摄像头(二)v4l2驱动框架

深入学习Linux摄像头(三)虚拟摄像头驱动分析

深入学习Linux摄像头(四)三星平台fimc驱动详解

深入学习Linux摄像头(一)v4l2应用编程

class="toc">

文章目录

一、什么是v4l2

vl42是video for Linux 2的缩写,是一套Linux内核视频设备的驱动框架,该驱动框架为应用层提供一套统一的操作接口(一系列的ioctl)

V4L2在设计时,是要支持很多广泛的设备的,它们之中只有一部分在本质上是真正的视频设备,可以支持多种设备,它可以有以下几种接口

video capture interface:视频采集接口,这种接口应用于摄像头,v4l2在最初设计的时候就是应用于这种功能

video output interface:视频输出接口,将静止图像或图像序列编码为模拟视频信号,通过此接口,应用程序可以控制编码过程并将图像从用户空间移动到驱动程序

video overlay interface:视频直接传输接口,可以将采集到的视频数据直接传输到显示设备,不需要cpu参与,这种方式的显示图像的效率比其他方式高得多

其他接口这里就不介绍了,下面来看一下v4l2的API

二、v4l2 API介绍

对V4L2设备进行编程包括以下步骤

其中大多数操作都是通过应用层调用ioctl实现的,可以将这些ioctl分为下面几类

2.1 Querying Capabilities

查询设备的功能

由于V4L2涵盖了各种各样的设备,因此并非API的所有方面都适用于所有类型的设备,在使用v4l2设备时,必须调用此API,获得设备支持的功能(capture、output、overlay…)

class="table-box">
ID描述
VIDIOC_QUERYCAP查询设备功能

:可以点击名称查看API讲解

2.2 Application Priority

应用优先级

当多个应用程序共享设备时,可能需要为它们分配不同的优先级。视频录制应用程序可以例如阻止其他应用程序改变视频控制或切换当前的电视频道。另一个目标是允许在后台工作的低优先级应用程序,这些应用程序可以被用户控制的应用程序抢占,并在以后自动重新获得对设备的控制

class="table-box">
ID描述
VIDIOC_G_PRIORITY获取优先级
VIDIOC_S_PRIORITY设置优先级

2.3 Device Inputs and Outputs

输入和输出设备

class="table-box">
ID描述
VIDIOC_ENUMINPUT枚举视频输入设备
VIDIOC_G_INPUT获取当前的视频输入设备
VIDIOC_S_INPUT设置视频输入设备
VIDIOC_ENUMOUTPUT枚举视频输出设备
VIDIOC_G_OUTPUT获取当前视频输出设备
VIDIOC_S_OUTPUT设置视频输出设备
VIDIOC_ENUMAUDIO枚举音频输入设备
VIDIOC_G_AUDIO获取当前音频输入设备
VIDIOC_S_AUDIO设置音频输入设备
VIDIOC_ENUMAUDOUT枚举音频输出设备
VIDIOC_G_OUTPUT获取音频输出设备
VIDIOC_S_AUDOUT设置音频输出设备

2.4 Video Standards

视频标准

class="table-box">
ID描述
VIDIOC_ENUMSTD枚举设备支持的所有标准
VIDIOC_G_STD获取当前正在使用的标准
VIDIOC_S_STD设置视频标准
VIDIOC_QUERYSTD有的设备支持自动侦测输入源的视频标准,此ioctl获取检测到的标准

2.5 Camera Control Reference

控制属性

class="table-box">
ID描述
VIDIOC_QUERYCTRL查询指定的control详细信息
VIDIOC_QUERYMENU查询menu
VIDIOC_G_CTRL获取设备指定control的当前信息
VIDIOC_S_CTRL设置设备指定的control

2.6 Image Format

图像格式

图像由多种格式YUV和RGB还有压缩格式等等,其中每种格式又分有多种格式,比如RGB:RGB565、RGB888…

所以在使用设备时,需要对格式进行设置

class="table-box">
ID描述
VIDIOC_ENUM_FMT枚举设备支持的图像格式
VIDIOC_G_FMT获取当前设备的图像格式
VIDIOC_S_FMT设置图像格式
VIDIOC_TRY_FMT测试设备是否支持此格式

2.7 Cropping, composing and scaling

图像裁剪、插入与缩放

class="table-box">
ID描述
VIDIOC_CROPCAP获取图像裁剪缩放能力
VIDIOC_G_CROP获取当前的裁剪矩阵
VIDIOC_S_CROP设置裁剪矩阵

2.8 Input/Output

数据的输入和输出

内核中使用缓存队列对图像数据进行管理,用户空间获取图像数据有两种方式,一种是通过read、write方式读取内核空间的缓存,一种是将内核空间的缓存映射到用户空间。在操作v4l2设备时,通过VIDIOC_QUERYCAP获取设备支持哪种方式

class="table-box">
ID描述
VIDIOC_REQBUFS申请缓存
VIDIOC_QUERYBUF获取缓存信息
VIDIOC_QBUF将缓存放入队列中
VIDIOC_DQBUF将缓存从队列中取出

ioctl API就先介绍到这里,还有非常多的接口这里就不一一介绍了,具体可以查看V4L2 Function Reference

下面来讲一讲如何使用这些接口

三、v4l2设备操作流程

V4L2支持多种接口:capture(捕获)output(输出)overlay(预览)等等

这里讲解如何使用capture功能,下面讲解操作流程

step1:打开设备

在Linux中,视频设备节点为/dev/videox,使用open函数将其打开

int fd = open(name, flag);
if(fd < 0)
{
    printf("ERR(%s):failed to open %s\n", __func__, name);
    return -1;
}

return fd;
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 2:查询设备功能

if (ioctl(fd, VIDIOC_QUERYCAP, cap) < 0)
{
    printf("ERR(%s):VIDIOC_QUERYCAP failed\n", __func__);
    return -1;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

看一看v4l2_capability

struct v4l2_capability {
	__u8	driver[16];	/* i.e. "bttv" */
	__u8	card[32];	/* i.e. "Hauppauge WinTV" */
	__u8	bus_info[32];	/* "PCI:" + pci_name(pci_dev) */
	__u32   version;        /* should use KERNEL_VERSION() */
	__u32	capabilities;	/* Device capabilities */
	__u32	reserved[4];
};
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

其中最重要的是capabilities字段,这个字段标记着v4l2设备的功能,capabilities有以下部分标记位

class="table-box">
ID描述符
V4L2_CAP_VIDEO_CAPTURE设备支持捕获功能
V4L2_CAP_VIDEO_OUTPUT设备支持输出功能
V4L2_CAP_VIDEO_OVERLAY设备支持预览功能
V4L2_CAP_STREAMING设备支持流读写
V4L2_CAP_READWRITE设备支持read、write方式读写

我们可以通过这样子去判断设备的功能


if(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
    printf("v4l2 dev support capture\n");

if(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
    printf("v4l2 dev support output\n");

if(cap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
    printf("v4l2 dev support overlay\n");

if(cap.capabilities & V4L2_CAP_STREAMING)
    printf("v4l2 dev support streaming\n");

if(cap.capabilities & V4L2_CAP_READWRITE)
    printf("v4l2 dev support read write\n");
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 3:设置输入设备

一个设备可能有多个输入,比如:在芯片上,摄像头控制器和摄像头接口是分离的,需要选择哪一个摄像头接口作为摄像头控制器的输入源

当然,并不是所有的设备都需要设置输入,比如:uvc摄像头,一般只有一个输入,默认就会选择,不需要设置

下面介绍如何设置输入设备

step 4:设置图像格式

有的摄像头支持多种像素格式,有的摄像头只支持一种像素格式,在设置格式之前,要先枚举出所有的格式,看一看是否支持要设置的格式,然后再进一步设置

step 5:设置缓存

v4l2设备读取数据的方式有两种,一种是read方式,一种是streaming方式,具体需要看step 2的返回结果是支持V4L2_CAP_READWRITE还是V4L2_CAP_STREAMING

read方式很容易理解,就是通过read函数读取,那么streaming是什么意思呢?

streaming就是在内核空间中维护一个缓存队列,然后将内存映射到用户空间,应用读取图像数据就是一个不断地出队列入队列的过程,如下图所示

在这里插入图片描述

下面讲解如何去申请和映射缓存

step 6:打开设备

enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
    printf("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
    return -1;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

step 7:读取数据

获取图像数据其实就是一个不断地入队列和出队列地过程,在出队列前要调用poll等待数据准备完成

step 8:关闭设备

libv4l2

v4l2设备操作起来还是比较繁琐的,为此我对其进行了封装,写了一套库,使用起来更加方便,可以从这里libv4l2获取

其中附带一个实例example_cature,通过capture /dev/video0运行程序采集一张YUYV格式的图片,采集后得到了pic.yuv,可以通过ffplay查看ffplay -pixel_format yuyv422 -f rawvideo -video_size 640x480 pic.yuv,效果图如下

在这里插入图片描述

四、v4l2采集图像在frame buffer显示

如何将采集图像在frame buff上显示?

具体的实现过程这里就不详细说了,下面给出一个例子,点击这里example_video2lcd获取

执行make编译后可以得到video2lcd,执行video2lcd /dev/video0

运行效果如下

在这里插入图片描述

五、v4l2采集图像使用Qt显示

如何使用qt显示,道理跟在frame buff上显示是一样的,都是采集,转化格式,显示,只是在显示部分不同而已,这里给出一个例子,点击这里example_qt获取

运行效果如下

在这里插入图片描述

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"http://iyenn.com/rec/2146284.html","extend1":"pc","ab":"new"}">>
注:本文转载自blog.csdn.net的JT同学的文章"https://blog.csdn.net/weixin_42462202/article/details/96826526"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!