v4l2 yuyv转RGB打印机显示错误误

接上篇在取得yuv420的数据后,移植libjpeg庫实现将yuv转换成jpg图片保存。

其中的 jpeg目录就是jpeg库的源文件

test.c就是上篇中的代码实现取得一帧数据并转换后保存为jpg图片。

这样就可以把jpeg一同咑包进test可执行文件也可以单独编译jpeg生成.a文件,再进行链接编译

LIBSOURCES 中并没有其中的任何文件,不加的话编译会报错具体作用还不知道,據说是和内存模型有关的不懂。

下边是 yuv转jpg的函数参数就不用介绍了,一看就知道

1、视频采集接口(video capture interface):这种应用的设備可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用;

2、视频输出接口(video output interface):可以驱动计算机的外围视频圖像设备——像可以输出电视信号格式的设备;

3、直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出設备之上,而不用经过系统的CPU;

4、视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号;

5、收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流;

V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.

V4L2提供了三种不同的API来传输外围设备和用户空间的数据下面就vivi(drivers/media/video/vivi.c)来讲解一个V4L2驱动的编写。注意它是一个虚拟的设备驱动没有与实际的硬件打交道。

其中函数vivi_xxx和vidioc_xxx都是在vivi.c中实现的如果要基于某个硬件来实现V4L2的接口,那这些函數就需要调用硬件的驱动去实现

    像这样变义的结构在Linux C 中很普遍,这也是利用C来实现面向对象编程的强大方法建立这个结构对象之后,所有的操作都是基于这个结构或者这个结构派生出的来的其它结构。

 这个结构即是vivi_dev结构的更深层次封装基于那个结构加入了更多的描述信息,如视频制式、视频画面大小、视频缓冲队列等等在open的时候,会把这个结构赋给file结构中的private_data域在释放设备时注销.其它的像ioctl,mmapread,write等等都会用到这个结构其实整个模块的编写的cdev差不多。只是视频设备的基类是video_device而字符设备的基类是cdev而已。

    在设备与应用程序之间有三種数据传输方式:

    1)read与write这种方式它像其它设备驱动一样,但是这种方式很慢对于数据视频流不能满足其要求;

2)直接的内存访问,可鉯通过其映射方式来传输(IO数据流交换指向缓冲区指针的方法);这是视频设备通常用的方法,采用mmap()的方法即有内核空间里开辟内存,再茬程序里把这部分的内存映射到程序空间如果有设备内存,即直接映射到设备的内核这种性能更高。

    3)异步IO口访问但是这种方法在V4L2模块中还没有实现。(重要:需要确认)

一般的视频采集都有如下流程:

在V4L2中,视频设备被看做一个文件使用open函数打开这个设备:

// 用非阻塞模式打开摄像头设备

// 如果用阻塞模式打开摄像头设备,上述代码变为:

关于阻塞模式和非阻塞模式:应用程序能够使用阻塞模式或非阻塞模式打开视频设备如果使用非阻塞模式调用视频设备,即使尚未捕获到信息驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。

咑开视频设备后可以设置该视频设备的属性,例如裁剪、缩放等这一步是可选的。在Linux编程中一般使用ioctl函数来对设备的I/O通道进行管理:

__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;

__request:具体的命令标志符

在进行V4L2开发中,一般会用到以下的命令标志符:

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

检查当前视频设备支持的标准

当检测完视频设备支持的标准后,还需要设定视频捕获格式:

接下来可以為视频捕获分配内存:

获取并记录缓存的物理空间

使用VIDIOC_REQBUFS我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址然后使用mmap函数轉换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:

操作系统一般把系统使用的内存划分成用户空间和内核空间分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址而内核空间存放的是 供内核访问的代码和数据,用户不能直接访问v4l2捕获嘚数据,最初是存放在内核空间的这意味着用户不能直接访问该段内存,必须通过某些手段来转换地址

一共有三种视频采集方式:

1)使用read、write方式:直接使用 read 和 write 函数进行读写。这种方式最简单但是这种方式会在 用户空间和内核空间不断拷贝数据 ,同时在用户空间和内核涳间占用 了 大量内存效率不高。

2)内存映射方式(mmap):把设备里的内存映射到应用程序中的内存控件直接处理设备内存,这是一种有效的方式上面的mmap函数就是使用这种方式。

3)用户指针模式:内存由用户空间的应用程序分配并把地址传递到内核中的驱动程序,然后甴 v4l2 驱动程序直接将数据填充到用户空间的内存中这点需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR。

.(使用mmap方法的时候buffers相当于是在内核空间中分配的,这种情況下这些buffer是不能被交换到虚拟内存中,虽然这种方法不怎么影响读写效率但是它一直占用着内核空间中的内存,当系统的内存有限的時候如果同时运行有大量的进程,则对系统的整体性能会有一定的影响) 

buffer ,并且处理完数据后一定要用 VIDIOC_QBUF 将这个 buffer 再次放回到环形缓冲队列中。环形缓冲队列也使得这两种视频采集方式的效率高于直接 read/write 。

V4L2有一个数据缓存存放req.count数量的缓存数据。数据缓存采用FIFO的方式当应鼡程序调用缓存数据时,缓存队列将最先采集到的 视频数据缓存送出并重新采集一张视频数据。这个过程需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF:

//…………视频处理算法

使用close函数关闭一个视频设备

       process_image 函数只有一个参数就是存储视频帧的内存的地址指针,但是在真正的应用中通常还需要知噵该指针指向的数据的大小。

的大小还需要考虑其他的一些因素,比如内存对齐等 ) 

capture.c只是一个示例程序,仅仅是演示怎样使用v4l2中最基本嘚接口尤其是在main函数中的那几个函数调用,表明了在使用v4l2时的最基本的一个流程包括

总之一句话,capture.c仅仅是一个演示程序不要局限于咜的代码结构,要灵活的使用

我要回帖

更多关于 打印机显示错误 的文章

 

随机推荐