【原文:
http://zjbintsystem.blog.51cto.com/964211/464729】
2010年即将过去,有很多感慨需要总结一下,自从2010年1月份开始着手写DM6446开发攻略以来,得到很多网友和客户对本人博客的支持,同时结识一些有诚意的客户,他们对本人和我们团队的认可,在这里表示感谢。特别是南京航空航天大学的一个非常有个性、有良知和责任的李博导,对本团队的项目设计速度的赞赏,让本人非常感动。潜水2个多月没有更新博客,多少有点对不住51CTO的关照,在另一款新产品出来前,DM6446开发攻略的2010年最后一篇文章,本人决定从做DAVINCI产品的角度,认真写好最有价值的视频处理。DAVINCI产品的视频驱动和应用,是非常重要的因素,就像LINUX的网络驱动和应用一样,没有网络,还叫LINUX吗?DAVINCI没有视频处理,还叫DAVINCI吗?
针对DAVINCI DM6446平台,网络上也有很多网友写了V4L2的驱动,但只是解析Montavista
linux-2.6.10V4L2的原理、结构和函数,深度不够。本文决定把Montavista 的
Linux-2.6.18 V4L2好好分析一下,顺便讲解在产品中的应用,满足一些客户提出要求,毕竟V4L2是LINUX一个很重要的视频驱动,适合很多嵌入式芯片平台。本文首先讲解DM6446
DAVINCI视频处理技术的硬件工作原理,然后讲解DM6446 V4L2采集驱动和输出驱动,然后对TI DVSDK2.0里边提供的V4L2的例子进行详细讲解,怎样和驱动配合起来。
第一节 DAVINCI视频处理硬件
有关DM6446 DAVINCI视频处理技术,有两个文档:VPFE sprue38ec.pdf和VPBE sprue37c.pdf,必须要看看的。下图是DAVINCI视频处理技术的框图,VPSS(视频处理子系统)包含VPFE和VPBE,VPFE负责前端视频采集和处理,而VPBE负责后端视频输出,通过OSD和VECN直接输出到DACS(数字转模拟输出口,一共4个通道DAC,通过外围视频编码芯片转换成复合视频CVBS输出到普通电视机)或者直接输出到LCD(DM6446支持RGB24位信号输出到数字LCD屏,4.3寸,7寸屏等)。
图-1 DAVINCI VPSS框图
从图-1可以看出,VPFE系统可以接CCD或者CMOS sensor,同时也可以接视频解码芯片,目前Montavista Linux-2.6.18驱动给出的TI EVM驱动支持MT9T001 CMOS芯片和TVP5146视频解码芯片,VPFE采用RAW模式控制MT9T001 CMOS芯片,数码相机产品基本是这种应用方式,而VPFE采用BT601或BT656的方式控制TVP5146视频解码芯片,很多做安防、机器视觉等的方案都是这种模式,因为这种方式最普通,视频前端买个普通的CCD摄像机,接条视频线和电源,就可以用通过类似TVP5146的芯片采集到图像了,本人也着重介绍这种情况。而图-1里边的Resizer(图像缩放1/4x~4x)、Preview(预览器)、H3A(硬件自动白平衡、自动对焦、自动曝光)、Histogram(
直方图)是对采集到的视频进行处理,一般常用到的是Resizer,不需要占用ARM和DSP的资源,对采集到的YUV422数据进行处理,然后才提交给H264等算法进行压缩,这一点可以在dvsdk_2_00_00_22dvsdk_demos_2_00_00_07dm6446里边的例子体现到。
VPBE系统可以对处理后的视频(VIDEO)数据或图像(IMAGE)进行处理和输出,一般用户可以通过OSD功能叠加自己的LOGO、字符、时间、坐标、框图等信息,然后通过VENC模块输出到DAC或者LCD接口。
VPFE和VPBE所有的数据交换都是在DDR上处理,VPFE采集的视频数据,比如YUV422格式(U0Y0V0Y1)都有指定的DDR地址,而VPBE也有另外指定的DDR地址。
第二节 V4L2采集驱动
对应上面的硬件处理过程,软件工程师最关心的是如何配置VPFE和VPBE的寄存器,如何实现DDR的视频数据视频缓冲处理,在LINUX内核里如何实现DMA处理。Montavista 的Linux-2.6.18 V4L2驱动源码已经帮客户实现VPFE和VPBE的处理,他们的源码目录是linux-2.6.18_pro500driversmediavideo和linux-2.6.18_pro500driversmediavideodavinci目录。对于LINUX驱动工程师,首先先按以下三个图配置Montavista
linux-2.6.18_pro500的内核,让linux-2.6.18_pro500支持V4L2。
图-2 配置Multimedia devices
按图-2选择Video For Linux,然后进入“Video Capture Adapters”,按图-3配置DAVINCI视频采集选项,
图-3 配置采集选项
同在一个配置界面,选择和进入“Encoders and Decoders”,配置VPBE实现视频输出处理。
图-4 配置VPBE DISPLAY选项
然后再去到驱动driver文件夹找到相关文件。
VPFE采集涉及到下面几个文件:
ccdc_davinci.c(主要工作把重点放在ccdc_config_ycbcr()函数上,主要是配置是否采用BT656或BT601,采集视频的数据格式等)
tvp5146.c(这个就是你板子外围视频采集芯片驱动,一般是I2C访问,有些朋友的项目可以是TVP5150,我们开发板的是TVP5158,还可以是Techwell的芯片和nextchip的芯片参考TVP5146的驱动,把自己的项目芯片驱动移植过来就OK了)
davinci_vpfe.c(这就是和应用程序打交道的内核程序,和v4l2配合使用,供应用层调用)
VPBE输出涉及到:
davinci_display.c
davinci_enc_mngr.c
davinci_osd.c
davinci_platform.c
vpbe_encoder.c
V4L2驱动:
在linux-2.6.18_pro500driversmediavideo目录里,
v4l2-common.c
video-buf.c
videodev.c
这些函数比较复杂,V4L2必须和davinci_vpfe.c、vpbe_encoder.c配合,借助davinci_vpfe.c提供的接口函数,LINUX应用程序才能控制TVP5156和CCDC采集;V4L2负责对采集到的视频数据进行管理,包括DMA和缓冲处理,Montavista已经帮客户搞定这些,我们需要的做的就是学习人家是如何实现这些处理的。本公司的开发板采用的是TVP5158芯片,见,
http://zjbintsystem.blog.51cto.com/964211/392221。移植修改基本上是上面的几个VPFE采集源文件。至于我们板子上的美光MT9M112、MT9D112等类似CMOS芯片的控制,基本也是修改上面的几个VPFE采集源文件。
第三节 V4L2例子源码分析
在dvsdk_2_00_00_22PSP_02_00_00_140examplesdm644xv4l2里,有V4L2应用的例子,里边有v4l2_mmap_loopback.c和v4l2_userptr_loopback.c,我们主要分析v4l2_mmap_loopback.c。很多网友介绍LINUX V4L2视频原理都是从本节开始的,以TVP5146采集芯片为例。
1、Makefile修改
下面的Makefile的内容也适合于其他LINUX应用程序,
# Makefile for v4l2 application
CROSSCOMPILE = arm_v5t_le-
CC=$(CROSSCOMPILE)gcc
LD=$(CROSSCOMPILE)ld
OBJCOPY=$(CROSSCOMPILE)objcopy
OBJDUMP=$(CROSSCOMPILE)objdump
INCLUDE = /home/davinci/dm6446/ty-dm6446-1000/linux-2.6.18_pro500/include
(本人把产品级的linux-2.6.18_pro500放到上面的目录,ty-dm6446-1000是本人公司深圳桐烨科技的一个DM6446产品)
all: tvp5146_v4l2_mmap
tvp5146_v4l2_mmap: v4l2_mmap_loopback.c
$(CROSSCOMPILE)gcc -Wall -O2 v4l2_mmap_loopback.c -I $(INCLUDE) -o tvp5146_v4l2_mmap
$(CROSSCOMPILE)strip tvp5146_v4l2_mmap
cp -f tvp5146_v4l2_mmap/home/davinci/nfs/tirootfs/opt/app/
(自动COPY到NFS进行调试)
%.o:%.c
$(CC) $(CFLAGS) -c $^
clean:
rm -f *.o *~ core tvp5146_v4l2_mmap
2、下面通过分析v4l2_mmap_loopback.c的源码,从应用层的角度讨论V4L2的原理:
#include
#include
#include
#include
#include
。。。。。。。。。。。。。。。。。。。。。。。。。。
#include
#include
/*以上指向你安装的linux主机/usr/include*/
#include /*指向Montavista linux-2.6.18includelinux*/
#include /*指向linux-2.6.18includeasm-arm*/
/* Kernel header file, prefix path comes from makefile */
#include /*指向linux-2.6.18 includemediadavinci*/
#include