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

这一节我们将了解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. 为你推荐一款高效的IO组件——okio

    原文:https://mp.weixin.qq.com/s/XnNhSq8ESoslb2DQEzMbCQ,点击链接查看更多技术内容.   前不久,三方组件库上新了一批JS/eTS组件,其中就包括oki ...

  2. ICMP 概念

    前言 打算从新整理网络这一块,那么我先把概念整理下来. 正文 ICMP是ip的一个组成.他传递差错报文以及其他需要注意的信息.主要用于反馈一些网络传输的问题.因为ip协议很容易丢包,那么icmp可以告 ...

  3. 力扣387(java)-字符串中的第一个唯一字符(简单)

    题目: 给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 .如果不存在,则返回 -1 . 示例 1: 输入: s = "leetcode"输出: 0示例 2: 输 ...

  4. 牛客网-SQL专项训练10

    ①SQL语句中与Having子句同时使用的语句是:group by 解析: SQL语法中,having需要与group by联用,起到过滤group by后数据的作用. ②下列说法错误的是?C 解析: ...

  5. 赋予企业更多可能,云数据库SQL Server 2019版这几大亮点别错过

    直播预告 2020年3月26日 15:00-16:30 邀您一同见证 云数据库SQL Server 2019版重磅发布 全面提升性价比及数据库能力 点我观看 RDS SQL Server 2019不仅 ...

  6. DataFunTalk:阿里建设一站式实时数仓的经验分享

    简介: 本文内容整理于阿里资深技术专家姜伟华在DataFunTalk上的演讲,为大家介绍阿里巴巴基于一站式实时数仓Hologres建设实时数仓的经验和解决方案. 导读:大数据计算正从规模化走向实时化, ...

  7. Apsara Stack 同行者专刊 | 怀同行之心,筑信任之基,践数智之行

    简介: 政企云平台处在怎样的历史阶段?数智创新的同行者们面临着怎样的挑战与机遇?在时代巨幕下,政企期待云厂商扮演怎样的角色?阿里云智能研究员.混合云平台总经理刘国华认为,云厂商不仅需要有定力与实力,也 ...

  8. ClickHouse Keeper 源码解析

    简介:ClickHouse 社区在21.8版本中引入了 ClickHouse Keeper.ClickHouse Keeper 是完全兼容 Zookeeper 协议的分布式协调服务.本文对开源版本 C ...

  9. WPF 已知问题 Popup 吃掉 PreviewMouseDown 事件

    在 WPF 中,使用 Popup 也许会看到 PreviewMouseDown 事件被吃掉 因为 PreviewMouseDown 是 RoutingStrategy.Direct 路由事件,不能在多 ...

  10. WPF 动画实战 点击时显示圆圈淡出效果

    本文告诉大家一个有趣的动画,在鼠标点击的时候,在点击所在的点显示一个圆圈,然后这个圆圈做动画变大,但是颜色变淡的效果.本文的控件可以让大家将对应的容器放在自己应用里面就能实现这个效果 这个效果特别简单 ...