1 OpenMAX IL介紹與其體系
這一部分的文檔描述 OpenMAX IL的特性與體系。
1.1 OpenMAX IL 簡述
OpenMAX IL 軟件接口層定義了一套API,用於訪問系統中的組件。OpenMAX IL軟件層的目的:可以對系統中的組件採用不同的初始化值和不同的命令集合;同時還能提供一套統一的命令集合和方法來構建和銷燬組件。
1.1.1 體系概覽
考慮一個系統要實現四個多媒體處理功能模塊,分別標記爲 F1, F2, F3, 和F4。這四個功能模塊中的任何一個都可能由不同的廠商或者同一個組織的不同部門所開發。每一個功能模塊的構建和銷燬都可能有不同的要求。同時,每一個模塊的配置和數據傳輸都有不同的方式。 OpenMAX IL API可以將這些功能模塊封裝成一個組件,既可以每個模塊一個組件或者在邏輯上相關的模塊組成一個組件。OpenMAX IL API提供一套標準的協議,可以讓來自不同的廠商或者組織的組件互相交換數據,同時組件本身也可被另一個組件替換。
與OpenMAX IL API通信的實體稱之爲IL client, 一般是多媒體框架或者應用層。IL client可以使用 OpenMAX core來加載和卸載組件,在兩個組件之間建立通信機制和訪問組件的功能函數。
IL client通過IL core和組件之間進行通信。大多數情況下,IL client通過調用IL core所定義的宏來與組件通信,這些宏展開之後就直接調用一個組件的函數。例外情況是,IL client直接調用IL core的函數來加載和銷燬組件,建立和撤銷組件之間的隧道化連接。
組件代表着多媒體處理的一個單元或者多個單元的集合。儘管這份規範清晰的定義了OpenMAX core的功能,但是具體的功能還是由各個組件提供者負責實現。根據組件輸出的參數數據類型的不同,把組件操作的數據類型分爲四種:audio 數據,video數據 ,image數據,和其他數據(比如時間或者同步數據)。
通過組件句柄可以訪問一個 OpenMAX 組件所提供的一系列標準方法。這些方法允許client取得和設置組件以及組件中port的配置參數,取得和設置組件的狀態,給組件發送命令,接收時間通知,分配buffer,和組件的一個port建立通信,以及在兩個組件port之間建立通信。
一個OpenMAX組件必須至少有一個port,以滿足 OpenMAX 的一致性標準。儘管廠商可能提供一個與OpenMax兼容的,不含有任何port的組件,但是大量的一致性測試都是基於組件含有至少一個port。 OpenMAX所定義的四種類型的port對應於port可能傳輸的四種數據類型;audio port,video port,image port和其他port。根據port是消費buffer還是生產buffer,可以把一個port分爲input類型和output類型。
在一個包含F1,F2,F3,F4四個多媒體處理功能模塊的系統中,系統實現者可能會爲每一個功能模塊提供一個標準的OpenMax 組件,也可以簡單的採取任何組合而提供一個組件。組件中的單獨功能模塊的區分就依賴於組件中的port。
圖1-1展現了一些OpenMAX組件的實現方式:
圖1-1 OpenMax組件的部分可能實現
1.1.2 關鍵詞彙
本節講述用於描述OpenMAX IL API的常用縮略語和定義。
1.1.2.1 縮寫
表1-1列出了描述 OpenMAX IL API的常用縮寫:
縮寫詞彙 |
含義 |
IPC |
處理器間的通信 |
OMX |
OpenMAX中的函數和數據結構的前綴。比如一個組件可能處於 OMX_StateExecuting的狀態 |
表1-1 縮寫詞彙
1.1.2.2 關鍵定義
表1-2 列出了用於描述OpenMax API的關鍵定義:
關鍵詞彙 |
含義 |
Accelerated component |
某一部分功能運行在加速器上的組件。加速組件有自己的特性,比如支持多種類型的隧道化 |
Accelerator |
用於加快某些功能處理速度的硬件 |
AMR |
adaptive multimedia retrieval的縮寫,3GGP consortium中的一種adaptive multi-rate編碼器 |
Host processor |
多核心繫統中用於控制多媒體加速的處理器 |
IL client |
調用OpenMax core或者組件方法的軟件層 |
Main memory |
host processor和accelerator所使用的外部內存 |
OpenMAX component |
包裝有目標系統所要求的功能的組件 |
OpenMAX core |
與特定平臺相關代碼,用於定位和加載組件到主存中,同時core也負責從主存中卸載組件,當應用層指明這個組件不再需要的時候 |
Resource manager |
管理硬件資源的軟件單元 |
RTP |
real-time protocol的簡稱,網絡標準協議用於傳輸實時數據,包括音頻和視頻 |
Synchronization |
同步機制 |
Tunnels/Tunneling |
建立和使用一種標準的數據通道,這個數據通道直接被兩個組件所管理。 |
表1-2 關鍵詞彙定義
1.1.3 系統組件
圖1-2描述了OpenMAX所支持的多種類型的交流機制。每一個組件可以有任意數目的port用於數據交換。只有一個output port的組件稱爲source component;只有一個input port的組件稱爲sink component;組件所有的功能運行在host processor上的稱爲host component;運行在accelerator上的組件稱之爲 accelerator component。OpenMAX既可以直接和應用層交流,也可以整合到多媒體框架中去。
接下來描述三種通信機制。Non-tunneled communication 定義了在IL client和組件之間交換數據buffer的通信機制;Tunneling 定義了組件之間直接進行數據buffer交換的標準機制;Proprietary communication描述了兩個組件之間直接進行數據交流的機制,
1.1.3.1 Component Profile
OpenMax的組件按照功能分爲兩類:base profile 和 interop profile。
base profile的組件應該要支持non-tunneled的通信機制。base profile可能支持proprietary communication機制。base profile組件不支持tunneled communication。
interop profile是base profile的超集。一個interop profile組件應該要支持non-tunneled和tunneled communication機制,可能支持proprietary communication機制
interop profile 和base profile最主要的不同點是前者支持tunneled communication機制。base profile的存在主要是爲了簡化OpenMax實現者的工作。
1.1.4 組件的狀態
如圖1-3 所示,一個組件可能要經歷一系列的狀態變化。假設每一個組件的初始狀態是unloaded。應用層通過調用OpenMax core的函數來加載組件。與組件之間的直接交流可以使組件變爲其他的狀態。
當狀態變化的時候使用了無效的數據,組件可能會進入到 invalid state。當IL cilent檢測到組件處於invalid state的時候,應該對組件進行如下動作:stop, de-initialize, unload, reload。
圖1-2描述了從任何狀態都可以變遷爲invalid state,但是要想退出 invalid state只有通過unload和reload組件。
圖1-3 組件狀態
當組件狀態進入 IDLE state的時候可能會失敗,因爲在IDLE state下,必須爲組件分配好所有的資源。當從LOADED到IDLE轉換失敗的時候,IL client可能會重試一次,或者將組件的狀態變遷爲WAIT FOR RESOURCES 。當組件進入WAIT FOR RESOURCES狀態,它便向廠商指定的資源管理單元註冊,一旦資源變爲可用的時候,組件就會收到通知。資源管理單元隨後將組件的狀態變更爲IDLE state。IL client向組件發送的命令控制着除INVALID state以外的其他狀態的變化。
IDLE state狀態表明組件已經擁有了所有它需要的資源,但是還沒有開始處理數據。EXECUTING state表明組件準確接收buffer去處理數據,並且會調用對應的callback。當組件處於PAUSED state 狀態的時候,組件保持着處理buffer數據的環境,但是沒有處理數據或者交換buffer。從PAUSED狀態變化爲EXECUTING狀態將使組件從上次暫停的地方開始處理buffer數據。從EXECUTING或者PAUSED狀態變化爲IDLE狀態,將會導致丟失buffer處理的環境,這就意味着數據流的處理開始點需要重新指定。從IDLE變化爲LOADED將會導致失去可操作的資源,比如通信buffer。
1.1.4 組件體系結構
圖1-4描述了組件的體系結構。組件的入口點只有一個(通過組件的具體來訪問一組標準函數),但是組件可能有多個向外的調用,這取決於組件有多少個port。每一個組件也會通過event handler來調用IL client的函數。每一個port也會發起對外部函數的調用。每一個port都有一個與之關聯的指向buffer header的指針隊列。命令函數所發送的命令也在組件內部對應一個命令隊列。所有的參數和配置調用,都有一個特有的index和與之關聯的數據結構。
圖 1-4 OpenMAX IL API組件體系結構
一個port必須支持callback調用到IL client,如果是支持interop profile 的組件,同時還要支持與其他組件的port之間的交流。
1.1.6 通信行爲
一旦從 OpenMAX core接收到了組件的句柄,就可以完成組件的配置工作。一旦組件的port配置完畢,每個port指定了其數據格式,並且組件進入合適的狀態,就可以與組件進行數據通信調用了,這種調用是非阻塞的。數據通信特定於組件的一個port。IL client通過 OMX_EmptyThisBuffer函數來與Input port進行通信。IL client通過OMX_FillThisBuffer函數來與output port進行通信。在相同的上下文實現中,OMX_EmptyBufferDone或者 OMX_FillBufferDone callback將會在IL client 調用函數返回之前被調用。圖1-5顯示了相同上下文和不同上下文兩種情況下對上述過程的不同實現。注意,IL client不要臆斷組件的callback/return的時序。
圖 1-5不同的上下文與相同上下文中不同的操作
和組件的數據通信一般直接發生在組件指定的port。每一個port都有一個它應該分配或者使用的組件自定義的最小的buffer數目。一個port將一個buffer header與一個buffer關聯。一個buffer header有成員指向了buffer中的數據,並且提供與buffer中內容相關聯的元數據。每一個組件port都應該有能力分配它自己的buffer,或者使用預先分配的buffer。
1.1.7 Tunneled Buffer的分配和共享
這節描述tunneling component buffer的分配和buffer共享。對於一個tunnel,一個port提供buffer,它稱爲supplier port,然後把這些buffer傳遞給另一個port,這個port稱爲non-supplier port。在最簡單的情況下,supplier 負責分配buffer,然而,複雜點的情況下, tunneling component可以選擇複用另外一個組件port的buffer,以避免內存的拷貝和優化內存的使用。這種情況下稱之爲buffer分享。
任何兩個port之間的一個tunnel,代表這兩個port之間的依賴關係。buffer分享機制,擴展了這種依賴,以便所有分享同一buffer集的port可以形成一條隱式的依賴鏈。準確的說,這條依賴鏈上的一個port分配buffer,其他的port共享這些buffer。
buffer共享在一個組件內實現,然後把這種共享關係傳遞到另外一個組件。一個non-supplier port不會知道supplier 組件的提供的buffer是自己分配的還是複用的此組件其他port上的buffer。更進一步說,supplier組件也不知道是否non-supplier組件會複用它所提供的buffer。
嚴格來說,一個組件僅有義務服從它所需的外部語義,並且可以實現這些語義背後的buffer共享。更具體的,外部語義要求一個組件做以下事情:
• 在它的所有supplier port上提供buffer。
• 準確的傳達port 上 buffer的要求。
• 使用OMX_EmptyThisBuffer調用將一個buffer從output port傳遞到input port
• 使用OMX_FillThisBuffer函數調用將一個buffer從input port返回到output buffer。
如果一個組件選擇共享buffer,那麼它可能需要執行以下操作來滿足這些要求:
• 在supplier port上提供複用的buffer。
• 當在port上傳達buffer的要求時,準確的記下需要分享buffer 的port的數目
• 在內部使用OMX_EmptyThisBuffer函數調用將一個buffer從一個input port傳遞到output port,對應的會有一個 OMX_EmptyBufferDone 回調。
1.1.7.1 相關條款
這一節描述在tunneled buffer分配和共享中用到的相關條款。圖1-6展示了總的概念圖:
圖1-6 buffer分配和共享關係的例子
一對tunneling port,主動發起UseBuffer調用的是supplier port。一個 buffer supplier port 並不一定要分配buffer,它可能複用同一個組件內其他port的buffer。圖1-6中 port a,c是 supplier port。接收相鄰port 的UseBuffer函數調用的port,稱之爲 non-supplier port。圖中b,d是 non-supplier port。
一個port的tunneling port是與之相鄰的,共享同一條tunnel的port。port b是port a的tunnelping port。同樣的,port a也是port b的tunneling port。
一個allocator port 是一個自己分配buffer的 supplier port。圖中只有port a是allocator port。
同一個組件中複用其他port的buffer的稱之爲 sharing port 。port c是一個sharing port。
至少使用了一條tunnel的組件稱之爲tunneling component。
一個port的 buffer requirement包括需要的buffer的數目和每一個buffer的size。一個port通過在它的 tunneled port上調用 OMX_GetParameter,可以獲得一個 OMX_PORTDEFINITIONTYPE數據結構,這個數據結構表示了buffer的requirement。注意一個port也可以從共享它buffer的port獲得buffer requirement而不用調用OMX_GetParameter,因爲這兩個port可以位於同一個組件內。
1.1.7.2 IL Client Component Setup
爲了構建一個tunneling component,IL client 需要遵循以下步驟:
1.加載所有tunneling component,並且在這些組件之間建立tunnel;
2.給所有的組件發送命令,以便組件的狀態從loaded state 變爲idle state;
如果IL client不按照上述步驟執行,組件可能由於彼此之間的依賴關係而導致永遠都不會進入到idle 狀態。
1.1.7.3 共享buffer組件從Loaded轉變爲Idle State
在 OMX_SetupTunnel被調用的時候,將會確認一條tunnel的兩個port中哪一個(input或者output)是buffer supplier。因此當一個組件接收命令從loaded轉換爲idle的時候,它應該清楚的知道它所有的組件的角色:supplier或者 non-supplier 。
當接收命令從loaded轉換爲idle,組件按順序執行以下操作:
1.組件確定採取拿一種方式實現buffer共享,遵循以下規則:
a) 組件可以複用buffer採取如下兩種方式:複用一個input的buffer到一個或者多個output port上;或者複用一個output的buffer到一個input上。
b) 只有 supplier port纔可以複用另一個port的buffer。
c) 當一個組件中有多個output port分享buffer的時候,port的buffer屬性爲只讀。
如圖1-7 所示:
圖1-7 允許的buffer分享關係
2.組件確定supplier port,以及哪些supplier port是allocator port。只有當一個supplier port不復用同一個組件的non-supplier port的buffer的時候,它就是 allocator port。圖1-8中,箭頭背向的port是supplier port,箭頭指向的port爲non-supplier port。一個port指出來的箭頭表示共享關係。帶有盒子的port代表 allocator port。
3.一個組件按照以下操作給它的每一個allocator port分配buffer:
a) allocator port確定 buffer requirement 根據每一個複用buffer的port。參見下面的A
b) allocator port通過調用OMX_GetParameter來確認每一個tunneled port的buffer requirement。參見條款B
c) allocator port根據自己的buffer requirement,tunneled port的buffer requirement,以及sharing port的buffer requirement來確定應該分配buffer的最大數目。
d) allocator port告知與之tunneling的non-supplier port的實際buffer數目。通過調用 OMX_SetParameter函數,參數OMX_IndexParamPortDefinition,以此來設置nBufferCountActual的合適參數。見條款E
e) allocator port 和每一個與之關聯的sharing port共享它的buffer。見條款D
f) 每一個已經分配的buffer,allocator port都要調用OMX_UseBuffer來傳遞buffer到tunneling port。見條款C
一個組件應該滿足以下條款:
A. 確定一個sharing port的requirement的時候,它應該首先在它的tunneled port上調用OMX_GetParameter查詢requirement,然後返回它自己的requirements和查詢所得的requirements的最大值。
B. 當 non-supplier port 接收 OMX_GetParameter調用,查詢它的buffer requirements的時候,non-supplier port應該首先查詢所有複用它的buffer的port的requirements,然後返回自己的requirements和查詢到的requirements中的最大值。
C. 當一個 non-supplier port接收到它的tunneled port所發起的OMX_UseBuffer調用時,non-supplier port 應該給和自己所在組件的複用它buffer的port共享這個buffer。
D. 在同一個組件上,A和B共享一塊buffer,當B複用這塊buffer的時候,它應該首先調用 OMX_UseBuffer,把這塊buffer傳遞給它的 tunneled port。
E. 當一個non-supplier port接收到來自它的tunneled port發起的針對OMX_IndexParamPortDefinition 的OMX_SetParameter 調用時,它應該把參數nBufferCountActual傳遞給任何複用它buffer的port。同樣的,每一個 supplier port通過這種方式接收到 nBufferCountActual的時候,應該通過執行OMX_SetParameter (OMX_IndexParamPortDefinition)調用把 nBufferCount傳遞給它的 tunneled port。通過這種方式,依賴鏈中實際使用的buffer的數目得以傳遞下去。
當所有enable的port都得到了他們所需要的buffer的時候,組件可以從loaded狀態變爲idle狀態
1.1.7.4 使用共享內存的協議
當一個input port通過 OMX_EmptyThisBuffer接收一個共享buffer的時候,這個input port可能和一個output port通過以下機制共享這塊buffer:
• 在input port 調用 OMX_EmptyBufferDone 作爲對它的tunneling port的回覆之前,output port在它的tunneling port上調用 OMX_EmptyThisBuffer。
• input port直到所有和它共享buffer的output已經分享了這塊buffer之後才調用 OMX_EmptyBufferDone
1.1.7.5 不共享buffer組件從Loaded轉變爲Idle狀態
如果組件不共享內存,比起共享組件的實現,將會減少很多步驟和所遵循的條款。非共享內存組件從loaded轉變爲idle,按照以下步驟:
1.確定buffer共享實現的方式。在這種case下,不用進行這一步。
2.確定哪一些supplier port是 allocator port。全部都是。
3.按照如下步驟爲每一個 allocator port分配內存:
a. 因爲沒有共享內存,所以不用詢問sharing port對buffer的要求;
b. allocator port 通過調用OMX_GetParameter來取得tunneled port對buffer的要求;
c. 根據allocator和與之關聯的tunneling port的buffer requirement的最大值,來分配內存;
d. 因爲沒有內存共享,所以不用向sharing port傳遞buffer.
e. 對每一塊分配的內存,allocator port 在tunneling port上調用 OMX_UseBuffer。
1.1.8 port重連
port重連允許一個tunneled 組件被另一個tunneled組件替換,而不用破環其他的組件。在圖1-10,組件B1被組件B2替換。爲了達到這點,組件A的output port和組件B的input port首先要通過port 禁止命令設置爲不可用。一旦分配的buffer被返回給它們的擁有者並被釋放,組件A的output port就可以連接到組件B2。接下來組件B1的output port和組件C的input port也要採取類似的方式禁用。當所有的分配的buffer都返回給它們的擁有者然後被釋放,組件C的input port可以連接到組件B2的output port。所有的port可以被允許使用通過發送使能命令。
圖1-10 port重連
在某些情況下,比如音頻,當重連一個組件到另一個組件的時候,可能希望新組件的數據採取fade-in的方式,而原始的組件的數據採取fade-out的方式(即淡入淡出)。圖1-11 說明了這是如何做到的。第一步,組件A發送數據到組件B1,組件B1發送數據到組件C;組件A和組件C都有一個額外的port處於禁用狀態。第二步,IL client首先爲A和B2建立tunnel,然後爲B2和C建立tunnel。然後使能兩條tunnel上的所有port。假設組件C是audio組件,那麼C就可以將組件B1和B2的數據採用變化的增益參數進行混合。在第三步,從組件A和C連接B1的port被禁用。
圖1-11 重連組件
圖1-11 重連組件
1.1.9 命令隊列和buffer刷新
組件內獨立的命令隊列可以使組件刷新那些還沒有處理的buffer,把它們歸還給IL client,當採取 non-tunneled通信機制的時候,或者歸還給與之關聯的tunneled port,當採取的是tunneled通信機制。圖1-12 假設組件有一個port使用了IL client分配的buffer。在這個例子中,client發送了5塊buffer給組件,在發送刷新命令之前。當組件處理刷新命令的時候,會按照原始的順序把未處理的buffer返回給client,然後觸發它的 event handler 發送event通知client。在接收到刷新命令之前,已經處理了兩塊buffer。連同爲處理的三塊buffer,組件會按照接收順序,全部返還給client。
圖1-12 刷新buffer
1.1.10 標記Buffer
IL client也可以通過標記buffer觸發產生一個事件。在一個buffer的buffer header中可以標記這塊buffer。在OpenMax的組件鏈中,標記從一個input port傳遞到一個output port。標記允許一個組件發送一個事件給IL client,當這個組件遇到一個標記buffer。圖1-13 解釋了這個過程:
圖1-13 標記buffer
IL client發送一條命令標記一個buffer。組件的output要發送的下一個buffer被標記,圖中爲B1。組件B處理B1的數據,然後把結果填入到B2,同時還帶上標記。當組件C通過它的input port接收到B2,組件不會觸發它的event handler,直到它已經處理完畢這塊buffer。
1.1.11 事件和callback
組件發送給IL client 6種事件:
• 錯誤事件
• 命令處理完成通知事件
• 標記buffer事件
• port設置變化通知事件
• buffer flag 事件,當遇到流的結尾
• 資源請求事件,當組件等待它所需要的資源的時候
1.1.12 Buffer Payload
port的配置定義了port上傳輸的buffer的數據格式,但是配置並沒有說明數據在buffer中是如何存放的。一般來說有三種case來描述一塊buffer如何被數據填充,這三種case都有各自的好處。在三種case中,buffer中有效數據的範圍和起點由buffer header中的pBuffer,nOffset,和nFilledLength三個參數來決定。pBuffer指向buffer中有效數據的起始點。nOffset表示buffer 起始點到有效數據起始點的偏移量。nFilledLength表明有效數據的長度。因此buffer中有效數據位於 pBuffer +nOffset 到 pBuffer + nOffset + nFilledLength的範圍內。下面的case,描述了在解碼或者編碼中,buffer中的壓縮數據流進或者流出一個組件。在所有的case下,buffer只是爲數據的傳遞提供了一種機制,而對buffer中的內容沒有特殊的要求。對於數據的要求定義在port的配置中。buffer中的陰影部分表示數據,空白部分表示沒有數據。case 1:buffer被部分或者全部填充。在這種case下,buffer中含有壓縮數據幀,使用f1到fn來標記。
case 1爲播放解碼數據提供了便利。一個buffer可以含有多個幀,減少了爲了達到解碼所要求的數據量而導致的buffer傳遞的次數。然後,這種情況下,需要decoder自己去buffer中解析幀數據。同時組件需要有一個幀buffer,這個buffer中存放解析數據或者存放一部分的幀數據,因爲完整的幀數據可能存在於下一個buffer中。
case 2 每一個buffer中填充的是完整的幀。
case 2和case 1不同,因爲case 1可能只含有一幀的部分數據。共同點都是需要解碼器從buffer中分析出一塊幀數據。
case 3 每一塊buffer都只含有一幀完整的數據。
case 3的好處是不需要解碼器解析幀數據了,解析幀數據的工作放在了 source component。但是每次只能傳輸一幀數據也可能會對性能造成很大的衝擊。
作爲基本的要求,解碼器或者編碼器都應該支持case 1.
1.1.13 Buffer Flags和時間戳
Buffer flags 表示着buffer數據中的某些屬性。時間戳描述着buffer中的數據在顯示時候的時間信息。一旦一個buffer的時間戳被 clock component組件所確定,任何的組件都不能爲了速率控制或者同步而修改這個值。
Buffer中的元數據(即標誌和時間戳),適用於buffer中的第一個新的邏輯單元。因此,對於一個buffer中含有多個邏輯單元,buffer的元數據適用於buffer起始邊界以後的邏輯單元。除非另有說明,否則當一個組件接收到標記了flag或者時間戳的邏輯輸入單元,它應該將這些元數據複製到邏輯輸出單元中去。
1.1.14 同步
通過clock component的同步port可以到達同步的目的。clock component和它的port被劃分在 其他組件中。clock component內部含有一個根據audio或者video的參考時鐘來記錄流媒體播放位置的多媒體時鐘。clock component可以通過同步port傳輸帶有時間信息的buffer到client 組件。client組件可能給某個操作打上時間戳(例如一個視頻幀的呈現),通過請求clock component發送時間戳信息,來匹配媒體時鐘。圖1-14 展示了這一過程:
1.1.15 速率控制
clock component通過提供一系列的配置來改變媒體時鐘,以此實現所有的速率控制。IL client可以通過改變媒體時鐘的比例係數(有效的改變媒體時鐘變化的方向和速度),來實現播放,快進,暫停,後退,以及慢放。IL client也可以通過這些配置來啓動或者暫停媒體時鐘,以此來改變媒體時鐘的狀態。clock component通過在同步port上發送帶有新的比例係數和媒體時鐘狀態的媒體時鐘變化通知,來告知所有的client組件,媒體時鐘的比例係數和狀態發生了變化。儘管一個組件可能並不會以改變buffer的時間戳來應對媒體時鐘比例係數的變化,但是它可能改變它相應的處理。
1.1.16 組件註冊
靜態鏈接或者動態加載。
1.1.17 資源管理
這一節描述OpenMax IL 中用於資源管理的API。
1.1.17.1 資源管理的必要
當一個組件因爲缺少資源而不允許變遷爲idle狀態時,IL client沒有必要知道缺少的資源,也沒有必要知道是哪一個組件在使用這些資源。
OpenMAX的一個目標是通過提供IL 層,是IL 層以上的軟件層與硬件無關。通過指定下面這些關於資源管理的條款,以使OpenMax達到與硬件無關。
• 一個IL client沒有必要知道IL 實現的細節或者IL 組件在使用哪一種資源
• 如果發生資源衝突,IL client能夠依賴組件的一致行爲而不用管IL的實現和具體的硬件平臺
• 一個IL client不應該和硬件廠商的資源管理器直接交互,有以下兩個原因:
• 和硬件無關原則相違反
• 和硬件資源管理器的具體工作大多數都是由IL client來處理,這會影響IL client在多種多媒體平臺上的表現
雖然資源管理在 OpenMAX IL API 1.0版本中解決,但是作爲資源管理的“鉤子”已經以行爲準則,組件的優先級,資源管理相關的組件狀態而落實。這些鉤子將會使在以後的版本中全面解決資源管理奠定基礎。
在繼續之前,資源管理和政策的定義會使下面的討論收益:
• Resource management負責組件訪問有限的資源。一個資源管理者要知道,當前有多少具體的資源可用,當前使用資源的組件,當前的組件使用了多少資源。一個資源管理器應該制定策略,當資源發生衝突的時候,哪一個組件可以優先使用。
• Policy 負責管理組件鏈。根據 resource managemen提供的信息,或者系統配置,或者應用層的請求,或者其他的因素,策略管理者應該能夠決定哪一個組件鏈可以運行或者恢復運行。
1.1.17.2 體系假設
下面有兩種關於 OpenMAX IL層的體系假設:
假設1:在應用層和 OpenMAX IL之間存在一個framework層,包含有策略管理者。
假設2:一個系統可能有多個硬件平臺供OpenMAX 組件使用,這些硬件平臺由硬件廠商指定的資源管理者管理。
1.1.17.3 組件優先級
每一個組件有一個由IL client設置的優先級(OMX_U32整形)。具體的優先級的範圍可以留給平臺去實現,但是優先級的目的是很重要的,並且能夠在不同的IL 實現上表現一致。組件的優先級按照數值從高到低越來越重要,0表示最高優先級。當兩個組件擁有相同的優先級,最近被擁有過資源的組件被認爲具有較高的優先級。
1.1.17.4 行爲規範
在IL 層定義瞭如下行爲規範:
• 只有當一個組件進入idle狀態沒有足夠的資源或者一個組件不能釋放佔用的資源,將會產生OMX_ErrorInsufficientResources錯誤。
• 當組件進入idle狀態的時候,它並不知道已經有人搶佔了資源,或者低優先級的組件需要釋放資源。
• 一個組件已經佔據了的資源被搶佔,當它從Executing或者Paused進入Idle的時候,要發送OMX_ErrorResourcesPreempted 給IL client,或者當它從Idle進入Loaded的時候,要發送 OMX_ErrorResourcesLost給IL client。
• 如果IL client想知道什麼時候與組件相關的流可以啓動或者恢復,它就應該請求得到一個通知,當組件的資源變爲可用的時候。當把組件的狀態置爲OMX_StateWaitForResources state,當資源可用,client就會收到通知。
1.1.17.5 硬件廠商相關的資源管理
爲了實現上述規範,需要一個位於IL層之下與硬件廠商相關的資源管理者執行下面的功能:
• 實現管理等待隊列
• 記錄可利用的資源
• 記錄使用資源的組件,以及他們使用的是什麼資源
• 當一個高優先級的組件需要資源的時候通知一個或者多個組件釋放他們所佔用的資源