在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.
蔣志峰((碩士研究生),主要研究方向為嵌入式系統、視頻信號處理。