This article is a summary of my own reading source code. Please indicate the origin of the transfer. Thank you.
Welcome to communicate with you. qq:1037701636 email: gzzaigcn2012@gmail.com
As mentioned in the previous blog post, AwesomePlayer::onPrepareAsyncEvent() begins to acquire and create Codec decoder components, which we share with you here.
1. Take the example of decoder as the breakthrough point.
-
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;
-
}
-
}
-
......
-
}
Here I have to explain the contents of the following member variables to facilitate the follow-up analysis:
MClinet: OMXClient (inherited) class object. As a member variable of AwesomePlayer, we can find some traces of him here.
-
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, maintain a mOMX:BpOMX after connect
Looking at the connect ion process here, let's look at what it has accomplished:
-
status_t OMXClient::connect() {
-
sp<IServiceManager> sm = defaultServiceManager();
-
sp<IBinder> binder = sm->getService(String16("media.player"));
-
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);//Get the MPS service BpMedia Player Service
-
-
CHECK(service.get() != NULL);
-
-
mOMX = service->getOMX();//Get an omx local interface and pass it to videosource, BpOMX
-
CHECK(mOMX.get() != NULL);
-
-
if (!mOMX->livesLocally(NULL /* node */, getpid())) {
-
ALOGI("Using client-side OMX mux.");
-
mOMX = new MuxOMX(mOMX);
-
}
-
-
return OK;
-
}
The Binder driver between threads is processed here. Get the interface of an OMX component to mOMX. We have to look at the implementation of getOMX on the MediaPlayService side:
-
sp<IOMX> MediaPlayerService::getOMX() {
-
Mutex::Autolock autoLock(mLock);
-
-
if (mOMX.get() == NULL) {
-
mOMX = new OMX;
-
}
-
-
return mOMX;
-
}
A new OMX component class is constructed, which inherits BnOMX. After the Binder driver returns, it eventually creates an anonymous driver like BpOMX.
After returning to BpOMX, a MuxOMX class mOMX is created on the OMXClient side, which exists as a member variable of the OMXClient.
The analysis shows that mClient.interace is the mOMX component created by connect.
b.
SetVideo Source (extractor - > getTrack (i); // Set video source mVideoTrack;
SetAudio Source (extractor - > getTrack (i); // Set audio source mAudioTrack;
mVideoTrack and mAudioTrack are member functions of the created AwesomePlay, whose type is MPEG4Source and inherits MediaSource.
Then mVideoTrack - > getFormat () is the format for obtaining the corresponding video information source.
2. Creation of OMXCodec
All decoders, whether soft or hard, are mounted under OMX and used as a Component. Let's look at a Codec creation process.
-
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);
-
-
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();
-
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<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)) {
-
-
-
-
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<OMXCodec> 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 Find Decoders Supported by Platform
Bool success = meta - > find CString (kKeyMIMEType, & mime); firstly, mime is extracted from the incoming video source trace. Then we continue to search for a decoder for the decoding of the current video source.
Find Matching Codecs (); // Find available decoders such as OMX.allwinner.video.decoder.avc, which I think is the core of finding the required decoders:
-
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 (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);
-
}
-
}
Here we are familiar with the creation of a single column mode called MediaCodecList, a list of multimedia decoders. Here we need to look at his construction process, because it reflects the Android 4.2.2 codec maintenance is different from the previous 2.3 and so on. It's also one of the manifestations of his closer approach to mobile interconnection.
2.2 Construction of 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 is characterized by its parsing of a / etc/media_codecs.xml, which makes it easy to see the features of the Internet. Let's take a look at the content of this configuration file under GLOBAL A31. It's obvious that the top priority is GLOBAL's own hardware and software decoder.
-
<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>
The parse of this file is completed by parseXMLFile, and the decoder property is maintained in mCodecInfos. The parsing process of xml file is not very familiar, but the core is to extract the name and type fields and then add MediaCodec.
Of course, we can also add by manually addMedia Codec, where ture represents the encoder and vice versa, the decoder.
Through the above means, we finally get all the types of codec supported by the hardware platform, that is, all kinds of Component components under OMX.
2.3
With this so-called codec list, everything becomes easier, which is processed as follows:
-
ssize_t matchIndex = list->findCodecByType(mime, createEncoder, index);
-
const char *componentName = list->getCodecName(matchIndex);//Get the name of the decoder.
CompoonentName will be the key to further processing.
3. Create a Node node belonging to the OMX decoder
-
status_t err = omx->allocateNode(componentName, observer, &node);
The omx here has been analyzed at the time of its introduction, and the variable type is an anonymous Binder service class BpOMX. Back at the BnOMX of MediaPlayService, it is estimated that the creation of the core decoder will still be handed over to 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);
-
-
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 Create a New Real OMXNodeInstance Example
3.2 mMaster - > makeComponentInstance () Really Acquires Control of a Multi-Next Layer Decoder
Here we want to analyze mMaster as a variable:
When acquiring BpOMX, new OMX is implemented in getOMX on the MPS side:
-
OMX::OMX()
-
: mMaster(new OMXMaster),
-
mNodeCounter(0) {
-
}
Here you see the sub-member mMaster of the mOMX member in MPS.
-
OMXMaster::OMXMaster()
-
: mVendorLibHandle(NULL) {
-
addVendorPlugin();
-
addPlugin(new SoftOMXPlugin);
-
}
Seeing this, I think OMXMaster is the administrator of all the underlying codecs. Therefore, the creation of components and so on need to be completed through him.
4. The Role of OMXMaster Manager
-
void OMXMaster::addVendorPlugin() {
-
addPlugin("libstagefrighthw.so");
-
}
See the addition of the so-called device vendor plug-in here, see that it is the addition of a libstage frighthw. so library. Let's see how he handles this so file:
-
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)());
-
}
-
}
Here we do the typical lib library operation, dlopen load library, dlsym get the operation function handle in the library. * createOMXPLugin () is a function that calls the so library and returns a type of OMXPluginBase *.
At this point, I think it is necessary and necessary to analyze the basic structure of the plug-in under OMX, because only by meeting the required structure can we become a reasonable plug-in under OMX. and
5. Magic libstage fighthw.so
This is called a component plug-in designed by platform vendors. In A31 we can see his source code: / home / A31_Android 4.2.2/ Android/hardware/aw/libstagefrighthw
Let me take a look at the function createOMXPlugin in the library that was called before. After obtaining its entry address, I directly invoked it and created an OMX plug-in belonging to AW.
-
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)();
-
}
-
}
The AwOMXPlugin class inherits the OMXPluginBase class and implements its related interfaces.
An OmxCore lib is opened here, and the interfaces of the above functions are obtained in turn, which will be further used by AwOMXPlugin. We see the execution of the mInit () function, and other similar function sources are located at: / home/A31_Android 4.2.2/android/hardware/aw/omx core/src/aw_omx_core.c.
6. Maintenance of OMX Plugin
Back to the processing flow in 4, continue to analyze the implementation of OMXMaster::addPluginOMXPluginBase *plugin() function.
-
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());
-
}
-
}
We can see that we first look for the components currently supported by this plug-in. Let's look at their implementation in 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;
-
}
See what is called here in the libOMXCore.so library:
-
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;
-
}
Here is a global variable of Core, which is structured as follows
-
omx_core_cb_type core[] =
-
{
-
{
-
"OMX.allwinner.video.decoder.avc",
-
NULL,
-
-
{
-
NULL,
-
NULL,
-
NULL,
-
NULL
-
},
-
NULL,
-
"libOmxVdec.so",
-
{
-
"video_decoder.avc"
-
}
-
},
-
....
-
}
Through the layer-by-layer analysis of the above functions, the name of the codec and the corresponding Lib Library in core are extracted.
Finally, after each name is obtained, the codec component of different names is added to the mPluginByComponentName variable through mPluginByComponentName. add (name 8, plugin), and the ownership of the variable is maintained by mMaster.
Here we have basically analyzed the OMX plug-ins and codec extraction. Specific components for specific video sources have not been built yet. So we have to go back to No. 3 and create a Node node that belongs to the OMX decoder.
7. OMXMaster:: MakeComponent Instance Processing
-
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;
-
}
This name is after we found the codec supported by the platform (obtained by parsing media_codec.xml), then according to this name, we find the index value and locate the plugin where the decoder is located. Here, for example, the name is OMX.allwinner.video.decoder.avc. The acquired component is libStragefighthw.so plugin 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));
-
}
A component created here has become a handle, so you can see that you are gaining access to this component. mGetHandle corresponds to OMX_GetHandle, which is located in the libOmxCore.so library.
-
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() retrieves its index in core based on the name of the incoming component
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");
-
-
.....
Assuming that the component corresponding to "OMX.allwinner.video.decoder.avc" is captured here, the lib library for its operation is "libOmxVdec.so". Complete the loading and get the handle of the library. In addition, the address of the function get_omx_component_factory_fn is returned here for subsequent operations on the decoding library.
7.3 Then look at void* pThis = (*fn_ptr)();
Call the get_omx_component_factory_fn function entry returned in 7.2.
-
void *get_omx_component_factory_fn(void)
-
{
-
return (new omx_vdec);
-
}
Here you see that a new omx_vdec object is created, as follows:
-
class omx_vdec: public aw_omx_component
-
{
-
public:
-
omx_vdec();
-
virtual ~omx_vdec();
Follow-up content is mainly related to the standard construction of OMX component construction, I have to learn before digestion, first share with you here, and eventually will extract a large framework and processing diagram between modules, to facilitate a better understanding of the OMX component construction process.
Here's a diagram. A simple flow chart is redrawn. It contains the encoding and decoding plug-in of A31.