Android Media Framework(三)OpenMAX API閱讀與分析

青山渺渺發表於2024-06-07

這篇文章我們將聚焦Control API的功能與用法,為實現OMX Core、Component打下堅實的基礎。

1、OMX_Core.h

OMX Core在OpenMAX IL架構中的位置位於IL Client與實際的OMX元件之間,OMX Core提供了兩組API給IL Client使用,一組API用於管理OMX元件,另一組API用於操作/使用建立的OMX元件。

1.1

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void);
  • OMX_Init:OMX_Init用來初始化OMX Core,在第一次使用OMX元件前它需要先被呼叫,並且只被呼叫一次;初始化可能包含以下幾個步驟:
    • 分配並初始化使用OMX元件所需的記憶體和資源;
    • 掃描系統中的所有可用OXM元件,並將它們載入到OMX Core中;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void);
  • OMX_Deinit:與OMX_Init功能相反,它用作於解除安裝OMX_Init載入的資源;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
    OMX_OUT OMX_STRING cComponentName,
    OMX_IN  OMX_U32 nNameLength,
    OMX_IN  OMX_U32 nIndex);
  • OMX_ComponentNameEnum:用於列舉OMX Core中可用的所有元件,該API包含三個引數,第一個引數cComponentName用於返回找到的元件名稱(輸出引數),第二個引數是字串的長度(輸入引數),第三個引數是遍歷OMX Core元件列表的索引,透過遞增索引並反覆呼叫這個函式,就可以列舉出OMX Core中所有的元件名稱,該API有兩個作用:
    • 當需要檢視 OMX Core 中有哪些可用的元件時,可以使用這個函式來獲取所有元件的名稱;
    • 當需要透過名稱來查詢特定的元件時,可以使用這個函式來對所有元件進行遍歷,直到找到與給定名稱匹配的元件;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
    OMX_OUT OMX_HANDLETYPE* pHandle,
    OMX_IN  OMX_STRING cComponentName,
    OMX_IN  OMX_PTR pAppData,
    OMX_IN  OMX_CALLBACKTYPE* pCallBacks);
  • OMX_GetHandle:用於建立一個OMX元件,返回的控制代碼就是我們前面學過的OMX_COMPONENTTYPE,該函式需要傳遞四個引數:
    • OMX_HANDLETYPE* pHandle:這是一個二級指標void**,用於接收建立的OMX_COMPONENTTYPE指標;
    • OMX_STRING cComponentName:元件名稱,根據該名稱建立對應的元件;
    • OMX_PTR pAppData:呼叫者(Application/IL Client)的指標;
    • OMX_CALLBACKTYPE* pCallBacks:給OMX_COMPONENTTYPE註冊的回撥函式,用於回傳訊息;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
    OMX_IN  OMX_HANDLETYPE hComponent);
  • OMX_FreeHandle:銷燬建立的OMX元件,傳入引數為OMX_HANDLETYPE hComponent
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
    OMX_IN  OMX_HANDLETYPE hOutput,
    OMX_IN  OMX_U32 nPortOutput,
    OMX_IN  OMX_HANDLETYPE hInput,
    OMX_IN  OMX_U32 nPortInput);

OMX_API OMX_ERRORTYPE   OMX_GetContentPipe(
    OMX_OUT OMX_HANDLETYPE *hPipe,
    OMX_IN OMX_STRING szURI);

這兩個API Android中沒有用到,暫不瞭解。

OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
    OMX_IN      OMX_STRING role,
    OMX_INOUT   OMX_U32 *pNumComps,
    OMX_INOUT   OMX_U8  **compNames);
  • OMX_GetComponentsOfRole:用於獲取在給定role(角色)下可以使用的所有OMX元件的列表,包含三個引數:
    • OMX_STRING role:Role是用來描述OMX元件功能的字串,每個OMX元件都擁有一個或多個角色,需要用role去指定OMX元件執行什麼任務,role的名字規律"video_decoder.avc"、"audio_encoder.aac",第一個欄位表示音訊/影片,下劃線後表示編碼/解碼,字尾表示具體的編解碼型別;
    • OMX_U32 *pNumComps:輸出引數,返回role對應的元件的數量;
    • OMX_U8 **compNames:輸出引數,返回role對應的所有元件的名稱
OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
    OMX_IN      OMX_STRING compName,
    OMX_INOUT   OMX_U32 *pNumRoles,
    OMX_OUT     OMX_U8 **roles);
  • OMX_GetRolesOfComponent:獲取一個元件名對應的所有的Role,功能和OMX_GetComponentsOfRole類似;

根據OMX_Init和OMX_ComponentNameEnum等API中的描述,我們大致可以猜到,OMX Core中需要維護一個列表(map),列表中的內容是一組一組的Role和Component Name。

1.2

在OpenMAX IL框架設計中,IL Client不能直接訪問OMX元件的函式,它需要呼叫OMX Core提供的宏來間接操作OMX元件。要注意的是,OMX Core沒有為OMX元件的所有函式都提供宏,換言之有些OMX元件函式不是給IL Client使用的。

首先來看定義的宏:

#define OMX_SendCommand(                                    \
         hComponent,                                        \
         Cmd,                                               \
         nParam,                                            \
         pCmdData)                                          \
     ((OMX_COMPONENTTYPE*)(hComponent))->SendCommand(       \
         hComponent,                                        \
         Cmd,                                               \
         nParam,                                            \
         pCmdData)

OMX_SendCommand用於傳送控制命令到元件,可用命令參考上文的列舉,該方法是非阻塞的,命令執行完成後需要傳送callback通知IL Client。包含有四個引數:

  • hComponent:元件控制代碼;
  • Cmd:要傳送的命令型別;
  • nParam:int型別的命令引數;
  • pCmdData:無法使用int表示的命令引數;
#define OMX_GetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)                       \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetParameter(       \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)

OMX_GetParameter用於從元件獲取引數設定,該方法為阻塞呼叫:

  • nParamIndex:引數索引,用來指定獲取什麼引數;
  • pComponentParameterStructure:指標,用於裝載獲取到的引數;
#define OMX_SetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)                       \
    ((OMX_COMPONENTTYPE*)(hComponent))->SetParameter(       \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)

OMX_SetParameter用於給元件設定引數,該方法為阻塞呼叫,引數功能與OMX_GetParameter類似。

#define OMX_GetConfig(                                      \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)                          \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetConfig(          \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)

#define OMX_SetConfig(                                      \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)                          \
    ((OMX_COMPONENTTYPE*)(hComponent))->SetConfig(          \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)

OMX_GetConfig和OMX_SetConfig分別用於從元件獲取配置、給元件設定配置,元件載入完成後可以
隨時呼叫這兩個方法,都是阻塞呼叫。不同於OMX_SetParameter設定的是元件的靜態引數值,SetConfig設定的是執行時可更改的配置資訊,例如影片的播放速度、音訊的音量、影片的亮度等。

#define OMX_GetExtensionIndex(                              \
        hComponent,                                         \
        cParameterName,                                     \
        pIndexType)                                         \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetExtensionIndex(  \
        hComponent,                                         \
        cParameterName,                                     \
        pIndexType)

OMX_GetExtensionIndex用於將OMX IL或廠商定義的擴充套件字串轉換為相應的結構體索引,該方法是阻塞的。許多音訊和影片處理硬體具有特定的特性和特性,這些在OpenMAX IL標準中並未明確定義,為了使這些功能可以被利用,硬體廠商會提供特定的擴充套件;當應用程式需要訪問這些特定的擴充套件功能時,就需要使用OMX_GetExtensionIndex來獲取相關擴充套件的索引,然後使用這個索引去訪問或者操作這些特定的擴充套件功能。

#define OMX_GetState(                                       \
        hComponent,                                         \
        pState)                                             \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetState(           \
        hComponent,                                         \
        pState)

OMX_GetState用於獲取元件的當前狀態。

#define OMX_UseBuffer(                                      \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           nSizeBytes,                                      \
           pBuffer)                                         \
    ((OMX_COMPONENTTYPE*)(hComponent))->UseBuffer(          \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           nSizeBytes,                                      \
           pBuffer)

OMX_UseBuffer用於讓元件使用由IL Client已經分配的buffer,或者使用tunneled元件已經提供的buffer。OMX_UseBuffer的實現應該分配出buffer header,並用引數填充它,最後透過ppBufferHdr返回。該方法是阻塞呼叫的,可以在LoadedToIdle狀態下使用,也可在OMX_StateExecuting、OMX_StateIdle且埠被禁用的情況下使用。

關注公眾號《青山渺渺》 獲取更多音影片開發內容

image

相關文章