MediaPlayer(二)--MediaPlayer基本框架

Android FFmpeg专题结构

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(二)--MediaPlayer基本框架_第1张图片

MediaPlayer是给应用层提供的接口,通过jni调用native层,native层又采用C/S框架,通过binder调用到service端, servcie端最终调用到本地播放器NuPlayer。
Binder是android普遍采用的架构,这里应该主要也是为了对资源和client进行统一管理。不过笔者不太明白为什么不跟其他模块一样在java层使用binder通讯呢
NuPlayer是andriod原生的播放器,芯片厂家一般会替换成自己的播放器。MediaPlayerService实际上持有的是MediaPlayerFactory, NuPlayer通过MediaPlayerFactory创建出来的,是典型的工厂设计模式
MediaPlayer(二)--MediaPlayer基本框架_第2张图片

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 MediaPlayerService::Client::createPlayer(player_type playerType)
{
    // determine if we have the right player type
    sp 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

你可能感兴趣的:(播放器)