深入理解linux内核v4l2框架之videobuf2【转】

转自:https://blog.csdn.net/ramon1892/article/details/8444193

Videobuf2框架

1. 什么是videobuf2框架?

它是一个针对多媒体设备的v4l2兼容驱动框架,是用户空间应用程序和设备驱动的中间层。它为驱动提供更为底层的模块化的内存管理功能。

它能够使得驱动开发变得简单,减少代码量,帮助合理的连续的实现驱动当中的v4l2接口。

videobuf2的内存管理是完全模块化的,这就允许在不改变更高级别缓冲管理框架的情况下可以为设备和平台定制内存管理方法。

框架提供了一下三种:

  • 实现了v4l2_ioctl的流控和文件操作

  • 高级的视频缓冲,视频队列和状态管理

  • 视频缓冲内存分配和管理

2.为什么要新开发一种框架呢?

在当前的videobuf实现当中,有很多问题,在2010年举行的赫尔欣基峰会上重点提到了这么几个:

  • V4L2 API出现异常和错误的内存管理设计

  • 不能停止stream请求,缓冲在streamoff的时候被释放

  • VIDIOC_REQBUFS 不释放内存,也不能重新分配内存

  • 视频内存在mmap,qbuf或者页错误的时候才分配

  • 每个缓冲都有一个等待队列

  • 扩展性不够强,尤其对于嵌入式多媒体设备来说支持不够

  • 很难加入定制的内存分配和管理机制

  • 不支持对缓存一致性和IOMMU设备

  • 不够灵活,只有一个包办一切的函数来处理内存锁定,缓存,sg-list的创建

  • 很多未使用的域,还有代码的重复,模糊晦涩的命名

很多驱动程序作者发布基于videobuf的基础组件.开发者也承认videobuf的功绩,也乐意使用它,但是由于灵活性不够现在不能这么做了。

3.重新设计的目的

  • 修正V4L2API的实现,修复videobuf的问题和缺陷

  • 分离缓冲队列管理和内存管理

  • 在内存的分配和管理上更加灵活,可以嵌入定制的机制

  • 更加有针对性的驱动回调函数,在不同的地方调用

  • 支持新的V4L2API扩展,例如多平面视频帧存储的支持

4. 驱动回调函数

对称的驱动回调函数设计:

  • buf_init 在内存被分配后或者一个新的USERPTR缓冲入队之后调用一次,比如用来锁定页,验证连续性,设置IOMMU映射等等。

  • buf_prepare每个QBUF都要调用,用来同步缓存,拷贝数据到buffer

  • buf_finish每个DQBUF调用,用来同步缓存,从buffer中取回数据等

  • buf_cleanup 在free/release内存的时候调用

其余的回调函数也有重新设计:

  • queue_negotiate现在合并了多平面的扩展;驱动返回所需要的缓冲数和每个缓冲的平面数。

  • plane_setup 驱动返回平面的尺寸大小

这两个调用取代了老的buf_setup

  • buf_queue 保留了原来的功能,将buffer放入请求队列。

5. 内存分配和处理

内存处理这块设计得更加个性化,使得内存分配可以定制,定制的函数放在一个叫做v4l2_alloc_ctx的结构体当中。它的目的是给videobuf提供操作函数,并且存放一些私有数据。私有数据可以被嵌入到更大的一些结构体当中。

Struct vb2_alloc_ctx {

const struct vb2_mem_ops *mem_ops;

}

struct vb2_foo_alloc_conf {

strucdt vb2_alloc_ctx alloc_ctx;

/* private data*/

}

更重要的是引入了一个buffer上下文结构的概念,在每次分配之后,分配器返回他们自己,定制的和每个buffer的结构。这个结构可以当作cookie传递给其他的内存处理方法。

存放在分配器上下文的内存操作可以被其他的分配器取代,详细的文档可以参考videobuf2-core.h

一个非常好的例子从三星galaxy S系列的android手机内核源码中的videbuf2-cma.c,可以看看这个例子。

原文地址:https://www.cnblogs.com/sky-heaven/p/9550249.html