基于V4L2驱动程序的USB摄像头Android(JNI)的编写(二)
来源:互联网 发布:便签的元数据 编辑:程序博客网 时间:2024/06/04 18:45
http://blog.csdn.net/JansonZhe/article/details/47334671
在我的上一篇文章基于V4L2驱动程序的USB摄像头Android(JNI)的编写(一)中,我详细介绍了如何配置V4L2驱动程序的采集环境,那么在这篇文章中,我将详细分析V4L2采集视频的过程。
一、向驱动程序申请缓冲帧
缓冲帧,顾名思义就是在Linux驱动程序中用于临时存放数据的“容器”,在V4L2驱动程序中,也就是存放我们的视频流数据。而什么又是向驱动程序申请缓冲帧呢,因为在V4L2驱动程序中,其配备的缓冲帧的个数并不是固定的,每一次我们使用的时候都要根据我们的需求向V4L2驱动程序申请,这也体现了V4L2的强大以及设计的合理性,保证了不必要的资源浪费。下面介绍如何向V4L2驱动程序申请缓冲帧。
使用命令:VIDIOC_REQBUFS
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
对于上面的程序,我想着重介绍的是v4l2_requestbuffers结构体,该结构体定义了一些设置缓冲帧的信息,其完整的结构体定义如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在程序中,我们为什么还要在用户空间里面定义一个buffer类型的结构体指针呢,并且申请的指针数量和内核空间里面定义的缓冲帧数一样,这是应用了我们Linux内核映射的一种方法。采用的内存映射的原因是因为由于视频流数据比较大,如果我们还采用以往的那种copy_from_user或者copy_to_user的方式的话,那么这样不仅耗费内核空间的额内存,而且还耗费用户空间的内存,同时还大大降低了驱动程序的性能。而采用内存映射的话,只要我们在用户空间将内存空间缓冲帧的物理地址映射到我们的用户空间就可以了,这样在用户空间我们就直接使用内核缓冲帧的数据就可以了。
二、将缓冲帧映射到用户空间
上一步中,我们已经在内核空间中申请了缓冲帧,同时还在用户空间中定义了相等数量的缓冲帧指针,那么这一步我们当然就要完成将内核中的缓冲帧映射到用户空间的工作啦。
这一步中,首先我们要使用VIDIOC_QUERYBUF命令获取缓冲帧的相关信息。然后获取之后,我们再对每一个缓冲帧进行逐一映射。主要代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
这一步中我们还使用了一个非常重要的结构体v4l2_buffer,关于此结构体的介绍可以查看官方文档。现在我们的初始化工作,到这里也就基本结束了。下一步将开始捕获视频流数据。
三、捕获视频流
捕获视频流主要分两个步骤进行,第一步是将我们在内核空间申请的缓冲帧逐一放入接收视频流数据的队列当中,采用的命令是:VIDIOC_QBUF,第二步是开启捕获视频数据,采用的命令是:VIDIOC_STREAMON,一般在写代码的时候,会将这两部分写在一起。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
四、读取缓冲帧数据
经过上面一步,这个时候应该视频流数据被逐一捕获并放入在接收数据队列的缓冲帧当中了,现在我们的主要工作就是要从接收队列的缓冲帧当中一帧帧读取出数据,然后将读取的数据进行处理。当然读取完了之后,我们还要重新将缓冲帧放入接收数据的队列当中。读取数据使用的命令是:VIDIOC_DQBUF,将缓冲帧放入接收数据队列的还是我们上一步使用的命令:VIDIOC_QBUF。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
整个视频流数据的接收过程可以用下面的图表示
程序中的processimage函数是用于处理视频流数据的。由于我们在基于V4L2驱动程序的USB摄像头Android(JNI)的编写(一)中的设置采集视频帧的格式、宽、高、大小这一步中,将采集的视频流数据的储存格式设置为YUYV格式,因此在我们的processimage函数中将对此进行处理。
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(二)
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(二)
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(一)
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(三)
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(一)
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(三)
- 基于V4L2框架的linux驱动程序编写
- USB驱动程序的编写
- 采用V4L2读取的USB摄像头
- Android NDK基于V4L2驱动使用USB摄像头
- 利用V4L2编写的USB摄像头程序1【经OK6410验证成功】
- 利用V4L2编写的USB摄像头程序2【经OK6410验证成功】
- 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集
- 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集
- (原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集(非常好)
- 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集
- 基于Linux的v4l2视频架构驱动编写(二)
- 485硬件调试心得
- Android AsyncTask
- Flume的安装与简单使用
- ActiveMQ消息处理机制-Queue方式
- CodeChef:Hasan and boring classes(组合数学 & 字符串)
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(二)
- hdu 1217 floyd
- Mapped Statements collection already contains value for com.xxxDao.findList
- 基于V4L2驱动程序的USB摄像头Android(JNI)的编写(三)
- 声纹识别技术简介——化繁为简的艺术
- MySql常见数据库引擎特点
- 【Spring Cloud】Hystrix 防御机制
- 自测一个小技巧解决手机端304 not modified问题
- OGG(oracle golden date)简单部署ORACLE 11g-ORACLE 11g