| 
 OMX Codec是stagefrightplayer中负责解码的模块。 由于遵循openmax接口规范,因此结构稍微有点负责,这里就依照awesomeplayer中的调用顺序来介绍。 主要分如下几步: 1 mClient->connect 2 InitAudioDecoder & InitVideoDecoder 3 消息通信机制模型的介绍 4 解码过程介绍   先看下类图 这里OMX Codec是以service的方式提供服务的。Awesomeplayer中通过mOmx(IOMX) 作为客户端通过binder方式与OMX 通信完成解码的工作 下面一句具体代码分析   1 mClient->connect 
 在awesomeplayer的构造函数中调用,具体代码如下   [html] view plaincopy 
 
 
- AwesomePlayer::AwesomePlayer()  
 - {  
 -     ******  
 -     CHECK_EQ(mClient.connect(), (status_t)OK);  
 -     ******  
 - }  
 
 
  
  看下具体实现   [html] view plaincopy 
 
 
- status_t OMXClient::connect() {  
 -     sp<</span>IServiceManager> sm = defaultServiceManager();  
 -     sp<</span>IBinder> binder = sm->getService(String16("media.player"));  
 -     sp<</span>IMediaPlayerService> service = interface_cast<</span>IMediaPlayerService>(binder);  
 -     
 -     CHECK(service.get() != NULL);  
 -     
 -     mOMX = service->getOMX();  
 -     CHECK(mOMX.get() != NULL);  
 -     
 -     if (!mOMX->livesLocally(NULL , getpid())) {  
 -         ALOGI("Using client-side OMX mux.");  
 -         mOMX = new MuxOMX(mOMX);  
 -     }  
 -     
 -     return OK;  
 - }  
 
 
  
  这里主要就是通过binder机制与mediaplayerservice通信来完成,具体实现看mediaplayerservice   [html] view plaincopy 
 
 
- sp<</span>IOMX> MediaPlayerService::getOMX() {  
 -     Mutex::Autolock autoLock(mLock);  
 -     if (mOMX.get() == NULL) {  
 -         mOMX = new OMX;  
 -     }  
 -     return mOMX;  
 - }  
 
 
  
 
  主要就是构造一个OMX对象返回给上层保存在mClient的IOMX对象mOmx中 看下构造函数都做了啥   [html] view plaincopy 
 
 
- OMX::OMX()  
 -     : mMaster(new OMXMaster),  
 -       mNodeCounter(0) {  
 - }  
 
 
  
  在构造函数中又调用了OMXMaster的构造函数,代码如下   [html] view plaincopy 
 
 
- OMXMaster::OMXMaster()  
 -     : mVendorLibHandle(NULL) {  
 -     addVendorPlugin();  
 -     addPlugin(new SoftOMXPlugin);  
 - }  
 
 
  
  这里OMXMaster可以看成是解码器的入口,通过makeComponentInstance建立解码器的实例,之后就可以进行解码操作了。 这里我们以软件解码器插件为例来看整个流程,主要是addPlugin(newSoftOMXPlugin);先看SoftOMXPlugin构造函数   [html] view plaincopy 
 
 
- SoftOMXPlugin::SoftOMXPlugin() {  
 - }  
 
 
  
  是空的~~ 再看下addPlugin代码   [html] view plaincopy 
 
 
- 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 0xx after registering %d "  
 -              "components", err, mPluginByComponentName.size());  
 -     }  
 - }  
 
 
  
  这里传入的plugin参数时上面SoftOMXPlugin 构造函数产生的实例 从代码可以看出主要是将enumerateComponents枚举出来的各种解码器存放在成员变量mPluginByComponentName中,类型为 KeyedVector 看下enumerateComponents实现   [html] view plaincopy 
 
 
- static c**t struct {  
 -     c**t char *mName;  
 -     c**t char *mLibNameSuffix;  
 -     c**t char *mRole;  
 -     
 - } kComponents[] = {  
 -     { "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },  
 -     { "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },  
 -     { "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },  
 -     { "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" },  
 -     { "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" },  
 -     { "OMX.google.amrwb.encoder", "amrwbenc", "audio_encoder.amrwb" },  
 -     { "OMX.google.h264.decoder", "h264dec", "video_decoder.avc" },  
 -     { "OMX.google.h264.encoder", "h264enc", "video_encoder.avc" },  
 -     { "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" },  
 -     { "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" },  
 -     { "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },  
 -     { "OMX.google.h263.encoder", "mpeg4enc", "video_encoder.h263" },  
 -     { "OMX.google.mpeg4.decoder", "mpeg4dec", "video_decoder.mpeg4" },  
 -     { "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" },  
 -     { "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },  
 -     { "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },  
 -     { "OMX.google.vpx.decoder", "vpxdec", "video_decoder.vpx" },  
 -     { "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },  
 -     { "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" },  
 - };  
 
 
  
[html] view plaincopy 
 
 
- OMX_ERRORTYPE SoftOMXPlugin::enumerateComponents(  
 -         OMX_STRING name,  
 -         size_t size,  
 -         OMX_U32 index) {  
 -     if (index >= kNumComponents) {  
 -         return OMX_ErrorNoMore;  
 -     }  
 -     
 -     strcpy(name, kComponents[index].mName);  
 -     
 -     return OMX_ErrorNone;  
 - }  
 
 
  
 
这里enumerateComponents主要就是将数组kComponents中的以为index下标的plugin传递出来  这里只是将插件名字返回最终存储在mPluginByComponentName列表中 后面还会通过makeComponentInstance产生实际的解码器实例,后面再详细看  至此mClient->connect()就结束了。 这里的主要工作就是通过getOMX()在mediaplayerservice端构造一个OMX实例,并返回给mClient的IOMX成员mOmx中 而且在OMX的构造函数中调用OMXMaster的构造函数,可以通过makeComponentInstance 建立实际的解码器实例。  2 InitAudioDecoder & InitVideoDecoder 
 awesomeplayer构造函数结束后,在setDataSource之后会调用prepare方法,其实现中会调用initAudioDecoder和initVideoDecoder 由于在setDataSource中已经拿到了对应的解码器信息,因此此处initAudioDecoder 便可以构造实际的解码器了。以audio为例   [html] view plaincopy 
 
 
- status_t AwesomePlayer::initAudioDecoder() {  
 -         mAudioSource = OMXCodec::Create(  
 -     
 -                 mClient.interface(), mAudioTrack->getFormat(),  
 -                 false, // createEncoder  
 -     
 -                 mAudioTrack);}  
 -     
 -            status_t err = mAudioSource->start();  
 -     
 -      return mAudioSource != NULL ? OK : UNKNOWN_ERROR;  
 -     
 - }  
 
 
  
  这里只列出的主要操作,下面依次来看OMXCodec::Create和mAudioSource->start的主要工作 代码比较多,我们这里主要将重要的代码列出,无关代码省略   [html] view plaincopy 
 
 
- sp<</span>MediaSource> OMXCodec::Create(*)  
 - {  
 -     
 -         findMatchingCodecs(  
 -             mime, createEncoder, matchComponentName, flags, &matchingCodecs);  
 -     
 -         sp<</span>OMXCodecObserver> observer = new OMXCodecObserver;  
 -         IOMX::node_id node = 0;  
 -     
 -         status_t err = omx->allocateNode(componentName, observer, &node);  
 -     
 -         sp<</span>OMXCodec> codec = new OMXCodec(  
 -                     omx, node, quirks, flags,  
 -                     createEncoder, mime, componentName,  
 -                     source, nativeWindow);  
 -     
 -         observer->setCodec(codec);  
 -     
 -         err = codec->configureCodec(meta);  
 -     
 - }  
 
 
  
下面依次来看每个过程  2.1 findMatchingCodecs 先看下代码   [html] view plaincopy 
 
 
- void OMXCodec::findMatchingCodecs(  
 -         c**t char *mime,  
 -         bool createEncoder, c**t char *matchComponentName,  
 -         uint32_t flags,  
 -         Vector<</span>CodecNameAndQuirks> *matchingCodecs) {  
 -     matchingCodecs->clear();  
 -     
 -     c**t MediaCodecList *list = MediaCodecList::getInstance();  
 -     if (list == NULL) {  
 -         return;  
 -     }  
 -     
 -     size_t index = 0;  
 -     for (;;) {  
 -         ssize_t matchIndex =  
 -             list->findCodecByType(mime, createEncoder, index);  
 -     
 -         if (matchIndex <</span> 0) {  
 -             break;  
 -         }  
 -     
 -         index = matchIndex + 1;  
 -     
 -         c**t 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找到与传入的matchComponentName对应的解码器  MediaCodecList 的实现不看了,感兴趣的看下,主要就是从/etc/media_codecs.xml解析出支持的解码器并匹配出对应的解码器 举例: 这里需要注意的是在前面我们看到 kComponents 数组定义了支持的解码器,这里/etc/media_codecs.xml 也列出了对应的解码器,这里名字要对应上 这里找到符合条件的解码器便通过matchingCodecs->add()添加一个项,并将各个成员赋值,主要是name 最终符合条件的插件便都放在了matchingCodecs列表中  2.2 allocateNode 这里主要有如下重要代码         sp observer = new OMXCodecObserver; 
    IOMX::node_id node = 0;     status_t err = omx->allocateNode(componentName, observer, &node); observer的作用主要用于消息传递。  这里allocateNode主要是调用service端的OMX类来完成工作(省略中间的binder操作)   [html] view plaincopy 
 
 
- status_t OMX::allocateNode(  
 -         c**t char *name, c**t sp<</span>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;  
 - }  
 
 
  
   首先构造了OMXNodeInstance,封装了传入的observer参数,作为消息传递的载体  调用mMaster->makeComponentInstance生成实际的解码器实例  生成node_id 将node_id与实际的解码器handle保存在instance中,最终instance会保存在OMX的mLiveNodes列表中 这样OMXCodec就可以通过OMXNodeInstance与解码器通信了,具体参考下面通信模型。 后面会介绍通信过程。这里重点讲解一下与解码器的操作   上面代码中通过mMaster->makeComponentInstance创建了解码器的实例,这里我们以android自带的mp3 解码器为例来讲解 通过上面介绍mp3解码器对应的项为(/etc/media_codecs.xml):   而findMatchingCodecs 传入的字符串为:audio/mpeg 以此为依据进行匹配 这里找到对应的解码器后,解码器的名字为:OMX.google.mp3.decoder 这样便可以通过查表(数组kComponents )得到实际的解码器了 实际的mp3解码器代码文件为:framework/av/media/libstagefright/codecs/mp3dec/SoftMP3.cpp 调用的方法为:mMaster->makeComponentInstance 实际代码是   [html] view plaincopy 
 
 
- OMX_ERRORTYPE OMXMaster::makeComponentInstance(  
 -         c**t char *name,  
 -         c**t OMX_CALLBACKTYPE *callbacks,  
 -         OMX_PTR appData,  
 -         OMX_COMPONENTTYPE **component) {  
 -     Mutex::Autolock autoLock(mLock);  
 -     
 -     *component = NULL;  
 -     
 -     ssize_t index = mPluginByComponentName.indexOfKey(String8(name));  
 -     
 -     if (index <</span> 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;  
 - }  
 
 
  
  主要是调用插件的makeComponentInstance方法 这里插件是通过OMXMaster构造函数addPlugin(new SoftOMXPlugin);加载的插件,因此这里makeComponentInstance 是SoftOMXPlugin 的方法 看下具体实现   [html] view plaincopy 
 
 
- OMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance(  
 -         c**t char *name,  
 -         c**t OMX_CALLBACKTYPE *callbacks,  
 -         OMX_PTR appData,  
 -         OMX_COMPONENTTYPE **component) {  
 -     ALOGV("makeComponentInstance '%s'", name);  
 -     
 -     for (size_t i = 0; i <</span> kNumComponents; ++i) {  
 -         if (strcmp(name, kComponents.mName)) {  
 -             continue;  
 -         }  
 -     
 -         AString libName = "libstagefright_soft_";  
 -         libName.append(kComponents.mLibNameSuffix);  
 -         libName.append(".so");  
 -     
 -         void *libHandle = dlopen(libName.c_str(), RTLD_NOW);  
 -     
 -         if (libHandle == NULL) {  
 -             ALOGE("unable to dlopen %s", libName.c_str());  
 -     
 -             return OMX_ErrorComponentNotFound;  
 -         }  
 -     
 -         typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(  
 -                 c**t char *, c**t OMX_CALLBACKTYPE *,  
 -                 OMX_PTR, OMX_COMPONENTTYPE **);  
 -     
 -         CreateSoftOMXComponentFunc createSoftOMXComponent =  
 -             (CreateSoftOMXComponentFunc)dlsym(  
 -                     libHandle,  
 -                     "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"  
 -                     "PvPP17OMX_COMPONENTTYPE");  
 -     
 -         if (createSoftOMXComponent == NULL) {  
 -             dlclose(libHandle);  
 -             libHandle = NULL;  
 -     
 -             return OMX_ErrorComponentNotFound;  
 -         }  
 -     
 -         sp<</span>SoftOMXComponent> codec =  
 -             (*createSoftOMXComponent)(name, callbacks, appData, component);  
 -     
 -         if (codec == NULL) {  
 -             dlclose(libHandle);  
 -             libHandle = NULL;  
 -     
 -             return OMX_ErrorInsufficientResources;  
 -         }  
 -     
 -         OMX_ERRORTYPE err = codec->initCheck();  
 -         if (err != OMX_ErrorNone) {  
 -             dlclose(libHandle);  
 -             libHandle = NULL;  
 -     
 -             return err;  
 -         }  
 -     
 -         codec->incStrong(this);  
 -         codec->setLibHandle(libHandle);  
 -     
 -         return OMX_ErrorNone;  
 -     }  
 -     
 -     return OMX_ErrorInvalidComponentName;  
 - }  
 
 
  
  这里主要是通过枚举kComponents找到对应的解码器记录 { "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" }, 这里可以看到每个库都是以.so的方式提供的,命名符合如下规则:libstagefright_soft_mp3dec.so 通过dlopen加载后通过dlsym找到createSoftOMXComponent方法并执行,这里每个解码器都应该实现此函数  
 |