楊明極,畢 晶
(哈爾濱理工大學(xué)測控技術(shù)與通信工程學(xué)院,黑龍江 哈爾濱 150080)
隨著21世紀(jì)的到來,全球快速的進入信息時代,移動通信系統(tǒng)由于綜合利用了有線和無線的傳輸方式,解決了人們在活動中與固定終端或其他移動載體上的對象進行通信聯(lián)系的要求,移動通信給社會帶來了深刻的信息化變革,已成為最受青睞的通信手段。如今,以嵌入式技術(shù)為依托,以網(wǎng)絡(luò)、通信技術(shù)為平臺的網(wǎng)絡(luò)視頻監(jiān)控,已經(jīng)越來越成熟,應(yīng)用范圍越來越廣闊。網(wǎng)絡(luò)視頻監(jiān)控突破了地域的限制,實現(xiàn)了遠(yuǎn)程監(jiān)控,可是,隨著“Any Time,Any Where,Any Device”(任何時間、任何地點、任何設(shè)備)等概念的提出,普通的網(wǎng)絡(luò)視頻監(jiān)控已經(jīng)不能滿足用戶日益增長的多元化需求。“手機視頻監(jiān)控”使這個問題有了答案,這項應(yīng)用將在安防行業(yè)中得到迅速推廣和普及,同時,它也會逐漸走入人們的家庭生活中,比如在工作中的白領(lǐng)人員可以在工作中用手機實時監(jiān)看家里無人照看的老人或幼兒園里孩子的情況,企業(yè)人員可以用手機隨時隨地監(jiān)看自己的店鋪、超市、公司的運營情況等。
本文主要是對基于Android平臺視頻客戶端進行設(shè)計,最后實現(xiàn)其播放的核心功能以及實時監(jiān)視等多項基本功能。
2007年11月5日,Google與其他33家手機制造商(包括摩托羅拉、宏達(dá)電、三星、LG)、手機芯片供應(yīng)商、軟硬件供應(yīng)商、電信業(yè)者所聯(lián)合組成的開放手機聯(lián)盟(Open Handset Alliance,OHA),發(fā)布了名為Android的開放手機軟硬件平臺。
Android是基于Linux內(nèi)核的軟件平臺和操作系統(tǒng)??蚣芙Y(jié)構(gòu)由5個部分組成,其核心為Linux內(nèi)核,逐次向上是Android開發(fā)的Libraries(函數(shù)庫)和Android Runtime(運行環(huán)境),以及搭配Application Framework(應(yīng)用程序框架)來開發(fā)各種不同的應(yīng)用程序[1]。
對于硬件開發(fā)商來說,Android是開放的平臺,只要廠商有實力和能力就可以在此平臺上自由添加特有的設(shè)備或功能,不受到手機操作系統(tǒng)的限制;對于手機開發(fā)者而言,Android是先進的平臺,平臺上的應(yīng)用程序可兼容于各種型號的Android手機,免除為各種不同手機機型開發(fā)的困擾。Android平臺支持各種先進的網(wǎng)絡(luò)、繪圖、3D處理能力,可以用來提供更好的用戶體驗。通過Android Market將自己的應(yīng)用程序銷售給世界各地用戶;對于用戶來說,Android是一個用于手機的操作系統(tǒng)。只要用戶申請了Google帳戶,當(dāng)想換手機時,可以在不同的廠牌同樣使用Android操作系統(tǒng)平臺的手機之間選擇,并且很容易將比如通訊薄等個人資料轉(zhuǎn)換到新手機上。
目前,遠(yuǎn)程實時視頻監(jiān)視技術(shù)主要趨向以下幾個方向:首先,支持多樣化格式。Xmms,Xmovie,QuickTime是主要針對固定的媒體格式類型或傳輸協(xié)議,具有一定的專用性,因此難以滿足廣大消費者的的需求,如今的音頻、視頻格式越來越多,如常見的音頻WMA、MP3以及視頻的RM、AVI等。如何能播放所有格式,是現(xiàn)今研究的方向。其次,可擴展性也是一個必要的趨勢,如今的播放器功能越來越強大,如何在現(xiàn)有的基礎(chǔ)上使功能更全面,也是人們接受的一個因素。這就是本設(shè)計選用開放式Android平臺的一個原因,代碼完全公開,為其功能擴展提供方便的條件。
遠(yuǎn)程視頻監(jiān)視系統(tǒng)無論播放本地文件還是網(wǎng)絡(luò)流媒體文件,都需要經(jīng)歷3個處理階段,分別是獲取媒體數(shù)據(jù)、對音視頻媒體流解碼以及將解碼后的媒體數(shù)據(jù)給用戶顯示[2],本設(shè)計依據(jù)這3個處理階段將遠(yuǎn)程視頻實時監(jiān)視在整體結(jié)構(gòu)上進行分層設(shè)計。
由于本地文件和網(wǎng)絡(luò)流媒體文件的數(shù)據(jù)獲取方式是相異的,若保證上層解碼的一致性,就要對本地文件和網(wǎng)絡(luò)流媒體文件進行預(yù)處理,使它們的數(shù)據(jù)格式相同以供上層解碼。因此,本設(shè)計結(jié)合以上特點以及文件的解碼流程對遠(yuǎn)程視頻實時監(jiān)視的整體結(jié)構(gòu)采用分層設(shè)計方案,每一層獨立完成工作,不但能夠降低系統(tǒng)的耦合度,而且各層的獨立擴展不干擾上下層的應(yīng)用。整體結(jié)構(gòu)層從上到下分別設(shè)計為用戶界面、音視頻解碼層、數(shù)據(jù)預(yù)處理層、數(shù)據(jù)提取層。整體結(jié)構(gòu)如圖1所示。
圖1 遠(yuǎn)程實時視頻監(jiān)視的整體結(jié)構(gòu)圖
遠(yuǎn)程視頻實時監(jiān)視的用戶界面主要由Android的GUI系統(tǒng)實現(xiàn),負(fù)責(zé)提供播放器和用戶之間的交互接口,例如播放時的快進、后退、暫停等功能。GUI系統(tǒng)由Java語言框架和C語言框架組成,對于下層,GUI系統(tǒng)通過調(diào)用顯示輸入、輸出設(shè)備的驅(qū)動將Android的軟件系統(tǒng)和底層的硬件聯(lián)系起來;對于上層,GUI系統(tǒng)提供了Java層次的繪圖接口,Android的Java框架層調(diào)用這些繪圖接口來構(gòu)建各種UI元素。此外,Java應(yīng)用程序?qū)右部梢哉{(diào)用這些繪圖接口。
音視頻解碼層包括解碼選擇組件、多樣主流音視頻格式的解碼器以及多路媒體流之間的同步的功能。解碼選擇組件先從本地文件或者流媒體文件中獲取媒體解碼格式的相關(guān)信息,通過獲取的信息來匹配出對應(yīng)的解碼器對媒體流解碼,此部分通過解碼算法的移植、修剪及優(yōu)化后完成。
數(shù)據(jù)預(yù)處理層對于媒體流文件來說,先要將RTP的包頭信息去除,再對RTP中的音視頻信息進行組幀,同時將全部的數(shù)據(jù)幀傳遞到上層待解碼緩沖區(qū);而對于本地文件,則需要按照相對應(yīng)的媒體格式進行解封裝,再將獲取文件的音視頻等信息按幀放入對應(yīng)的上層待解碼緩沖區(qū)。
數(shù)據(jù)獲取層的功能主要是對本地或流媒體文件的獲取。對本地文件信息獲取需要讀取本地文件即可,而對于流媒體信息文件的獲取,則需要從流媒體服務(wù)器上獲取數(shù)據(jù)信息,獲取信息期間包括前期會話協(xié)商、數(shù)據(jù)緩沖、數(shù)據(jù)發(fā)送等部分。此外,媒體協(xié)商部分中協(xié)商媒體流的常規(guī)信息,例如音視頻媒體類型、傳輸協(xié)議以及媒體傳輸端口等信息,這些都需用到RTSP協(xié)議[3]。
用戶界面是基于Android的GUI系統(tǒng)實現(xiàn)的[4],由類Video Monitor來具體實現(xiàn),其類圖如圖2所示。
圖2 Video Monitor類圖
登錄界面效果如圖3所示。
圖3 登錄界面效果
本設(shè)計的核心只需要利用解碼算法對視頻文件解封裝以及對音視頻解碼,因為若將整個遠(yuǎn)程視頻實時監(jiān)視的系統(tǒng)全部移植到Android平臺上,可能會造成大批量代碼冗余。同時,整個項目的開發(fā)是基于Linux操作系統(tǒng),忽視了手機平臺能源不足、處理能力不夠大等限制因素的問題,所以面對客戶端手機的功能需求來說,將解碼算法進行移植、修剪和優(yōu)化是很重要的。
3.2.1 解碼算法的移植
NDK的makefile文件是由Google發(fā)布,實質(zhì)是Android.mk文件,其語法和一般的makefile文件有很多相異點。因為原有的makefile文件在跨平臺編譯時不能被使用,所以將解碼算法里的makefile文件全部替換成NDK中的Android.mk文件是解碼算法移植的必要條件。通過對解碼層結(jié)構(gòu)的分析可以看出,最基礎(chǔ)模塊是avutil,基于已經(jīng)編譯好的avutil模塊之上的是avcodec模塊,基于avutil和avcodec兩者模塊之上的是avformat模塊。依據(jù)這種結(jié)構(gòu),本設(shè)計將編譯移植的順序由下到上設(shè)計為avutil,avcoedec,avformat,編譯的步驟如下說明:
1)說明config.h和config.mak文件
config.h和config.mak文件非常重要,因為很多不同的文件都會用到include config.h,編譯器也會依據(jù)它而優(yōu)先選擇對代碼編譯。此外,解碼器自帶的makefile框架通過configure命令之后將產(chǎn)生1個config.h文件和1個config.mak文件,2個文件加起來共有600~700個宏定義,這些宏定義主要用于描述編譯后代碼各部分的參數(shù)設(shè)置,包括體系架構(gòu)、編譯器、版本、頭文件、編解碼器等設(shè)置。與此同時,有關(guān)平臺差異方面的定義在此部分需要重新修改,例如把體系架構(gòu)改成Android平臺下的ARMv5TE,只有這樣編譯時的指令集才不會選擇X86的指令集而是ARM的指令集。
2)編譯libavutil.a
首先,在libavutil里創(chuàng)建一個Android.mk文件,然后在libavutil里的makefile文件調(diào)用subdir.mak就實現(xiàn)了真正的編譯,需要注意的是在Android.mk下書寫make文件可以在此省略,只要直接把對應(yīng)的源文件引入即可;標(biāo)準(zhǔn)的makefile是指定.o目標(biāo)文件,但是在Android.mk中需要直接指定.c源文件,Android.mk文件如下所示:
其中,在編譯時出現(xiàn)的錯誤大部分來自于頭文件沒有引入,例如不識別某些文件的size_t關(guān)鍵字在該文件include stdio.h后就不報錯等類似問題,修改時只需要把對應(yīng)的頭文件引入即可。其他層也可以按照以上相同的方法書寫Android.mk文件,并移植到Android平臺。
3.2.2 解碼算法的修剪及優(yōu)化
在Linux下編譯運行解碼代碼時,要經(jīng)過三步才能將解碼算法正確的編譯到Linux系統(tǒng)中,即configure,make,make install。第一步configure過程中將生成1個configure.h和1個make文件,作用是查找此次編譯了何種文件。經(jīng)過操作和嘗試發(fā)現(xiàn)可以在configure源代碼中添加多種配置參數(shù),這些參數(shù)包括基本選項參數(shù)、高級選項參數(shù)以及專門提供的優(yōu)化參數(shù),而優(yōu)化參數(shù)就是用于配置編譯過程中用到的編譯內(nèi)容。因此本設(shè)計也利用這些優(yōu)化參數(shù),擇優(yōu)選擇出合適的方法查詢出遠(yuǎn)程視頻實時監(jiān)視需要的文件,而解碼算法的修剪即將其中不需要的文件進行刪除。編譯時設(shè)置的參數(shù)如下所示:
其中,參數(shù)配置在編譯源文件過程中,整個項目只有一部分編譯到鏈接庫,分別是H.264、amr_nb的編碼方法、3gp的文件封裝格式、解封裝文件的源代碼以及全部的解碼格式。而鏈接庫里已被編譯的源代碼的集合就是本設(shè)計所需要的源代碼的有效集,可以通過configure.h和make文件中的后綴名為.o文件來進行查找,編譯.c代碼時生成的目標(biāo)文件其后綴名為.o的文件,因為任何一個被編譯的.c文件都能生成.o文件,所以可以利用查找后綴名為.o文件的方法來判斷配置參數(shù)下有哪些文件被編譯,哪些沒有被編譯,最后便可以得出本設(shè)計所需要的已編譯的源文件的最小集合。
開源代碼目前能夠跨平臺編譯運行,但是由于手機的CPU處理能力、能源、內(nèi)存等各方面的限制資源都與PC機存在很大的不同,因此,本設(shè)計針對客戶端手機的特性來對代碼進行優(yōu)化,具體有以下幾點:
1)去除冗余代碼以及調(diào)試過程中的打印語句,減少if-else的判斷及不必要的代碼冗余,對局部和全局變量進行調(diào)整,對程序結(jié)構(gòu)進行規(guī)范,使用寄存器變量代替局部變量。
2)由于邏輯移位指令的執(zhí)行時間遠(yuǎn)遠(yuǎn)小于乘除運算指令,因此乘除操作可以用邏輯移位運算來代替,特別是除法指令,被代替后能夠縮短指令運行的時間。
3)在編寫代碼過程中,盡量避免多重循環(huán)函數(shù)的調(diào)用以及盡量降低上下次循環(huán)的相關(guān)性,這樣做可大大減少沒必要的計算量。
4)設(shè)置合理的緩存,設(shè)置適合解碼算法移植的目標(biāo)平臺Android平臺的緩存大小。
本層針對本地文件的預(yù)處理可以依賴于解碼算法解封裝功能,但是對流媒體文件的預(yù)處理需要將一個或多個RTP數(shù)據(jù)包整合在一起,其中傳輸階段主要任務(wù)是為解碼模塊提供RTP數(shù)據(jù)包[5]。
RTP實現(xiàn)流程如圖4所示。
圖4 RTP實現(xiàn)流程
1)函數(shù)RTP_Create(context*the_context)用于完成RTP會話的初始化和為其上下分配內(nèi)存,函數(shù)先調(diào)用ITP Context_Create(the_context),然后再調(diào)用RTP_Session_Save_Cxinfo(*the_context,conx_cc),從而完成 RTP 會話初始化后上下文信息的創(chuàng)建和保存。
2)創(chuàng)建RTP結(jié)構(gòu),此部分由函數(shù)Create_Socket()完成,先調(diào)用 sockfd=socket(AF_INET,SOCK_DGRAM,0)來創(chuàng)建套接字,若創(chuàng)建成功,則可調(diào)用bind(sockfd,(struct sockaddr*)&local,sizeof(local)綁定套接字。
3)獲取且保存本地IP地址,隨機產(chǎn)生同步源標(biāo)志、創(chuàng)建新的同步源和設(shè)置規(guī)范名。關(guān)鍵代碼如下:
4)判斷會話是否結(jié)束。若是,結(jié)束網(wǎng)絡(luò)數(shù)據(jù)接收線程;若不是,進入步驟5)。
5)接收RTP包,該部分由函數(shù)RTP_Receive(context cid,int fd,char*payload,int*len,struct sockaddr*sin)完成。
6)更新新包號的順序,設(shè)置序列號和信息時間標(biāo)簽。
7)將步驟5)中接收到的RTP數(shù)據(jù)包加入視頻幀緩沖區(qū)中,為解碼使用做準(zhǔn)備。
8)回到步驟4)繼續(xù)執(zhí)行。
該層完成主要功能是與流媒體服務(wù)器端協(xié)商媒體信息細(xì)節(jié),并根據(jù)協(xié)商結(jié)果從服務(wù)器端獲取流媒體數(shù)據(jù),將流媒體數(shù)據(jù)存入緩沖區(qū),按照本設(shè)計緩沖方案將數(shù)據(jù)包發(fā)送給數(shù)據(jù)預(yù)處理層,其結(jié)構(gòu)圖如圖5所示。
圖5 數(shù)據(jù)獲取模塊結(jié)構(gòu)圖
該層一共啟動5個線程,其中1個線程中啟動TCP連接,用于RTSP會話協(xié)商并且在RTP數(shù)據(jù)傳輸期間,該TCP連接必須一直保留。2個線程分別為接收音頻和視頻RTP數(shù)據(jù)的線程,另外2個線程分別為接收以及發(fā)送音頻和視頻的RTCP數(shù)據(jù)包[6]。
首先在PC機進行模擬測試,即在Android編譯環(huán)境eclipse中將程序運行,通過模擬器測試成功。然后將程序移植到具備Android操作系統(tǒng)的手機里,利用WiFi無線網(wǎng)絡(luò)連接服務(wù)器并且通過了權(quán)限訪問,測試結(jié)果驗證了此視頻客戶端軟件在功能上滿足設(shè)計的基本需求。其效果如圖6所示。
本文實現(xiàn)了客戶端基于Android平臺的遠(yuǎn)程視頻實時監(jiān)視功能,能夠播放本地及流媒體視頻文件。遠(yuǎn)程視頻實時監(jiān)視系統(tǒng)整體采用分層的設(shè)計理念,本文分析了各層的結(jié)構(gòu)特點和關(guān)鍵技術(shù),并對解碼層的源代碼進行了修剪和優(yōu)化。通過對各層的設(shè)計,還實現(xiàn)了訪問權(quán)限的設(shè)置、播放、暫停等功能。本文移植的程序代碼目前能夠穩(wěn)定的在手機上運行。該設(shè)計具有一定的通用性和開放性,可以被應(yīng)用到其他的客戶終端,對Android開發(fā)人員有一定的借鑒意義。
[1]Code Home.Android-An Open Handset Alliance Project[EB/OL].[2011-04-15].http://code.Google.com/android/what is android.Html.
[2]趙亮,張維.基于Android技術(shù)的界面設(shè)計與研究[J].電腦知識與技術(shù),2009,29(5):8183-8185.
[3]陳瑕,陳平華,李文亮.Android內(nèi)核分析[J].現(xiàn)代計算機,2009(11):112-115.
[4]余志龍.Google Android SDK開發(fā)范例大全[M].北京:人民郵電出版社,2009.
[5]魏聰穎.基于實時流媒體傳輸系統(tǒng)的H.264組包算法研究[J].計算機科學(xué),2007(34):41-44.
[6]西剎子.安防天下——智能網(wǎng)絡(luò)視頻監(jiān)控技術(shù)詳解與實踐[M].北京:清華大學(xué)出版社,2010:3-10.