Android MultiMedia框架——OMXPlugin

Posted VNanyesheshou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MultiMedia框架——OMXPlugin相关的知识,希望对你有一定的参考价值。

Android MultiMedia框架——OMX服务启动
Android MultiMedia框架——OMXPlugin
Android MultiMedia框架——MediaCodec编码(上)
Android MultiMedia框架——MediaCodec编码(下)
上一篇OMX服务启动有 提到OMXMaster添加两个Plugin,一个是SoftOMXPlugin,另一个是供应商实现的硬件Plugin,其父类是OMXPluginBase。

OMXPluginBase

路径:frameworks/native/headers/media_plugin/media/hardware/OMXPluginBase.h

OMXPluginBase 主要包含四个虚拟方法。硬件厂商接入自己的编解码器,需要继承OMXPluginBase 类,并实现抽象方法。

struct OMXPluginBase 
    OMXPluginBase() 
    virtual ~OMXPluginBase() 

    virtual OMX_ERRORTYPE makeComponentInstance(
            const char *name,
            const OMX_CALLBACKTYPE *callbacks,
            OMX_PTR appData,
            OMX_COMPONENTTYPE **component) = 0;

    virtual OMX_ERRORTYPE destroyComponentInstance(
            OMX_COMPONENTTYPE *component) = 0;

    virtual OMX_ERRORTYPE enumerateComponents(
            OMX_STRING name,
            size_t size,
            OMX_U32 index) = 0;

    virtual OMX_ERRORTYPE getRolesOfComponent(
            const char *name,
            Vector<String8> *roles) = 0;

private:
    OMXPluginBase(const OMXPluginBase &);
    OMXPluginBase &operator=(const OMXPluginBase &);
;

先看下硬件厂商实现的Plugin

QComOMXPlugin

路径:hardware/qcom/media/**/libstagefrighthw/QComOMXPlugin.cpp

QComOMXPlugin继承自OMXPluginBase,是高通实现的硬编解码。

OMXPluginBase *createOMXPlugin() 
    return new QComOMXPlugin;


QComOMXPlugin::QComOMXPlugin()
    : 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");

        if (!mInit || !mDeinit || !mComponentNameEnum || !mGetHandle ||
            !mFreeHandle || !mGetRolesOfComponentHandle) 
            dlclose(mLibHandle);
            mLibHandle = NULL;
         else
            (*mInit)();
    

  1. OMXMaster通过createOMXPlugin创建QComOMXPlugin对象;
  2. QComOMXPlugin构造函数中加载libOmxCore.so;
  3. 通过dlsym查找OMX_Init、OMX_Deinit等符号值;
  4. 这些方法对应OMXPluginBase中的抽象方法;

libOmxCore.so中为厂商高通实现的具体硬件编解码功能,这里先不分析了。

SoftOMXPlugin

路径:frameworks/av/media/libstagefright/omx/SoftOMXPlugin.cpp

SoftOMXPlugin是google提供的原生编解码插件,它并不负责实现编解码,而是负责管理加载编解码器。如下是其支持的音视频编解码格式,这些都是软件编解码

static const struct 
    const char *mName;
    const char *mLibNameSuffix;
    const char *mRole;

 kComponents[] = 
    // two choices for aac decoding.
    // configurable in media/libstagefright/data/media_codecs_google_audio.xml
    // default implementation
     "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" ,
    // alternate implementation
     "OMX.google.xaac.decoder", "xaacdec", "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", "avcdec", "video_decoder.avc" ,
     "OMX.google.h264.encoder", "avcenc", "video_encoder.avc" ,
     "OMX.google.hevc.decoder", "hevcdec", "video_decoder.hevc" ,
     "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" ,
     "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" ,
     "OMX.google.mpeg2.decoder", "mpeg2dec", "video_decoder.mpeg2" ,
     "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.opus.decoder", "opusdec", "audio_decoder.opus" ,
     "OMX.google.vp8.decoder", "vpxdec", "video_decoder.vp8" ,
     "OMX.google.vp9.decoder", "vpxdec", "video_decoder.vp9" ,
     "OMX.google.vp8.encoder", "vpxenc", "video_encoder.vp8" ,
     "OMX.google.vp9.encoder", "vpxenc", "video_encoder.vp9" ,
     "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" ,
     "OMX.google.flac.decoder", "flacdec", "audio_decoder.flac" ,
     "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" ,
     "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" ,
;

makeComponentInstance函数

OMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance(
        const char *name,
        const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData,
        OMX_COMPONENTTYPE **component) 
    ALOGV("makeComponentInstance '%s'", name);

    for (size_t i = 0; i < kNumComponents; ++i) 
        if (strcmp(name, kComponents[i].mName)) 
            continue;
        

        AString libName = "libstagefright_soft_";
        libName.append(kComponents[i].mLibNameSuffix);
        libName.append(".so");

        // RTLD_NODELETE means we keep the shared library around forever.
        // this eliminates thrashing during sequences like loading soundpools.
        // It also leaves the rest of the logic around the dlopen()/dlclose()
        // calls in this file unchanged.
        //
        // Implications of the change:
        // -- the codec process (where this happens) will have a slightly larger
        //    long-term memory footprint as it accumulates the loaded shared libraries.
        //    This is expected to be a small amount of memory.
        // -- plugin codecs can no longer (and never should have) depend on a
        //    free reset of any static data as the library would have crossed
        //    a dlclose/dlopen cycle.
        //

        void *libHandle = dlopen(libName.c_str(), RTLD_NOW|RTLD_NODELETE);

        if (libHandle == NULL) 
            ALOGE("unable to dlopen %s: %s", libName.c_str(), dlerror());

            return OMX_ErrorComponentNotFound;
        

        typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
                const char *, const 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<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;

  • 该函数 通过ACodec 传递的name 参数,动态加载对应的编解码器,如 libstagefright_soft_aacdec.so。其包含的so如下:

  • dlsym 查找createSoftOMXComponent符号值;
  • 创建编解码器
android::SoftOMXComponent *createSoftOMXComponent(
        const char *name, const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData, OMX_COMPONENTTYPE **component) 
    return new android::SoftAACEncoder2(name, callbacks, appData, component);

SoftAACEncoder2为aac 编码器对应的实现类。其继承关系如下:

总结:OMXPlugin分为软硬编解码库,分别加载不同给so,实现其对应的编解码。

以上是关于Android MultiMedia框架——OMXPlugin的主要内容,如果未能解决你的问题,请参考以下文章

Android MultiMedia框架——MediaCodec编码(上)

Android MultiMedia框架——OMXPlugin

Android MultiMedia框架——ALooper AHandler AMessage

Android MultiMedia框架——MediaCodec编码(下)

Android Multimedia框架总结(十三)CodeC部分之OpenMAX框架初识及接口与适配层实现

Android音视频——OpenMAX (OMX)框架