MKV是一種新的多媒體封裝格式,支持多種視頻和音頻編碼格式,能夠將多達16路不同格式的音頻和不同語言的字幕流封裝到一個文件中,在高清影片中得到了廣泛的應用,越來越多的視頻和影片采用MKV作為其封裝格式。能否支持MKV封裝格式是高清播放機性能的一個重要指標。本文提出了一種基于SMP8654平臺的MKV播放器設計與實現方案,并針對嵌入式系統和高清媒體的特點做了進一步優化,能夠提供對MKV文件的流暢播放。
1 MKV封裝格式
MKV全稱為Matroska Video,是一種新的多媒體封裝格式。多媒體封裝格式也稱多媒體容器(MulTImedia Container),它不同于H264、MPEG-2、MPEG-4這類編碼格式,它只是為多媒體編碼提供了一個“外殼”,本身不涉及編碼。MKV是由開源組織Matroska Development Team制定的一個標準,總共包括三部分:MKV(Matroska Video)、MKA(Matroska Audio)和MKS(Matroska Subtitles),后兩種格式分別針對音頻和字幕,應用較少。MKV的目的是代替AVI等傳統封裝格式。AVI是Microsoft于1992年推出一種封裝格式。其含義是Audio Video Interactive,就是把視頻和音頻編碼混合在一起儲存。微軟在1996年推出了AVI的改進版本AVl2.0。AVI格式上限制比較多,只能有一個視頻軌道和一個音頻軌道,還可以有一些附加軌道,如文字等。AVI格式不提供任何控制功能。總體而言,AVI為主的傳統封裝格式結構陳舊,只能包含少數幾種音視頻格式,并且不夠開放,可擴展性差。正因為如此,才促成了Matroska這類新的多媒體封裝格式的誕生。
MKV相對于傳統的封裝格式,有如下優點:支持可變比特率(VBR),支持錯誤檢測以及修復軟字幕,支持流式傳輸,強大的開放性和跨平臺兼容性,支持16 路以上的音頻流和字幕流等。Matroska最大的特點是能容納幾乎所有類型的視頻、音頻及字幕流,除H.264以外,也可包括MPEG4、MPEG2、 Ac3、AAC等其他視頻和音頻格式,即使是非常封閉的RealMedia及QuicklTime也被它包括進去了,并將它們的音視頻進行了重新組織來達到更好的效果。
由于MKV封裝格式本身具有眾多優點,隨著互聯網和高清影片的流行,MKV格式得到了廣泛的應用,互聯網上越來越多的高清影片采用MKV格式。然而,MKV是一個由開源組織制定和推廣的標準,缺乏大商業公司的支持,導致MKV文件的播放缺乏一個完整和有效的設計實現。在性能和資源受限的嵌入式平臺上,這個問題尤為嚴重。雖然目前有很多高清播放機都提供了對MKV格式的支持,但是大部分實現方案都存在支持不完善、播放效率比較低的問題,播放高碼率的影片時會出現不流暢、畫面卡頓等問題,影響觀看效果。本文提出了一種基于SMP8654平臺的MKV播放器的設計與實現方案,并針對嵌入式系統的特點做了優化,較好地達到了MKV文件流暢播放的要求。
2 硬件平臺和軟件總體設計
硬件平臺以SMP8654芯片為核心,通過總線與RAM、SATA硬盤、Flash閃存、輸入輸出設備等外設相連。SMP8654是Sigma Design公司推出的多媒體播放SoC解決方案,集成了一個強大的多媒體處理器、強健的內容保障系統、新的DDR2內存控制器、多個片上CPU以及完備的系統外圍設備接口。從媒體播放角度看,smp8654提供了一個完整支持高清晰度視頻解碼的先進解碼引擎,能夠支持對MPEGl、MPEG-2、 MPEG-4、H.264、WMV9、VCl以及AVS等格式的硬件解碼,支持高效能的圖形加速,支持多標準音頻解碼和先進的顯示處理能力。Siena Design公司為方便第三方廠商開發應用,提供了與芯片相關的開發工具包和開發框架。本文的工作也基于這個框架進行二次開發。軟件平臺方面,由于一個完善的播放系統已經相當復雜,不適合直接操縱底層硬件來完成功能,需要操作系統的支持。本項目中操作系統采用uclinux,文件系統采用Romfs。 uclinux是專為嵌入式系統定制的一款Linux,它具有標準Linux操作系統的穩定性、強大網絡功能等主要優點,但是卻不像標準Li-nux那樣復雜,主要針對沒有MMU(內存管理單元)的微控制器。Romfs是一款專門為嵌入式系統設計的文件系統,體積小、可靠性好、讀取速度快,是嵌入式系統常用的文件系統。
媒體文件的播放流程一般包括如下幾個步驟:系統初始化、判斷文件類型、文件解析、設置硬件解碼器和音視頻解碼,其中文件解析和音視頻解碼是關鍵部分。由于 SMP8654集成了完善的音視頻硬件解碼器,解碼工作主要由硬件完成,我們只需將音視頻數據按要求送入相應的解碼緩沖區即可。整體的軟件架構如圖2所示。
3 系統關鍵技術設計和實現
3.1 MKV文件解析
MKV文件解析主要是對MKV格式的各個組成元素進行解析,以獲得必需的音視頻參數和媒體數據。MKV作為一種封裝格式,實際的視頻和音頻數據都被封裝到某一個子模塊中,要想獲得實際的數據,必須首先對文件進行解析,并且文件解析貫穿播放的全過程。能否有效并正確的解析,關系到讀取數據的準確性,進而影響播放的效果。MKV格式采用可變長編碼,能夠減少存儲空間,另一方面,也給解析帶來了新問題。
MKV文件格式建立在EBML(Extensible Binary MetaLanguagel基礎上,EBML是一種類似于XML格式的可擴展二進制元語言,使用可變長度的整數存儲,以節省空間。EBML的基本結構是典型的TLV結構,有三部分組成:
ID標志屬性類型,size為后面data部分的大小,data部分為ID所標識屬性的實際數據,ID和size均為可變長編碼的整數。整數的長度為 length="1"+[number of leADIng zero bits]。前面的零的個數最多為7個,即最多能表示56個比特的整數。文件中不允許出現大于56比特的數。
MKV文件格式的顯著特點是模塊化、結構化存儲。每一個高一級的元素由若干次一級的元素組成,直至最基本的組成元素,每個元素都是一個TLV結構。一個標準的MKV文件有兩部分組成:EBML Header和Segment。EBML Header由EBMLVersion、DocType等子元素組成,包含了文件的版本、文檔類型等相關信息。Segment部分保存了媒體文件的視頻和音頻的實際數據,其data部分又可以分為SeekHead、Tracks、Cluster等若干子元素(表1)。所有元素的處理都可以按照一個統一的流程來進行。我們可以仿照TCP/IP協議分層的思想,對每一層的每個功能都用一個函數來完成,使用更底層的函數完成此項功能,并可被更高層的函數調用。文件解析時,從文件頂層開始,每當上一級的元素解析到有某個子元素時,調用此函數進行次一級的解析,依次直至文件結束,即可完成對文件的解析處理。整個 MKV的解析調用過程如圖3所示。Hea-der Parse和Segment Parse為文件最上層的元素解析函數,Cluster Parse、Tracks_Parse等為次一級組成元素的解析函數。ebml_read_ele-ment_idebml read element length為最底層基本組成元素的解析函數。
3.2 設置硬件解碼器音視頻核心參數
Tracks用來描述文件中包含的每一路多媒體流的信息。一路多媒體流用一個TrackEntry描述,所有的track都要在一個Tracks中進行描述。一個TrackEntry主要包含:TrackNumber(判定屬于哪一路流的ID)、TrackType(video、audio或者 subTItle)、TimeScale(時間戳單位)、CodecID(編碼格式);CodecPrivate(不同的編碼格式所需的私有數據)等;對于視頻,還包含以下信息:PixelWidth、PixelHeight等。對于音頻,track還包含以下信息:channels、Sampling Frequency等。這些是關于音視頻能否正確解碼播放的關鍵參數,需要在解析時獲得,然后通過硬件操縱函數設置。
Cluster包含實際的數據,一個Cluster塊,通常是幾秒鐘時間跨度的媒體數據,一個文件有數以千計的Cluster。每個Cluster又有若干個BlockGroup。根據Cluster和BlockGroup的起始pts和持續時間,可以計算出當前Block的實際pts。PTS是用來確定播放時間的重要數據,也是音視頻同步的關鍵信息。這部分信息要在送入視頻或音頻數據的同時設置硬件解碼器。
3.3 性能優化
MKV封裝的影片通常為高清影片,分辨率在1920×1080,即使采用H.264等先進編碼格式,碼率依然非常高。同時,MKV支持可變碼率,可變碼率能夠減少文件的體積,但是劇烈波動的碼率會使播放不能流暢進行。在高清文件中碼率一般在10~30M/ps之間,最高可達60Mp/ s,如此高的碼率,如果不做特殊處理,播放時很容易出現卡頓,播放不流暢等問題。為解決這個問題,我們從兩方面考慮。
在解析方面,解析的效率關系到能否盡快將數據讀入緩沖區,如果處理時間過長,造成一段時間內緩沖區為空,這時候就會出現卡頓。 MKV文件中通常包含一路視頻、多路音頻和多路字幕,播放時只選中其中一路音頻和一路字幕,其他路的數據可以被視為無效數據。在解析時,可以根據 Block頭的標記判斷出這路數據是當前播放需要的有效數據還是無效數據。如果是有效數據,則繼續解析,并將音視頻數據送入緩沖區,如果是無效數據,不進行解析,直接移動文件指針到下一個Block,這樣可大大加快文件解析和數據讀取速度。
在播放方面,通常播放時的處理流程是讀取一幀數據,然后送入硬件解碼器,等到收到硬件解碼器為空的信號,再讀取下一幀的數據。如果是處理低碼率文件的播放,這樣做不會有問題,但是當文件分辨率比較高,碼率比較高時,解析讀取時問和解碼時間都會增加,這樣做就會造成卡頓。為解決這個問題,我們在內存中設計了一個緩沖FIFO,相當于一個滑動窗口(圖4),緩沖區可以存放若干個幀(一幀就是一個Block,根據幀的大小緩沖區存放的個數不等)。當緩沖區未滿時,讀取文件中的一個Block并解析,然后將實際數據到緩沖區的隊尾。當發現硬件緩沖區空閑時,將FIFO隊首的數據從內存直接送入硬件緩沖區,不需要再去讀取文件。由于緩沖區中有多個幀,能夠提供一定的緩沖,這樣在碼率波動時就仍然能夠及時提供數據,避免出現硬件緩沖區為空造成的卡頓,播放不流暢等問題。
4 結語
本文詳細介紹了MKV封裝格式的特點。并基于SMP8654提出了一種MKV播放器的設計與實現方案,經驗證,能夠達到對高清MKV文件的流暢播放,并已經實際應用到產品上。接下來將做進一步研究,在MKV播放器的基礎上,設計一種針對多種封裝格式的通用媒體播放器框架,將FLV、FLAC等其他格式也融合進來,并提供較好的可擴展性,方便后續擴充其他的封裝格式。
評論
查看更多