OpenMAX Introduction
1、OpenMAX Introduction
OpenMAX 是由Khronos組織所訂定的跨平台多媒體介面標準,其目的是為了降低日益增加的多媒體格式複雜度,使得多媒體應用程式開發人員可以直接使用軟體或特殊硬體進行編碼、解碼的加速或優化,而對外保持統一的接口,使得編碼解碼更為便利。
OpenMAX在該標準訂定了三層介面,如圖figure 1所示:
Figure 1
(1) Application Layer:
AL層提供應用程式和多媒體的溝通介面,使得應用程式可以透過AL層提供的API直接對多媒體格式進行Playback、Recording以及其他多媒體影音的基本操作。
(2) Integration Layer:
IL層提供了多媒體格式codec的存取介面,使OpenMAX IL 的任何client可以直接使用IL層所提供的codec。在IL層中各種codec的implementation被視為一個component,而component則負責將各種多媒體格式的資料串流讀入並且將編碼、解碼之後的資料輸出。
而在Android OpenCORE裡也實作了IL層,另外在Linux上的Bellagio也是一個實現IL層的OpenSource 軟體。
(3) Development Layer:
DL層提供了許多多媒體格式codec所需使用的函數集合,並且將codec分成五種領域,分別是Audio Coding、Signal Processing、Video Coding、Image Processing、Image Coding,而每種領域又分成幾個子領域,如圖figure 2、figure 3所示。晶片廠商可以依照DL層的標準對處理器進行優化和實現,而codec廠商也能依據DL層標準提供的函式來設計codec,使得codec的集成在各種平台更為容易。
而OpenMAX三層可分別獨立實作也可以將三層實現成為一體,figure 4描述了一個多媒體應用程式對OpenMAX各層的使用與否進行多媒體的處理,如有顏色部分即為應用程式遵循OpenMAX 標準而開發。
Figure 4
2、Implementation of OpenMAX in OpenCORE
在OpenCORE底下的OpenMAX則是一個純軟體編碼、解碼多媒體格式的實現,並且以IL層為主,其目錄在Android/external/opencore/codec_v2,所以接下來討論IL層中的Codec Component和IL Client之間的溝通,而這裡的IL Client則是OpenCORE Framework。
在IL層的API主要分成兩類:一種為Core API另一種為Component API。
Core API:目的為載入或卸載Component以及處理Component之間的溝通。主要對Core的函式呼叫method有:
(1) OMX_Init()
(2) OMX_Deinit
(3) OMX_GetHandle
(4) OMX_FreeHandle
(5) OMX_ComponentNameEnum
(6) OMX_GetComponentsOfRole
(7) OMX_GetRolesOfComponent
(8) OMX_SetupTunnel
(9) OMX_GetContentPipe
Component API:目的為處理各種多媒體格式,其角色可以是source(資料來源端)、sink(資料接收端)、或者可以直接是codec的實現,在OpenCORE裡的Component則是與Codec直接溝通的橋梁,其Component功用主要為將需要被編碼、解碼的Buffer讀入並且傳遞給Codec編碼、解碼,最後再將編碼、解碼完成後的Buffer回傳給IL Client。而Component之間是依靠Port來進行溝通,溝通的方式分為:
(1) Non-Tunneled: Component之間的溝通必須經過IL Client才能傳遞到另一方
(2)Tunneled: Component彼此之間建立通道直接溝通,不需經過IL Client
figure 5為OpenMAX Component之間溝通示意圖。
Figure 5
2-1 OpenCORE and OpenMAX Core/Component Interaction
在OpenCORE中的OpenMAX Component會歷經一系列的狀態並且會依據其狀態的改變而呼叫對應的函式,Component的State Diagram如figure 6。
Figure 6
Component狀態的改變都是經由IL Client透過OMX_SendCommand()來執行,而Component在每個State所代表的意義如figure 7所示。
Figure 7
2-1-1.OMX_StateLoaded
OpenMAX IL Core的實現一開始由OMX_Init()進行初始化,這的步驟主要是向系統要求所有Component清單並且對每個Component進行註冊。
之後則使用OMX_GetHandle()將目前所需要的Component載入,而由於OMX_GetHandle()是依照Component和其對應的role的名字來載入,所以必須確保名字的唯一性。
接著執行所需要的Component Construct()、Component Init()設定參數如Sample Rate、Channels和進一步設定有關此格式所需要的Port參數等等的配置並且取得該Component的Handle以便之後進行操作,於此完成初始化的步驟。
OpenMAX Core、Component初始化完成後,此時Component就進入LOADED狀態,接者呼叫OMX_GetParameter()、OMX_SetParameter()來對Component的Input/Output Port的Buffer相關參數做設定,如Set Buffer Size、Buffer Number、minimum/actual number of buffer。
2-1-2.OMX_StateIdle
IL Client呼叫OMX_UseBuffer() or OMX_AllocateBuffer()對Input/Output Ports進行Buffer個數和大小的配置,配置的數量以及大小會根據先前設置在Input/Output Ports的Buffer Number、Buffer Size來配置,之後IL Client才將State改變為Idle,若Resource不足則進入WaitResource狀態等待Resource。
Component在Idle狀態下意味著Component已經配置好所需的Resource,隨時可以被使用來進行多媒體格式的編碼、解碼。
2-1-3.OMX_StateExecuting
當IL Client發出命令將Component State從Idle轉變為Executing,這時Component便會開始傳遞Buffer並且開始對Buffer編碼、解碼。
此時IL Client透過呼叫OMX_FillThisBuffer()函式先將Output Buffer送至Component的Output Port就緒。
接著呼叫OMX_EmptyThisBuffer()將待編碼、解碼的Input Buffer送至Component的Input Port。
之後Component藉著自身Process()函式將Input Buffer送至更底層的Codec,於此才開始真正進行編碼、解碼。而編碼、解碼後將資料寫入Output Buffer。
最後再藉由EmptyBufferDone()、FillBufferDone() 通知IL Client完成Buffer的傳遞,示意圖如figure 8
Figure 8
2-1-4.OMX_StatePause
當IL Client將Component狀態轉變為Pause時,此時IL Client便不再繼續送Input/Output Buffer至Component,而當IL Client將狀態再次改變為Executing時,才繼續送Input/Output Buffer。
而此時正在傳送給Component的Buffer(藉著EmptyThisBuffer())仍然可以繼續送至Component的Input Port。
2-1-6.OMX_StateInvalid
當所有Buffer已經處理完畢,IL Client先將Component狀態從Executing改成Idle。
於此狀態時呼叫OMX_FreeBuffer()將Component的Input/Output Port Buffer釋放,再呼叫Core API的OMX_FreeHandle()將Component Handle釋放。
IL Client將Component改變為Invalid狀態,此時呼叫Component自身的Component Deinit()結束IL Client與此Component間的互動,最後呼叫Core API OMX_DeInit()作De-Initialization。
沒有留言:
張貼留言