Android MultiMedia框架——OMX服务启动

Posted VNanyesheshou

tags:

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

Android MultiMedia框架——OMX服务启动
Android MultiMedia框架——OMXPlugin
Android MultiMedia框架——MediaCodec编码(上)
Android MultiMedia框架——MediaCodec编码(下)

基于android9.0 源码分析

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服务流程图如下:

看一下其内部实现

main_codecservice.cpp

int main(int argc __unused, char** argv)

    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);

    // 定制编解码器服务
    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
        using namespace ::android::hardware::media::omx::V1_0;
        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.";
        
        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,创建OmxStore,Omx, 分别注册服务;

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中,

通过日志观察下大致数据:

mServiceAttributeList

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

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>

Omx

查看Omx 初始化

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

Omx 初始化:创建OMXMaster,xml 解析类;

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);

  1. 读取processName,删除换行符,

    walleye:/proc/924 # cat comm
    omx@1.0-service
    
  2. addVendorPlugin 添加厂商实现的硬件编码 plugin;

  3. addPlugin(new SoftOMXPlugin) 添加软件编码 plugin;

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中

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" ,
;
以上是关于Android MultiMedia框架——OMX服务启动的主要内容,如果未能解决你的问题,请参考以下文章

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

Android MultiMedia框架——OMXPlugin

Android MultiMedia框架——ALooper AHandler AMessage

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

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

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