当前位置:   article > 正文

GEC6818 V4L2+USB 摄像头的使用_粤嵌gec6818摄像头

粤嵌gec6818摄像头

GEC6818 V4L2摄像头的使用

本文主要涉及GEC6818开发板V4L2的使用,用具体的实例展示了使用一个USB摄像头的使用,其中前面详细讲解了V4L2的相关函数的使用,如果已经知道的可以直接看最后的完整代码。

文章目录

  • GEC6818 V4L2摄像头的使用
    • 一、 V4L2(Video4Linux2)
      • 1.1 结构体:v4l2_capability
      • 1.2 结构体:v4l2_format
      • 1.3 结构体:v4l2_buffer
        • 1.3.1 v4l2_buffer的type字段
      • 1.4 API:ioctl
        • 1.4.1 `ioctl` 的基本使用方式
        • 1.4.2 实例分析
    • 二、 实例使用逐步解析
      • 2.1 打开设备
      • 2.2 获取摄像头功能参数
      • 2.3 获取摄像头支持的格式
      • 2.4 设置视频输入通道
      • 2.5 设置摄像头采集格式
        • 2.5.1 YUYV格式(这个格式需要转化为RGB才可以显示)--转换代码在后面的完整代码中
        • 2.5.2 24位位图(RGB)格式
        • 2.5.3 其他格式的关键字
      • 2.6 与V4L2(Video4Linux2)子系统的交互
      • 2.7 启动摄像头
    • 三、完整代码
      • 3.1 完整代码--YUYV格式
      • 3.2 完整代码--RGB格式
      • 3.3 实现效果

一、 V4L2(Video4Linux2)

V4L2(Video4Linux2)是Linux操作系统中用于处理视频设备的内核框架。V4L2提供了一个统一的API,允许开发者在不同的硬件平台上编写通用的应用程序,从而访问、配置和操作视频设备,如摄像头、USB视频捕获卡等。

以下是有关V4L2摄像头在Linux中的一些关键点和概念:

  1. 设备文件

    • 在Linux中,摄像头通常表示为/dev/videoX,其中X是一个数字,代表摄像头的索引。
    • 例如,第一个检测到的摄像头设备可能是/dev/video0,第二个则可能是/dev/video1,以此类推。
  2. 主要结构和概念

    • v4l2_capability:这是一个结构,用于查询设备的功能。它告诉您设备是否支持视频捕获、视频输出、视频覆盖等功能。
    • v4l2_format:这是一个结构,用于设置和查询视频格式,例如帧大小、格式类型(YUV、RGB等)和帧率。
    • v4l2_buffer:这是一个结构,用于描述单个视频缓冲区的属性和状态。视频帧数据通常存储在这些缓冲区中。
    • ioctl:V4L2 API主要通过ioctl系统调用进行交互。使用不同的ioctl命令和结构体,您可以查询设备能力、设置格式、请求和查询缓冲区等。
  3. 基本操作流程

    • 打开摄像头设备文件(例如/dev/video0)。
    • 查询设备的能力和支持的格式。
    • 设置所需的视频格式。
    • 分配和映射视频缓冲区。
    • 将缓冲区入队以开始视频流捕获。
    • 循环从队列中取出已满的缓冲区,并处理视频帧数据。
    • 将处理后的缓冲区重新入队。

1.1 结构体:v4l2_capability

v4l2_capability 结构体在C语言中的定义如下:

struct v4l2_capability {
   
    __u8  driver[16];           // 驱动名称或标识符
    __u8  card[32];             // 设备名称或描述
    __u8  bus_info[32];         // 设备连接到的总线信息
    __u32 version;              // V4L2驱动版本
    __u32 capabilities;         // 设备的功能标志位掩码
    __u32 reserved[4];          // 保留字段
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这个结构体为了节省内存使用了__u8__u32这样的类型,它们通常是无符号整数类型,但确切的大小和类型可能会根据系统架构和编译器而有所不同。

v4l2_capability 结构是用于V4L2(Video4Linux2)API中的一个关键结构,用于查询和描述设备的能力。通过查询这个结构,应用程序可以了解特定摄像头或视频设备支持的功能和特性。

以下是 v4l2_capability 结构中的一些主要字段及其解释:

  1. char driver[16]:

    • 这是一个16字节的字符串,表示设备的驱动名称标识符
  2. char card[32]:

    • 这是一个32字节的字符串,表示设备的名称或描述
  3. __u32 bus_info[32]:

    • 一个32字节的数组,表示设备连接到的总线信息
  4. __u32 version:

    • 表示V4L2驱动的版本号
  5. __u32 capabilities:

    • 这是一个位掩码,用于表示设备支持的各种功能。
    • 一些常见的功能标志包括:
      • V4L2_CAP_VIDEO_CAPTURE: 设备支持视频捕获
      • V4L2_CAP_VIDEO_OUTPUT: 设备支持视频输出
      • V4L2_CAP_VIDEO_OVERLAY: 设备支持视频覆盖
      • V4L2_CAP_STREAMING: 设备支持视频流
      • … 还有其他的功能标志。
  6. __u32 reserved[4]:

    • 一个4元素的保留字段数组,未使用。

当应用程序想要知道摄像头或视频设备的能力时,它会使用ioctl(fd, VIDIOC_QUERYCAP, &cap)系统调用查询该结构。查询结果将填充v4l2_capability结构的字段,应用程序可以基于这些信息进行决策或配置。

例如,如果应用程序需要捕获视频,但摄像头不支持视频捕获功能(即V4L2_CAP_VIDEO_CAPTURE标志未设置),那么应用程序可能会选择一个不同的摄像头或采取其他行动。

1.2 结构体:v4l2_format

v4l2_format 结构体用于描述和设置视频格式,例如视频的帧大小、像素格式等。在V4L2编程中,会经常使用这个结构体来告诉摄像头或视频设备你希望的数据格式

以下是 v4l2_format 结构体的定义和相关参数的详细解释:

struct v4l2_format {
   
    __u32 type;                 // 数据流类型 (例如:V4L2_BUF_TYPE_VIDEO_CAPTURE 或 V4L2_BUF_TYPE_VIDEO_OUTPUT)
    union {
   
        struct v4l2_pix_format    pix;      // 像素格式相关的信息
        // 更多的联合字段可以添加到这里,每个字段表示不同类型的数据流格式
    } fmt;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其中,union 中的 v4l2_pix_format 结构体用于描述像素格式相关的信息:

struct v4l2_pix_format {
   
    __u32 width;                 // 帧的宽度
    __u32 height;                // 帧的高度
    __u32 pixelformat;           // 像素格式 (例如:V4L2_PIX_FMT_YUYV 或 V4L2_PIX_FMT_MJPEG)
    __u32 field;                 // 采样格式 (例如:V4L2_FIELD_NONE 或 V4L2_FIELD_INTERLACED)
    __u32 bytesperline;          // 每行的字节数
    __u32 sizeimage;             // 帧大小(以字节为单位)
    __u32 colorspace;            // 颜色空间 (例如:V4L2_COLORSPACE_SRGB)
    __u32 priv;                  // 预留字段(私有数据,可能由特定的驱动程序使用)
    __u32 flags;                 // 标志位,例如 V4L2_PIX_FMT_FLAG_CONTINUOUS_BYTE_STREAM
    __u32 ycbcr_enc;             // YCbCr 编码规范
    __u32 quantization;          // 量化范围
    __u32 xfer_func;             // 传输函数
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这些字段的具体含义和值会根据所使用的设备和驱动程序而有所不同。当想要设置或查询视频格式时,会使用这些结构体和相关的系统调用,如 ioctl()

1.3 结构体:v4l2_buffer

v4l2_buffer 结构体用于描述视频缓冲区的信息,包括缓冲区的状态、数据的位置等。在V4L2编程中,会用这个结构体来管理视频数据的传输和接收

以下是 v4l2_buffer 结构体的定义及相关参数的详细解释:

struct v4l2_buffer {
   
    __u32               index;          // 缓冲区的索引号,用于标识特定的缓冲区
    enum v4l2_buf_type  type;           // 缓冲区的类型 (例如:V4L2_BUF_TYPE_VIDEO_CAPTURE)
    __u32               bytesused;      // 缓冲区中实际使用的字节数
    __u32               flags;          // 标志位,例如 V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
    enum v4l2_field     field;          // 采样的字段 (例如:V4L2_FIELD_NONE 或 V4L2_FIELD_INTERLACED)
    struct timeval      timestamp;      // 时间戳,记录帧的时间信息
    struct v4l2_timecode timecode;       // 时间码,用于视频同步和编辑
    __u32               sequence;       // 用于同步帧的顺序,例如丢帧后恢复顺序
    __u32               memory;         // 缓冲区的内存类型 (例如:V4L2_MEMORY_MMAP 或 V4L2_MEMORY_USERPTR)
    union {
   
        __u32           offset;         // 内存映射类型 (V4L2_MEMORY_MMAP) 下的偏移量
        unsigned long   userptr;        // 用户指针类型 (V4L2_MEMORY_USERPTR) 下的指针
    } m;
    __u32               length;         // 缓冲区的长度(以字节为单位)
    __u32               input;          // 输入设备的索引号,用于多路复用的设备
    __u32               reserved;       // 保留字段,未使用
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

其中,typememory 字段是两个重要的字段,它们分别指定了缓冲区的类型和内存分配方式:

  • type: 这是一个枚举值,表示缓冲区的类型,例如视频捕获、视频输出等。

  • memory: 这也是一个枚举值,表示缓冲区的内存类型,例如通过内存映射 (V4L2_MEMORY_MMAP) 或用户指针 (V4L2_MEMORY_USERPTR) 进行管理。

1.3.1 v4l2_buffer的type字段

在V4L2(Video4Linux2)中,v4l2_buffer 结构体用于描述视频缓冲区的属性和状态。其中,enum v4l2_buf_type type; 字段用于指定缓冲区的类型。以下是一些常用的缓冲区类型:

  1. V4L2_BUF_TYPE_VIDEO_CAPTURE

    • 表示缓冲区用于视频捕获。
    • 当你想从摄像头或其他视频输入设备捕获视频帧时,你会使用这种类型的缓冲区。
  2. V4L2_BUF_TYPE_VIDEO_OUTPUT

    • 表示缓冲区用于视频输出。
    • 这种类型的缓冲区通常用于播放或发送视频数据。
  3. V4L2_BUF_TYPE_VIDEO_OVERLAY

    • 表示缓冲区用于视频叠加。
    • 用于将视频数据叠加到其他视频流或图像上。
  4. V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY

    • 表示缓冲区同时用于视频输出和叠加。
    • 通常在某些特殊场景中使用。
  5. V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE

    • 表示多平面视频捕获缓冲区。
    • 这是一个多平面缓冲区类型,用于存储多个平面的视频数据。
  6. V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE

    • 表示多平面视频输出缓冲区。
    • 与上述捕获缓冲区类型类似,但是用于视频输出。

这些只是V4L2中可用的一些缓冲区类型。实际上,V4L2提供了更多的缓冲区类型和子类型,以满足不同应用和设备的需求。选择合适的缓冲区类型非常关键,因为它决定了如何配置和使用缓冲区,以及如何处理视频数据。

1.4 API:ioctl

ioctl(Input/Output Control)是Linux系统中的一个系统调用,主要用于设备驱动程序与用户空间应用程序之间进行交互。通过 ioctl,用户空间程序可以发送特定的命令和参数给设备驱动程序,从而控制或查询设备的状态、配置和功能。

1.4.1 ioctl 的基本使用方式

ioctl 的函数原型如下:

int ioctl(int fd, unsigned long request, ...);
  • 1
  • fd: 是一个打开的文件描述符,通常是对应于某个设备文件的。
  • request: 是一个无符号长整型值,表示要执行的操作或查询。
  • ...: 是可选的参数,用于传递与特定命令相关的数据。
1.4.2 实例分析

假设我们要使用 ioctl 查询一个V4L2设备的能力。

  1. 打开设备:首先,我们需要打开设备文件,并获取其文件描述符。

    int fd_v4l2 = open("/dev/video7", O_RDWR);
    if (fd_v4l2 == -1) {
         
        perror("Failed to open device");
        exit(EXIT_FAILURE);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  2. 查询设备能力:使用 ioctlVIDIOC_QUERYCAP 命令来查询设备的能力。

    struct v4l2_capability cap = {
         };
    if (ioctl(fd_v4l2, VIDIOC_QUERYCAP, &cap) == -1) {
         
        perror("ioctl VIDIOC_QUERYCAP failed");
        close(fd_v4l2);
        exit(EXIT_FAILURE);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

在这个例子中,我们使用了 VIDIOC_QUERYCAP 命令来查询设备的基本信息和能力,并将结果存储在 cap 结构体中。

  1. 处理查询结果:根据 cap 结构体中的信息,我们可以知道设备是否支持视频捕获、视频输出等功能,并据此进行相应的处理。

    if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
         
        printf("Device supports video capture.\n");
    }
    
    • 1
    • 2
    • 3
    • 4

这只是一个简单的例子,实际的应用场景可能涉及更多的 ioctl 命令和参数,以及复杂的设备配置和操作。

ioctl 提供了一个强大的接口,允许用户空间程序与设备驱动程序进行灵活的交互,从而实现设备的配置、控制和数据传输等功能。

二、 实例使用逐步解析

2.1 打开设备

首先需要确定自己的设备的名称是什么,可以通过SecureCRT进行查看。在目录/dev下面,通过命令ls /dev/video*,通过拔插检测插入自己的摄像头的时候,多出来的设备是哪一个,比如我的就是"videos7".

在Linux中一切皆是文件,所以可以通过open()函数,打开这个设备。

// 打开摄像头
    int fd_v4l2 = open("/dev/video7", O_RDWR); // 根据secureCRT确定设备
    if (fd_v4l2 == -1)
    {
   
        perror("open error");
        exit(-1);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.2 获取摄像头功能参数

使用V4L2(Video4Linux2) API查询视频设备(如摄像头)的能力(capabilities)。

 // 获取功能参数
    struct v4l2_capability cap = {
   };
    int res = ioctl(fd_v4l2, VIDIOC_QUERYCAP, &cap);
    if (res == -1)
    {
   
        perror("ioctl cap");
        exit(-1);
    }
     // 先确定摄像头功能可以使用
    if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
    {
   
        printf("is a capture device!\n");
    }
    else
    {
   
        printf("is not a capture device!\n");
        exit(-1);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  1. 目的

    • 查询摄像头或其他视频设备的能力,以确定其支持的功能。
  2. 代码解析

    • struct v4l2_capability cap = {};

      • 定义并初始化一个名为capv4l2_capability结构体实例。该结构体用于存储从设备查询到的能力信息。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/855529
推荐阅读
相关标签
  

闽ICP备14008679号