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

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

在前面的博文中提到,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<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<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的创建过程。

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, 个人认为这是查找到所需要的解码器的核心所在:

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 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.
/*
<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下的这个配置文件部分内容,显然放在最前面的是全志自己的软硬件解码器:

 <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);//请求mediaplayerservice创建一个节点,真正的解码器所在

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

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:

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<OMX_HANDLETYPE *>(component),
const_cast<char *>(name),
appData,
const_cast<OMX_CALLBACKTYPE *>(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的编解码器插件:

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

  1. Android4.2.2的Stagefright中编解码器数据流的维护

    本文均属自己阅读源码的点滴总结,转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:gzzaigcn2012@gmail.com Android源码版本Version:4.2 ...

  2. Android4.2.2的Stagefright维护编解码器的数据流

    这里是他们自己的源代码阅读点滴总结属性,转请注明出处,谢谢. 欢迎和大家分享.qq:1037701636 email:gzzaigcn2012@gmail.com Android源代码版本号Versi ...

  3. 企业架构中的业务架构分析和理解

    因为最近在重新规整企业架构方面的资料和文章,特别是企业架构中的业务架构部分,因此今天想重点对业务架构的一些关键点进行说明. 注:这篇文章仅仅作为关键点的记录,不作为体系化介绍业务架构的文章.如果希望了 ...

  4. 02全志r58平台Android4.4.4下关闭内核中的CPU的开启关闭提示

    02全志r58平台Android4.4.4下关闭内核中的CPU的开启关闭提示 2017/8/18 13:53 版本:V1.0 开发板:SC5806(全志R58平台) SDK:android4.4.4 ...

  5. ASP.NET Core Web API下事件驱动型架构的实现(四):CQRS架构中聚合与聚合根的实现

    在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅.通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现.接下来对于事件驱动型架构的讨论,就需 ...

  6. ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理

    在ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行 ...

  7. 虚拟主机中,不修改IIS设置,在IIS6下运行MVC架构的网站

    虚拟主机中,不修改IIS设置,在IIS6下运行MVC架构的网站 我为什么要写这个教程呢? 主要是为了解决把网站部署在虚拟主机上的人,因为你根本不能去配置虚拟主机所以,用下面的方法,可以实现不配置IIS ...

  8. ac ap方案 华为_今天给大家总结下AC+AP架构使用过程中的若干问题及解决办法

    原标题:今天给大家总结下AC+AP架构使用过程中的若干问题及解决办法 早前发布了一篇<手把手教您如何大范围无线组网>,当时有朋友留言要我给点更详细的配置,有朋友建议用华为设备,也有朋友建议 ...

  9. 亿级流量、高并发与高性能场景下的电商详情页架构_2(缓存架构中的Redis)

    亿级流量.高并发与高性能场景下的电商详情页架构_2(缓存架构中的Redis) 缓存架构一定要学好的Redis,缓存架构中的高可用,高并发,海量数据,备份,随时可恢复,缓存架构要支持这些,则redis一 ...

最新文章

  1. java时间格式转换_Java中System.currentTimeMillis()计算方式与时间的单位转换
  2. feachall php_timthumb.php详解
  3. 08 | 事务到底是隔离的还是不隔离的
  4. SQLite Insert 语句(http://www.w3cschool.cc/sqlite/sqlite-insert.html)
  5. ecos内核概览--bakayi译
  6. Java NIO系列教程(十一) Pipe
  7. 清华图书馆机器人小图_机器人“小图”带你逛“国家图书馆110周年公共数字文化展”...
  8. 数据结构思维 第二章 算法分析
  9. linux mint安装类型,如何在Linux Mint 16中正确安装Ubuntu One
  10. JavaScript循环结构(1)
  11. Ubuntu16.04再次装机记
  12. 校外用Cterm登陆郁金香的方法
  13. 工作之余可以回味的经典
  14. Python实现计算MD5
  15. new className() new出来的深意
  16. 第91届奥斯卡奖公布提名名单《罗马》《宠儿》10项提名领跑
  17. 绘制简单封闭图形并且进行填充
  18. 【学习笔记】刚体角速度的唯一性问题
  19. 永远的Beatles
  20. 什么是sys文件系统

热门文章

  1. bigsur cdr文件_macOS Big Sur 11.2 原版引导镜像下载
  2. 你会仲裁吗——劳动仲裁需要准备
  3. 将百分制成绩转化为5分制成绩。
  4. 使用android7的手机,手机评测 篇一:7年果粉的一加7t使用体验
  5. 网孔型中级维修电工实训考核装置
  6. 如何白嫖微软云Azure12个月及避坑指南
  7. java中关系运算符_Java 关系运算符
  8. AAA企业信用评级的好处
  9. SimpleDateFormat 的使用及其 注意事项
  10. 各省投入产出表数据(2002、2007、2012)