在DSP平台上移植音视频编解码算法通常分为3个阶段: 第1个阶段产生并评估C代码;第2个阶段优化C代码;第3个阶段进行汇编优化[1]。整个过程比较耗时,工作量巨大。为减小移植工作量,可引入ffmpeg音视频开发包,在开发包基础上进行开发可以免去第一阶段工作,并减少部分第二阶段的工作。ffmpeg是一个优秀的音视频解决方案,在此框架下可以方便、快速地进行进一步的开发。在嵌入式硬件平台和嵌入Linux环境下,本文搭建了一种基于ffmpeg框架的音视频编解码软件开发平台,可供算法改进、性能测试,使得视频编解码算法的优化改进得以在一个高起点上快速进行。本文分别介绍了平台搭建步骤(包括UBoot、Linux、ffmpeg的移植)和基于ffmpeg开发的要点。
1 ffmpeg简介
ffmpeg是一个集录制、转换、音/视频编解码功能为一体的、完整的开源解决方案。ffmpeg的开发基于Linux操作系统,也可在大多数操作系统中编译和使用。ffmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多种编码,AVI、MPEG、OGG、Matroska、ASF等90多种解码;TCPMP、VLC、MPlayer等开源播放器都用到了ffmpeg。它能够快速实现音视频格式转换,也能从音视频源获取数据并将其保存。在捕获视频数据时可以设置捕获设备和视频输入标准(包括NTSC、PAL 及SECAM),对于DV1394还可设置视频捕获通道。ffmpeg 使用video4linux 架构的视频源,以及其他任何开源系统的音频源。
2 建立嵌入式Linux开发平台
2.1 bootloader移植
UBoot是一个著名的开放源码项目,支持ARM、PowerPC等多种架构的处理器,也支持Linux、NetBSD 和VxWorks 等多种操作系统。UBoot是用于初始化目标板硬件,为嵌入式操作系统提供目标板硬件配置信息,完成嵌入式操作系统装载、引导和运行的固件程序。
本嵌入式平台硬件环境的CPU为S3C2410,板上用来启动的NOR Flash为Intel公司的E28F320J3。移植工作的板极配置主要是配置好NOR Flash的驱动,用于存放UBoot镜像文件,配置网卡芯片是为了可以使用网络加载Linux内核镜像文件。
本平台使用uboot1.1.5版本,使用cross3.2交叉编译工具[2]。UBoot的移植详见参考文献[3]。在其基础上,笔者做了以下修改:新建开发板目录,名称为myboard,拷贝driver/cfi_flash.c代替 board/myboard/flash.c,并改名为flash.c。修改include/configs/myboard.h文件,添加(或者修改为)如下宏定义:
#define CFG_FLASH_CFI1
#define CFG_FLASH_DRIVER1
#define CFG_FLSH_USE BUFFER_WRITE 1
#define CFG_FLASH_PROTECTION1
#define CFG_ENV_IS_IN_FLASH1
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x40000)
#define CFG_ENV_SECT_SIZE(0x20000)
#define CFG_INIT_CRITICAL1
UBoot编译好之后下载到开发板,设置网卡物理地址、IP地址、服务器地址和启动参数,并把系统控制权交给Linux操作系统。其中,启动参数用来自动从服务器下载编译好的Linux内核。设置UBoot的命令如下:
#setenv bootcmd tftp 32000000 uImage\\;bootm 32000000
#saveenv
2.2 Linux移植
本文移植Linux2.6内核。2.6内核比2.4内核在调度器性能、实时性、内核可抢占性等方面都有大幅提高。参照参考文献[3]进行移植,在文件系统方面,为方便开发调试,采用NFS网络文件系统。在裁减配置内核时,选择NFS配置。内核配置的kernel command line如下:
root=/dev/nfs rw nfsroot=192.168.0.1:/home/arm/rootfs noinitrd init=/linuxrc console=ttySAC0,115200 ip=192.168.0.2
2.3 USB摄像头驱动配置
USB摄像头使用网眼V2000。这款摄像头使用ov511芯片,它的驱动在配置Linux内核时可以选择加载。
3 建立ffmpeg的嵌入式运行环境
3.1 ffmpeg的移植及编译
下载最新的ffmpeg包解压缩,在嵌入式平台上使用开发包需要交叉编译,手工修改配置文件如下:
#vi configure
prefix="/home/arm/files/video/libffmpge"
cross_prefix="usr/local/arm/3.4.1/bin/"
cc="armlinuxgcc"
ar="armlinuxar"
ranlib="armlinuxranlib"
strip="armlinuxstrip"
然后运行命令
./configure cpu=armv4l enable shared enable pthreads
参考文献[4]直接使用ffmpeg编译后产生的可执行文件来采集视频。本文中应用程序开发需要用到ffmpeg的动态库,加上enableshared即可。配置完成后,运行make、make install 命令,可在路径/home/arm/files/video/libffmpge下生成可供嵌入式平台程序动态调用的库libavformat.so和libavcodec.so。
3.2 视频处理应用程序开发
基于ffmpeg开发的文档资料不多,因此,本文对ffmpeg的使用进行详细说明。本文基于ffmpeg库的应用是低帧率视频采集编码与网络传输。这里以H.263编码格式为例。
应用程序要用到几个主要的结构:
AVFormatContext *m_pFormatCtx_dec;
AVCodecContext *m_pCodecCtx_dec;
AVCodec*m_pCodec_dec;
AVFrame*m_pFrame_dec;
AVCodecContext *m_pCodecCtx_cd;
AVCodec*m_pCodec_cd;
应用程序主要流程如图1所示。
图1 应用程序主要流程
下面具体介绍核心函数和主要数据结构的使用。
初始化部分:
//指定设备"/dev/v4l/video0"及视频分辨率等参数
AVFormatParameters formatParams;
AVInputFormat* pInputFormat;
char *filename = "";
pInputFormat = av_find_input_format("video4linux");
(1) 找到视频流
//注册库中含有的所有可用的文件格式和编码器
av_register_all();//打开视频摄像头文件
av_open_input_file(&m_pFormatCtx_dec,filename,pInputFormat,0,&formatParams);//取出包含在文件中的流信息,用有效的信息把AVFormatContext的流域(streams field)填满
av_find_stream_info(m_pFormatCtx_dec);
if(m_pFormatCtx_dec>streams[i]>codec.codec_type == CODEC_TYPE_VIDEO)
m_videostream = i; //寻找第一个视频流
(2) 得到视频流编码上下文的指针
m_pCodecCtx_dec = &(m_pFormatCtx_dec>streams[m_videostream]>codec);//寻找视频流的解码器并打开它
m_pCodec_dec = avcodec_find_decoder(m_pCodecCtx_dec>codec_id);
avcodec_open(pCodecCtx, pCodec);
(3) 分配空间用来存储解码后的图片
m_pFrame_dec = avcodec_alloc_frame();
(4) 设置编码器
编码器参数需在m_pCodec_cd中初始化。
m_pCodec_cd = avcodec_find_encoder(CODEC_ID_H263P);//H.263格式
avcodec_open(m_pCodecCtx_cd,m_pCodec_cd);
(5) 开始编码
初始化完毕之后,就可以对摄像头取得的视频帧进行解码,解码完成之后再对其编码。
avcodec_decode_video(pCodecCtx_dec,pFrame_dec,&frameFinished, packet.data,packet.size);
avcodec_encode_video(pCodecCtx_cd,pOutBuf,pVideoCap>m_out_buf_size,pFrame_dec);
每帧编完码之后,可以调用网络接口发送视频数据到网络终端,实现远程监控或者测试。
4 视频编解码算法改进与开发方法
应用程序编写时调用ffmpeg库函数,方法简单易行。调用原始的未进行算法改进的库函数并不能得到理想的编解码速度,因此需要对原来的开发包源代码进行算法级改进。核心的运行量大的算法需要改用汇编代码,以充分挖掘硬件潜力。对源码修改之后重新编译,得到可供应用程序调用的动态库,而应用程序本身不必进行修改,因此非常方便。
结语
本文介绍的视频开发方法可以省去开发过程中第一阶段和部分第二阶段的工作量,从而快速地对现有算法进行改进、优化、测试。另外,本平台搭建方法也可以用于其他硬件平台(如ADSPBF561平台)上,以满足更高的实时性需求。
参考文献
[1] 安向阳,沈庭芝.基于DSP TMS320DM642的H.264视频编码的实现和优化[J]. 微计算机信息,2005,21(72): 128130.
[2] http://ftp.arm.linux.org.uk/pub/ armlinux/toolchain/.
[3] 吴张顺,张珣. 基于ffmpeg的视频编码存储研究与实现[J]. 杭州电子科技大学学报,2006,26(3): 3034.
蒋志峰((硕士研究生),主要研究方向为嵌入式系统、视频信号处理。