一、OpenCore简介
OpenCore是Android的多媒体核心,采用C++实现,定义了全功能的操作系统移植层(OSCL),各种基本的功能均被封装成类的形式,各层次之间的接口多使用继承等方式。
从宏观上来看,它主要包含了两大方面的内容:
- PVPlayer:提供媒体播放器的功能,完成各种音频(Audio)、视频(Video)流的回放(Playback)功能。
- PVAuthor:提供媒体流记录的功能,完成各种音频(Audio)、视频(Video)流的以及静态图像捕获功能 。
二、OpenCore在Android系统中的位置
首先来一张抽象一点的图(如下):
从上图我们可以感觉到OpenCore封装了一些接口给应用程序。具体是什么呢?下面以音频/视频播放器为例,看看具体的过程:
其中,
-
- VideoView.java 是一个media集成的高层的JAVA类,这个类的文件在/frameworks/base/core/java/android/widget/。它集成了MediaPlayer和SurfaceView的类,可以作为一个UI元素(View)直接放在界面中,用于视频的播放。
- MediaPlayer.java和MediaRecorder.java 为基本的处理音频数据的Java类,它里面直接调用很多本地接口。
- android_media_MediaPlayer.cpp 和android_media_MediaRecorder.cpp 封装了相应的JNI接口。
三、多媒体播放的过程
视频文件(流)播放过程就像一个状态机。图形如下,其中椭圆形代表MediaPlayer类的状态;线代表状态变化,由源状态指向目标状态,它旁边标注有状态变化的条件,其中单箭头的线表示同步(synchronous)方法调用,双箭头表示异步(asynchronous)方法调用。
这幅状态运行图显示了视频播放时的各种状态之间的切换方法,除此之外,为了方便用户处理,在一些状态下,系统会调用回调函数,只要用户提前注册好相应的回调函数即可。
状态 | 回调函数 | 注册方法 |
Error | OnErrorListener.onError() | setOnErrorListener(android.media.MediaPlayer.OnErrorListener) |
Prepared | OnPreparedListener.onPrepared() | setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener) |
Started | OnBufferingUpdateListener.onBufferingUpdate() | setOnBufferingUpdateListener(OnBufferingUpdateListener) |
使用seekTo(int)后 | OnSeekComplete.onSeekComplete() | setOnSeekCompleteListener(OnSeekCompleteListener) |
PlaybackCompleted | OnCompletionListener.onCompletion() | setOnCompletionListener(OnCompletionListener) |
四、OpenCore内部的重要概念
OSCL :Operating System Compatibility Library (操作系统兼容库),包含了一些操作系统底层的操作,为了更好地在不同操作系统移植。包含了基本数据类型、配置、字符串工具、IO、错误处理、线程等内容,类似一个基础的C++库。
PVMF :PacketVideo Multimedia Framework(PV多媒体框架),在框架内实现一个文件解析(parser) 和组成(composer) 、编解码 的NODE ,也可以继承其通用的接口,在用户层实现一些NODE。
五、OpenCore的内部调度过程
PlayerDriver创建后进入OSCL 线程来处理消息,engine 创建完各个node 节点并将其连接起来,剩下的就是node间的通讯问题,各node状态变化会触发oscl对其下一次调度,参与到oscl调度中的模块都必须提供一个Run函数 ,oscl会去call这个函数。 内部流程图如下:
文件的播放过程如下:
-
- 判断源文件的格式,根据文件格式创建对应的文件解析节点ParseNode : PVPlayerRecognizerRegistry负责文件格式识别,并将结果返回给PVPlayerEngine;
- 通过文件解析节点(ParseNode)来完成音视频文件格式的解析,并将文件中的音频、视频数据送到对应的解码节点进行解码;
- 解码节点(DecNode)通过调用底层的opencoreMAX 通用接口实现媒体数据的解码;对于一个普通的视频文件,存在2个解码节点:音频解码节点 和视频解码节点 ;
六、解码的内部流程:
参考OpenMax 的相关介绍。
七、Android上的视频输出方案
为了使opencore的视频播放支持Android系统,谷歌定义了两套视频输出方案,一种是由硬件 厂商实现硬件加速的视频输出( libopencorehw.so ),硬件视频输出里面可以调用硬件Overlay模块对输出的视频数据进行硬件混叠,这样输出效率会非常的高;另外一种为谷歌定义的软视频输出,该软视频输出定义为AndroidSurfaceOutput 类,这种方案中系统会调用SurfaceFilnger对输出视频数据进行混叠,该混叠为软件混叠,执行效率比较低。
八、OpenCore的测试方式
参考《Build OpenCORE 2.05 on x86 Linux .PDF》和《pvplayer_engine_unit_test_guide.pdf》