Android4.2.2下Stagefright多媒体架构中的A31的OMX插件和Codec组件

xiaoxiao2021-02-28  110

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。

欢迎和大家交流。qq:1037701636 email: gzzaigcn2012@gmail.com

 

 

在前面的博文中提到,AwesomePlayer::onPrepareAsyncEvent()开始进行Codec解码器组件的获取以及创建,这里和大家分享。

1.以解码器实例作为切入点

[cpp]  view plain  copy 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的成员变量,在这里能找到他的一些踪迹。

[html]  view plain  copy 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的处理,我们来看看其所完成的工作:

[html]  view plain  copy 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的实现:

[cpp]  view plain  copy sp<IOMX> 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的创建过程。

[cpp]  view plain  copy sp<MediaSource> OMXCodec::Create(           const sp<IOMX> &omx,           const sp<MetaData> &meta, bool createEncoder,           const sp<MediaSource> &source,           const char *matchComponentName,           uint32_t flags,           const sp<ANativeWindow> &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<CodecNameAndQuirks> 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<OMXCodecObserver> 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<MediaSource> 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<OMXCodec> 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, 个人认为这是查找到所需要的解码器的核心所在:

[cpp]  view plain  copy void OMXCodec::findMatchingCodecs(           const char *mime,           bool createEncoder, const char *matchComponentName,           uint32_t flags,           Vector<CodecNameAndQuirks> *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 0xx",                     entry->mName.string(), entry->mQuirks);           }       }          if (flags & kPreferSoftwareCodecs) {           matchingCodecs->sort(CompareSoftwareCodecsFirst);       }   }  

在这里很熟悉的看到一个单列模式的创建MediaCodecList,一个多媒体解码器列表的创建。在这里我们很有必要看一下他的构造过程,因为这里体现出android4.2.2的编解码器维护和之前2.3等的不同。也是他更接近移动互联的表现之一。

 

2.2 MediaCodecList的构建

[cpp]  view plain  copy 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.   /*              <MediaCodec name="OMX.allwinner.video.decoder.avc" type="video/avc" />             <MediaCodec name="OMX.allwinner.video.decoder.mpeg2" type="video/mpeg2" />            */           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下的这个配置文件部分内容,显然放在最前面的是全志自己的软硬件解码器:

[html]  view plain  copy  <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,一切的变得更加的轻松,分别经过如下处理:

[html]  view plain  copy ssize_t matchIndex = list->findCodecByType(mime, createEncoder, index);   [html]  view plain  copy const char *componentName = list->getCodecName(matchIndex);//获取解码器的名字  

componentName将成为后续的进一步处理的关键  

 3. 创建一个属于OMX解码器的Node节点

[cpp]  view plain  copy status_t err = omx->allocateNode(componentName, observer, &node);//请求mediaplayerservice创建一个节点,真正的解码器所在  

这里的omx在传入时已经分析过,变量类型为一个匿名Binder服务类BpOMX.回到在MediaPlayService的BnOMX处,估计核心的创建解码器等还是要交给MPS来完成的。

[cpp]  view plain  copy status_t OMX::allocateNode(           const char *name, const sp<IOMXObserver> &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:

[cpp]  view plain  copy OMX::OMX()       : mMaster(new OMXMaster),//新建一个mMaster         mNodeCounter(0) {   }  

这里看到MPS中的mOMX成员的子成员mMaster。

[cpp]  view plain  copy OMXMaster::OMXMaster()       : mVendorLibHandle(NULL) {       addVendorPlugin();//插入设备厂商的编解码器插件libstagefrighthw       addPlugin(new SoftOMXPlugin);   }  

看到这里我会觉得OMXMaster是所有底层编解码的管理者吧。因此组件的创建等都需要通过他来完成。

 

4.OMXMaster管理者的角色扮演

[cpp]  view plain  copy void OMXMaster::addVendorPlugin() {       addPlugin("libstagefrighthw.so");//厂商的硬件编解码器   }  

看到这里添加了所谓的设备厂商的插件,看到其是添加了一个libstagefrighthw.so库。我们看看他是如何对这个so文件做处理的:

[cpp]  view plain  copy 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插件

[cpp]  view plain  copy extern "C" OMXPluginBase* createOMXPlugin()   {       return new AwOMXPlugin;//创建一个解码器插件   }   [cpp]  view plain  copy 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()函数的实现。

[cpp]  view plain  copy 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 0xx after registering %d "                "components", err, mPluginByComponentName.size());       }   }  

我们可以看到先查找当前的这个插件支持的组件,我们来看其在AwOMXPlugin中的实现。

[cpp]  view plain  copy 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库里面的内容:

[cpp]  view plain  copy 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的全局变量,其具体的结构如下

[cpp]  view plain  copy 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的处理

[cpp]  view plain  copy 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

[cpp]  view plain  copy 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<OMX_HANDLETYPE *>(component),                            const_cast<char *>(name),                            appData,                            const_cast<OMX_CALLBACKTYPE *>(callbacks));   }  

这里的创建的一个组件,变成了handle,可见是获取对这个组件的操作权。而mGetHandle对应的是OMX_GetHandle其位于libOmxCore.so库之中。

[cpp]  view plain  copy 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

[cpp]  view plain  copy 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函数入口。

[cpp]  view plain  copy void *get_omx_component_factory_fn(void)   {       return (new omx_vdec);   }  

这里看到是新建了一个omx_vdec对象,如下所示:

[cpp]  view plain  copy class omx_vdec: public aw_omx_component   {   public:       omx_vdec();           // constructor       virtual ~omx_vdec();  // destructor  

后续内容的主要是涉及相关OMX组件构造的标准构造,自己也要学习后才能消化,先和大家分享到这里,最终会提炼出一个大的框架和模块间的处理图,方便更好的理解这个OMX组件的构建过程。

来图了,重新整理画了一个简单的流程图,内部含有A31的编解码器插件:

 

 

 

 

转载请注明原文地址: https://www.6miu.com/read-40845.html

最新回复(0)