聞連臣,段曉輝,郭躍超,張 振
(北京大學(xué) 無(wú)線通信與信號(hào)處理研究中心,北京 100871)
多媒體的呈現(xiàn)方式從本地播放、下載存儲(chǔ)播放逐步發(fā)展到流式播放[1]。流媒體融合了網(wǎng)絡(luò)和多媒體編解碼等技術(shù),雖然在PC領(lǐng)域上的應(yīng)用已比較成熟,但是在嵌入式領(lǐng)域,仍有著很大的開(kāi)發(fā)空間。文中提到的向Mplayer的解碼庫(kù)中添加S3C6410的多媒體編解碼模塊MFC(multi format codec)[2],具有很強(qiáng)的應(yīng)用價(jià)值。
本設(shè)計(jì)的平臺(tái)是HINOC手持測(cè)試儀。HINOC[3](High performance Network Over Coax)是“三網(wǎng)融合”中的從光纖網(wǎng)到用戶(hù)的一個(gè)傳輸方案,如圖1所示。頭端設(shè)備(HINOC Brige,HB)對(duì)多個(gè)終端設(shè)備(HINOC Modem,HM)進(jìn)行管理。
HINOC手持測(cè)試儀的主要功能是不僅有 HM的功能,還能協(xié)助工程人員進(jìn)行故障定位。圖2和圖3顯示了其硬件和軟件結(jié)構(gòu)。
工作人員通過(guò)流式傳輸可以觀看遠(yuǎn)程業(yè)務(wù)視頻,而且能直觀地驗(yàn)證網(wǎng)絡(luò)的底層是否連通。
圖1 HINOC網(wǎng)絡(luò)結(jié)構(gòu)圖
本系統(tǒng)采用了ARM-Linux,處理器是基于ARM1176-JZF-S的S3C6410,播放器是Linux系統(tǒng)上最優(yōu)秀的播放器之一 Mplayer[4],結(jié)構(gòu)如圖 4所示。將S3C6410的MFC加入Mplayer的解碼庫(kù)中,通過(guò)移植協(xié)議棧 live555,Mplayer支持流式傳輸。
圖2 手持測(cè)試儀硬件架構(gòu)
圖3 手持測(cè)試儀軟件架構(gòu)
圖4 Mplayer結(jié)構(gòu)圖
研究發(fā)現(xiàn)為Mplayer添加解碼器的方法有多種,總結(jié)如表1所示,本文采用了第3個(gè)方案。
表1 Mplayer添加解碼器的方法
S3C6410這款16/32位的微處理器,主頻可達(dá)667 MHz,主處理器之外集成了MFC,如圖5所示,能支持MPEG4/H.263/H.264/VC1的編解碼,解碼性能可達(dá) 720×480 30 f/s或者720×576 25 f/s。S3C6410還支持實(shí)時(shí)視頻會(huì)議等功能。
MFC由BIT和視頻編解碼器組成。BIT處理器對(duì)數(shù)據(jù)流進(jìn)行分解,一方面與主處理器通信來(lái)協(xié)調(diào)整個(gè)流程,另一方面控制視頻解碼器進(jìn)行解碼。BIT處理器主要包括:BIT處理器內(nèi)核、程序內(nèi)存、數(shù)據(jù)內(nèi)存、與主處理器進(jìn)行交互的接口。視頻編解碼器受BIT處理器的控制來(lái)完成解碼,內(nèi)部包含宏塊控制器、預(yù)測(cè)、塊效應(yīng)濾波、重構(gòu)等子模塊。
解碼時(shí)需對(duì)中間運(yùn)算緩存,圖5中的外部存儲(chǔ)器提供了這些空間,可分為BIT處理器緩沖和數(shù)據(jù)緩沖,如圖6和圖7。代碼緩沖區(qū)的主要作用是存儲(chǔ)啟動(dòng)代碼。工作緩存區(qū)緩存中間結(jié)果,其配合流緩沖區(qū)進(jìn)行工作。參數(shù)緩存區(qū)主要存幀緩沖的地址。主處理器對(duì)流緩沖區(qū)進(jìn)行寫(xiě)操作,BIT處理器對(duì)其進(jìn)行讀操作,其緩存的是待解碼的數(shù)據(jù)。幀緩沖區(qū)存儲(chǔ)的是解碼后的YUV數(shù)據(jù)。
圖5 S3C6410中的主處理器和MFC關(guān)系圖
圖6 BIT緩沖區(qū)存儲(chǔ)結(jié)構(gòu)圖
圖7 數(shù)據(jù)緩沖區(qū)存儲(chǔ)結(jié)構(gòu)圖
由圖4知,Mplayer的結(jié)構(gòu)是模塊化的,各個(gè)模塊在mplayer.c的協(xié)同下工作。下面對(duì)其簡(jiǎn)要分析。
(1)stream.c所在的輸入層,根據(jù)讀入方式來(lái)調(diào)用文件,正如圖 4中 stream_*.c所示, 如 strean_file.c、stream_ftp.c、stream_netstream.c等。這個(gè)過(guò)程通過(guò)查詢(xún)、跳轉(zhuǎn)、緩存等來(lái)完成。
(2)demuxer.c所在的音視頻分流層。demuxer.c是一個(gè)基本的框架,對(duì)于具體的流如mpeg-es、avi、asf等,都有相應(yīng)的 demux_*.c。
(3)解碼。解碼器由libmpcodecs/*和分離的庫(kù)組成,如liba52、libmpeg2等。Mplayer.c通過(guò)dec_audio.c和dec_video.c對(duì)流頭sh_audio_t和sh_video_t中的格式進(jìn)行判斷來(lái)選擇解碼器。通過(guò)dec_audo.c來(lái)調(diào)用ad_*.c;通過(guò)dec_video.c來(lái)調(diào)用vd_*.c,即視頻解碼器。解碼之后還需對(duì)視頻后期處理,即需用到視頻濾波器vf_*.c。
(4)顯示。video_out.c和 audio_out.c調(diào)用不同的顯示模塊,如 vo_directfb.c、vo_fbdev.c等。
應(yīng)用程序調(diào)用MFC的API,現(xiàn)在對(duì)其進(jìn)行介紹,其中涉及了Mplayer中的函數(shù):SsbSipH264DecodeInit():解碼實(shí)例的創(chuàng)建,即初始化;SsbSipH264DecodeGetInBuf():獲取輸入緩存區(qū)的地址,待解碼數(shù)據(jù)從這里讀??;
以上函數(shù)作為初始化,需要在編寫(xiě)的vd_*.c中的初始化函數(shù)int init(sh_video_t*sh)中調(diào)用;
SsbSipH264DecodeGetConfig():在 vd_*.c 的 mp_image_t*decode(sh_video_t*sh,void*data,int len,int flags)中兩處被調(diào)用:其一是為了獲得視頻流的信息,如分辨率的長(zhǎng)、寬等,只能在 mp_image_t*decode()第一次執(zhí)行時(shí)調(diào)用,否則因時(shí)間開(kāi)銷(xiāo)而影響視頻的顯示,調(diào)用的格式為:Ssb-SipH264DecodeGetConfig(handle,H264_DEC_GETCONF_STREAMINFO,&stream_info);其二獲得輸出地址,格式為:SsbSipH264DecodeGetConfig(handle,H264_DEC_GETCONF_PHYADDR_FRAM_BUF,pYUVBuf)。其源碼結(jié)構(gòu)如下:
SsbSipH264DecodeExe():在函數(shù)mp_image_t*decode(sh_video_t*sh,void*data,int len,int flags)中被調(diào)用的解碼函數(shù)。
SsbSipH264DecodeDeInit():最后對(duì)硬件資源的釋放,在 void uninit(sh_video_t*sh)中調(diào)用。
首先,將live555源碼中l(wèi)ive中的文件config.armlinux里的CROSS_COMPILE改為CROSS_COMPILE?=arm-linux-;然后依次執(zhí)行./genMakefile armlinux、make;最后,將編譯好的目錄復(fù)制到/usr/local/lib下。其次完成Mplayer軟解碼的移植[5]。
下面介紹如何將MFC添加到Mplayer中,這是本文的關(guān)鍵。
首先,在文件etc/codecs.conf中增加解碼器實(shí)體。codecs.conf是對(duì)音視頻解碼器的聲明,其關(guān)鍵字是固定的,如videocodec說(shuō)明是視頻解碼器。
其次,編寫(xiě)解碼器vd_mfc264.c。Mplayer定義了一個(gè)vd_functions_t型結(jié)構(gòu)體。原型定義在vd.h中,如下所示:
(1)int init(sh_video_t*sh)完成解碼之前的初始化,包括MFC的啟動(dòng)以及一些API句柄的獲得;
(2)void uninit(sh_video_t*sh)是結(jié)束函數(shù),完成解碼后的資源的釋放;
(3)mp_image_t*decode(sh_video_t*sh,void*data,int len,int flags)完成解碼。讀取到的待解碼數(shù)據(jù)填充到圖7中的流緩沖區(qū),通過(guò)與工作緩沖區(qū)的交互,將解碼后的YUV數(shù)據(jù)放入圖7中的幀緩沖區(qū)。
Mplayer的視頻解碼器都被libmpcodec目錄下vd.c中的指針數(shù)組mpcodecs_vd_drivers所管理,因此增加:
(4)int control(sh_video_t*sh,int cmd,void*arg,...)的作用是控制視頻的解碼和顯示,這個(gè)函數(shù)是為保障音視頻的同步。
再次,編寫(xiě)顯示模塊vo_mfcfb.c。S3C6410的MFC可以對(duì)解碼后的數(shù)據(jù)進(jìn)行縮放、濾波等后期處理。在Mplayer的源碼中,是把數(shù)據(jù)傳給 video_out.c,然后通過(guò)調(diào)用vo_fbdev.c來(lái)使用framebuffer顯示。在硬解碼中,由于存儲(chǔ)解碼后的數(shù)據(jù)的物理地址,并不是在處理器的緩存中,而是在外部存儲(chǔ)器中,這導(dǎo)致Mplayer的vo_fbdev.c無(wú)法獲得緩存地址。解決辦法就是編寫(xiě)vo_mfcfb.c,它完成將幀緩存區(qū)中的YUV數(shù)據(jù)進(jìn)行后期處理并顯示。整個(gè)流程如圖4所示。將vo_mfcfb.c加入到video_out.c中,不再具體敘述。
最后,修改 Mplayer下的相關(guān) Makefile,將編寫(xiě)的兩個(gè)源文件和相應(yīng)的頭文件編譯成靜態(tài)鏈接庫(kù)。
現(xiàn)在用一臺(tái)PC運(yùn)行l(wèi)ive555來(lái)充當(dāng)流媒體服務(wù)器,通過(guò)搭建HB,來(lái)驗(yàn)證手持測(cè)試儀上的流媒體播放功能。
通過(guò)軟件Media Coder將測(cè)試視頻轉(zhuǎn)換成編碼幀率25 f/s、分辨率720×480和不同的編碼碼率的視頻。圖8從播放幀率角度顯示了對(duì)比的解碼性能。
圖8 軟硬解碼性能對(duì)比
分辨率為720×480、編碼幀率為25 f/s的 H.264視頻,在Arm11平臺(tái)下,要想達(dá)到人眼視覺(jué)可以接受的流暢性,Mplayer的軟解只能達(dá)到的碼率為500 kb/s,而使用MFC硬解可以高達(dá)3 500 kb/s,比軟解碼提高約3 000 kb/s。
流媒體最耗資源的是視頻的解碼,本文利用支持live555的Mplayer的成熟框架,將S3C6410的MFC添加到Mplayer的解碼庫(kù)中,不僅可以降低系統(tǒng)對(duì)CPU、內(nèi)存等硬件資源的要求,而且大大提高了視頻質(zhì)量,這體現(xiàn)了嵌入式應(yīng)遵循的高性?xún)r(jià)比理念。而Mplayer在嵌入式領(lǐng)域的應(yīng)用,通常是對(duì)已有軟件解碼器進(jìn)行算法的優(yōu)化,或者直接進(jìn)行移植應(yīng)用[5],本文的開(kāi)發(fā)方案為相關(guān)應(yīng)用提供了很好的借鑒。
[1]CONKLIN G J,GREENBAUM G S,LILLEVOLD K O,et al.Video coding for streaming media delivery on the Internet[J].IEEE Transactions on Circuits And Systems for Video Technology,2001,11(3):269-281.
[2]Samsung Electronics.S3C6410X RISC microprocessor user′s Manual[Z].2008.
[3]國(guó)家廣播電影電視總局廣播科學(xué)研究院,北京大學(xué),西安電子科技大學(xué),上海明波通信技術(shù)股份有限公司,上海未來(lái)寬帶技術(shù)及應(yīng)用工程研究中心有限公司.高性能同軸電纜接入技術(shù)(HINOC)研究與實(shí)現(xiàn)論文集[M].遼寧:遼寧石油化工大學(xué),2011.
[4]Mplayer.The online documentation of Mplayer[EB/OL].(2013-05-01)[2014-06-30].http://www.mplayerhq.hu/DOCS/HTML/zh_CN/intro.html.
[5]慈文彥,何君,朱明祥.基于ARM處理器的流媒體播放器客戶(hù)端的構(gòu)建[J].信息技術(shù),2012(1):106-112.