嵌入式Linux系统下MPEG-4专用编码器驱动设计

嵌入式Linux系统下MPEG-4专用编码器驱动设计摘要:嵌入式视频监控的方案设计已有众多论述,但针对实现过程中Linux下视频MPEG-4编码的驱动设计鲜有提及。本文以视频编码芯片IME6410的驱动设计为实例,主要论述了基

<script src=”/html/ad/jswz/ad-jswz_6.js” type=”text/javascript”></script>

摘要:嵌入式视频监控的方案设计已有众多论述,但针对实现过程中Linux下视频MPEG-4编码的驱动设计鲜有提及。本文以视频编码芯片IME6410的驱动设计为实例,主要论述了基于Video for Linux (V4L) 规范的视频驱动实现方法,包括硬件接口、设备初始化、文件操作实现等,并着重分析了V4L规范、视频驱动及内核之间的内在联系。 关键词:嵌入式Linux,Video4Linux,驱动, IME6410

AbstractThere are many researches on the design of embedded video surveillance system already. However, the method of design about Linux driver for MPEG-4 Codec has rarely been reported. In this paper, Linux driver for video Codec is discussed and an example of driver design for IME6410 is presented. The implement of driver based on V4L interface was introduced, of which the hardware interface, device initialization, file operations etc are involved as well. The fundamental relations between V4L interface, video drivers and linux kernel are analyzed deeply.

Key wordsEmbedded Linux,Video4Linux,driver, IME6410

1 引言

随着嵌入式技术与流媒体技术的蓬勃发展,视频监控系统正由基于PC的监控方案转为嵌入式的视频监控方案。由于嵌入式的数字监控系统有着布控区域广泛、可组成非常复杂的监控网络且性能稳定可靠等优点,因此更具发展前景[1]。目前,基于MPEG-2压缩标准的嵌入式视频监控已经得到广泛应用,即便如此,用户和环境对视频监控的要求越来越苛刻,寻求一种更好的压缩方法和传输方式成为新的目标。基于该目标,本文以一种专用MPEG-4编码芯片IME6410为例,从视频压缩的角度改进视频监控方案。其中,主要描述了视频编码部分在嵌入式Linux下的驱动程序设计与实现。

本文首先介绍了本系统硬件结构,之后深入剖析了V4L规范,在此规范基础上以IME6410为例具体阐述驱动程序的设计开发过程,包括芯片初始化,设备注册等,最后给出结论。

 

2 视频系统硬件设计

在本系统中,MPEG-4编码芯片采用IME6410。它是一款单路音视频压缩器件,其外围集成了多种外设控制器和接口,如SDRAM控制器、I2C接口、I2S接口、主机控制器等。IME6410内部带有RAM,可存放供芯片运行的Firmware程序。根据芯片特性,设计其外围电路如图1所示。

 

嵌入式Linux系统下MPEG-4专用编码器驱动设计

1 视频服务器编码部分硬件图

编码芯片IME6410在音视频压缩过程中产生的大量中间数据则须放置在大容量的32位外部SDRAM中,IME6410的视频接口符合CCIR-601 16位标准,对外支持YUV422,对内采用YUV420采样。外部视

频Decoder采用SAA7111,支持NTSC/PAL制式,SAA7111的片内寄存器可通过其外部I2C接口设置。在视频服务器系统中,有的ARM处理器自带I2C总线,有的则没有,而压缩芯片IME6410片内带有I2C总线控制器,提供作为master的访问方式,因而可以通过用IME6410间接控制SAA7111。单路视频编码输出的数据量不超过14.745Mbps,应用16位总线的ARM 9系统负荷量不大。

视频采集及压缩部分的大致数据流如下:从摄像头采集的模拟信号通过A/D传送给IME6410,IME6410将视频数据在SDRAM中进行实时编码压缩,并合成音频编码(可选),将编码后的数据送往片内1K的FIFO中,当FIFO半满或者全满时,产生外部信号nfull,ARM控制器可通过中断方式或者查询方式获知FIFO状态,在需要时读取FIFO数据,将其放在自己的RAM存储器中以备后处理。

 

3 驱动程序设计

驱动程序介于操作系统与硬件之间,与硬件底层联系紧密。Linux下的视频采集及压缩系统中,一般都需要用到Video for Linux(V4L)驱动规范[2],该模块是底层驱动程序与应用程序之间的接口。它为Linux下的视频设备提供了一套API 和相关的标准,按照V4L规定的接口访问方式控制和读写设备,即可完成视频编码及相关参数的采集或设置。

 

1.V4L规范的深入剖析

V4L 将视频设备分为四类[3],规定所有视频设备文件的主设备号都是一致的都是81 ,但是,对于不同的硬件类型,其特殊文件的次设备号不一致,且各类设备都有一段独立的次设备号范围。通过这种方式,可以从设备文件的次设备号中判断该设备到底属于那种类型。V4L 和特定的设备驱动是通过它定义的一些数据结构和相关的函数关联起来的,其中关键的数据结构是video_device 结构,其定义如下: 

struct video_device

{

char name[32];     //设备名

int type;    // 设备类型

int minor;   //次设备号

devfs_handle_t devfs_handle;   //设备句柄

/*以下为重要成员指针,有删减*/

int (*open)(struct video_device *, int mode);

void (*close)(struct video_device *);

long (*read)(struct video_device *, char *, unsigned long, int noblock);

long (*write)(struct video_device*,char *, unsigned long, int noblock);

int (*ioctl)(struct video_device *, unsigned int , void *);

int (*mmap)(struct video_device *, const char*, unsigned long);

int (*initialize)(struct video_device *);

};

该结构对应于驱动程序控制的一个设备,其中的minor 成员代表该设备对应的次设备号,其他的open,close,read,write,ioctl等成员都代表相应的函数指针,这些函数指针都是指示特定设备的相关操作,V4L 利用统一的接口注册了另一个设备操作结构,这个统一的设备操作结构里的驱动接口函数根据被打开特殊设备文件的次设备号,来定位该设备文件对应的struct video_device ,从而实现对特定设备的控制。为了实现这种定位,V4L 定义了一个静态数组static struct video_device *video_device[256],每个特定的设备都在该数组里占据一项。设计驱动程序时,需要通过V4L 提供的一个设备注册函数video_register_device 将每个所要控制的硬件设备数据结构填充到该静态数组中,调用该函数的时候,应该提供设备特定数据结构以及设备类型。

video_register_device函数在videodev.c中实现,事实上V4L规范的主要实现都在该文件中,文件位于/driver/media/video/目录下。videodev.c本身也是一个驱动模块,一般通过menuconfig选项在内核编译时静态加载。加载V4L模块的初始化函数module_init() 主要完成了字符型设备注册的功能,过程如下:首先注册一个主设备号为81的字符型设备驱动,通过次设备号区分每个特定设备的驱动程序。注册成功后,如果存在proc文件系统,则在/proc文件目录下创建专用目录/proc/video/dev/,当实际设备文件被注册后,将在该目录下生成一个设备文件[4]

当注册一个实际设备,调用注册函数video_register_device时,注册要求的三个参数分别为设备结构体(device struct),设备类型,次设备号。类型决定了次设备号的起始地址段,当注册次设备号为-1时,系统自动为设备分配一个可用的最小设备号,若指定的设备还存在initialize函数,则亦在此运行,然后执行devfs_register,自动创建/dev目录下的设备文件如video0,挂载文件操作file_operations指针,该指针地址同样指向V4L模块加载时定义的文件指针,最后在/proc/video/dev/下创建设备文件(上已提及)。所以,V4L与具体驱动设备注册之间的挂钩主要就是通过devfs_register 函数实现。

在剖析V4L接口规范后,根据其结构体,最重要的工作是模块初始化, module_init系统调用加载video_IME_init函数,完成硬件初始化及设备结构填充工作。

 

2.完成IME6410和SAA7111的初始化

首先需要对IME6410及SAA7111分别初始化,在硬件设计中,设置SAA7111寄存器所采用的I2C接口通过IME6410输出,所以必须先对IME6410初始化。

不同于一般的芯片,IME6410的芯片需要先下载Firmware程序然后才能正常工作,此时再初始化其片内寄存器,配置成要求的参数。根据硬件设计,首先配置ARM处理器的外部总线接口(EBI),从时序、延迟、电平有效等多方面满足IME6410的时序要求。其次,根据图2流程初始化IME6410,IME6410下载Firmware较为特殊,在硬件选择Host下载后,片内ROM检测外部总线类型及宽度,随即等候Host端向其发送数据,其接收数据的方式类似于flash烧写的有限状态机:先接收下载程序待存放的基地址和偏移地址;再接收Firmware的一个半字(half word)数据;然后,再次从Host端口等待一个传送命令,并开始真正的将数据存到片内RAM中,主机可通过查询状态寄存器获知传送情况,并循环以上过程完成下载过程,下载完毕后的IME6410将自动置位版本寄存器及各种编码方式寄存器,查询版本寄存器获知Firmware下载是否成功。

 

嵌入式Linux系统下MPEG-4专用编码器驱动设计

2 视频外设初始化流程图

Firmware使能片内I2C模块,对ARM控制器而言就是一个外部I2C控制器,在Linux中利用宏抽象I2C读写操作。IME6410的片内I2C总线只支持最多四字节的块写操作,这给SAA7111的寄存器初始化增添了麻烦,但因为SAA7111内部待设置的寄存器不多,通过几次操作即可完成。

 

3.实现视频设备注册和中断程序注册

视频设备注册调用的源函数包含了模块计数增1,因而无需调用MOD_INC_USE_COUNT宏计数[4]。在视频注册调用时引用的video_device 数据结构应填充完毕,其文件操作指针通过回调函数指定,如:

static struct video_device IME_template =

{     ……

open:      video_IME_open,

read:       video_IME _read,

ioctl:       video_IME _ioctl,

 ……

};

该结构体中各文件操作指针回调函数的功能按实际需求定义,这里列出本系统中的部分功能分配。

open:open操作使能IME6410的工作,首先查询IME6410的状态寄存器,当一切正常时,使能IME6410寄存器开始图像编码。

read:读取IME6410的FIFO,每次读取一包(512字节)的缓冲区,对于每一包数据,其前4个字节标注了包大小及类型等信息,供应用层使用。

write:IME6410不需要实现写数据操作,因而基本不起作用。

mmap:映射视频设备缓冲到本地内存缓存。

ioctl:不同于一般的设备文件,符合V4L的视频文件操作一般都通过ioctl函数设置、获取各类参数甚至图像数据。V4L列出了所有的相关操作[5],对于本视频编码只实现一部分实用操作,如表1,视频采集或编码的操作差异较大,需要实现各自的控制方式。有些通过ARM设定的参数就直接在本地访问了。

视频编码控制操作

VIDIOCGPICT

获取图像参数,包括分辨率,帧速率,比特率控制等

VIDIOCSPICT

设置图像参数

VIDIOCGMBUF

获取本地映射缓存的参数,主要是其地址和大小

VIDIOCMCAPTURE

获取图像编码到映射缓冲区

VIDIOCSYNC

获取帧结束标志

 

中断程序的注册采用request_irq系统调用,在本程序中,采用外部IO中断,须根据ARM芯片硬件设置选择中断向量号。中断句柄指向了中断处理程序,该程序在内核态执行。当IME6410的FIFO半满或全满时,ARM处理器产生IO中断,Linux内核相应中断句柄,从而进入中断处理程序,程序读取一包数据后,通过消息机制通知上层应用。

编译后的驱动程序在/dev目录下生成名为v4lvideo0的inode节点文件。至此,完成整个驱动程序的设计与编写。

 

4 结束语

本文深入剖析了V4L规范与视频驱动的上下关系,以编码芯片IME6410为例,介绍了基于视频编码模块的驱动开发的具体方法,针对视频压缩编码选择了合理的ioctl命令。编译后的程序文件其系统调用遵循V4L规范,在应用程序的测试中获得了较好的性能。文中适用于一切符合V4L规范的视频驱动开发。

本文作者创新点:

1.  在嵌入式Linux上设计了符合V4L规范的驱动程序,使该驱动程序有一定的通用性。

2.  提供了符合V4L规范的驱动程序设计一般方法

3.  为专用MPEG-4编码器在嵌入式系统中的应用提供了一种参考方法

 

参考文献:

1 南冰,李兴华,荆涛. 基于MPEG-4标准和嵌入式技术的监控系统设计[J]. 微计算机信息,2005,9-3:112-113

2 Alan Cox. Video4Linux Programming.[M] alan@redhat.com. 2000

3 李根深,邢汉承.Linux平台下PCI接口视频采集卡的驱动程序编写技术[J],计算机辅助工程,2003, Vol.12 No.1:12-19

4 ALESSANDRO RUBINI.魏永明等译.LINUX 设备驱动程序[M]. 北京 中国电力出版社,2002

5 杨继华,严国萍.基于嵌入式Linux与S3C2410平台的视频采集[J],单片机与嵌入式系统应用,2004, No.11:69-71

今天的文章嵌入式Linux系统下MPEG-4专用编码器驱动设计分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12759.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注