摘要:本文簡(jiǎn)要介紹了OpenMax 的集成層,并闡述了其在Android上的實(shí)現(xiàn)和運(yùn)行過程。
關(guān)鍵字:OMX, 多媒體框架, IL, Android, Stagefright
1、OpenMax 集成層介紹
OpenMax是一個(gè)多媒體應(yīng)用程序的框架標(biāo)準(zhǔn)。它自上而下分為三層,Application Layer, Integration Layer和Development Layer。應(yīng)用層規(guī)定了應(yīng)用程序和多媒體中間層的標(biāo)準(zhǔn)接口,使應(yīng)用程序的移植性更好。集成層定義了多媒體組件的接口,使得多媒體框架能以一種統(tǒng)一的方式訪問多媒體Codec和組件,以便在嵌入式流媒體框架中快速集成加速編解碼器。。開發(fā)層為Codec廠商和硬件廠商提供了一套API,使開發(fā)更加便捷。
圖1 OpenMax的分層結(jié)構(gòu)
OMX集成層由Client、Core、Component和Port組成,Client通過Core得到對(duì)應(yīng)Component的Handle,而后通過命令直接和Component進(jìn)行交互。每個(gè)Component至少有一個(gè)Port進(jìn)行數(shù)據(jù)交互,如Decoder有一個(gè)輸入Port接收碼流,一個(gè)輸出Port輸出YUV序列。Component內(nèi)部可能通過消息處理機(jī)制完成Client要求的任務(wù)。
圖2 OMX IL層的組成
在Android中,OpenMax IL層,通??梢杂糜诙嗝襟w引擎的插件,Android2.2的多媒體引擎StageFright都可以使用OpenMax作為插件,主要用于編解碼(Codec)處理。
在Android的框架層,定義了由Android封裝的OpenMax接口,和標(biāo)準(zhǔn)的接口概念基本相同,使用C++類型的接口,并且使用了Android的Binder IPC機(jī)制實(shí)現(xiàn)了函數(shù)遠(yuǎn)程調(diào)用。Android封裝OpenMax的接口被StageFright使用。
解碼Component通過輸入Port和輸出Port來(lái)進(jìn)行交互,可以通過和OMXCodec共享buffer來(lái)進(jìn)行編解碼。
圖3 StageFright的OMX結(jié)構(gòu)
2、OMX相關(guān)的類關(guān)系
StageFright的核心播放器AwesomePlayer中包含了sp<MediaSource>型的mVideoSource指針,初始化時(shí)指向OMXCodec的實(shí)際對(duì)象。OMXCodec使用了Binder機(jī)制,實(shí)現(xiàn)了遠(yuǎn)程函數(shù)調(diào)用,且函數(shù)調(diào)用模式于本地函數(shù)無(wú)異,其中IOMX作為接口類定義了OMX的大部分接口函數(shù)。OMX的具體實(shí)現(xiàn)時(shí),OMXMaster類用于管理OMX的插件,OMXNodeInstance類代表OMX的具體實(shí)例,完成和Component的調(diào)用和交互,內(nèi)部類CallbackDispatcher是一個(gè)主動(dòng)類,它用于調(diào)度處理回調(diào)函數(shù)傳回的消息。OMXNodeInstance和CallbackDispatcher一一對(duì)應(yīng),協(xié)同工作,完成不同實(shí)例的消息處理。
圖4 OMX相關(guān)類關(guān)系圖
OMXNodeInstance類中最重要的幾個(gè)函數(shù)為:
allocateBuffer: Client通過調(diào)用此函數(shù)讓Component分配Buffer。
useBuffer: Client通過此函數(shù)將已分配好的Buffer傳給Component,讓其使用。
freeBuffer: Client通過調(diào)用此函數(shù)讓Component釋放allocateBuffer()分配的Buffer。
fillBuffer: Client通過調(diào)用此函數(shù)傳遞空的Buffer給Component,讓其將處理好的數(shù)據(jù)填入其中。此函數(shù)會(huì)調(diào)用OMX標(biāo)準(zhǔn)接口OMX_FillThisBuffer()。
emptyBuffer: Client通過調(diào)用此函數(shù)傳遞輸入Buffer給Component,讓其讀取其中的數(shù)據(jù)進(jìn)行編解碼等處理。此函數(shù)會(huì)調(diào)用OMX標(biāo)準(zhǔn)接口OMX_ EmptyThisBuffer ()。
OnEmptyBufferDone: Component完成對(duì)輸入buffer的讀取后,調(diào)用此回調(diào)函數(shù),向Client發(fā)送EmptyBufferDone消息。
OnFillBufferDone: Component完成相應(yīng)處理將輸出數(shù)據(jù)填入輸出Buffer后,調(diào)用此回調(diào)函數(shù),向Client發(fā)送FillBufferDone消息。
以Decoder為例,說(shuō)明OMX Codec執(zhí)行解碼的過程,
圖5 OMX Codec解碼序列圖
OMXCodec使用emptyBuffer()函數(shù)(IL層中為OMX_EmptyThisBuffer()傳遞未解碼的buffer給component,component收到該命令后會(huì)讀取input port buffer中的數(shù)據(jù),將其組裝成幀進(jìn)行解碼,讀取buffer中的數(shù)據(jù)完成后會(huì)調(diào)用EmptyBufferDone通知OMXCodec。
Compoment使用EmptyBufferDone消息通知OMXCodec已完成input buffer的讀取, 具體的實(shí)現(xiàn)是通過調(diào)用回調(diào)函數(shù)OnEmptyBufferDone()實(shí)現(xiàn)的。OMXCodec收到該命令后會(huì)通過mVideoTrack讀取新的視頻碼流到input port的buffer中,并調(diào)用OMX_EmptyThisBuffer通知component。
OMXCodec使用OMX_FillThisBuffer傳遞空的bffer給component用于存儲(chǔ)解碼后的幀,Component收到該命令后將解碼好的幀數(shù)據(jù)復(fù)制到該buffer上,然后調(diào)用FillBufferDone通知OMXCodec。
Compoment使用FillBufferDone通知OMXCodec已完成output port buffer的填充,具體的實(shí)現(xiàn)是通過調(diào)用回調(diào)函數(shù)OnFillBufferDone()實(shí)現(xiàn)的。OMXCodec收到該命令后將解碼好的幀存入可顯示隊(duì)列中,AwesomePlayer調(diào)用OMXCodec::read()函數(shù)讀出可顯示隊(duì)列的對(duì)頭送給Renderer完成顏色轉(zhuǎn)換等操作再傳遞給mISurface進(jìn)行圖像繪制,同時(shí)Render調(diào)用release()函數(shù),其中的SignalBufferDone()會(huì)用OMX_FillThisBuffer通知component有空的buffer可填充。
聯(lián)系客服