Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android4.2.2下Stagefright多媒體架構中的A31的OMX插件和Codec組件

Android4.2.2下Stagefright多媒體架構中的A31的OMX插件和Codec組件

編輯:關於Android編程

本文均屬自己閱讀源碼的點滴總結,轉賬請注明出處謝謝。

歡迎和大家交流。qq:1037701636 email: [email protected]

在前面的博文中提到,AwesomePlayer::onPrepareAsyncEvent()開始進行Codec解碼器組件的獲取以及創建,這裡和大家分享。

1.以解碼器實例作為切入點

status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
    ATRACE_CALL();
......
    ALOGV("initVideoDecoder flags=0x%x", flags);
    mVideoSource = OMXCodec::Create(
            mClient.interface(), mVideoTrack->getFormat(),//提取視頻流的格式, mClient:BpOMX
            false, // createEncoder
            mVideoTrack,
            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);//創建一個解碼器mVideoSource

    if (mVideoSource != NULL) {
        int64_t durationUs;
        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
            Mutex::Autolock autoLock(mMiscStateLock);
            if (mDurationUs < 0 || durationUs > mDurationUs) {
                mDurationUs = durationUs;
            }
        }

        status_t err = mVideoSource->start();//啟動解碼器OMXCodec

        if (err != OK) {
            ALOGE("failed to start video source");
            mVideoSource.clear();
            return err;
        }
    }
......
}

這裡不得不先說明以下幾個成員變量的相關內容,方便後續的分析:

a. mClinet:OMXClient(繼承於)類對象。做為AwesomePlayer的成員變量,在這裡能找到他的一些蹤跡。

AwesomePlayer::AwesomePlayer()
    : mQueueStarted(false),
      mUIDValid(false),
      mTimeSource(NULL),
      mVideoRenderingStarted(false),
      mVideoRendererIsPreview(false),
      mAudioPlayer(NULL),
      mDisplayWidth(0),
      mDisplayHeight(0),
      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
      mFlags(0),
      mExtractorFlags(0),
      mVideoBuffer(NULL),
      mDecryptHandle(NULL),
      mLastVideoTimeUs(-1),
      mTextDriver(NULL) {
    CHECK_EQ(mClient.connect(), (status_t)OK);//OMXClient,connect後維護一個mOMX:BpOMX

看到這裡進行了connect的處理,我們來看看其所完成的工作:

status_t OMXClient::connect() {
    sp sm = defaultServiceManager();
    sp binder = sm->getService(String16("media.player"));
    sp service = interface_cast(binder);//獲取MPS服務BpMediaPlayerService

    CHECK(service.get() != NULL);

    mOMX = service->getOMX();//獲取一個omx在本地的接口傳給videosource, BpOMX
    CHECK(mOMX.get() != NULL);

    if (!mOMX->livesLocally(NULL /* node */, getpid())) {
        ALOGI("Using client-side OMX mux.");
        mOMX = new MuxOMX(mOMX);
    }

    return OK;
}

這裡進行線程間的Binder驅動處理。獲取一個OMX組件的接口到mOMX。我們不得不去看MediaPlayService端的getOMX的實現:

sp MediaPlayerService::getOMX() {
    Mutex::Autolock autoLock(mLock);

    if (mOMX.get() == NULL) {
        mOMX = new OMX;//新建一個本地匿名的OMX
    }

    return mOMX;
}

新構建了一個OMX組件類,該類繼承了BnOMX。使得Binder驅動返回後最終創建的是一個BpOMX這麼個匿名驅動。

返回BpOMX後在OMXClient側創建一個MuxOMX類mOMX,其作為OMXClient的成員變量而存在。

分析可知mClient.interace即是connect創建的mOMX組件。

b.

setVideoSource(extractor->getTrack(i));//設置視頻源mVideoTrack ;

setAudioSource(extractor->getTrack(i));//設置音頻源mAudioTrack;

mVideoTrack和mAudioTrack的做為創建的AwesomePlay的成員函數,其類型為MPEG4Source,繼承了MediaSource。

那麼mVideoTrack->getFormat(),是獲取對應視頻信息源的格式。

2.OMXCodec的創建

所有的解碼器無論是軟解還是硬解,都是掛載OMX下面,作為其的一個Component來使用。下面來看一個Codec的創建過程。

sp OMXCodec::Create(
        const sp &omx,
        const sp &meta, bool createEncoder,
        const sp &source,
        const char *matchComponentName,
        uint32_t flags,
        const sp &nativeWindow) {
    int32_t requiresSecureBuffers;
    if (source->getFormat()->findInt32(
                kKeyRequiresSecureBuffers,
                &requiresSecureBuffers)
            && requiresSecureBuffers) {
        flags |= kIgnoreCodecSpecificData;
        flags |= kUseSecureInputBuffers;
    }

    const char *mime;
    bool success = meta->findCString(kKeyMIMEType, &mime);
    CHECK(success);

    Vector matchingCodecs;
    findMatchingCodecs(
            mime, createEncoder, matchComponentName, flags, &matchingCodecs);//尋找可用的解碼器如OMX.allwinner.video.decoder.avc

    if (matchingCodecs.isEmpty()) {
        ALOGV("No matching codecs! (mime: %s, createEncoder: %s, "
                "matchComponentName: %s, flags: 0x%x)",
                mime, createEncoder ? "true" : "false", matchComponentName, flags);
        return NULL;
    }

    sp observer = new OMXCodecObserver;
    IOMX::node_id node = 0;

    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
        const char *componentNameBase = matchingCodecs[i].mName.string();//OMX組件的名字
        uint32_t quirks = matchingCodecs[i].mQuirks;
        const char *componentName = componentNameBase;

        AString tmp;
        if (flags & kUseSecureInputBuffers) {
            tmp = componentNameBase;
            tmp.append(".secure");

            componentName = tmp.c_str();
        }

        if (createEncoder) {//軟解碼器createEncoder = 1;
            sp softwareCodec =
                InstantiateSoftwareEncoder(componentName, source, meta);

            if (softwareCodec != NULL) {
                ALOGV("Successfully allocated software codec '%s'", componentName);

                return softwareCodec;
            }
        }

        ALOGV("Attempting to allocate OMX node '%s'", componentName);

        if (!createEncoder
                && (quirks & kOutputBuffersAreUnreadable)
                && (flags & kClientNeedsFramebuffer)) {
            if (strncmp(componentName, "OMX.SEC.", 8)) {
                // For OMX.SEC.* decoders we can enable a special mode that
                // gives the client access to the framebuffer contents.

                ALOGW("Component '%s' does not give the client access to "
                     "the framebuffer contents. Skipping.",
                     componentName);

                continue;
            }
        }

        status_t err = omx->allocateNode(componentName, observer, &node);//請求mediaplayerservice創建一個節點,真正的解碼器所在
        if (err == OK) {
            ALOGV("Successfully allocated OMX node '%s'", componentName);

            sp codec = new OMXCodec(
                    omx, node, quirks, flags,
                    createEncoder, mime, componentName,
                    source, nativeWindow);//創建一個本地OMXCodec解碼器

            observer->setCodec(codec);//將解碼器交給observer

            err = codec->configureCodec(meta);

            if (err == OK) {
                if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) {
                    codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime;
                }

                return codec;
            }

            ALOGV("Failed to configure codec '%s'", componentName);
        }
    }

    return NULL;
}

2.1 查找平台支持的解碼器

bool success = meta->findCString(kKeyMIMEType, &mime);首先對傳入的視頻源track進行mime的提取。然後是繼續一個解碼器的查找,為當前視頻源的解碼所用:

findMatchingCodecs();//尋找可用的解碼器如OMX.allwinner.video.decoder.avc, 個人認為這是查找到所需要的解碼器的核心所在:

void OMXCodec::findMatchingCodecs(
        const char *mime,
        bool createEncoder, const char *matchComponentName,
        uint32_t flags,
        Vector *matchingCodecs) {
    matchingCodecs->clear();

    const MediaCodecList *list = MediaCodecList::getInstance();
    if (list == NULL) {
        return;
    }

    size_t index = 0;
    for (;;) {
        ssize_t matchIndex =
            list->findCodecByType(mime, createEncoder, index);

        if (matchIndex < 0) {
            break;
        }

        index = matchIndex + 1;

        const char *componentName = list->getCodecName(matchIndex);//獲取解碼器的名字

        // If a specific codec is requested, skip the non-matching ones.
        if (matchComponentName && strcmp(componentName, matchComponentName)) {
            continue;
        }

        // When requesting software-only codecs, only push software codecs
        // When requesting hardware-only codecs, only push hardware codecs
        // When there is request neither for software-only nor for
        // hardware-only codecs, push all codecs
        if (((flags & kSoftwareCodecsOnly) &&   IsSoftwareCodec(componentName)) ||
            ((flags & kHardwareCodecsOnly) &&  !IsSoftwareCodec(componentName)) ||
            (!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {

            ssize_t index = matchingCodecs->add();
            CodecNameAndQuirks *entry = &matchingCodecs->editItemAt(index);
            entry->mName = String8(componentName);
            entry->mQuirks = getComponentQuirks(list, matchIndex);

            ALOGV("matching '%s' quirks 0x%08x",
                  entry->mName.string(), entry->mQuirks);
        }
    }

    if (flags & kPreferSoftwareCodecs) {
        matchingCodecs->sort(CompareSoftwareCodecsFirst);
    }
}

在這裡很熟悉的看到一個單列模式的創建MediaCodecList,一個多媒體解碼器列表的創建。在這裡我們很有必要看一下他的構造過程,因為這裡體現出android4.2.2的編解碼器維護和之前2.3等的不同。也是他更接近移動互聯的表現之一。

2.2 MediaCodecList的構建

const MediaCodecList *MediaCodecList::getInstance() {
    Mutex::Autolock autoLock(sInitMutex);

    if (sCodecList == NULL) {
        sCodecList = new MediaCodecList;
    }

    return sCodecList->initCheck() == OK ? sCodecList : NULL;
}

MediaCodecList::MediaCodecList()//單列模式的創建,解析xml完成當前mCodecInfos的維護,支持的編解碼器
    : mInitCheck(NO_INIT) {
    FILE *file = fopen("/etc/media_codecs.xml", "r");

    if (file == NULL) {
        ALOGW("unable to open media codecs configuration xml file.");
        return;
    }

    parseXMLFile(file);//解析xml文件提取其中支持的codec

    if (mInitCheck == OK) {
        // These are currently still used by the video editing suite.
/*
			
		   

		*/
        addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm");//硬解碼器

        addMediaCodec(
                false /* encoder */, "OMX.google.raw.decoder", "audio/raw");//軟解碼器
    }

#if 0
    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
        const CodecInfo &info = mCodecInfos.itemAt(i);

        AString line = info.mName;
        line.append(" supports ");
        for (size_t j = 0; j < mTypes.size(); ++j) {
            uint32_t value = mTypes.valueAt(j);

            if (info.mTypes & (1ul << value)) {
                line.append(mTypes.keyAt(j));
                line.append(" ");
            }
        }

        ALOGI("%s", line.c_str());
    }
#endif

    fclose(file);
    file = NULL;
}

MediaCodecList的特點在於它對一個/etc/media_codecs.xml進行了解析,很容易看到xml讓人感覺到了互聯網的特色所在。我們來看看在全志A31下的這個配置文件部分內容,顯然放在最前面的是全志自己的軟硬件解碼器:

 
 93     
 94         
 95         
 96         
 97         
 98         
 99 
100         
101         
102         
103         
104         
105         
106         
107         
108 
109     
110 
111     
112         
113 
114         
115         
116         
117         
118         
119         
120     
121 

而這個文件的解析通過parseXMLFile來完成,最終解碼器屬性維護在了mCodecInfos,這其中xml文件的解析過程不是很熟悉,但核心是提取name和type這兩個字段後進行addMediaCodec的操作。
當然,我們也可以通過手動addMediaCodec來完成添加,其中ture代表的是編碼器,反之則為解碼器。

通過以上的手段,最終我們獲取到了硬件平台所支持的所有編解碼器的類型,也就是OMX下的各種Component組件。

2.3

有了這個所謂的編解碼器list,一切的變得更加的輕松,分別經過如下處理:

ssize_t matchIndex = list->findCodecByType(mime, createEncoder, index);
const char *componentName = list->getCodecName(matchIndex);//獲取解碼器的名字

componentName將成為後續的進一步處理的關鍵

3. 創建一個屬於OMX解碼器的Node節點

        status_t err = omx->allocateNode(componentName, observer, &node);//請求mediaplayerservice創建一個節點,真正的解碼器所在

這裡的omx在傳入時已經分析過,變量類型為一個匿名Binder服務類BpOMX.回到在MediaPlayService的BnOMX處,估計核心的創建解碼器等還是要交給MPS來完成的。

status_t OMX::allocateNode(
        const char *name, const sp &observer, node_id *node) {
    Mutex::Autolock autoLock(mLock);

    *node = 0;

    OMXNodeInstance *instance = new OMXNodeInstance(this, observer);//新建一個OMXNodeInstance實例

    OMX_COMPONENTTYPE *handle;
    OMX_ERRORTYPE err = mMaster->makeComponentInstance(
            name, &OMXNodeInstance::kCallbacks,
            instance, &handle);//創建一個組件,並獲取其操作句柄

    if (err != OMX_ErrorNone) {
        ALOGV("FAILED to allocate omx component '%s'", name);

        instance->onGetHandleFailed();

        return UNKNOWN_ERROR;
    }

    *node = makeNodeID(instance);
    mDispatchers.add(*node, new CallbackDispatcher(instance));

    instance->setHandle(*node, handle);

    mLiveNodes.add(observer->asBinder(), instance);
    observer->asBinder()->linkToDeath(this);

    return OK;
}

3.1 新建一個真正的OMXNodeInstance實例

3.2 mMaster->makeComponentInstance()真正獲取一個多下一層解碼器的控制權
這裡要和大家分析mMaster這個變量:

在獲取BpOMX時,在MPS側的getOMX裡實現了new OMX:

OMX::OMX()
    : mMaster(new OMXMaster),//新建一個mMaster
      mNodeCounter(0) {
}

這裡看到MPS中的mOMX成員的子成員mMaster。

OMXMaster::OMXMaster()
    : mVendorLibHandle(NULL) {
    addVendorPlugin();//插入設備廠商的編解碼器插件libstagefrighthw
    addPlugin(new SoftOMXPlugin);
}

看到這裡我會覺得OMXMaster是所有底層編解碼的管理者吧。因此組件的創建等都需要通過他來完成。

4.OMXMaster管理者的角色扮演

void OMXMaster::addVendorPlugin() {
    addPlugin("libstagefrighthw.so");//廠商的硬件編解碼器
}

看到這裡添加了所謂的設備廠商的插件,看到其是添加了一個libstagefrighthw.so庫。我們看看他是如何對這個so文件做處理的:

void OMXMaster::addPlugin(const char *libname) {
    mVendorLibHandle = dlopen(libname, RTLD_NOW);

    if (mVendorLibHandle == NULL) {
        return;
    }

    typedef OMXPluginBase *(*CreateOMXPluginFunc)();
    CreateOMXPluginFunc createOMXPlugin =
        (CreateOMXPluginFunc)dlsym(
                mVendorLibHandle, "createOMXPlugin");
    if (!createOMXPlugin)
        createOMXPlugin = (CreateOMXPluginFunc)dlsym(
                mVendorLibHandle, "_ZN7android15createOMXPluginEv");

    if (createOMXPlugin) {
        addPlugin((*createOMXPlugin)());//將當前的lib插件加入到Component中去
    }
}

這裡做了典型的lib庫的操作,dlopen加載庫,dlsym獲取庫中的操作函數handle。*createOMXPLugin()是調用這個so庫中的函數,這個函數返回的是一個OMXPluginBase*的類型。

到這裡,我覺得和有必要和大家分析下OMX下的插件的基本結構了,因為只有滿足這個規定的結構,才能成為一個合理的OMX下的插件。而

5. 神奇的libstagefighthw.so

這個被稱之為平台廠商所設計的組件插件。在A31裡面我們可以看到他的源碼:/home/A31_Android4.2.2/android/hardware/aw/libstagefrighthw

我來看看之前調用該庫裡面的函數createOMXPlugin,獲取其入口地址後,直接調用後是創建了屬於AW的一個OMX插件

extern "C" OMXPluginBase* createOMXPlugin()
{
    return new AwOMXPlugin;//創建一個解碼器插件
}
AwOMXPlugin::AwOMXPlugin()
    : mLibHandle(dlopen("libOmxCore.so", RTLD_NOW)),
      mInit(NULL),
      mDeinit(NULL),
      mComponentNameEnum(NULL),
      mGetHandle(NULL),
      mFreeHandle(NULL),
      mGetRolesOfComponentHandle(NULL)
{
    if (mLibHandle != NULL)
    {
        mInit                      = (InitFunc)dlsym(mLibHandle, "OMX_Init");
        mDeinit                    = (DeinitFunc)dlsym(mLibHandle, "OMX_Deinit");
        mComponentNameEnum         = (ComponentNameEnumFunc)dlsym(mLibHandle, "OMX_ComponentNameEnum");
        mGetHandle                 = (GetHandleFunc)dlsym(mLibHandle, "OMX_GetHandle");
        mFreeHandle                = (FreeHandleFunc)dlsym(mLibHandle, "OMX_FreeHandle");
        mGetRolesOfComponentHandle = (GetRolesOfComponentFunc)dlsym(mLibHandle, "OMX_GetRolesOfComponent");

        (*mInit)();
    }
}

AwOMXPlugin類繼承了OMXPluginBase類,實現了其相關接口

這裡又打開了一個OmxCore這個lib,依次獲取了以上幾個函數的接口,將會被AwOMXPlugin來進一步使用。我們看到mInit()函數的執行,其他類似的函數源碼位於:/home/A31_Android4.2.2/android/hardware/aw/omxcore/src/aw_omx_core.c

6. OMX Plugin的維護

回到4中的處理流程,繼續分析OMXMaster::addPluginOMXPluginBase *plugin()函數的實現。

void OMXMaster::addPlugin(OMXPluginBase *plugin) {
    Mutex::Autolock autoLock(mLock);

    mPlugins.push_back(plugin);

    OMX_U32 index = 0;

    char name[128];
    OMX_ERRORTYPE err;
    while ((err = plugin->enumerateComponents(
                    name, sizeof(name), index++)) == OMX_ErrorNone) {
        String8 name8(name);

        if (mPluginByComponentName.indexOfKey(name8) >= 0) {
            ALOGE("A component of name '%s' already exists, ignoring this one.",
                 name8.string());

            continue;
        }

        mPluginByComponentName.add(name8, plugin);//增加stragefright裡面的插件
    }

    if (err != OMX_ErrorNoMore) {
        ALOGE("OMX plugin failed w/ error 0x%08x after registering %d "
             "components", err, mPluginByComponentName.size());
    }
}

我們可以看到先查找當前的這個插件支持的組件,我們來看其在AwOMXPlugin中的實現。

OMX_ERRORTYPE AwOMXPlugin::enumerateComponents(OMX_STRING name, size_t size, OMX_U32 index)
{
    if (mLibHandle == NULL)
    {
        return OMX_ErrorUndefined;
    }

    OMX_ERRORTYPE res = (*mComponentNameEnum)(name, size, index);

    if (res != OMX_ErrorNone)
    {
        return res;
    }

    return OMX_ErrorNone;
}

看到這裡調用的是libOMXCore.so庫裡面的內容:

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName, OMX_IN OMX_U32 nameLen, OMX_IN OMX_U32 index)
{
	OMX_ERRORTYPE eRet = OMX_ErrorNone;
	ALOGV("OMXCORE API - OMX_ComponentNameEnum %x %d %d\n",(unsigned) componentName, (unsigned)nameLen, (unsigned)index);
	if(index < SIZE_OF_CORE)
	{
		strlcpy(componentName, core[index].name, nameLen);
	}
	else
	{
		eRet = OMX_ErrorNoMore;
	}

	return eRet;
}

這裡有一個Core的全局變量,其具體的結構如下

omx_core_cb_type core[] =
{
	{
		"OMX.allwinner.video.decoder.avc",
		NULL, // Create instance function
		// Unique instance handle
		{
			NULL,
			NULL,
			NULL,
			NULL
		},
		NULL,   // Shared object library handle
		"libOmxVdec.so",
		{
			"video_decoder.avc"
		}
	},
....
}

通過以上函數的層層分析,提取到了core中的編解碼器name以及對應的Lib庫。

最終是獲取了各個name之後,通過mPluginByComponentName.add(name8, plugin),添加不同name的編解碼器component到mPluginByComponentName變量中,而這個變量的所有權歸mMaster維護。

到這裡我們基本分析完了OMX插件和codec的提取。還沒有完成針對特定的視頻源,構建出專門的組件。這樣我們得回歸到3中創建一個屬於OMX解碼器的Node節點處。

7.OMXMaster::makeComponentInstance的處理

OMX_ERRORTYPE OMXMaster::makeComponentInstance(
        const char *name,
        const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData,
        OMX_COMPONENTTYPE **component) {
    Mutex::Autolock autoLock(mLock);

    *component = NULL;

    ssize_t index = mPluginByComponentName.indexOfKey(String8(name));//根據傳入的解碼器的名字,獲取組件索引

    if (index < 0) {
        return OMX_ErrorInvalidComponentName;
    }

    OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
    OMX_ERRORTYPE err =
        plugin->makeComponentInstance(name, callbacks, appData, component);//創建硬件,完成初始化,返回handle到component

    if (err != OMX_ErrorNone) {
        return err;
    }

    mPluginByInstance.add(*component, plugin);//將插件維護起來

    return err;
}

這個name是之前我們查找到平台支持的codec後(通過解析media_codec.xml獲得)後,再根據這個name,找到這個index值,定位到這個解碼器所在的插件plugin.這裡比如name是OMX.allwinner.video.decoder.avc,這個獲取的組件就是libStragefighthw.so這個插件AwOXPlugin

OMX_ERRORTYPE AwOMXPlugin::makeComponentInstance(const char* name, const OMX_CALLBACKTYPE* callbacks, OMX_PTR appData, OMX_COMPONENTTYPE** component)
{
	ALOGV("step 1.");
    if (mLibHandle == NULL)
    {
        return OMX_ErrorUndefined;
    }

	ALOGV("step 2.");

    return (*mGetHandle)(reinterpret_cast(component),
                         const_cast(name),
                         appData,
                         const_cast(callbacks));
}

這裡的創建的一個組件,變成了handle,可見是獲取對這個組件的操作權。而mGetHandle對應的是OMX_GetHandle其位於libOmxCore.so庫之中。

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(OMX_OUT OMX_HANDLETYPE* handle, OMX_IN OMX_STRING componentName, OMX_IN OMX_PTR appData, OMX_IN OMX_CALLBACKTYPE* callBacks)
{
     OMX_ERRORTYPE  eRet = OMX_ErrorNone;
     int cmp_index = -1;
     int hnd_index = -1;

     create_aw_omx_component fn_ptr = NULL;

     ALOGV("OMXCORE API :  Get Handle %x %s %x\n",(unsigned) handle, componentName, (unsigned) appData);

     if(handle)
     {
          cmp_index = get_cmp_index(componentName);

          if(cmp_index >= 0)
          {
               ALOGV("getting fn pointer\n");

               // dynamically load the so

               // ALOGV("core[cmp_index].fn_ptr: %x", core[cmp_index].fn_ptr);

               fn_ptr = omx_core_load_cmp_library(cmp_index);                    
          
               if(fn_ptr)
               {
                    // Construct the component requested
                    // Function returns the opaque handle

                    void* pThis = (*fn_ptr)();
                    if(pThis)
                    {
                         void *hComp = NULL;
                         hComp = aw_omx_create_component_wrapper((OMX_PTR)pThis);
                         if((eRet = aw_omx_component_init(hComp, componentName)) != OMX_ErrorNone)
                         {
                              ALOGE("Component not created succesfully\n");
                              return eRet;
                         }

                         aw_omx_component_set_callbacks(hComp, callBacks, appData);
                         
                         hnd_index = set_comp_handle(componentName, hComp);
                         if(hnd_index >= 0)
                         {
                              *handle = (OMX_HANDLETYPE) hComp;
                         }
                         else
                         {
                              ALOGE("OMX_GetHandle:NO free slot available to store Component Handle\n");
                              return OMX_ErrorInsufficientResources;
                         }

   .......

     return eRet;
}

7.1 get_cmp_index()根據傳入的組件name獲取其在core中的索引

7.2 omx_core_load_cmp_library

static create_aw_omx_component omx_core_load_cmp_library(int idx)
{
     create_aw_omx_component fn_ptr = NULL;

     pthread_mutex_lock(&g_mutex_core_info);


     if(core[idx].so_lib_handle == NULL)
     {
          ALOGV("Dynamically Loading the library : %s\n",core[idx].so_lib_name);

          core[idx].so_lib_handle = dlopen(core[idx].so_lib_name, RTLD_NOW);
     }

     if(core[idx].so_lib_handle)
     {
          if(core[idx].fn_ptr == NULL)
          {
               core[idx].fn_ptr = dlsym(core[idx].so_lib_handle, "get_omx_component_factory_fn");

  .....

假設這裡獲取的是 "OMX.allwinner.video.decoder.avc"對應的組件,則其操作的lib庫為"libOmxVdec.so"。完成加載,獲取庫的handle。此外這裡返回的是一個函數get_omx_component_factory_fn的地址,用於後續的對這個解碼庫的操作。

7.3 接著看 void* pThis = (*fn_ptr)();
就是調用7.2中返回的get_omx_component_factory_fn函數入口。

void *get_omx_component_factory_fn(void)
{
	return (new omx_vdec);
}

這裡看到是新建了一個omx_vdec對象,如下所示:

class omx_vdec: public aw_omx_component
{
public:
    omx_vdec();           // constructor
    virtual ~omx_vdec();  // destructor

後續內容的主要是涉及相關OMX組件構造的標准構造,自己也要學習後才能消化,先和大家分享到這裡,最終會提煉出一個大的框架和模塊間的處理圖,方便更好的理解這個OMX組件的構建過程。

來圖了,重新整理畫了一個簡單的流程圖,內部含有A31的編解碼器插件:










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