Linux下V4L2实时显示摄像头捕捉画面(完整QT+C++代码)

目录

一、V4L2

1、简介

2、编程与应用

二、示例演示

1、例子说明:

2、关键的代码演示

3、完整的例子的代码


一、V4L2

1、简介

        V4L2,即Video for Linux Two,是Linux下关于视频设备的内核驱动框架,为驱动和应用程序提供了一套统一的接口规范。

        在Linux中,视频设备被视为设备文件,通常位于/dev/video目录下。如果只有一个视频设备,它通常是/dev/video0

2、编程与应用

(1)编程框架:V4L2是针对UVC免驱USB设备的编程框架,主要用于采集USB摄像头等。编程时,开发者可以通过ioctl函数对设备的I/O通道进行管理,使用一系列特定的命令标志符来实现不同的功能。

(2)重要数据结构:V4L2在include/linux/videodev.h文件中定义了一些重要的数据结构,如v4l2_formatv4l2_crop等,用于描述视频设备的行为和数据的格式。

(3)主要函数:通过ioctl函数和一系列特定的命令标志符(如VIDIOC_REQBUFS、VIDIOC_QUERYBUF、VIDIOC_STREAMON等),开发者可以对视频设备进行参数设置、数据采集和处理等操作。

(4)注册流程:在进行视频数据流操作之前,首先需要通过标准的字符设备操作接口open方法来打开一个video设备,并返回设备句柄。之后的一系列操作都是基于对这个句柄的操作。在打开的过程中,会给每一个子设备进行各自的一系列初始化操作。

(5)应用场景:V4L2在远程会议、可视电话、视频监控系统和嵌入式多媒体终端等领域有广泛应用。

        总之,V4L2是Linux下功能强大的视频设备驱动框架,它提供了丰富的接口和灵活的数据结构,使得开发者能够轻松地实现视频数据的采集、处理和传输等功能。

二、示例演示

1、例子说明:

在ARM系统的机器中有摄像头,要对此机器的摄像头进行开关控制,并显示在屏幕上(或者实时显示Qt的窗口上)

或者用你的虚拟机连接摄像头设备也是可以。

(1)查看机器上面的摄像机设备号

Linux下V4L2实时显示摄像头捕捉画面(完整QT+C++代码)_第1张图片

2、关键的代码演示

(1)打开设备

int CameraCapture::Camera_OpenCam(const char *devicePath)
{
    qDebug() << __FUNCTION__ << __LINE__ ;

    fd_cam = open(devicePath, O_RDWR, 0);
    if (fd_cam < 0)
    {
        qDebug() << QString("Open failed (%1), %2 ")
                    .arg(QString::fromStdString(devicePath))
                    .arg(strerror(errno));
        return -1;
    }

    qDebug() << QString("fd_cam (%1) open successfully ").arg(QString::number(fd_cam));
    return fd_cam ;

}

(2)关闭摄像头

int CameraCapture::closeCamera()
{
    qDebug() << __FUNCTION__ << __LINE__ ;

    // 防止打开程序时候,就要关闭摄像头。
    if(fd_cam == -1)
    {
        qDebug() << __FUNCTION__ << __LINE__ << "当前没有打开摄像头,直接返回。";
        return 0;
    }

    // 清空当前数据
    Camera_UNMap(framebuf1);

    qDebug() << __FUNCTION__ << __LINE__  << QString("fd_cam " + QString::number(fd_cam));

    return close(fd_cam);
}

(3)获取摄像头的相关信息

int CameraCapture::Camera_GetCamInfo()
{
    int ret=-1 ;

    // GetDevicInfo
    struct v4l2_capability cap;
    ret = ioctl(fd_cam, VIDIOC_QUERYCAP, &cap);
    if (ret < 0)
    {
        qDebug() << "VIDIOC_QUERYCAP failed: " << QString::number(ret);
        return ret;
    }

    return ret ;
}

(4)获取摄像头中视频流的数据

int CameraCapture::Camera_RequestBuffers(v4l2_requestbuffers *reqbuf__)
{
    // Request Buffers from kernel
    int ret =-1 ;
    reqbuf__->count = BUFFER_COUNT;
    reqbuf__->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf__->memory = V4L2_MEMORY_MMAP;

    ret = ioctl(fd_cam , VIDIOC_REQBUFS, reqbuf__);

    if(ret < 0)
    {
        qDebug() << "VIDIOC_REQBUFS failed: " << QString::number(ret);
        return ret;
    }
    return ret ;
}
3、完整的例子的代码

(1)简单的例子演示

//下面是一段使用 V4L2 (Video for Linux 2) API 来打开和关闭摄像头的基本示例代码。
//这段代码展示了如何初始化设备、设置视频格式、捕获一帧图像并释放资源。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define DEVICE_NAME "/dev/video0"
#define BUFFER_COUNT 4

// 结构体用于存储缓冲区信息
struct buffer {
    void *start;
    size_t length;
};

// 初始化缓冲区
int init_buffers(int fd, struct buffer *buffers) {
    struct v4l2_requestbuffers req;

    memset(&req, 0, sizeof(req));
    req.count = BUFFER_COUNT;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;

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

    buffers->length = req.length;
    for (unsigned int i = 0; i < req.count; ++i) {
        struct v4l2_buffer buf;

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

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

        buffers[i].length = buf.length;
        buffers[i].start = mmap(NULL, buf.length,
                                PROT_READ | PROT_WRITE,
                                MAP_SHARED, fd, buf.m.offset);

        if (buffers[i].start == MAP_FAILED) {
            perror("mmap");
            return -1;
        }
    }

    return 0;
}

// 清理缓冲区
void cleanup_buffers(int fd, struct buffer *buffers) 
{
    for (unsigned int i = 0; i < BUFFER_COUNT; ++i)
        munmap(buffers[i].start, buffers[i].length);
}

int main()
{
    int fd;
    struct v4l2_capability cap;
    struct v4l2_format fmt;
    struct buffer buffers[BUFFER_COUNT];
    struct v4l2_buffer buf;
    int ret;

    // 打开设备
    fd = open(DEVICE_NAME, O_RDWR);
    if (fd == -1) 
    {
        perror("open");
        return -1;
    }

    // 获取设备能力
    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1)
    {
        perror("VIDIOC_QUERYCAP");
    }
}
      

(2)将摄像头的功能进行简单封装,项目中实际应用

由于代码有点长,直接上传资源,有需要自行下载。

Linux下V4L2实时显示摄像头捕捉画面(完整QT+C++代码)资源-CSDN文库

你可能感兴趣的:(Linux,linux,V4L2,qt)