Video2Lcd

本文将会详细分析项目二中的Video2Lcd 首先,要有一个感性的认识,从摄像头捕获视频数据,到显示在lcd屏幕上,经历了以下几个步骤: 摄像头读取图像数据--->图像数据格式转换--->图像缩...

本文将会详细分析项目二中的Video2Lcd

首先,要有一个感性的认识,从摄像头捕获视频数据,到显示在lcd屏幕上,经历了以下几个步骤:

摄像头读取图像数据--->图像数据格式转换--->图像缩放--->图像合并进framebuffer--->图像显示

现在我将按步骤来分析

一. 摄像头读取图像数据

我们可以把所想想到的环节都抽象出来,比如,摄像头就抽象为VideoDevice结构体,获取图像等过程抽象为VideoOpr结构体。摄像头包含获取图像等功能,现在我们的任务是来细化这些结构体,怎么样才能实现我们的目的呢?

以下代码段为抽象出的摄像头设备结构体,包含文件句柄、像素格式、分辨率、申请buffer数目、大小、索引等,最后还有个成员是操作函数

struct VideoDevice {
int iFd;
int iPixelFormat;
int iWidth;
int iHeight;
int iVideoBufCnt;
int iVideoBufMaxLen;
int iVideoBufCurIndex;
unsigned char *pucVideBuf[NB_BUFFER];
/* 函数 */
PT_VideoOpr ptOPr;
};

以下代码段为操作函数的抽象结构体,包含获取图像过程中用到的各种操作、属性等

struct VideoOpr {
    char *name;
    int (*InitDevice)(char *strDevName, PT_VideoDevice ptVideoDevice);
    int (*ExitDevice)(PT_VideoDevice ptVideoDevice);
    int (*GetFrame)(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf);
    int (*GetFormat)(PT_VideoDevice ptVideoDevice);
    int (*PutFrame)(PT_VideoDevice ptVideoDevice, PT_VideoBuf ptVideoBuf);
    int (*StartDevice)(PT_VideoDevice ptVideoDevice);
    int (*StopDevice)(PT_VideoDevice ptVideoDevice);
    struct VideoOpr *ptNext;
};
有了面向对象的思想还不够,最重要的是实现功能。我们获取视频数据的方式有两种(streaming/readwrite)

摄像头数据的获取流程如下:

/* open
 * VIDIOC_QUERYCAP 确定它是否视频捕捉设备,支持哪种接口(streaming/read,write)
 * VIDIOC_ENUM_FMT 查询支持哪种格式
 * VIDIOC_S_FMT    设置摄像头使用哪种格式
 * VIDIOC_REQBUFS  申请buffer
 对于 streaming:
 * VIDIOC_QUERYBUF 确定每一个buffer的信息 并且 mmap
 * VIDIOC_QBUF     放入队列
 * VIDIOC_STREAMON 启动设备
 * poll            等待有数据
 * VIDIOC_DQBUF    从队列中取出
 * 处理....
 * VIDIOC_QBUF     放入队列
 * ....
 对于read,write:
    read
    处理....
    read
 * VIDIOC_STREAMOFF 停止设备
 *
 */

通过分配、设置、注册全局变量g_tV4l2VideoOpr,实现了结构体与功能函数间的串联。将V4L2.c注册进video_manager.c中

有几个ioctl起了至关重要的作用:

iError = ioctl(iFd, VIDIOC_QUERYCAP, &tV4l2Cap);tV4l2Cap.capabilities & V4L2_CAP_VIDEO_CAPTURE;   //确定是否为视频捕获设备
iError = ioctl(iFd, VIDIOC_ENUM_FMT, &tFmtDesc);   //枚举摄像头支持的格式
iError = ioctl(iFd, VIDIOC_S_FMT, &tV4l2Fmt);     //设置格式
iError = ioctl(iFd, VIDIOC_REQBUFS, &tV4l2ReqBuffs);//请求buffer
iError = ioctl(iFd, VIDIOC_QUERYBUF, &tV4l2Buf);   //查询buffer
iError = ioctl(iFd, VIDIOC_QBUF, &tV4l2Buf);   //将buffer放入队列
iError = ioctl(ptVideoDevice->iFd, VIDIOC_QBUF, &tV4l2Buf);   //取出队列中的buffer



你可能感兴趣的文章

相关问题

0 条评论&回复

请先 登录 后评论
Litchi_Zheng
Litchi_Zheng

5 篇文章

作家榜 »

  1. 百问网-周老师 18 文章
  2. st_ashang 14 文章
  3. 渐进 12 文章
  4. zxq 11 文章
  5. helloworld 8 文章
  6. 谢工 5 文章
  7. Litchi_Zheng 5 文章
  8. 星星之火 5 文章