search
HomeDatabaseMysql TutorialV4L2驱动的移植与应用(二)
V4L2驱动的移植与应用(二)Jun 07, 2016 pm 03:33 PM
underintroduceapplicationSimpledrive

二、 V4L2 的应用 下面简单介绍一下 V4L2 驱动的应用流程。 1、 视频采集的基本流程 一般的,视频采集都有如下流程: 2、 打开视频设备 在 V4L2 中,视频设备被看做一个文件。使用 open 函数打开这个设备: // 用非阻塞模式打开摄像头设备 int cameraFd; cam

二、V4L2的应用

    下面简单介绍一下V4L2驱动的应用流程。

1、  视频采集的基本流程

一般的,视频采集都有如下流程:

 

 

2、  打开视频设备

V4L2中,视频设备被看做一个文件。使用open函数打开这个设备:

// 用非阻塞模式打开摄像头设备
int cameraFd;
cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);
//
如果用阻塞模式打开摄像头设备,上述代码变为:
//cameraFd = open("/dev/video0", O_RDWR, 0);

关于阻塞模式和非阻塞模式:应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。

3、  设定属性及采集方式

打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:

extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd

__request:具体的命令标志符。

在进行V4L2开发中,一般会用到以下的命令标志符:

VIDIOC_REQBUFS:分配内存

VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址

VIDIOC_QUERYCAP:查询驱动功能

VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式

VIDIOC_S_FMT:设置当前驱动的频捕获格式

VIDIOC_G_FMT:读取当前驱动的频捕获格式

VIDIOC_TRY_FMT:验证当前驱动的显示格式

VIDIOC_CROPCAP:查询驱动的修剪能力

VIDIOC_S_CROP:设置视频信号的边框

VIDIOC_G_CROP:读取视频信号的边框

VIDIOC_QBUF:把数据从缓存中读取出来

VIDIOC_DQBUF:把数据放回缓存队列

VIDIOC_STREAMON:开始视频显示函数

VIDIOC_STREAMOFF:结束视频显示函数

VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PALNTSC

这些IO调用,有些是必须的,有些是可选择的。

4、  检查当前视频设备支持的标准

在亚洲,一般使用PAL720X576)制式的摄像头,而欧洲一般使用NTSC720X480),使用VIDIOC_QUERYSTD来检测:

v4l2_std_id std;
do {
  ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {
    case V4L2_STD_NTSC:
        //……
    case V4L2_STD_PAL:
        //……
}

5、  设置视频捕获格式

当检测完视频设备支持的标准后,还需要设定视频捕获格式:

struct v4l2_format    fmt;
memset ( &fmt, 0, sizeof(fmt) );
fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width       = 720;
fmt.fmt.pix.height      = 576;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
  return -1;
}

v4l2_format结构体定义如下:

struct v4l2_format
{
    enum v4l2_buf_type type;    //
数据流类型,必须永远是
V4L2_BUF_TYPE_VIDEO_CAPTURE
    union
    {
        struct v4l2_pix_format    pix; 
        struct v4l2_window        win; 
        struct v4l2_vbi_format    vbi; 
        __u8    raw_data[200];         
    } fmt;
};
struct v4l2_pix_format
{
    __u32                   width;         //
宽,必须是16的倍数

    __u32                   height;        //
高,必须是16的倍数
    __u32                   pixelformat;   //
视频数据存储类型,例如是YUV422还是RGB
    enum v4l2_field         field;
    __u32                   bytesperline;   
    __u32                   sizeimage;
    enum v4l2_colorspace    colorspace;
    __u32                   priv;      
};

6、  分配内存

接下来可以为视频捕获分配内存:

struct v4l2_requestbuffers  req;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
  return -1;
}

v4l2_requestbuffers定义如下:

struct v4l2_requestbuffers
{
    __u32               count;  //
缓存数量,也就是说在缓存队列里保持多少张照片

    enum v4l2_buf_type  type;   //
数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
    enum v4l2_memory    memory; // V4L2_MEMORY_MMAP
V4L2_MEMORY_USERPTR
    __u32               reserved[2];
};

7、  获取并记录缓存的物理空间

使用VIDIOC_REQBUFS,我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:

 

typedef struct VideoBuffer {
    void   *start;
    size_t  length;
} VideoBuffer;

VideoBuffer*          buffers = calloc( req.count, sizeof(*buffers) );
struct v4l2_buffer    buf;

for (numBufs = 0; numBufs     memset( &buf, 0, sizeof(buf) );
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = numBufs;
    //
读取缓存

    if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
        return -1;
    }

    buffers[numBufs].length = buf.length;
    //
转换成相对地址
    buffers[numBufs].start = mmap(NULL, buf.length,
        PROT_READ | PROT_WRITE,
        MAP_SHARED,
        fd, buf.m.offset);

    if (buffers[numBufs].start == MAP_FAILED) {
        return -1;
    }

    //
放入缓存队列
    if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
        return -1;
    }
}

8、  关于视频采集方式

操作系统一般把系统使用的内存划分成用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是供内核访问的代码和数据,用户不能直接访问。v4l2捕获的数据,最初是存放在内核空间的,这意味着用户不能直接访问该段内存,必须通过某些手段来转换地址。

一共有三种视频采集方式:

1)使用readwrite方式:直接使用readwrite函数进行读写。这种方式最简单,但是这种方式会在用户空间和内核空间不断拷贝数据,同时在用户空间和内核空间占用大量内存,效率不高。

2)内存映射方式(mmap):把设备里的内存映射到应用程序中的内存控件,直接处理设备内存,这是一种有效的方式。上面的mmap函数就是使用这种方式。

3)用户指针模式:内存由用户空间的应用程序分配,并把地址传递到内核中的驱动程序,然后由v4l2驱动程序直接将数据填充到用户空间的内存中。这点需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR

第一种方式效率是最低的,后面两种方法都能提高执行的效率,但是对于mmap 方式,文档中有这样一句描述 --Remember the buffers are allocated in physical memory, as opposed to virtual memory which can be swapped out to disk. Applications should free the buffers as soon as possible with the munmap () function .(使用mmap方法的时候,buffers相当于是在内核空间中分配的,这种情况下,这些buffer是不能被交换到虚拟内存中,虽然这种方法不怎么影响读写效率,但是它一直占用着内核空间中的内存,当系统的内存有限的时候,如果同时运行有大量的进程,则对系统的整体性能会有一定的影响。)

       所以,对于三种视频采集方式的选择,推荐的顺序是 userptr mmap read-write 。当使用 mmap userptr 方式的时候,有一个环形缓冲队列的概念,这个队列中,有 n buffer ,驱动程序采集到的视频帧数据,就是存储在每个 buffer 中。在每次用 VIDIOC_DQBUF 取出一个 buffer ,并且处理完数据后,一定要用 VIDIOC_QBUF 将这个 buffer 再次放回到环形缓冲队列中。环形缓冲队列,也使得这两种视频采集方式的效率高于直接 read/write

9、  处理采集数据

V4L2有一个数据缓存,存放req.count数量的缓存数据。数据缓存采用FIFO的方式,当应用程序调用缓存数据时,缓存队列将最先采集到的视频数据缓存送出,并重新采集一张视频数据。这个过程需要用到两个ioctl命令,VIDIOC_DQBUFVIDIOC_QBUF

struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=0;

//读取缓存
if (ioctl(cameraFd, VIDIOC_DQBUF, &buf) == -1)
{
    return -1;
}
//…………
视频处理算法
//
重新放入缓存队列
if (ioctl(cameraFd, VIDIOC_QBUF, &buf) == -1) {

    return -1;
}

10、              关闭视频设备

使用close函数关闭一个视频设备

close(cameraFd)

(待续)

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
显卡装驱动就黑屏是什么原因显卡装驱动就黑屏是什么原因Feb 24, 2023 pm 02:59 PM

显卡装驱动就黑屏是分辨率超出设置或显卡驱动不匹配或不兼容的原因导致的,其解决办法:1、一开机就不停按“F8”,然后选择安全模式;2、在安全模式下卸载显卡驱动或在设备管理器禁用显卡设备后重启;3、卸载显卡驱动,然后去显卡对应的官网下载对应系统版本的驱动安装即可。

驱动是软件还是硬件驱动是软件还是硬件Sep 06, 2022 pm 03:58 PM

驱动是软件。驱动全称“设备驱动程序”,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息,用于使计算机与相应的硬件设备进行通信。驱动本质上是软件代码,其主要作用是计算机系统与硬件设备之间完成数据传送的功能,只有借助驱动程序,两者才能通信并完成特定的功能。

如何卸载win11上的网卡驱动如何卸载win11上的网卡驱动Dec 28, 2023 pm 07:04 PM

网卡驱动的不匹配会导致无法正常上网,但是又无法正常更新,这时候可以在win11卸载网卡驱动,然后重新安装来解决问题,只需要在设备管理器里就能操作了。win11卸载网卡驱动教程:1、首先右键底部“Windows徽标”2、接着点开右键菜单中的“设备管理器”3、打开后,展开“网络适配器”,找到网卡设备。4、随后双击打开想要卸载驱动的设备,进入“驱动程序”5、最后选择“卸载设备”就可以卸载win11网卡驱动了。

修复:系统驱动程序被锁定到制造商规格修复:系统驱动程序被锁定到制造商规格Sep 23, 2023 pm 07:25 PM

图形驱动程序是PC上最重要的驱动程序之一,直接影响性能和游戏体验。但是,当通过安装程序更新驱动程序时,许多人遇到“您的系统具有锁定到制造商规格的驱动程序”错误。出现此问题的原因是制造商限制更新,除非从其末端专门推送更新。这确保了稳定性,但对许多人来说可能是一个问题。因此,让我们找出如何立即解决问题!如何修复您的系统具有锁定在Windows11上的制造商规范的驱动程序?在我们转向稍微复杂的解决方案之前,请先尝试以下快速解决方案:确保你的电脑和操作系统满足驱动程序的系统要求。将电脑启动到安全模式,然

赛睿驱动是否只能安装在C盘上?赛睿驱动是否只能安装在C盘上?Jan 02, 2024 am 08:07 AM

一些赛睿的用户在购买驱动后发现,默认安装路径都是在C盘上。然而,很多人可能还不知道,其实可以更改安装路径。现在我们来看看如何进行更改。赛睿驱动只能装c盘吗赛睿驱动并不限制只能安装在C盘。赛睿的驱动文件通常会被安装在Windows操作系统的C盘下面的特定文件夹中。请注意,电脑系统默认会将自带驱动安装在C盘。用户可以将下载的第三方电脑软件保存在其他磁盘中。用户只需在安装时将安装路径更改为所需位置,即可进行更换。

win10驱动安装路径详解win10驱动安装路径详解Jan 04, 2024 pm 07:56 PM

在使用Windows10操作系统时,为了确保正常运行,我们需要安装相应的驱动程序。然而,很多朋友可能不知道在哪里可以找到Windows10的驱动程序。通常情况下,我们可以在C盘的drivers文件夹中找到Windows10的驱动程序。现在,让我们一起来了解一下具体的查找过程吧。win10驱动在哪:首先,我们需要按下键盘上的“Win徽标”和“R”键来打开运行窗口。在运行中,我们输入“devmgmt.msc”,然后点击“确定”。请展开想要查看的设备类型。如果你想了解更多关于设备类型的信息,请继续阅读

win10USB驱动安装详细步骤分享win10USB驱动安装详细步骤分享Dec 27, 2023 am 10:29 AM

越来越多的人都在使用Win10系统,驱动安装也是系统使用过程中的一个常见问题。那么win10的usb驱动是怎么安装的呢?下面就看看小编怎么做的吧,希望可以帮助到你哦!win10usb驱动怎么安装:1、首先下载并安装驱动精灵软件。2、完成后打开后软件会自动检测电脑的驱动安装情况。3、然后等待检测完毕,点击“驱动程序”。4、再点击驱动程序后,默认进入的是“标准模式”,找到需要安装的USB驱动程序,然后点击下载。5、等待驱动程序下载完成。6、驱动程序下载完成后点击“安装”。7、点击安装后等待驱动程序安

解决驱动安装失败的有效方法解决驱动安装失败的有效方法Jan 02, 2024 pm 04:05 PM

当用户在连接设备和电脑时遇到驱动安装失败的问题时,可能是因为设备与系统不兼容。在这种情况下,建议用户下载并安装与设备相对应的驱动程序来解决问题。驱动安装失败怎么办:第一方法:《文字玩出花》是一款备受欢迎的文字解谜游戏,每天都会有新的关卡更新。其中之一是名为“怀旧大扫除”的关卡,在这个关卡中,我们需要在图片中找到12处与年代不符的地方。今天我将与大家分享一下《文字玩出花》怀旧大扫除关卡的通关攻略,希望对还没有通关的小伙伴们有所帮助。目前,几乎所有的厂商都会发布相应的驱动程序。如果我们遇到设备自动安

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools