MediaPlayer(二)--MediaPlayer基本框架
MediaPlayer涉及的的文件路径
这里参考的是android8.1 的代码
JAVA类的路径:
frameworks/base/media/java/android/media/MediaPlayer.java
JNI路径:
frameworks/base/media/jni/android_media_MediaPlayer.cpp
编译为 libmedia_jni.so
native 层的接口
frameworks/av/media/libmedia
编译为 libmedia.so
native层服务:
frameworks/av/media/libmediaplayerservice/
编译为 libmediaplayerservice.so
#MediePlayer框架
MediaPlayer是给应用层提供的接口,通过jni调用native层,native层又采用C/S框架,通过binder调用到service端, servcie端最终调用到本地播放器NuPlayer。
Binder是android普遍采用的架构,这里应该主要也是为了对资源和client进行统一管理。不过笔者不太明白为什么不跟其他模块一样在java层使用binder通讯呢
NuPlayer是andriod原生的播放器,芯片厂家一般会替换成自己的播放器。MediaPlayerService实际上持有的是MediaPlayerFactory, NuPlayer通过MediaPlayerFactory创建出来的,是典型的工厂设计模式
IFactory为MediaPlayerFactory的内部类,芯片厂家只要创建自己的factory和player就能替换掉android原生的nuplayer
#Nuplayer的注册创建过程
MediaPlayerService 在构造函数中会去创建各个Player Factory, 并保存到sFactoryMap 中, 后续创建播放器会通过对应的type去获取到对应的factory。
MediaPlayerService::MediaPlayerService()
{
ALOGV("MediaPlayerService created");
mNextConnId = 1;
MediaPlayerFactory::registerBuiltinFactories();
}
void MediaPlayerFactory::registerBuiltinFactories() {
Mutex::Autolock lock_(&sLock);
if (sInitComplete)
return;
IFactory* factory = new NuPlayerFactory();
if (registerFactory_l(factory, NU_PLAYER) != OK)
delete factory;
factory = new TestPlayerFactory();
if (registerFactory_l(factory, TEST_PLAYER) != OK)
delete factory;
#ifdef USE_FFPLAYER
factory = new FFPlayerFactory();
if (registerFactory_l(factory,FF_PLAYER) != OK)
delete factory;
#endif
sInitComplete = true;
}
status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
player_type type) {
if (NULL == factory) {
ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
" NULL.", type);
return BAD_VALUE;
}
if (sFactoryMap.indexOfKey(type) >= 0) {
ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
" already registered.", type);
return ALREADY_EXISTS;
}
if (sFactoryMap.add(type, factory) < 0) {
ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
" to map.", type);
return UNKNOWN_ERROR;
}
return OK;
}
播放器实例会在上层调用setDataSource时调用到createPlayer创建,MediaPlayerFactory会根据playerType,调用对应的factory去创建player
sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
{
// determine if we have the right player type
sp<MediaPlayerBase> p = getPlayer();
if ((p != NULL) && (p->playerType() != playerType)) {
ALOGV("delete player");
p.clear();
}
if (p == NULL) {
p = MediaPlayerFactory::createPlayer(playerType, this, notify, mPid);
}
if (p != NULL) {
p->setUID(mUid);
}
return p;
}
openCore,StageFright, NuPlayer的关系
如果接触Android比较早的人,可能有听过openCore,StageFright。 这几个层次是并列的,都属于android底层播放器的实现框架。
Android上的MediaPlayer播放底层框架已经经历了多次变动,从最早先的OpenCore到后来的StageFright再到现在的NuPlayer,这些框架在演进过程中一般都是先两种框架并存,然后再在某个版本中将其移除,早先Android中使用的是Stagefright + NuPlayer并存的方式,其中前者负责播放本地的媒体文件,后者用于播放网络流媒体文件,但是在后来的Android L开始NuPlayer渐渐开始替代了Stagefright,目前本地播放已经切换到NuPlayer上了,在Android N AOPS 源代码中已经移除了Stagefright。
MediaCodec 、OpenMAX、ACodec关系
OpenMAX确立了一套标准的接口,用于编解码,上层App直接调用这些接口,底层硬件厂商直接实现这些接口,从而实现了上层软件开发与底层芯片开发地彻底分离,加速了跨平台的多媒体组件的开发、整合和编程。
Android上的MediaCodec是通过ACodec来加载openmax层
StageFright 直接通过OpenMAX进行编辑码,NuPlayer是通过ACodec进行编解码
参考
https://blog.csdn.net/zds05/article/details/52837998
https://blog.csdn.net/u012188065/article/details/86723535
上一篇: Unity NGUI和UGUI与模型、特效的层级关系
下一篇: Mac 安装 mongodb
推荐阅读
-
MediaPlayer(二)--MediaPlayer基本框架
-
Android XUtils3框架的基本使用方法(二)
-
Android XUtils3框架的基本使用方法(二)
-
详解Android之图片加载框架Fresco基本使用(二)
-
详解Android之图片加载框架Fresco基本使用(二)
-
Linux 字符设备驱动基本框架(二)
-
Android开发之MediaPlayer基本使用方法详解
-
Android开发之MediaPlayer基本使用方法详解
-
Delphi MediaPlayer Android 的问题 之二
-
Fragment实现底部导航栏,TabLayout实现顶部导航栏,二者相互嵌套完成App基本布局框架