在前面的博文中提到,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(),
- false,
- mVideoTrack,
- NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
-
- 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();
-
- 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<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.player"));
- sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(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;
- }
-
- 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);
-
- 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();
- 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) {
- 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)) {
-
-
-
- ALOGW("Component '%s' does not give the client access to "
- "the framebuffer contents. Skipping.",
- componentName);
-
- continue;
- }
- }
-
- status_t err = omx->allocateNode(componentName, observer, &node);
- if (err == OK) {
- ALOGV("Successfully allocated OMX node '%s'", componentName);
-
- sp codec = new OMXCodec(
- omx, node, quirks, flags,
- createEncoder, mime, componentName,
- source, nativeWindow);
-
- observer->setCodec(codec);
-
- 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 (matchComponentName && strcmp(componentName, matchComponentName)) {
- continue;
- }
-
-
-
-
-
- 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()
- : 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);
-
- if (mInitCheck == OK) {
-
-
-
-
-
-
- addMediaCodec(true , "AACEncoder", "audio/mp4a-latm");
-
- addMediaCodec(
- false , "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下的这个配置文件部分内容,显然放在最前面的是全志自己的软硬件解码器:
- <MediaCodecs>
- 93 <Decoders>
- 94 <MediaCodec name="OMX.allwinner.video.decoder.avc" type="video/avc" />
- 95 <MediaCodec name="OMX.allwinner.video.decoder.mpeg2" type="video/mpeg2" />
- 96 <MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es" />
- 97 <MediaCodec name="OMX.google.h263.decoder" type="video/3gpp" />
- 98 <MediaCodec name="OMX.google.vpx.decoder" type="video/x-vnd.on2.vp8" />
- 99
- 100 <MediaCodec name="OMX.google.mp3.decoder" type="audio/mpeg" />
- 101 <MediaCodec name="OMX.google.amrnb.decoder" type="audio/3gpp" />
- 102 <MediaCodec name="OMX.google.amrwb.decoder" type="audio/amr-wb" />
- 103 <MediaCodec name="OMX.google.aac.decoder" type="audio/mp4a-latm" />
- 104 <MediaCodec name="OMX.google.g711.alaw.decoder" type="audio/g711-alaw" />
- 105 <MediaCodec name="OMX.google.g711.mlaw.decoder" type="audio/g711-mlaw" />
- 106 <MediaCodec name="OMX.google.vorbis.decoder" type="audio/vorbis" />
- 107 <MediaCodec name="OMX.google.raw.decoder" type="audio/raw" />
- 108
- 109 Decoders>
- 110
- 111 <Encoders>
- 112 <MediaCodec name="OMX.allwinner.video.encoder.avc" type="video/avc" />
- 113
- 114 <MediaCodec name="OMX.google.h263.encoder" type="video/3gpp" />
- 115 <MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es" />
- 116 <MediaCodec name="OMX.google.amrnb.encoder" type="audio/3gpp" />
- 117 <MediaCodec name="OMX.google.amrwb.encoder" type="audio/amr-wb" />
- 118 <MediaCodec name="OMX.google.aac.encoder" type="audio/mp4a-latm" />
- 119 <MediaCodec name="OMX.google.flac.encoder" type="audio/flac" />
- 120 Encoders>
- 121 MediaCodecs>
而这个文件的解析通过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);
这里的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);
-
- 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),
- mNodeCounter(0) {
- }
这里看到MPS中的mOMX成员的子成员mMaster。
- OMXMaster::OMXMaster()
- : mVendorLibHandle(NULL) {
- addVendorPlugin();
- 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库的操作,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);
- }
-
- 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,
-
- {
- NULL,
- NULL,
- NULL,
- NULL
- },
- NULL,
- "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);
-
- 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<char *>(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");
-
-
-
-
-
- fn_ptr = omx_core_load_cmp_library(cmp_index);
-
- if(fn_ptr)
- {
-
-
-
- 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();
- virtual ~omx_vdec();
后续内容的主要是涉及相关OMX组件构造的标准构造,自己也要学习后才能消化,先和大家分享到这里,最终会提炼出一个大的框架和模块间的处理图,方便更好的理解这个OMX组件的构建过程。
来图了,重新整理画了一个简单的流程图,内部含有A31的编解码器插件:
原文地址:http://blog.csdn.net/gzzaigcnforever/article/details/26405739?utm_source=tuicool