2.1.1.11在LCD上显示摄像头图像2_实现摄像头模块

本文档介绍了在Linux系统中处理USB摄像头的框架,包括videoManage.h、videoManage.c和v4l2.c模块。内容涉及摄像头硬件操作、视频格式转换、数据获取和设备管理。通过VideoOpr结构体,实现了对不同底层驱动如V4L2的适配,以及InitDevice、GetFrame等关键函数。
摘要由CSDN通过智能技术生成

目录

Video 文件实现

上图的框架理解:

(1)video_manage.h、video_manage.c模块

(2)v4l2.c:


数码相框部分有写好的代码,可以直接拷贝过来用。

新建工程文件,新建文件夹 render、 video、 convert、 include 等,主要实现功能如下:
video – 对设备的处理 :对 USB 摄像头进行操作,比如 open, close,十多个 ioctl
convert – 视频格式转换 :我们从 USB 摄像头中获取到的数据可能是不同格式的数据,而我们 LCD 只能支持 RGB 格式的数据
render – 缩放函数、合并函数
include – 头文件
 

Video 文件实现

实现 video 文件下的函数 (实现从摄像头读出数据)
我们在 video 文件下的框架是什么样的呢?
我们的 USB 摄像头硬件在 linux 内核中的驱动可能是 V4L2 框架,也可以是其他的框架比如 V4L,或者我们的 linux 内核中本来
并不支持我们这种摄像头驱动,是自己实现的某种摄像头的驱动,所以我们这个 video 目录下就要针对不同的摄像头驱动在应
用层就要有不同的对摄像头硬件的操作函数。所以我们 video 目录就要兼容不同的驱动来实现对他们的操作。

上图的框架理解:

我们要实现针对于 USB 摄像头不同底层驱动的操作函数,比如我们的摄像头在底层驱动中可能是用 V4L2 框架支持的,或者老
版的 V4L 框架支持的,那么我们就要分别实现一个 v4l2.c 和一个 v4l.c 来和底层对应。
在这两个文件里面要做的事情肯定就是调用驱动里面的 open, ioctl 等等函数来操作 USB 摄像头设备。
我们可以想到是构造一个操作 USB 摄像头设备的结构体: VideoOpr,这个结构体里面就是应用层来操作 USB 摄像头的各种函数
里面的成员肯定要有:
1: InitDevice:这个函数里面肯定就要调用 open 来打开 USB 摄像头设备,然后要调用 ioctl,比如查询我们摄像头是什么类
型的设备(视频捕获还是其他),查询支持什么格式的数据等等
2: ExitDevice:和 InitDevice 对应
3: GetFrame:通过 Poll 来从缓冲区里获取视频的数据,然后调用 VIDIOC_DQBUF ioctl 从队列中删除这个 buffer
4: PutFrame: 调用 VIDIOC_QBUF 将一个缓冲区放入队列中
5: StartDevice:调用 VIDIOC_STREAMON ioctl 启动数据传输
6: StopDevice:调用 VIDIOC_STREAMOFF 关闭数据传输
v4l2.c 和 v4l.c 就是要实现上面的结构体中的几个函数,之后注册给上层统一的接口
那么上层的文件我们同样在 video 中实现,也就是 video_manager.c.这个文件我们知道其实就是实现一个 VideoOpr 链表,将
前面的 v4l2.c 和 v4l.c 实现的 VideoOpr 结构体通过链表管理起来
另外,我们上面要实现的 VideoOpr 结构体的函数参数我们应该传递什么呢?我们通过 VideoOpr 中函数无非就是对 USB 摄像头
设备进行操作,所以我们要定一个描述 USB 摄像头设备的结构体,通过各种 ioctl 命令之后就可以获取到这个 USB 摄像头的信
息:
VideoDevice:
他里面的成员:
1: iFd:文件句柄,我们在 VideoOpr 中的 InitDevice 的肯定要进行 open 操作, open 出来的某个文件的文件描述符我们要记
录下来
2: iPixelFormat:我们视频数据的格式,我们在调用 VIDIOC_ENUM_FMT 是可以获得该 USB 视频设备支持的数据格式
3: iWidth:我们在 VIDIOC_S_FMT 或者 VIDIOC_G_FMT 肯定要涉及分辨率的信息
4: iHeight:同 iWidth
5: iVideoBufCnt:我们分配的缓冲区的个数
6: iVideoBufMaxLen:缓冲区的大小
7: iVideoBufCurIndex:当前是正在使用哪个缓冲区,也就是说当前是哪个缓冲区有数据
8: unsigned char *pucVideBuf[]:我们应用层对应的所有缓冲区,我们应用层申请缓冲区之后, mmap 将内核的缓冲区映射到
了应用层,也就是说我们这个 unsigned char *pucVideBuf 就是相当于内核对应的缓冲区了
9: ptOPr:这个就是我们 VideoOpr 这个结构体变量,之所以放这里面,是为了方便
另外我们的 VideoOpr 的操作函数中涉及到了视频的数据操作,所以我们要定义一个 VideoBuf 结构用来描述一个缓冲区的数据
的信息:比如某个缓冲区有数据了,那么这帧数据的所代表的分辨率是多少,他的实际的数据内容又是什么呢?
我们可以用之前的 PixelDatas 来表示具体这帧数据代表的含义:

另外我们还需要知道这个数据的数据格式是什么,所以最终我们的 VideoBuf 定义如下:

主要 video 涉及到结构体就上面提及到的几个,我们把这几个结构体放到一个 video_manager.h 中
摄像头模块即video部分代码,这部分代码实现对设备的处理,具体做法是从摄像头中将视频数据读出供后续模块处理

(1)video_manage.h、video_manage.c模块

① video_manage.h:负责抽象出所有与设备有关的结构体

#ifndef _VIDEO_MANAGER_H
#define _VIDEO_MANAGER_H

#include <config.h>
#include <pic_operation.h>
#include <linux/videodev2.h>

#define NB_BUFFER 4

/* 这里有一个问题:在VideoDevice 中引用了VideoOpr 结构体,同时在VideoOpr 结构体中的函数又引用了VideoDevice 结构体,这里交叉引用了。因此需要在最前面首先声明,后面就可以引用了 */

struct VideoDevice;
struct VideoOpr;
typedef struct VideoDevice T_VideoDevice, *PT_VideoDevice;
typedef struct VideoOpr T_VideoOpr, *PT_VideoOpr; //PT_VideoOpr为指向结构体的指针类型

struct VideoDevice { //用该结构体表示这个设备
    int iFd;  //记录打开设备时的文件句柄
    int iPixelFormat;  //摄像头视频数据的格式
    int iWidth;  //分辨率的宽
    int iHeight;  //分辨率的高

    int iVideoBufCnt;
    int iVideoBufMaxLen;
    int iVideoBufCurIndex;
    unsigned char *pucVideBuf[NB_BUFFER]; //用来存放mmap之后的地址。

    /* 函数 */
    PT_VideoOpr ptOPr;  //ptOPr指向VideoOpr 这个结构体
};

注释:当我们在程序中构造VideoDevice 实体时,就会让ptOPr这个结构体指向我们在v4l2.c文件中构造的VideoOpr 结构体

/* v4l2.c */
/* 构造一个VideoOpr结构体 */
static T_VideoOpr g_tV4l2VideoOpr = {
    .name        = "v4l2",
    .InitDevice  = V4l2InitDevice,
    .Exit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值