美文网首页
Android多媒体框架--19:OMX服务启动

Android多媒体框架--19:OMX服务启动

作者: DarcyZhou | 来源:发表于2023-05-03 09:19 被阅读0次

    "本文转载自:[VNanyesheshou]的Android MultiMedia框架——OMX服务启动"

    1.概述

      hw/android.hardware.media.omx@1.0-service和audioserver进程类似,也是通过init进程加载rc文件的方式,启动service。rc配置文件:frameworks/av/services/mediacodec/android.hardware.media.omx@1.0-service.rc

    service vendor.media.omx /vendor/bin/hw/android.hardware.media.omx@1.0-service
        class main
        user mediacodec
        group camera drmrpc mediadrm
        ioprio rt 4
        writepid /dev/cpuset/foreground/tasks
    

    OMX服务流程图如下:

    01.png

    看一下其内部实现:

    • main_codecservice.cpp
    int main(int argc __unused, char** argv)
    {
        //(1)修改进程名
        strcpy(argv[0], "media.codec");
    
        signal(SIGPIPE, SIG_IGN);
        SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
    
        android::ProcessState::initWithDriver("/dev/vndbinder");
        android::ProcessState::self()->startThreadPool();
    
        ::android::hardware::configureRpcThreadpool(64, false);
    
        //(2)定制编解码器服务
        void *registrantLib = dlopen(
                "libmedia_codecserviceregistrant.so",
                RTLD_NOW | RTLD_LOCAL);
        if (registrantLib) {
            RegisterCodecServicesFunc registerCodecServices =
                    reinterpret_cast<RegisterCodecServicesFunc>(
                    dlsym(registrantLib, "RegisterCodecServices"));
            if (registerCodecServices) {
                registerCodecServices();
            } else {
                LOG(WARNING) << "Cannot register additional services "
                        "-- corrupted library.";
            }
        } else {
            // Default codec services
            // (3)默认codec services
            using namespace ::android::hardware::media::omx::V1_0;
            //(4)创建OmxStore,并注册服务
            sp<IOmxStore> omxStore = new implementation::OmxStore();
            if (omxStore == nullptr) {
                LOG(ERROR) << "Cannot create IOmxStore HAL service.";
            } else if (omxStore->registerAsService() != OK) {
                LOG(ERROR) << "Cannot register IOmxStore HAL service.";
            }
            //(5)创建Omx,并注册服务
            sp<IOmx> omx = new implementation::Omx();
            if (omx == nullptr) {
                LOG(ERROR) << "Cannot create IOmx HAL service.";
            } else if (omx->registerAsService() != OK) {
                LOG(ERROR) << "Cannot register IOmx HAL service.";
            } else {
                LOG(INFO) << "IOmx HAL service created.";
            }
        }
    
        ::android::hardware::joinRpcThreadpool();
    }
    

    上述代码主要实现了以下操作:
    (1)strcpy修改进程名为media.codec;修改后的进程信息为:

    mediacodec 910 1 1 19:08:07 ? 00:00:00 media.codec hw/android.hardware.media.omx@1.0-service
    

    (2)加载libmedia_codecserviceregistrant.so,判断是否有定制编解码器服务;
    (3)默认codec services;
    (4)创建OmxStore,并注册服务;
    (5)创建Omx,并注册服务。

    2.OmxStore

      查看OMXStore初始化方法:

    OmxStore::OmxStore(
            const char* owner,
            const char* const* searchDirs,
            const char* mainXmlName,
            const char* performanceXmlName,
            const char* profilingResultsXmlPath) {
        MediaCodecsXmlParser parser(searchDirs,
                mainXmlName,
                performanceXmlName,
                profilingResultsXmlPath);
        mParsingStatus = toStatus(parser.getParsingStatus());
    
        const auto& serviceAttributeMap = parser.getServiceAttributeMap();
        mServiceAttributeList.resize(serviceAttributeMap.size());
        size_t i = 0;
        for (const auto& attributePair : serviceAttributeMap) {
            ServiceAttribute attribute;
            attribute.key = attributePair.first;
            attribute.value = attributePair.second;
            mServiceAttributeList[i] = std::move(attribute);
            ++i;
        }
    
        const auto& roleMap = parser.getRoleMap();
        mRoleList.resize(roleMap.size());
        i = 0;
            //.......
        mPrefix = parser.getCommonPrefix();
    }
    
    

    OMXStore初始化通过MediaCodecsXmlParser加载media_codecs.xml、media_codecs_performance.xml,并将信息保存在mServiceAttributeList、mRoleList中,通过日志观察下大致数据:

    (1)mServiceAttributeList

    attribute key: 'max-video-encoder-input-buffers', value: '11'
    

    (2)mRoleList

    03-19 19:53:19.510 D/OmxStore(  909): role:'audio_decoder.aac', type:audio/mp4a-latm, isEncoder:0, preferPlatformNodes:1
    03-19 19:53:19.510 D/OmxStore(  909): node name:'OMX.google.aac.decoder', owner: default
    03-19 19:53:19.510 D/OmxStore(  909): ----------------------
    03-19 19:53:19.510 D/OmxStore(  909): role:'audio_decoder.amrnb', type:audio/3gpp, isEncoder:0, preferPlatformNodes:1
    03-19 19:53:19.510 D/OmxStore(  909): node name:'OMX.google.amrnb.decoder', owner: default
    03-19 19:53:19.510 D/OmxStore(  909): ----------------------
    03-19 19:53:19.510 D/OmxStore(  909): role:'audio_decoder.amrwb', type:audio/amr-wb, isEncoder:0, preferPlatformNodes:1
    03-19 19:53:19.510 D/OmxStore(  909): node name:'OMX.google.amrwb.decoder', owner: default
    ......
    

    mPrefix 为 OMX。

      下面再看一下media_codecs.xml文件:

    <MediaCodecs>
        <Include href="media_codecs_google_audio.xml" />
        <Include href="media_codecs_google_telephony.xml" />
        <Settings>
            <Setting name="max-video-encoder-input-buffers" value="11" />
        </Settings>
        <Encoders>
            <!-- Audio Hardware  -->
            <!-- Audio Software  -->
            <!-- Video Hardware  -->
            <MediaCodec name="OMX.qcom.video.encoder.avc" type="video/avc" >
                <Quirk name="requires-allocate-on-input-ports" />
                <Quirk name="requires-allocate-on-output-ports" />
                <Quirk name="requires-loaded-to-idle-after-allocation" />
                <Limit name="size" min="96x64" max="4096x4096" />
                <Limit name="alignment" value="2x2" />
                <Limit name="block-size" value="16x16" />
                <Limit name="block-count" range="1-34560" /> <!-- max 4096x2160 -->
                <Limit name="blocks-per-second" min="1" max="979200" />
                <Limit name="bitrate" range="1-100000000" />
                <Limit name="frame-rate" range="1-240" />
                <Limit name="concurrent-instances" max="16" />
            </MediaCodec>
                    //......
        </Encoders>
        <Decoders>
           <!-- Video Hardware  -->
            <MediaCodec name="OMX.qcom.video.decoder.avc" type="video/avc" >
                <Quirk name="requires-allocate-on-input-ports" />
                <Quirk name="requires-allocate-on-output-ports" />
                <Limit name="size" min="64x64" max="4096x4096" />
                <Limit name="alignment" value="2x2" />
                <Limit name="block-size" value="16x16" />
                <Limit name="block-count" range="1-34560" /> <!-- max 4096x2160 -->
                <Limit name="blocks-per-second" min="1" max="1958400" />
                <Limit name="bitrate" range="1-100000000" />
                <Feature name="adaptive-playback" />
                <Limit name="concurrent-instances" max="16" />
            </MediaCodec>
                     //..........
            <!-- Audio Software  -->
        </Decoders>
        <Include href="media_codecs_google_video.xml" />
    </MediaCodecs>
    

    3.Omx

      查看Omx 初始化:

    Omx::Omx() :
        mMaster(new OMXMaster()),
        mParser() {
    }
    

    这里创建了OMXMaster,xml 解析类。

    (1)OMXMaster管理plugin,包括硬编码和软编码。

    OMXMaster::OMXMaster()
        : mVendorLibHandle(NULL) {
    
        pid_t pid = getpid();
        char filename[20];
        snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
        int fd = open(filename, O_RDONLY);
        if (fd < 0) {
          ALOGW("couldn't determine process name");
          strlcpy(mProcessName, "<unknown>", sizeof(mProcessName));
        } else {
          ssize_t len = read(fd, mProcessName, sizeof(mProcessName));
          if (len < 2) {
            ALOGW("couldn't determine process name");
            strlcpy(mProcessName, "<unknown>", sizeof(mProcessName));
          } else {
            // the name is newline terminated, so erase the newline
            mProcessName[len - 1] = 0;
          }
          close(fd);
        }
    
        addVendorPlugin();
        addPlugin(new SoftOMXPlugin);
    }
    
    • 读取processName,删除换行符;
    xxx:/proc/924 # cat comm
    omx@1.0-service
    
    • addVendorPlugin 添加厂商实现的硬件编码 plugin;
    • addPlugin(new SoftOMXPlugin) 添加软件编码 plugin。

    3.1 Vendor硬件plugin

      接着看addVendorPlugin:

    void OMXMaster::addVendorPlugin() {
        addPlugin("libstagefrighthw.so");
    }
    
    void OMXMaster::addPlugin(const char *libname) {
        mVendorLibHandle = android_load_sphal_library(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)());
        }
    }
    

    addVendorPlugin加载共享库libstagefrighthw.so,查找createOMXPlugin函数,并调用createOMXPlugin 获得OMXPluginBase类型对象。

    OMXPluginBase *createOMXPlugin() {
        return new QComOMXPlugin;
    }
    

    接着看addPlugin((*createOMXPlugin)()):

    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 %zu "
                 "components", err, mPluginByComponentName.size());
        }
    }
    

    while循环plugin中的components,并将name 和plugin对应关系保存在在向量mPluginByComponentName中。

    3.2 Soft软件plugin

      addPlugin(new SoftOMXPlugin)对应上述函数,加载其包含的components。这里主要是获取其mName属性, 如下:

    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" },
    };
    

    4.总结

      omx service启动主要创建OmxStore和Omx两个服务,加载解析media_codec相关配置文件,添加硬件、软件插件,并保存plugin与支持的component对应关系。

    相关文章

      网友评论

          本文标题:Android多媒体框架--19:OMX服务启动

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