OMX服务启动及加载

一、引言:
OMX作为跨平台的多媒体解码框架,在Android上使用的尤其广泛,不论是Android移动平台还是Android TV,OMX已经成为了硬解通路的必然选择,在Android原生的媒体服务上,OMX是stagefright框架的底层重要支撑,随着Android版本的提升,媒体相关的服务被逐渐细化,Android P上,OMX被划到MediaCodec的服务中。

二、OMX服务启动及插件加载:
Android的init.rc脚本会去执行[email protected]脚本(framework/av/services/mediacodec):

service vendor.media.omx /vendor/bin/hw/[email protected]
    class main
    user mediacodec
    group camera drmrpc mediadrm
    capabilities SYS_NICE
    ioprio rt 4
    writepid /dev/cpuset/foreground/tasks

脚本会去启动[email protected]服务,从对应路径下的mk可以看到,这个服务是由main_codecservice.cpp编译出来的,下面看一下其main函数:

int main(int argc __unused, char** argv)
{
    
    
    strcpy(argv[0], "media.codec");
    LOG(INFO) << "mediacodecservice starting";
    signal(SIGPIPE, SIG_IGN);
    SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);

    android::ProcessState::initWithDriver("/dev/vndbinder");
    android::ProcessState::self()->startThreadPool();

    ::android::hardware::configureRpcThreadpool(64, false);

    // Registration of customized codec services
    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.";
        }
        /* 实例化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();
}

main函数中会去实例化OMX,看一下OMX的构造函数:

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

这里会去实例化OMXMaster:

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


我们重点关注addVendorPlugin()

void OMXMaster::addVendorPlugin() {
    
    
    addPlugin("libstagefrighthw.so");
}

看下addPlugin

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

这里会去加载libstagefrighthw.so并且重定向到函数createOMXPlugin。到这里需要确认一个问题,芯片平台的libstagefrighthw.so是从哪里来的,其对应的createOMXPlugin函数是如何实现的。我目前使用的是MTK的芯片平台,库是由MTK自己命名的文件编译出来的,只要保证库名是libstagefrighthw.so并且实现一些OMX标准组件的接口,就可以加载芯片平台的硬解库了,找到对应的源码及函数createOMXPlugin

OMXPluginBase *createOMXPlugin() {
    
    
    return new MSOMXPlugin;
}

这里会去构造芯片平台自己的MSOMXPlugin类对象:

MSOMXPlugin::MSOMXPlugin()
      : mLibHandle(dlopen("libOMX.MStar.so", RTLD_NOW)),
      mInit(NULL),
      mDeinit(NULL),
      mComponentNameEnum(NULL),
      mGetHandle(NULL),
      mFreeHandle(NULL),
      mGetRolesOfComponentHandle(NULL),
      mSetupTunnel(NULL),
      mTearDownTunnel(NULL) {
    
    
    ALOGD("MSOMXPlugin::MSOMXPlugin");
    if (mLibHandle != NULL) {
    
    
        ALOGD("Get libOMX.MStar.so");
        mInit = (InitFunc)dlsym(mLibHandle, "MS_OMX_Init");
        mDeinit = (DeinitFunc)dlsym(mLibHandle, "MS_OMX_DeInit");

        mComponentNameEnum =
            (ComponentNameEnumFunc)dlsym(mLibHandle, "MS_OMX_ComponentNameEnum");

        mGetHandle = (GetHandleFunc)dlsym(mLibHandle, "MS_OMX_GetHandle");
        mFreeHandle = (FreeHandleFunc)dlsym(mLibHandle, "MS_OMX_FreeHandle");

        mGetRolesOfComponentHandle =
            (GetRolesOfComponentFunc)dlsym(
                    mLibHandle, "MS_OMX_GetRolesOfComponent");

#ifdef BUILD_GOOGLETV
        mSetupTunnel = (SetupTunnelFunc)dlsym(mLibHandle, "MS_OMX_SetupTunnel");
        mTearDownTunnel = (SetupTunnelFunc)dlsym(mLibHandle, "MS_OMX_TearDownTunnel");
#endif
        CHECK(mInit != NULL);
        (*mInit)();
		...
}

函数包含的信息非常多,首先会去打开芯片平台的动态库,其次重定向各个OMX组件重要的函数指针,最后还会调用mInit指向的函数做进一步的初始化。这里就把整个OMX服务的启动分析完了。

三、总结:
1.OMX服务是隶属于MediaCodec的binder服务下的子项,在系统服务启动的时候,会去加载MediaCodec的服务,OMX软解的库是一定会加载的,如果芯片平台支持硬解会去加载OMX的硬解库;
2.重启mediaserver进程可以重新加载OMX的硬解库,后续有应用申请OMX组件将以OMX client的方式去访问;

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/achina2011jy/article/details/124630440