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

圖1 MediaRecorder流程及Stagefright Recorder支持輸出的文件格式
在StartMPEG4Recording的處理中創建MPEG4Writer,用于寫數據,設置setupAudioEncoder和setupVideoEncoder,把audio track和video track放入到track。
本文將default選項提取出來,進行單獨的處理,如圖2所示,圖中虛線部分即為添加處理部分。

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

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

圖4 測試APK系統框架圖

圖5 H.264視頻流數據存儲或RTSP傳輸播放流程圖
通過以上方法,本文實現了H.264原始數據的文件存儲,而且在移植了live555服務器源代碼后,利用管道文件的方式,實現了手機端作為RTSP服務器的功能,從而在其他設備上實現了實時視頻流播放功能,并且穩定、可靠。同時也擴展了Android系統對視頻數據處理的方式,唯一不足是視頻延時較大,接近500 ms。如何解決時延問題,不在本文討論范圍內。
[1] 李宗辰. 基于Android的多路視頻監控用戶平臺的研究與實現[D]. 南京:南京郵電大學,2014.
[2] liujikunljk. android流媒體之硬編碼代碼篇[EB/OL].(2012-10-30)[2016-05-20]. http://www.apkbus.com/blog-86476-43829.html.
[3] 畢厚杰. 新一代視頻壓縮編碼標準—H.264/AVC[M]. 北京: 人民郵電出版社, 2004:162-163.
[4] 李俊. Android系統源代碼分析[M]. 北京: 中國鐵道出版社, 2015:157-183.
[5] 陳強. Android底層接口與驅動開發技術詳解[M]. 北京: 中國鐵道出版社, 2012:143-166.
[6] 林學森. 深入理解Android內核設計思想[M]. 北京: 人民郵電出版社, 2014: 676.
[7] Iain Richardson. H.264和MPEG-4視頻壓縮[M]. 歐陽合,譯. 長沙: 國防科技大學出版社, 2004:252-254.
[8] 巢文涵. Android多媒體開發高級編程[M]. 北京: 清華大學出版社, 2012:143-159.
[9] 李洋. 網絡協議本質論[M]. 北京: 電子工業出版社, 2011:332-338.
[10] 謝希仁. 計算機網絡[M]. 6版. 北京: 電子工業出版社, 2013:331-340.
[11] 陳強. 精通Android 實例開發[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。兵器裝備集團公司基金項目(EJ13-8028,EJ11-8014)。張斌,高工,主研領域:嵌入式Linux,Android系統開發。
TP391.41
A
10.3969/j.issn.1000-386x.2017.07.022