作者:武汉华嵌-嵌入式培训中心  吴老师

Linux下V4L2编程小结

一.设置采集方式,格式 常用命令标志

打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在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:检查当前视频设备支持的标准,例如PAL或NTSC。

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

二.一般操作流程(视频设备)

1. 打开设备文件。

int fd=open(”/dev/video0″,O_RDWR);

2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability

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:

//……

}

3. 选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input(可不要)

4. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。

VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format

struct v4l2_format    fmt;

/*

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;   // 视频数据存储类型,例如是YUV 4 :2 :2 还是RGB

enum v4l2_field         field;

__u32                   bytesperline;

__u32                   sizeimage;

enum v4l2_colorspace    colorspace;

__u32                   priv;

};

*/

样例:

memset ( &fmt, 0, sizeof(fmt) );

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

fmt.fmt.pix.width = 320;

fmt.fmt.pix.height = 240;

fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;

if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)

{

printf("set format failed\n");

//return 0;

}

5. 向驱动申请帧缓冲,一般不超过5个。struct 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];

};

样例:

struct v4l2_requestbuffers req;

memset(&req, 0, sizeof (req));

req.count = 4;

req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

req.memory = V4L2_MEMORY_MMAP;

if (ioctl(fd,VIDIOC_REQBUFS,&req) == -1)

{

perror("VIDIOC_REQBUFS error \n");

//return -1;

}

6.申请物理内存 ,并将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer

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

printf("sizeof(VideoBuffer) is %d\n",sizeof(VideoBuffer));

struct v4l2_buffer    buf;

for (numBufs = 0; numBufs < req.count; 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) < 0)

{

printf("VIDIOC_QUERYBUF error\n");

//return -1;

}

printf("buf len is %d\n",sizeof(buf));

//内存映射

buffers[numBufs].length = buf.length;

buffers[numBufs].offset = (size_t) buf.m.offset;

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

printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);

printf("buf2 len is %d\n",sizeof(buffers[numBufs].start));

if (buffers[numBufs].start == MAP_FAILED)

{

perror("buffers error\n");

//return -1;

}

if (ioctl (fd, VIDIOC_QBUF, &buf) < 0)

{

printf("VIDIOC_QBUF error\n");

//return -1;

}

}

7. 开始视频的采集。VIDIOC_STREAMON

enum v4l2_buf_type type;

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)

{

printf("VIDIOC_STREAMON error\n");

// return -1;

}

8. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF, 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF

if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0)

{

perror("VIDIOC_DQBUF failed.\n");

//return -1;

}

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory = V4L2_MEMORY_MMAP;

unsigned char *ptcur = buffers[numBufs].start;

DEBUG("buf.bytesused = %d \n",buf.bytesused);

int i1;

for(i1=0; i1

{

if((buffers[numBufs].start[i1] == 0x000000FF) && (buffers[numBufs].start[i1+1] == 0x000000C4))

{

DEBUG("huffman table finded! \nbuf.bytesused = %d\nFFC4 = %d \n",buf.bytesused,i1);

break;

}

}

if(i1 == buf.bytesused)printf("huffman table don't exist! \n");

int i;

for(i=0; i

{

if((buffers[numBufs].start[i] == 0x000000FF) && (buffers[numBufs].start[i+1] == 0x000000D8)) break;

ptcur++;

}

DEBUG("i=%d,FF=%02x,D8=%02x\n",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);

int imagesize =buf.bytesused - i;

DEBUG("buf.bytesused = %d \n",buf.bytesused);

DEBUG ("imagesize = %d \n",imagesize);

9. 停止视频的采集。VIDIOC_STREAMOFF

10. 关闭视频设备。close(fd);

linux v4l2 反操作,Linux下V4L2编程小结--吴老师相关推荐

  1. linux文件编辑操作,Linux下文本编辑及其文件操作

    文本编辑及其文件操作 Vim 命令模式: dd 删除当前行 yy 2yy nyy 复制 从光标算起,复制n行 p 粘贴 默认粘贴在光标的下一行 u 撤销 末行模式: :wq 保存退出 :wq! 强制保 ...

  2. linux文件怎么操作,linux文件操作学习1

    由于实验室的项目需要开始学习linux,为了更好的学习和掌握linux的一些基本操作以及顺便做个备忘录,时间久了也可以看看自己的学习成果. 学习linux应该先抛开windows的C.D.E...盘的 ...

  3. linux c文件操作,Linux C 文件的输入/输出操作

    10.1 文件I/O操作概述 在Linux系统中,文件I/O操作可以分为两类,一类是基于文件描述符的I/O操作,另一类是基于数据流的I/O操作. 10.1.1 文件描述符简介 在文件操作一章中,也经常 ...

  4. linux 文档操作,Linux学习之文档操作

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? The Linux Command Line 学习翻译 mkdir The mkdir command is used ...

  5. linux系统常见操作,Linux系统基本操作

    我们可以认为Linux是一套自由使用的类Unix操作系统,与Windows相比较而言,Linux具有安全.开源.稳定等特点.下面我来介绍Linux中一些的登录登出基本操作. 1. 启动系统 通常LIL ...

  6. linux 进程的操作,linux进程操作命令

    linux进程操作命令 (4页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 简单概述简单概述 Linux 进程操作命令进程操作命令Lin ...

  7. linux 内核文件操作,Linux 内核文件操作

    正常思路是应用里读取文件内容,再通过ioctl.write等方式把文件buffer传送到内核,内核里不推荐使用对文件IO直接操作,但是要使用还是可以的. 思路如下: 一.filp_open打开获取句柄 ...

  8. linux uvc摄像头操作,Linux uvc摄像头驱动初探

    本文基于AM6C平台Linux3.0.8内核. 1.drivers/media/video/uvc/Makefile uvcvideo-objs := uvc_driver.o uvc_queue.o ...

  9. linux 通配符 正则表达式 区别,linux 正则表达式和通配符

    linux 正则表达式和通配符 通配符用于查找文件 包含三种:  * ? [] * 代表任意个任意字符 ? 代表任意一个字符 [] 代表中括号中的一个字符 正则表达式(正则是包含匹配,只要包含就可以匹 ...

最新文章

  1. 2019年首趟春运年货集装箱班列抵达北京
  2. 字节Java面试必问:mysql索引类型属于
  3. c语言中的字节序和字节对齐,C语言字节序对齐以及空间利用率
  4. 1.9 Java 9增强的自动资源管理
  5. 实录 | 平安人寿资深算法工程师谢舒翼:智能问答系统探索与实践
  6. mac 不能连接wi-fi_如何阻止Mac自动连接到Wi-Fi网络
  7. IE8中如何添加Activity
  8. (27)呼吸灯verilog与VHDL编码(学无止境)
  9. IE浏览器中访问jsp页面,页面不执行ajax请求,后台控制台报错
  10. 小白学数据分析-----留存率的三个普适原则
  11. linux增加虚拟内存
  12. DeepStream3必须安装Video_Codec_SDK9
  13. 小程序学习笔记(8)-导航组件
  14. 多Excel合并成一个Excel的多sheet
  15. 移动端 h5页面 长安保存图片到手机
  16. Elasticsearch 实现类似SQL语句中like %关键字% 的单纯模糊查询(不进行分词)
  17. 【莫安迪原创摄影作品】深圳最美夕阳-烟云成画
  18. USB设备无法识别也无法读取怎么办?
  19. uniapp实战项目 (仿知识星球App) - - 配置开发工具和全局css样式
  20. maven中生成文件时缺少proprieties文件解决,输入流读取properties文件 总是为null

热门文章

  1. 动圈耳机振膜_耳机振膜的制作方法
  2. 安装OracleXE
  3. 没有一种工作是不委屈的
  4. html5 canvas 自动改变宽高,H5 canvas中width、height和style的宽高区别详解
  5. android 相机和照片一起_Android-----调用系统相机拍照并把照片展示在图库中
  6. 删除Microsoft Word中空白页的方法
  7. PS基础-通道、蒙版
  8. Isolation Level
  9. 用python实现打印各种图形总结(包括等腰三角形,菱形,近似圆等)(Python经典编程案例)
  10. MySQL——删除索引