Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android4.2.2下Stagefright下OMX編解碼器組件的控制流

Android4.2.2下Stagefright下OMX編解碼器組件的控制流

編輯:關於Android編程

之所以單獨把這塊內容提煉出來,在於其具備的一定的層次性,結構上具備統一性,API函數的設計需要實現OMX架構獨有的接口。

1. 在上一博文Android4.2.2下Stagefright多媒體架構中的A31的OMX插件和Codec組件 中我們提到,通過Binder架構,在MPS的線程上創建完一個實際的編解碼器節點後,獲取到了一個node:node_id。如下所示將會根據相關的節點信息,創建一個MPS側的OMXCodec結構體,作為類似本地的一個編解碼器。

.....        
    sp codec = new OMXCodec(
                    omx, node, quirks, flags,
                    createEncoder, mime, componentName,
                    source, nativeWindow);//創建一個本地OMXCodec解碼器,node成為後續的操作的關鍵IOMX::node_id
//omx為Master
            observer->setCodec(codec);//將解碼器交給observer

            err = codec->configureCodec(meta);//根據數據源配置本地的這個解碼器
........

在configureCodec對這個解碼器的配置中,我們可以看到一些對之前分配的解碼器節點的控制操作。我們以它其中的一個函數調用為例,進行控制流的層層分析:

 setVideoOutputFormat(mMIME, meta);//設置視頻輸出格式
mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def))

這裡看到mOMX是在創建AwesomePlayer時獲取的一個匿名的BpOMX對象。最終的實現在MediaPlayerService中的中的OMX對象來實現getParameter。

2.OMX對象下的操作。

status_t OMX::getParameter(
        node_id node, OMX_INDEXTYPE index,
        void *params, size_t size) {
    return findInstance(node)->getParameter(
            index, params, size);
}

findInstance(node)這裡就是根據這個node_id來獲取之前注冊的一個OMXNodeInstance對象實例:

OMXNodeInstance *OMX::findInstance(node_id node) {
    Mutex::Autolock autoLock(mLock);

    ssize_t index = mNodeIDToInstance.indexOfKey(node);

    return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
}

最終就變成了如下的調用:

status_t OMXNodeInstance::setParameter(
        OMX_INDEXTYPE index, const void *params, size_t size) {
    Mutex::Autolock autoLock(mLock);

    OMX_ERRORTYPE err = OMX_SetParameter(
            mHandle, index, const_cast(params));

    return StatusFromOMXError(err);
}

3.OMX_XXX的實現

#define OMX_GetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        ComponentParameterStructure)                        \
    ((OMX_COMPONENTTYPE*)hComponent)->GetParameter(         \
        hComponent,                                         \
        nParamIndex,                                        \
        ComponentParameterStructure)    /* Macro End */

OMX_SetParameter等宏函數是OMX_CORE的核心所在,也是原來OpenOMx裡的OMX IL層的體現。來看mHandle的類型,作為一個OMXNodeInstance對象的成員變量,他維護著之前makeComponentInstance返回的一個對底層編解碼組件庫的句柄。這裡看上去就是一個OMX節點實例,一個句柄可操作最下層的解碼組件。可以看到handle轉為OMX_COMPONENTTYPE類型。裡看看其的結構體類型:

typedef struct OMX_COMPONENTTYPE
{
    OMX_U32 nSize;

    OMX_VERSIONTYPE nVersion;

    OMX_COMPONENTNAMETYPE eCompName;

    OMX_PTR pComponentPrivate;

    OMX_ERRORTYPE (*GetParameter)(
            OMX_IN  OMX_HANDLETYPE hComponent, 
            OMX_IN  OMX_INDEXTYPE nIndex,
            OMX_IN  OMX_PTR ComponentParameterStructure);...............

這個handle的獲取是在之前創建解碼器節點時完成的,通過需要創建的解碼器的name,通過OMX插件庫,再進入到libOmxCore.so(OMX IL固有結構)調用OMX_GetHandle來獲取對應組件name下的平台解碼庫libOmxVdec.so,或者libOmxVenc.so等。這個handle通過以下完成初始化:

void* aw_omx_create_component_wrapper(OMX_PTR obj_ptr)
{
    aw_omx_component *pThis        = (aw_omx_component *)obj_ptr;//omx_vdec對象
    OMX_COMPONENTTYPE* component   = &(pThis->m_cmp);//對m_cmp進行初始化
    memset(&pThis->m_cmp,0,sizeof(OMX_COMPONENTTYPE));

    component->nSize               = sizeof(OMX_COMPONENTTYPE);
    component->nVersion.nVersion   = OMX_SPEC_VERSION;
    component->pApplicationPrivate = 0;
    component->pComponentPrivate   = obj_ptr;//保存著omx_vdec這個對象

    component->AllocateBuffer      = &aw_omx_component_allocate_buffer;
    component->FreeBuffer          = &aw_omx_component_free_buffer;
    component->GetParameter        = &aw_omx_component_get_parameter;
    component->SetParameter        = &aw_omx_component_set_parameter;
    component->SendCommand         = &aw_omx_component_send_command;
    component->FillThisBuffer      = &aw_omx_component_fill_this_buffer;
    component->EmptyThisBuffer     = &aw_omx_component_empty_this_buffer;
    component->GetState            = &aw_omx_component_get_state;
    component->GetComponentVersion = &aw_omx_component_get_version;
    component->GetConfig           = &aw_omx_component_get_config;
    component->SetConfig           = &aw_omx_component_set_config;
    component->GetExtensionIndex   = &aw_omx_component_get_extension_index;
    component->ComponentTunnelRequest = &aw_omx_component_tunnel_request;
    component->UseBuffer           = &aw_omx_component_use_buffer;
    component->SetCallbacks        = &aw_omx_component_set_callbacks;
    component->UseEGLImage         = &aw_omx_component_use_EGL_image;
    component->ComponentRoleEnum   = &aw_omx_component_role_enum;
    component->ComponentDeInit     = &aw_omx_component_deinit;
    return (void *)component;
}

通過以上的賦值操作,我們關注這個component->pComponentPrivate = obj_ptr,他是將硬件平台的解碼器實例維護到handle結構體中,因為最終的操作肯定都要回到最底層的解碼器控制。這也就是OMX IL的架構給予了開發者的方便性和規劃化。通過這個我們就可以總結出需要以下幾個文件來銜接更底層的編解碼器:

xxx_omx_core.c和omx_core_cmp.c兩個源文件來完成。前者提供向上的接口用於創建編解碼器實例,後者提供例如上述的xxx_omx_component_api接口的實現,而實際其實現是調用的是編解碼的相關API來處理:

OMX_ERRORTYPE aw_omx_component_get_parameter(OMX_IN OMX_HANDLETYPE     hComp,
                                             OMX_IN OMX_INDEXTYPE paramIndex,
                                             OMX_INOUT OMX_PTR     paramData)
{
	OMX_ERRORTYPE eRet = OMX_ErrorBadParameter;
	aw_omx_component *pThis = (hComp)? (aw_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL;
	DEBUG_PRINT("OMXCORE: aw_omx_component_get_parameter %x, %x , %d\n",(unsigned)hComp,(unsigned)paramData,paramIndex);

	if(pThis)
	{
		eRet = pThis->get_parameter(hComp,paramIndex,paramData);
	}

	return eRet;
}

這裡的pThis技術當前最底層的解碼器組件的控制入口。即所謂的aw_omx_component的派生類對象。這樣也就是說明了我們自己要構建的編解碼需要實aw_omx_component的相關接口函數,可以看到這裡我們最底層的解碼器組件就是對這些函數的實現,加快了自定義一個新的組件類型,以下是幾個接口的定義和實現:

OMX_ERRORTYPE  omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp, OMX_IN OMX_INDEXTYPE paramIndex,  OMX_IN OMX_PTR paramData)
OMX_ERRORTYPE  omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
                                       OMX_IN OMX_INDEXTYPE  paramIndex,
                                       OMX_INOUT OMX_PTR     paramData)

到這裡我們基本走通了從OMXCodec到對最底層的編解碼器組件的控制,層次分明,接口規范帶給我們的是快速開發,我們需要做的核心是在自己的編解碼器組件中實現相關的業務,而這和自身的硬件平台具有緊密性。

4.總結新建一個屬於stagefright下OMX的編解碼組件需要做的事情

我們所要做的核心工作就在libOmxCore.so和libOmxVdec.so這兩個庫文件的設計。但都需要符合OMX的協議即可。


分析了那麼多的控制流,也已經有了所謂的OMXCodec,那麼後續主要內容將是數據流的處理。






  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved