转:https://www.jianshu.com/p/593b14444e79
Android系统整体架构:
我们先看一下多媒体框架在整个Android系统所处的位置
![](https://i-blog.csdnimg.cn/blog_migrate/61b0a6dda3c3b86cf9a5a73572b8d06d.webp?x-image-process=image/format,png)
从框架图可以看出Media Framework处于Libraries这一层,这层的Library不是用Java实现,一般是C/C++实现,它们通过Java的JNI方式调用。
![](https://i-blog.csdnimg.cn/blog_migrate/9bf04590eb84de3ec688b6976300ded9.webp?x-image-process=image/format,png)
Android系统的多媒体业务:
![](https://i-blog.csdnimg.cn/blog_migrate/145cde4c3e175686bd7f08b20d9643dc.webp?x-image-process=image/format,png)
多媒体框架变动:
Android froyo版本多媒体引擎做了变动,新添加了stagefright框架,并且默认情况android选择stagefright,弃用之前的opencore,仅仅对opencore中的omx-component部分做了引用。Stagefright自android2.0后才添加,其稳定性有待商榷,是否存在bug也未知,opencore自android诞生起便存在,稳定性有保障。
Opencore上的开发较stagefright上要复杂耗时些。不过,从目前android代码看,opencore有被stagefright取代的趋势,从Android2.3 (Gingerbread) 开始,预设的多媒体框架为 Stagefright。
![](https://i-blog.csdnimg.cn/blog_migrate/18ace1b93f8e4ab570f1ed32f40a63ec.webp?x-image-process=image/format,png)
以MediaPlayer为例,我们先看一下多媒体的简单框架。
![](https://i-blog.csdnimg.cn/blog_migrate/664c7415254186c087595e70de49202e.webp?x-image-process=image/format,png)
上图可知,stagefright是在MediaPlayerService这一层加入的,和opencore是并列的,在选用opencore还是stagefright的代码切换上也非常容易。
OpenCore框架介绍:
Open Core是Android 多媒体框架的核心,所有Android平台的音视频采集,播放的操作都是通过它来实现。它也被称为PV(Packet Video), Packet Video是一家专门提供多媒体解决方案的公司。
通过Open Core程序员可以方便快速的开发出想要的多媒体应用程序,例如:音视频的采集,回放,视频会议,实时的流媒体播放等等应用。在实际开发中我们并不会过多的研究Open Core的实现,Android提供了上层的Media API给开发人员使用,MediaPlayer和MediaRecorder。
CODEC(编解码器)使用OpenMAX IL interface 接口进行扩展,可以方便得支持hardware / software codec plug-ins,支持的格式包括:MPEG4、H.264、MP3、AAC、AMR、JPG、PNG、GIF等。
![](https://i-blog.csdnimg.cn/blog_migrate/3fa4bc531001066d4c257d5c57123b10.webp?x-image-process=image/format,png)
Open Core的代码在Android代码的External/Opencore目录中。这个目录是OpenCore的根目录,其中包含的子目录如下所示:
· android:这里面是一个上层的库,它实现了一个为Android使用的音视频采集,播放的接口,和DRM数字版权管理的接口实现。
· baselibs:包含数据结构和线程安全等内容的底层库
· codecs_v2:音视频的编解码器,基于OpenMAX实现
· engines:核心部分,多媒体引擎的实现
· extern_libs_v2:包含了khronos的OpenMAX的头文件
· fileformats:文件格式的解析(parser)工具
· nodes:提供一些PVMF的NODE,主要是编解码和文件解析方面的。
· oscl:操作系统兼容库
· pvmi: 输入输出控制的抽象接口
· protocols:主要是与网络相关的RTSP、RTP、HTTP等协议的相关内容
· pvcommon:pvcommon库文件的Android.mk文件,没有源文件。
· pvplayer:pvplayer库文件的Android.mk文件,没有源文件。
· pvauthor:pvauthor库文件的Android.mk文件,没有源文件。
· tools_v2:编译工具以及一些可注册的模块。
![](https://i-blog.csdnimg.cn/blog_migrate/3783c36e0733fb37199fc9c63c4c93ec.webp?x-image-process=image/format,png)
StageFright框架介绍:
具体stagefright的内部变动,可见下图概述。Stagefright并没有完全抛弃opencore,主要是做了一个OMX层,用来引用opencore的omx-component部分。而stagefright内部而言,与opencore是完全不同的设计。
![](https://i-blog.csdnimg.cn/blog_migrate/f31219d7c63a4c82360d2ef511d74b3c.webp?x-image-process=image/format,png)
Stagefright的内部组成模块
![](https://i-blog.csdnimg.cn/blog_migrate/3ed56533ea765b5a9e6eca43e2eb7c96.webp?x-image-process=image/format,png)
AwesomePlayer的内部组成模块
![](https://i-blog.csdnimg.cn/blog_migrate/d23e59563499ad90ec63674853693e8a.webp?x-image-process=image/format,png)
调用openMAX IL层时的Video Buffer传输流程
![](https://i-blog.csdnimg.cn/blog_migrate/6fa0053bb95f06bae3b2a394984b1814.webp?x-image-process=image/format,png)
Video Rendering内部组成模块
![](https://i-blog.csdnimg.cn/blog_migrate/75c5b655c33f6a1e2703ffd141f5178b.webp?x-image-process=image/format,png)
Video Playback流程
![](https://i-blog.csdnimg.cn/blog_migrate/88cab6d56c3662f126db573fffbe5a82.webp?x-image-process=image/format,png)
VideoEvent事件驱动
![](https://i-blog.csdnimg.cn/blog_migrate/bf0d6395b3d47f30c0a258b717b44bd3.webp?x-image-process=image/format,png)
Audio Playback流程
![](https://i-blog.csdnimg.cn/blog_migrate/d7f6bf5bab68e4180ae6e1ad3a8e19ba.webp?x-image-process=image/format,png)
awesomeplayer初始化流程
![](https://i-blog.csdnimg.cn/blog_migrate/e433898b01f4e960045622c5bdcbbec8.webp?x-image-process=image/format,png)
- MediaCodec:负责媒体文件的编码和解码工作,内部方法均为native
- MediaExtractor:负责将指定类型的媒体文件从文件中找到轨道,并填充到MediaCodec的缓冲区中
- AudioTrack:负责将解码之后的音频播放
- SurfaceView:展示解码之后的视频
视频被播放主要分为以下步骤:
- 将资源加载到extractor
- 获取视频所在轨道
- 设置extractor选中视频所在轨道
- 创将解码视频的MediaCodec,decoder
- 开始循环,直到视频资源的末尾
- 将extractor中资源以一个单位填充进decoder的输入缓冲区
- decoder将解码之后的视频填充到输出缓冲区
- decoder释放输出缓冲区的同时,将缓冲区中数据渲染到surface
音频的播放类似,只多了AudioTrack部分,少了渲染到surface部分。
MediaCodec.releaseOutputBuffer(int outputBufferIndex, boolean render);
- render为
true
就会渲染到surface
两个框架之间的具体差异:
Opencore所支持的格式![](https://i-blog.csdnimg.cn/blog_migrate/8246e3e52567da023d8859e6c6c09e2c.webp?x-image-process=image/format,png)
Stagefright所支持的格式
![](https://i-blog.csdnimg.cn/blog_migrate/cfe993d4b051501bc3b621145e11c6fa.webp?x-image-process=image/format,png)
Opencore与stagefright两套机制,对于我们的开发而言,主要体现在parser和codec部分。Opencore方面,必须按照其规范完成相应的parser-node,codec则要按照omx规范实现相应的component。Stagefright方面,则要按照其规范实现相应的extractor和decoder。 最基本的实现,二者是相同的,可以共用,差别在封装上,opencore难度和工作量要大。
Opencore处理流程如下图示
![](https://i-blog.csdnimg.cn/blog_migrate/09ed15261ce1b453e954df3e90a0f5ac.webp?x-image-process=image/format,png)
engine分别创建audio/video datapath,parser/dec/sink作为node节点由各自datapath连接起来,后续node节点由统一调度器调度。
Stagefright处理流程如下图示。
![](https://i-blog.csdnimg.cn/blog_migrate/f62379ce7c9036a41a25d0be0f2c25fa.webp?x-image-process=image/format,png)
Audioplayer为AwesomePlayer的成员,audioplayer通过callback来驱动数据的获取,awesomeplayer则是通过videoevent来驱动。二者有个共性,就是数据的获取都抽象成mSource->Read()来完成,且read内部把parser和dec绑在一起。
Opencore和stagefright处理机制对比:
(1)Opencore的parser与dec是分离的,各行其职;stagefright则是绑在一起作为一个独立的原子操作。
(2)Stagefright通过callback和videoevent来驱动数据输出;opencore是通过sink-node节点控制输出。
(3)Opencore中parser/dec/sink是并行处理的;stagefright中为串行处理。
Opencore有一个主clock,audio/video分别与该主clock同步,作为输出的判定依据,且audio会不断校准主clock。
Stagefright部分,audio完全是callback驱动数据流,video部分在onVideoEvent里会获取audio的时间戳,是传统的AV时间戳做同步。
- Opencore相对成熟稳定,作为框架采用,风险小;parser/codec集成相对复杂,如果android后续版本弃用opencore转用stagefright,那多媒体引擎的选择是个问题。
- Stagefright新推出,肯定有未预知的bug,直接采用有潜在风险;parser/codec集成相对容易,架构较opencore做了极大简化,通俗易懂。
- 目前来看opencore支持的文件格式多些。
- Opencore与stagefright在数据处理机制及AV同步上有很大差异,需要在实际板子上评估性能差异。
- 如果在android froyo版本开发多媒体相关产品,建议采用opencore框架,这样旧版本opencore上的成果可以沿用,且节省项目时间。
- Opencore支持的文件格式较stagefright丰富。
stagefright框架中调用OMX的时序图
![](https://i-blog.csdnimg.cn/blog_migrate/0303d73893dce30482beb4f0e7e93cc3.webp?x-image-process=image/format,png)
Openmax架构在Android中位置
![](https://i-blog.csdnimg.cn/blog_migrate/3b0ca3c4e701bbd4ae9a08580e4a6301.webp?x-image-process=image/format,png)
Openmax架构
![](https://i-blog.csdnimg.cn/blog_migrate/eeabda337dbdf815d71d2d4321ee9266.webp?x-image-process=image/format,png)