IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> OMX服务启动及加载 -> 正文阅读

[移动开发]OMX服务启动及加载

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

二、OMX服务启动及插件加载:
Android的init.rc脚本会去执行android.hardware.media.omx@1.0-service.rc脚本(framework/av/services/mediacodec):

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

脚本会去启动android.hardware.media.omx@1.0-service服务,从对应路径下的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的方式去访问;

在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:02:43  更:2022-05-10 12:02:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 2:00:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码