关注公众号免费阅读全文,进入音视频开发技术分享群!

这一节我们将了解Android OpenMax框架,该框架了解完成之后,我们会再回过头去了解 ACodec,将 MediaCodec - ACodec - OpenMax 连接起来,了解组件的创建控制以及 buffer 的流转。
本篇属于个人学习笔记,如有错误欢迎指出。

我将Android OpenMax框架分为3个部分来学习:

  1. media.codec service:vendor下的HIDL服务,用于查询平台编解码能力,创建/管理编解码组件;
  2. OpenMax IL:OpenMax 框架标准接口,底层编解码组件须实现这些接口;
  3. OMXNodeInstance:OpenMax AL 完成 OpenMax IL层的封装与调用,提供给上层 ACodec 调用;

这一节我们先来了解下相关的代码路径:

  1. hardware/interfaces/media/omx/1.0: 目录下定义有 media.codec 提供的 HIDL service 接口,我们接触比较多的是IOmx.halIOmxStore.halIOmxStore.hal以及IOmxNode.hal
  2. frameworks/av/services/mediacodec:目录下是 media.codec service 实现文件,编译后会生成 android.hardware.media.omx@1.0-service,位于板子 /vendor/bin/hw 目录下;
  3. frameworks/av/media/libstagefright/omx:目录下放有 media.codec service 的 Bn 端实现,以及一些工具OMXUtils.cpp
  4. frameworks/native/headers/media_plugin/media/openmax:目录下放有 OpenMax 的标准接口,底层 Omx Component 需要实现这些标准接口,上层 ACodec 也需要按照标准接口来调用;
  5. frameworks/av/media/libmedia/omx
    frameworks/av/media/libmedia/omx/1.0:
    以上两个目录下放有对 HIDL 调用的封装,封装有两种类型,一种是 LW (Legacy Wrapper)开头的类,另一种是 TW(Treble Wrapper)开头的。

接下来我们来看这些文件是如何使用的?

media.codec 作为一个 HIDL service 首先要有接口定义,我们查看 hardware/interfaces/media/omx/1.0 目录,可以发现 OpenMax 相关的类定义都是以大写的 I 开头,后面接上 Omx(这里的 O 是大写, mx 是小写)。

接着看 frameworks/av/media/libstagefright/omx/1 目录,路径下看到有 Omx.cppOmxStore.cpp,这两个就是 media.codec 的 native 实现,但是我们似乎没看到 IOmxNode ?不要着急我们先接着往下看。

实现了服务相关的文件,那么就要开启进程启动服务了,相关的代码在 frameworks/av/services/mediacodec 下,阅读 main_codecservice.cpp 的代码我们很容易就看出这个进程提供两个服务 IOmxIOmxStore,具体的代码这里不再展开,所以上面提到的 IOmxNode 并不是一个服务,而是服务提供的内容,接下来的问题就是内容实现在哪里呢?

服务启动后我们要获取并调用服务,这里就要看 ACodec 的代码了:

    sp<CodecObserver> observer = new CodecObserver(notify);
sp<IOMX> omx;
sp<IOMXNode> omxNode;
status_t err = NAME_NOT_FOUND;
OMXClient client;
if (client.connect(owner.c_str()) != OK) {
return false;
}
omx = client.interface();
int prevPriority = androidGetThreadPriority(tid);
err = omx->allocateNode(componentName.c_str(), observer, &omxNode);

这里看到 ACodec 并没有获取 IOmx 服务,而是使用 OMXClient 封装了服务获取过程,接着再调用其 interface 接口返回获取的服务代理,不过这里有点要注意,返回代理的类型是 IOMX(三个字母都是大写),并不是之前提到的 IOmx,里面发生了什么?

status_t OMXClient::connect(const char* name) {
using namespace ::android::hardware::media::omx::V1_0;
if (name == nullptr) {
name = "default";
}
sp<IOmx> tOmx = IOmx::getService(name);
if (tOmx.get() == nullptr) {
ALOGE("Cannot obtain IOmx service.");
return NO_INIT;
}
if (!tOmx->isRemote()) {
ALOGE("IOmx service running in passthrough mode.");
return NO_INIT;
}
mOMX = new utils::LWOmx(tOmx);
ALOGI("IOmx service obtained");
return OK;
}

从 OMXClient::connect 我们可以看到,内部获取的服务代理类型仍为 IOmx,但是又对该代理做了一层封装。IOmx 是一个 Treble 类型的对象,LWOmx 是一个 Legacy 类型的对象。

我们都知道调用 Treble 对象方法时会比较麻烦,要回传函数调用返回值时需要构造一个Lambda函数;Legacy 对象的使用是符合我们常规使用习惯的对象。所以,将 IOmx 封装成为 LWOmx 是为了封装 HIDL 调用,简化使用。

WOmx.h 位于 frameworks/av/media/libmedia/include/media/omx/1.0,可以看到它是继承于 IOMX的,再看 IOMX.h 可以发现其方法名和 IOmx 提供的服务是一致的,那这里就验证了我们的猜想:IOMX 是对 IOmx 代理调用的封装。

与之类似的,调用 IOmx 服务获取 IOmxNode 对象后也要将其封装成为 LW 类型,以便后续的使用:

status_t LWOmx::allocateNode(
char const* name,
sp<IOMXObserver> const& observer,
sp<IOMXNode>* omxNode) {
status_t fnStatus;
status_t transStatus = toStatusT(mBase->allocateNode(
name, new TWOmxObserver(observer),
[&fnStatus, omxNode](Status status, sp<IOmxNode> const& node) {
fnStatus = toStatusT(status);
*omxNode = new LWOmxNode(node);
}));
return transStatus == NO_ERROR ? fnStatus : transStatus;
}

上面都是讲 mediaserver 进程使用 media.codec 进程的服务代理,那有没有反过来调用的情况?当然是有的。

还是看 LWOmx::allocateNode,我们会传入一个 CodecObserver 对象用于接收Omx Callback,但是CodecObserver 是继承于 BnOMXObserver 的,这里会有个问题,CodecObserver 将无法通过 HIDL 调用传递给 media.codec 进程,所以调用之前 LWOmx::allocateNode 将 CodecObserver 封装到了 TWOmxObserver 以便该对象可以通过 HIDL 传输。

struct TWOmxObserver : public IOmxObserver {
sp<IOMXObserver> mBase;
TWOmxObserver(sp<IOMXObserver> const& base);
Return<void> onMessages(const hidl_vec<Message>& tMessages) override;
};

TWOmxObserver 继承于IOmxObserver 接口,因此可以在 HIDL 中进行传输,这也是 TW (Treble Wrapper)的作用。

再看 frameworks/av/media/libmedia/include/media/omx/1.0/WOmxObserver.h 里面还有个 LWOmxObserver ,它的作用上面我们已经讲过了,是将 mediaserver 进程传过来的 TWOmxObserver 对象进行封装,达到简化 HIDL 调用的目的。


这一节我们对 Android OpenMax 相关的文件以及类做了简单介绍,了解这些之后我们再追代码就可以忽略掉一些中间层,后期如果相关的写作疑问也可以参考这里。

Android 13 - Media框架(13)- OpenMax(一)的更多相关文章

  1. 简析Android 兼容性测试框架CTS使用

    一.什么是兼容性测试? 1)为用户提供最好的用户体验,让更多高质量的APP可以顺利的运行在此平台上 2)让程序员能为此平台写更多的高质量的应用程序 3)可以更好的利用Android应用市场 二.CTS ...

  2. 15 个 Android 通用流行框架大全(转)

    1. 缓存 DiskLruCache    Java实现基于LRU的磁盘缓存 2.图片加载 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picas ...

  3. Android 通用流行框架

    原文出处: http://android.jobbole.com/83028/ 1. 缓存 名称 描述 DiskLruCache Java实现基于LRU的磁盘缓存 2.图片加载 名称 描述 Andro ...

  4. 经受时间沉淀的15 个 Android 通用流行框架大全

    1. 缓存 名称描述 DiskLruCache: Java实现基于LRU的磁盘缓存 2.图片加载 名称描述 Android    Universal Image Loader 一个强大的加载,缓存,展 ...

  5. Android通用流行框架大全

    1. 缓存 名称 描述 DiskLruCache Java实现基于LRU的磁盘缓存 2.图片加载 名称 描述 Android Universal Image Loader 一个强大的加载,缓存,展示图 ...

  6. 60.Android通用流行框架大全

    转载:https://segmentfault.com/a/1190000005073746 Android通用流行框架大全 1. 缓存 名称 描述 DiskLruCache Java实现基于LRU的 ...

  7. 15 个 Android 通用流行框架大全

      1. 缓存 名称 描述 DiskLruCache Java实现基于LRU的磁盘缓存 2.图片加载 名称 描述 Android Universal Image Loader 一个强大的加载,缓存,展 ...

  8. Android 通用流行框架大全

    1. 缓存 DiskLruCache    Java实现基于LRU的磁盘缓存 2.图片加载 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库 Picas ...

  9. 玩转Android之数据库框架greenDAO3.0使用指南

    用过ActiveAndroid.玩过ORMLite,穿过千山万水,最终还是发现greenDAO好用,ActiveAndroid我之前有一篇文章介绍过 玩转Android之数据库框架ActiveAndr ...

  10. Android的MVC框架

    http://www.cnblogs.com/wanghafan/archive/2012/07/20/2600786.html MVC是当前比较流行的框架,随便Google下,就可以发现几乎所有的应 ...

随机推荐

  1. HarmonyOS传感器开发指南

      HarmonyOS系统传感器是应用访问底层硬件传感器的一种设备抽象概念.开发者根据传感器提供的Sensor接口,可以查询设备上的传感器,订阅传感器数据,并根据传感器数据定制相应的算法开发各类应用, ...

  2. maven 创建spring boot 需要的配置[一]

    前言 之所以写这个是因为现在官方推荐云创建: 所以标注一下maven project,创建后,如何导入spring boot. 正文 1.步骤一 在pom.xml 中加入: <dependenc ...

  3. c# 反编译对比(旧)

    前言 旧的都是我以前博客的迁移. 我们写代码有时候遇到一些问题,或者我们想优化我们的代码,我们想要看编译后的运行情况,那么反编译是必须要做的一件事. 正文 在此我自己使用的是reflector和ILS ...

  4. 实验k8s ————— k8s 搭建[一]

    前言 以前学习k8s记录的.这里简单整理一下搭建,当时是我们学习环境的搭建,正式环境得专门的运维人员来,毕竟人家考虑的东西不一样. 正文 这里用kubeadm进行搭建,更加详细信息,在这里: http ...

  5. mmcls 多标签模型部署在torch serve

    GitHub仓库:gy-7/mmcls_multi_label_torchserve (github.com) 各个文件说明: cls_requests_demo:分类模型请求api服务的demo d ...

  6. Python阿里云消息推送调用API

    很多公司测试APP推送时候,应该也是很头疼:推送环境:测试.正式,稍不注意就把测试的push到正式上,导致所有用户都收到 例子很多: 其实阿里.极光都有推送Api,直接调用API就ok,特别是有的公司 ...

  7. List拖拽功能的实现

    概述   如何在HarmonyOS应用中实现一个可拖拽的列表组件,通过这个组件,用户可以拖动列表中的项并将其放置在新的位置,实现列表的动态排序.   核心功能   列表初始化:创建并填充列表数据. 拖 ...

  8. 小白也能懂的 Nacos 服务模型介绍

    简介: 理解了 Nacos 的服务模型,也有利于我们了解 Nacos 背后的工作原理,从而确保我们正确地使用 Nacos. 作者:岛风 前言 按照目前市场上的主流使用场景,Nacos 被分成了两块功能 ...

  9. 超详攻略!Databricks 数据洞察 - 企业级全托管 Spark 大数据分析平台及案例分析

    简介: 5分钟读懂 Databricks 数据洞察 ~ 更多详细信息可登录 Databricks 数据洞察 产品链接:https://www.aliyun.com/product/bigdata/sp ...

  10. 深入解析 Dubbo 3.0 服务端暴露全流程

    ​简介: 随着云原生时代的到来,Dubbo 3.0 的一个很重要的目标就是全面拥抱云原生.正因如此,Dubbo 3.0 为了能够更好的适配云原生,将原来的接口级服务发现机制演进为应用级服务发现机制. ...