美文网首页
Android多媒体框架--20:OMXPlugin

Android多媒体框架--20:OMXPlugin

作者: DarcyZhou | 来源:发表于2023-05-04 08:58 被阅读0次

    "本文转载自:[VNanyesheshou]的Android MultiMedia框架——OMXPlugin"

    1.概述

      上一篇《Android多媒体框架--19:OMX服务启动》中提到OMXMaster添加两个Plugin,一个是SoftOMXPlugin,另一个是供应商实现的硬件Plugin,其父类是OMXPluginBase。

    2.OMXPluginBase

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

    • frameworks/native/headers/media_plugin/media/hardware/OMXPluginBase.h
    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。

    3.QComOMXPlugin

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

    • hardware/qcom/media/**/libstagefrighthw/QComOMXPlugin.cpp
    OMXPluginBase *createOMXPlugin() {
        //(1)创建QComOMXPlugin
        return new QComOMXPlugin;
    }
    ---------------
    QComOMXPlugin::QComOMXPlugin()
        //(2)加载libOmxCore.so
        : mLibHandle(dlopen("libOmxCore.so", RTLD_NOW)),
          mInit(NULL),
          mDeinit(NULL),
          mComponentNameEnum(NULL),
          mGetHandle(NULL),
          mFreeHandle(NULL),
          mGetRolesOfComponentHandle(NULL) {
        if (mLibHandle != NULL) {
            //(3)通过dlsym查找OMX_Init、OMX_Deinit等符号值
            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中为厂商高通实现的具体硬件编解码功能,这里先不分析了。

    4.SoftOMXPlugin

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

    • frameworks/av/media/libstagefright/omx/SoftOMXPlugin.cpp
    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.
            //
    
            //(1)动态加载对应的编解码器
            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 **);
            //(2)dlsym查找createSoftOMXComponent符号值
            CreateSoftOMXComponentFunc createSoftOMXComponent =
                (CreateSoftOMXComponentFunc)dlsym(
                        libHandle,
                        "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
                        "PvPP17OMX_COMPONENTTYPE");
    
            if (createSoftOMXComponent == NULL) {
                dlclose(libHandle);
                libHandle = NULL;
    
                return OMX_ErrorComponentNotFound;
            }
    
            // (3)创建编解码器
            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;
    }
    

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

    01.png

    (2)dlsym 查找createSoftOMXComponent符号值;
    (3)创建编解码器;

    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编码器对应的实现类。其继承关系如下:

    02.png

    5.总结

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

    相关文章

      网友评论

          本文标题:Android多媒体框架--20:OMXPlugin

          本文链接:https://www.haomeiwen.com/subject/eweqjdtx.html