Android Multimedia框架总结(十一)CodeC部分之AwesomePlayer到OMX服务
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52623882
前言:上篇文《Android Multimedia框架总结(十)》总结了音视频的输出过程,从今天开始分析Codec部分,今天分析的是AwesomePlayer到OMX服务过程,也就是开启OpenMax准备相关。
先看下今天的Agenda:
- 一张图看清OMX在stagefright中的位置
- 一张图看清OpenMax与Stagefright层级的关系
- OMX初始化流程
- OMX服务之NodeInstance列表的管理
- OMX服务之NodeInstance节点的操作
- 总结AwesomePlayer到OMX服务过程
背景: Android系统中用OpenMAX来做编解码,Android向上抽象了一层OMXCodec,提供给上层播放器AwesomePlayer用。播放器中音视频解码器mVideosource、mAudiosource都是OMXCodec的实例。
OMXCodec::Create是解码器初始化的入口。
OMXCodec通过IOMX 依赖binder机制 获得OMX服务,OMX服务才是OpenMAX在Android中实现
一张图看清OMX在stagefright中的位置:
一张图看清OpenMax与Stagefright层级的关系:
OMX初始化流程
AwesomePlayer是如何获得OMX服务的?
- 在AwesomePlayer初始化的时候,会调用AwesomePlayer::onPrepareAsyncEvent。
- 继而调用AwesomePlayer::initVideoDecoder以及AwesomePlayer::initAudioDecoder。
- 然后开始正式的进入OMX以及硬件解码器的初始化工作。
之前的AwesomePlayer初始化的一些工作都是在小打小闹。当OMX开始初始时,才是开始真正核心的初始化工作。我们知道,android中的组件都是在提供服务,有server,有client,大多是C/S模型,前面文章已介绍。
AwesomePlayer 中有个变量 OMXClient mClient;
先了解OMXClient.cpp,如下:
OMXClient 有个IOMX的变量mOMX ,这个就是和OMX服务进行binder通信的。
在AwesomePlayer的构造函数中会调用:
CHECK_EQ(mClient.connect(), (status_t)OK);
OMXClient中代码如下:
OMXClient::connect函数是通过binder机制 获得到MediaPlayerService,然后通过MediaPlayerService来创建OMX的实例。这样OMXClient就获得到了OMX的入口,接下来就可以通过binder机制来获得OMX提供的服务。
也就是说OMXClient 是android中 openmax 的入口。
在创建音视频解码mVideoSource、mAudioSource的时候会把OMXClient中的sp mOMX的实例 传给mVideoSource、mAudioSource来共享使用这个OMX的入口。
也就是说一个AwesomePlayer对应着 一个IOMX 变量,AwesomePlayer中的音视频解码器共用这个IOMX变量来获得OMX服务。
以上分为1,2两个步骤,先看下1中OMXCodec::Create函数
每个AwesomePlayer实例只有一个OMX服务的入口,但是AwesomePlayer不一定就只需要1种解码器。音视频都要有,部分场景下还有多路音频,或者多路视频。
这个时候OMX那边需要建立不同的解码器的组件来对应着AwesomePlayer中不同的解码需求。
本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52623882
OMX中非常重要的2个成员: OMXMaster 和 OMXNodeInstance。
- OMX通过这俩个成员来创建和维护不同的openmax 解码器组件,为AwesomePlayer中不同解码需求提供服务。
OMXNodeInstance 负责创建并维护不同的实例,这些实例是根据实际的解码需求创建的,以node_id作为唯一标识。 - 这样解码器组件中每个OMXCodec在OMX服务端都对应有了自己的OMXNodeInstance实例。AwesomePlayer就可以根据这个OMXNodeInstance来操作相应解码器
- OMXMaster 维护底层软硬件解码库,是对解码器组件的一个大管家,根据OMXNodeInstance中想要的解码器来创建解码实体组件。
所以我们要追踪下OMXMaster和OMXNodeInstance。
OMX构造函数中会进行初始化。
OMX.cpp中
OMXMaster.cpp中
到这里,我们就明白了AwesomePlayer是如何利用具体的硬件平台上的硬件解码器。
那么针对不同的文件格式,如何选择具体的解码器组件呢?
继续顺着前面的OMXCodec::Create介绍。看一下allocateNode
在OMX.cpp中
会调用makeComponentInstance函数
这样就实现了根据文件编码格式,对具体解码器的连接
接下来了解下OMXcodec如何注册和初始化OMX所需要的回调函数。
OMX服务主要完成三个任务: NodeInstance列表的管理,NodeInstance的操作, 事件的处理。
本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52623882
NodeInstance列表的管理
- OMX对解码器组件component的使用,是通过OMXNodeInstance来实现的。
OMXNodeInstance自身的动作包括NodeInstance的生成(allocateNode)和删除(freeNode)。
其实就是对mDispatchers和 mNodeIDToInstance进行添加和删除。 - mNodeIDToInstance就是一个key为node_id,value为 NodeInstance的名值对列表。
而mDispatchers就是一个key为node_id,value为 OMX::CallbackDispatcher的名值对列表。
并且,一个NodeInstance都拥有一个 OMX::CallbackDispatcher。 - CallbackDispatcher的作用主要是解码器组件component发出回调动作后,将message分发给对应的OMXcodec客户端。
NodeInstance节点的操作
OMXNodeInstance主要成员函数如下:
这些方法执行时,都是先通过findInstance在mNodeIDToInstance列表中找到对应的NodeInstance,然后调用NodeInstance对应的方法。
- OMXCodec对具体的component方法的操作,是通过OMXNodeInstance来实现的。
如fillBuffer,emptybuffer,sendCommand等,都是通过OMX_Core.h中的宏定义间接调用OMX_Component.h中的 - OMX_COMPONENTTYPE这个struct中的相应函数指针来完成。OMX_Core.h和 OMX_Component.h都是OpenMAX标准头文件。
在OMXNodeInstance.cpp中的这样一段代码:
- 它把三个OMXNodeInstance类的静态方法注册给了kCallbacks。
- kCallbacks实际就是struct OMX_COMPONENTTYPE和struct OMX_CALLBACKTYPE的具体实现。
- 而这两者就是在OMX_Core.h和 OMX_Component.h中定义的。
kCallbacks在哪里使用呢?看一下OMX.cpp中的allocateNode方法中的代码:
事件处理函数传给了组件ComponentInstance。也就是传给了具体芯片平台相关的OMX IL 层。
当组件有事件发生时,就会调用OMXNodeInstance中这几个注册过的事件处理函数:
而这几个函数又会去调用OMX中对应的函数,也就是下面这三个:
总结以上代码如下:
- 这几个函数都采用相同的方式:
- 根据node_id找到CallbackDispatcher,并把事件信息post过去。
也就是:findDispatcher(node)->post(msg)。
进一步,须要了解CallbackDispatcher的实现机制。它内部开启了一个线程,使用了信号量机制(signal)。
findDispatcher(node)->post(msg)是一个异步操作,只把msg给POST过去,不会等待事件处理完毕就返回了。
问题来了,那么CallbackDispatcher是怎么处理接收到的msg呢?
看以下代码:
这样事件最终还是跨Binder又传到了OMXCodec里面去,交给OMXCodecObserver了。也就是交给了调用OMX service的client端了。
将回调的发生,从service端发送到了client端。
最后,总结一下前面:
- 1、AwesomePlayer初始化过程中,中通过initVideoDecoder / init AudioDecoder来创建video/Audio解码器mVideoSource/mAudioSource
- 2、mVideoSource 中通过mVideoTrack来demux 媒体文件,从中获得文件编码格式,继而得到需要的解码器类型,通过类型调用omx->allocateNode 创建OMX node实例与编码格式对应。以后都是通过node实例来操作实际的硬件解码器。
- 3、MediaPlayerService对象初始化的时候会创建OMX对象,OMX对象的构造函数会创建mMaster,mMaster负责获得与管理硬件平台的硬件解码器组件库。
- 4、在 omx->allocateNode中 通过mMaster->makeComponentInstance 来创建真正对应的解码器组件。这个解码器组件是完成之后实质的解码工作的。
- 5、在创建mMaster->makeComponentInstance过程中,也是通过上面mVideoTrack 过来的解码器类型名,找到相对应的解码器的库,然后实例化。
- 6、解码Component通过输入Port和输出Port来进行交互,通过和OMXCodec共享buffer来进行编解码。
- 7、AwesomePlayer中包含了mVideoSource,初始化时指向OMXCodec的实际对象。OMXCodec使用了Binder机制,实现了对OMX服务的远程调用,其中IOMX作为接口类定义了OMX的大部分接口函数。
- 8、OMX的具体实现时,OMXMaster类用于管理OMX的插件,OMXNodeInstance类代表OMX的具体实例,完成和Component的调用和交互,
- 9、CallbackDispatcher用于调度处理回调函数传回的消息。OMXNodeInstance和CallbackDispatcher一一对应,协同工作,完成不同实例的消息处理。
- 10、OMXNodeInstance是OMX端的概念,是service端的概念。其service端与OMX在一个进程空间中。
- 11、OMXObserver是OMXCodec端的概念,是client端的概念。其service端与OMXCodec在一个进程空间中。其Bn,Bp 方向和OMX,OMXNodeInstance相反。主要是用来反向通知onMessage消息
到此,我们就介绍完了awesomeplayer是如何对OMX初始化,以及如何关联到对应硬件平台上的HW decoder的。
第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。
如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易
Android Multimedia框架总结(十一)CodeC部分之AwesomePlayer到OMX服务的更多相关文章
- Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52629449 前言:上篇文中分析 ...
- Android Multimedia框架总结(十三)CodeC部分之OpenMAX框架初识及接口与适配层实现
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52629598 前言:上篇中介绍O ...
- Android Multimedia框架总结(九)Stagefright框架之数据处理及到OMXCodec过程
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52532085 不知不觉到第九篇了,感觉还有 ...
- Android Multimedia框架总结(十五)Camera框架之Camera2补充
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52751055 前言:监于5.0之 ...
- Android Multimedia框架总结(七)C++中MediaPlayer的C/S架构补充及MediaService介绍
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼,文章链接: http://blog.csdn.net/hejjunlin/article/details/52465168 前面一篇主要介绍 ...
- Android Multimedia框架总结(六)C++中MediaPlayer的C/S架构
转载请把头部出处链接和尾部二维码一起转载,本文出自: http://blog.csdn.net/hejjunlin/article/details/52435789 前面几节中,都是通过java层调用 ...
- Android Multimedia框架总结(一)MediaPlayer介绍之状态图及生命周期
请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52349221 前言:从本篇开始,将进入Multimedia框架,包含 ...
- Android Multimedia框架总结(二十三)MediaCodec补充及MediaMuxer引入(附案例)
请尊重分享成果,转载请注明出处,本文来自逆流的鱼yuiop,原文链接:http://blog.csdn.net/hejjunlin/article/details/53729575 前言:前面几章都是 ...
- Android Multimedia框架总结(二十)MediaCodec状态周期及Codec与输入/输出Buffer过程(附实例)
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53183718 前言:前面几节都是 ...
随机推荐
- mysql之连接查询小作业
#数据准备drop table if exists class;create table class( class_no int(2) unsigned zerofill primary key ...
- 实验吧_天下武功唯快不破&让我进去(哈希长度拓展攻击)
天下武功唯快不破 第一反应就去抓包,看到返回包的header中有FLAG的值,base64解码后得到下图所示 这就要求我们在请求头中post相应key的值,我直接在burp中尝试了多次都没有用,想起来 ...
- php一句话反弹bash shell
来源:https://www.leavesongs.com/PHP/backshell-via-php.html 用到了,记录一下 $sock = fsockopen($ip, $port); $de ...
- 洛谷4月月赛R1 Happy Poppin' Party Train
来自FallDream的博客,未经允许,请勿转载,谢谢. 听学长说的就来玩一玩,随便乱打打 没想到一堆人被取消了成绩,莫名混了个Rank3 还有第一题数据肯定是有问题 --------------- ...
- 一起来Fit TDMA over WiFi(1)
1 概述 WiFI TDMA领域,2009年Sam Leffler在<TDMA for Long Distance Wireless Networks>首次系统提出了TDMA技术方案,并 ...
- USB_ESD处理
今天收到客户反馈说碰到USB后机器会死机,之前一直没有关注ESD问题. 现在整理之前用过的成熟的ESD电路: 电感为 PZ3216D101-3R0TF,1206封装. 用ESD枪测试OK, 用打火机持 ...
- 数据结构之堆Heap
1. 概述 堆(也叫优先队列),是一棵完全二叉树,它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等. 2. 堆 ...
- 关于一些基础的Java问题的解答(一)
学习一门语言基础是非常重要的,因此本文总结了一些常见的Java基础问题的解答,希望可以帮到大家. 1. 九种基本数据类型的大小,以及他们的封装类. 9种基本数据类型 基本类型 包装类型 大小 bool ...
- 数据挖掘_requests模块的post方法
前面已经跟大家讲了requests模块的get方法,这一篇文章我们要介绍的是requests模块中的另一个比较常用的方法,post方法 post方法的形式相比于get要复杂一些,这时因为post在提交 ...
- RedHatEnterpriseLinuxServerRelease7.3上配置vsftp服务器
1.vsftpd 服务启停相关命令 systemctl start vsftpd systemctl stop vsftpd systemctl restart vsftpd 2.配置文件/etc/v ...