張 斌
(中國(guó)兵器工業(yè)第五八研究所軍品部 四川 綿陽(yáng) 621000)
?
基于Android4.2系統(tǒng)的H.264視頻數(shù)據(jù)的獲取
張 斌
(中國(guó)兵器工業(yè)第五八研究所軍品部 四川 綿陽(yáng) 621000)
針對(duì)目前Android系統(tǒng)下利用MediaRecorder和LocalSocket類從MPEG4文件數(shù)據(jù)中獲得H.264原始數(shù)據(jù)存在的問(wèn)題:需要手工填寫SPS、PPS幀數(shù)據(jù)和沒(méi)有NAL同步頭造成數(shù)據(jù)讀取不可靠,提出新的H.264原始數(shù)據(jù)的獲得方法。利用Android系統(tǒng)MediaRecorder類自身的數(shù)據(jù)輸出格式(DEFAULT)作為參數(shù),在HAL層StagefrightRecorder類的處理方式中,構(gòu)建H264Writer類,實(shí)現(xiàn)H.264原始數(shù)據(jù)的獲得或文件存儲(chǔ)。同時(shí)兼容MPEG4的所有處理方式,并提高獲取數(shù)據(jù)的效率和穩(wěn)定性。該方案豐富了Android系統(tǒng)對(duì)視頻數(shù)據(jù)的處理方法。
H.264 MPEG4 SPS PPS HAL RTSP
Andriod系統(tǒng)本身不支持H.264視頻原始?jí)嚎s數(shù)據(jù)(即符合H.264壓縮標(biāo)準(zhǔn),具有NAL同步頭的視頻流數(shù)據(jù))的實(shí)時(shí)獲取。通過(guò)研究文獻(xiàn)表明,解決方法主要有2種:1)利用MediaCodec[1]類對(duì)攝像頭數(shù)據(jù)進(jìn)行壓縮獲得H.264數(shù)據(jù);2)利用MediaRecorder[2]類、setOutputFile()函數(shù)可以接收文件描述符作為參數(shù)的特點(diǎn),用LocalSocket類的文件描述符從MPEG4文件流中獲得H.264視頻流數(shù)據(jù),實(shí)現(xiàn)視頻數(shù)據(jù)存儲(chǔ)或傳輸。經(jīng)過(guò)實(shí)際測(cè)試發(fā)現(xiàn),方法1)存在的缺點(diǎn)是需要從攝像頭獲得AD數(shù)據(jù),不停地傳輸給MediaCodec編碼,對(duì)壓縮后的數(shù)據(jù)進(jìn)行打包傳輸時(shí),節(jié)奏控制不好容易卡頓。方法2)有兩個(gè)缺點(diǎn):(1) 在MPEG4文件流中,H.264[3]壓縮數(shù)據(jù)拋棄了同步頭NAL(Hex Data:00,00,00,01),轉(zhuǎn)而依靠4字節(jié)的幀數(shù)據(jù)長(zhǎng)度來(lái)獲得一幀數(shù)據(jù)。當(dāng)讀寫錯(cuò)誤造成數(shù)據(jù)指針出錯(cuò),不能獲得有效的數(shù)據(jù)長(zhǎng)度錯(cuò)誤,編程人員并不能進(jìn)行有效的判斷,從而造成解碼端不能正確解碼或數(shù)據(jù)丟幀,影響視頻實(shí)時(shí)播放效果。(2)視頻流數(shù)據(jù)是MPEG4文件流中獲取的, H.264視頻流SPS和PPS幀不能直接確定,當(dāng)視頻流的分辨率等相關(guān)信息改變后,需要人工填寫通過(guò)協(xié)議傳送到解碼端,這樣不是很靈活。因此,通過(guò)分析Android 4.2.2的源代碼和MediaRecorder類的框架體系[4],在HAL[5]層上解決了該問(wèn)題,并實(shí)現(xiàn)了H.264視頻流數(shù)據(jù)獲取、傳輸或者數(shù)據(jù)文件保存。兼容MPEG4等視頻格式的所有處理方式,提高了獲取數(shù)據(jù)的效率和穩(wěn)定性,同時(shí)也豐富了Android系統(tǒng)對(duì)視頻數(shù)據(jù)的處理方法。
本文Android版本為4.2.2,硬件平臺(tái)為OMAP4660開(kāi)發(fā)板PandaBoardES1。OMAP4460包含兩個(gè)Cortex-A9核,頻率達(dá)到1.5 GHz,同時(shí)集成了兩個(gè)Cortex-M3核,還包括圖像、視頻加速子系統(tǒng)IVA-HD3和PowerVR SGX540圖形核心,相比于OMAP4430,大幅提升了其圖形性能,1080p視頻播放性能提升一倍,達(dá)到了PC 式 Web 瀏覽。OMAP4460支持HDMI 1.4接口3D高清視頻輸出,支持1080p/60FPS高清解碼,支持最高1 200萬(wàn)像素雙攝像頭,支持全高清1080P/30FPS 多標(biāo)準(zhǔn)視頻編碼/解碼。另外,OMAP4460還支持SmartReflexTM2 技術(shù),根據(jù)設(shè)備活動(dòng)、操作模式和溫度來(lái)動(dòng)態(tài)控制電壓、頻率和功率,進(jìn)一步降低功耗。
Android的MediaRecorder類是用來(lái)實(shí)現(xiàn)Audio和video的記錄功能,Android系統(tǒng)自帶的Music和Video APK就是調(diào)用MediaRecorder類開(kāi)發(fā)實(shí)現(xiàn)的。 MediaRecorder在底層基于OpenCore(PVMF)庫(kù)實(shí)現(xiàn)的,在上層利用進(jìn)程間通信等內(nèi)容(這種進(jìn)程間通信的基礎(chǔ)是Android基本庫(kù)中的Binder機(jī)制[6])構(gòu)建一個(gè)MediaRecorder程序。
MediaRecorder類從上到下的類調(diào)用順序如下:
MediaRecorder.java
+- android_media_MediaRecorder.cpp
+- MediaRecorder.cpp
+- MediaPlayerService.cpp
+- MediaRecorderClient.cpp
+- StagefrightRecorder.cpp
+- MPEG4Writer.cpp,AACWriter.cpp等
針對(duì)Android系統(tǒng)與硬件有關(guān)的代碼處理都集中在HAL層的特點(diǎn),利用系統(tǒng)視頻壓縮格式缺省的文件輸出格式3GPP(default)作為參數(shù)傳遞,即在MediaRecorder類調(diào)用時(shí),設(shè)置視頻文件的輸出格式為MediaRecorder.OutputFormat.DEFAULT。然后在StagefrightRecorder類中對(duì)缺省編碼方式實(shí)現(xiàn)特殊處理,并且參照MPEG4Writer類實(shí)現(xiàn)了自定義的H264Writer類,從而實(shí)現(xiàn)了H.264原始數(shù)據(jù)的文件存儲(chǔ)和數(shù)據(jù)傳輸功能。
本文在StagefrightRecorder類的構(gòu)造函數(shù)中調(diào)用reset函數(shù)進(jìn)行了初始化設(shè)置。該類默認(rèn)的文件OutputFormat為3GPP,AudioEncoder為AMR NB,VideoEncoder為H.264。圖1為MediaRecorder流程及StagefrightRecorder類支持輸出的文件格式。

圖1 MediaRecorder流程及Stagefright Recorder支持輸出的文件格式
在StartMPEG4Recording的處理中創(chuàng)建MPEG4Writer,用于寫數(shù)據(jù),設(shè)置setupAudioEncoder和setupVideoEncoder,把a(bǔ)udio track和video track放入到track。
本文將default選項(xiàng)提取出來(lái),進(jìn)行單獨(dú)的處理,如圖2所示,圖中虛線部分即為添加處理部分。

圖2 Stagefright Recorder增加default處理后框圖
該類源代碼所在目錄路徑為:
./frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp。
代碼修改如下:
1) 添加頭文件
#include
2) 修改setOutputFormat()函數(shù)
屏蔽對(duì)OUTPUT_FORMAT_DEFAULT的處理,直接將參數(shù)of賦值給mOutputFormat;
3) 修改start函數(shù)
屏蔽系統(tǒng)對(duì)OUTPUT_FORMAT_DEFAULT的默認(rèn)處理,添加單獨(dú)處理代碼:
case OUTPUT_FORMAT_DEFAULT:
startH264Recording();
break;
4) 仿照setupMPEG4Recording()函數(shù),創(chuàng)建setupH264Recording()函數(shù),將new MPEG4Writer(outputFd)替換為new H264Writer(outputFd);
5) 仿照startMPEG4Recording()函數(shù),創(chuàng)建startH264Recording()函數(shù)。
MPEG4Writer類主要實(shí)現(xiàn)將H.264壓縮編碼獲得的H.264視頻流數(shù)據(jù),以MPEG4文件格式為存儲(chǔ)方式進(jìn)行一系列處理,如填寫MPEG4文件[7]頭塊ftpy、壓縮視頻數(shù)據(jù)存放等。MPEG4 Writer封裝好的視頻格式如圖3所示。

圖3 MPEG4視頻文件存儲(chǔ)格式
在該封裝格式中,首先填寫fypy塊,然后填寫mdat。H.264視頻流數(shù)據(jù)就存放在mdat塊中,其中將NAL(00,00,00,01)頭以4個(gè)字節(jié)一幀數(shù)據(jù)的長(zhǎng)度替換,逐幀存儲(chǔ)。當(dāng)結(jié)束錄像(文件保存)后,再回填moov等box數(shù)據(jù),該數(shù)據(jù)塊包含該段視頻總幀數(shù)和時(shí)長(zhǎng)等相關(guān)數(shù)據(jù)信息。
H264Writer類主要為獲取H.264壓縮視頻流數(shù)據(jù),直接存儲(chǔ)到Java層傳遞來(lái)的文件描述符的句柄中。因此MPEG4Writer類里面的填寫fypy塊,回填moov等box塊數(shù)據(jù)的處理方式都屏蔽了。
1) 仿照MPEG4Writer.cpp,MPEG4Writer.h生成相應(yīng)的H264Writer.cpp、H264Writer.h,并且將頭文件拷貝到相應(yīng)的include目錄。
2) 修改start()函數(shù),屏蔽寫FtypBox的過(guò)程,屏蔽代碼從writeFtypBox(param)開(kāi)始到status_t err = startWriterThread()之前結(jié)束。
3) 修改reset()函數(shù),該函數(shù)主要實(shí)現(xiàn)moov等各種box塊的填寫,屏蔽代碼從if (mUse32BitOffset)開(kāi)始到CHECK(mBoxes.empty())之前結(jié)束。
4) 修改Track::threadEntry()函數(shù):
① 屏蔽if(buffer->meta_data()->findInt32 (kKeyIsCodecConfig, &isCodecConfig)的整個(gè)處理過(guò)程;
② 屏蔽代碼從mOwner->trackProgressStatus (mTrackId, -1, err)開(kāi)始到sendTrackSummary (hasMultipleTracks)結(jié)束。
5) 修改addLengthPrefixedSample()函數(shù),將代碼:
uint8_t x=length >> 24;
::write(mFd, &x, 1);
x=(length >> 16) & 0xff;
::write(mFd, &x, 1);
x=(length >> 8) & 0xff;
::write(mFd, &x, 1);
x=length & 0xff;
::write(mFd, &x, 1);
修改為:
uint8_t x = 0x00;
::write(mFd, &x, 1);
::write(mFd, &x, 1);
::write(mFd, &x, 1);
x=0x01;
::write(mFd, &x, 1);
6) 修改MPEG4Writer.cpp文件所在目錄的Android.mk文件,添加H264Writer.cpp。
為了檢驗(yàn)以上的驅(qū)動(dòng)開(kāi)發(fā)是否可行、可靠,筆者編寫了APK測(cè)試程序,利用Media Recorder類進(jìn)行視頻流媒體數(shù)據(jù)采集[8],同時(shí)移植了live555服務(wù)器程序,以RTSP[9-11]傳輸?shù)姆绞?,在兩個(gè)Android設(shè)備之間實(shí)現(xiàn)了實(shí)時(shí)視頻傳輸實(shí)現(xiàn),整個(gè)程序的流程如圖4、圖5所示。

圖4 測(cè)試APK系統(tǒng)框架圖

圖5 H.264視頻流數(shù)據(jù)存儲(chǔ)或RTSP傳輸播放流程圖
通過(guò)以上方法,本文實(shí)現(xiàn)了H.264原始數(shù)據(jù)的文件存儲(chǔ),而且在移植了live555服務(wù)器源代碼后,利用管道文件的方式,實(shí)現(xiàn)了手機(jī)端作為RTSP服務(wù)器的功能,從而在其他設(shè)備上實(shí)現(xiàn)了實(shí)時(shí)視頻流播放功能,并且穩(wěn)定、可靠。同時(shí)也擴(kuò)展了Android系統(tǒng)對(duì)視頻數(shù)據(jù)處理的方式,唯一不足是視頻延時(shí)較大,接近500 ms。如何解決時(shí)延問(wèn)題,不在本文討論范圍內(nèi)。
[1] 李宗辰. 基于Android的多路視頻監(jiān)控用戶平臺(tái)的研究與實(shí)現(xiàn)[D]. 南京:南京郵電大學(xué),2014.
[2] liujikunljk. android流媒體之硬編碼代碼篇[EB/OL].(2012-10-30)[2016-05-20]. http://www.apkbus.com/blog-86476-43829.html.
[3] 畢厚杰. 新一代視頻壓縮編碼標(biāo)準(zhǔn)—H.264/AVC[M]. 北京: 人民郵電出版社, 2004:162-163.
[4] 李俊. Android系統(tǒng)源代碼分析[M]. 北京: 中國(guó)鐵道出版社, 2015:157-183.
[5] 陳強(qiáng). Android底層接口與驅(qū)動(dòng)開(kāi)發(fā)技術(shù)詳解[M]. 北京: 中國(guó)鐵道出版社, 2012:143-166.
[6] 林學(xué)森. 深入理解Android內(nèi)核設(shè)計(jì)思想[M]. 北京: 人民郵電出版社, 2014: 676.
[7] Iain Richardson. H.264和MPEG-4視頻壓縮[M]. 歐陽(yáng)合,譯. 長(zhǎng)沙: 國(guó)防科技大學(xué)出版社, 2004:252-254.
[8] 巢文涵. Android多媒體開(kāi)發(fā)高級(jí)編程[M]. 北京: 清華大學(xué)出版社, 2012:143-159.
[9] 李洋. 網(wǎng)絡(luò)協(xié)議本質(zhì)論[M]. 北京: 電子工業(yè)出版社, 2011:332-338.
[10] 謝希仁. 計(jì)算機(jī)網(wǎng)絡(luò)[M]. 6版. 北京: 電子工業(yè)出版社, 2013:331-340.
[11] 陳強(qiáng). 精通Android 實(shí)例開(kāi)發(fā)[M]. 北京: 人民郵電出版社, 2015:522-527.
THE VIDEO DATA OF H.264 ENCODED OBTAIN BASED ON ANDROID 4.2 SYSTEM
Zhang Bin
(DepartmentofMilitaryProducts,No. 58ResearchInstituteofChinaOrdnanceIndustries,Mianyang621000,Sichuan,China)
For the current Android system, the MediaRecorder Class and LocalSocket Class are used to obtain the data of H.264 Encoded data from the MPEG4 file, but the method has the problem that the SPS should be filled manually and the data reading is unreliable since the PPS frame data is not synchronized with the NAL. Thus, the new data obtaining method is proposed. In the article, the self-DEFAULT is used as parameter in the MediaRecorder in Android system, then, the H264Writer class is constructed in the dealing method of the StagefrightRecorder in HAL layer, realizing the achievement and the save of the files of H.264. Meanwhile, the method handling the data of MPEG4 are compatible and improves the efficiency and stability of the data acquisition. The technique enriches a way to handle the video data for Android.
H.264 MPEG4 SPS PPS HAL RTSP
2016-09-18。兵器裝備集團(tuán)公司基金項(xiàng)目(EJ13-8028,EJ11-8014)。張斌,高工,主研領(lǐng)域:嵌入式Linux,Android系統(tǒng)開(kāi)發(fā)。
TP391.41
A
10.3969/j.issn.1000-386x.2017.07.022