4. Android MultiMedia框架完全解析 - MediaPlayerFactory中OMX_Player的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yanbixing123/article/details/88927013

这里的实现,可以参照C++设计模式中的工厂模式,:http://blog.csdn.net/wuzhekai1985/article/details/6660462

这里插讲一下厂商定制Player的过程,可以参考NuPlayer的创建过程,通过这个过程,也能够对MediaPlayerFactory类有个比较深入的理解。

(这里需要注意,代码是KK442版本的,FSL在那个版本使用OMXPlayer和GMPlayer来播放,他们是通过OMX Plugin来搭建的一个播放器,在N7.1代码中并没有下面的代码,放在这里只是为了加深理解,和送给有需要定制播放器的同学)

首先来看这个class MediaPlayerFactory,它定义在MediaPlayerFactory.h文件中,里面包含一个IFactory类和其他的功能函数,如注册工厂类函数:registerFactory等等操作。而这个IFactory类,就是每个工厂类的基类。

核心就是这个class MediaPlayerFactory。

每个工厂类都继承自这个IFactory基类,如

class OMXPlayerFactory : public MediaPlayerFactory::IFactory
class StagefrightPlayerFactory : public MediaPlayerFactory::IFactory 
class NuPlayerFactory : public MediaPlayerFactory::IFactory

下面来看看这个IFactory类:

class IFactory {
   public:
     virtual ~IFactory() { }
     virtual float scoreFactory(const sp<IMediaPlayer>& client,
                                const char* url,
                                float curScore,
                                const KeyedVector<String8, String8> *headers = NULL) { return 0.0; }
     virtual float scoreFactory(const sp<IMediaPlayer>& client,
                                int fd,
                                int64_t offset,
                                int64_t length,
                                float curScore) { return 0.0; }
     virtual float scoreFactory(const sp<IMediaPlayer>& client,
                                const sp<IStreamSource> &source,
                                float curScore) { return 0.0; }
     virtual sp<MediaPlayerBase> createPlayer() = 0;
 };

想要新建一个工厂类其实是很简单的,只需要创建一个工厂类,继承自IFactory类,并实现其中的虚函数(scoreFactory和createPlayer)即可(仿照已经创建好的工厂类,如StagefrightPlayerFactory等等)。最终通过registerFactory_l函数将新建的工厂类注册到MediaPlayerFactory里面。

创建OMXPlayerFactory工厂类与StagefrightPlayerFactory,NuPlayerFactory一样,都需要实现了scoreFactory和createPlayer这几个虚函数。而createPlayer这个虚函数,就是真正的创建player的函数。

怎么注册到MediaPlayerFactory里面呢?就是通过下面这个函数:

void MediaPlayerFactory::registerBuiltinFactories() {
    Mutex::Autolock lock_(&sLock);

    if (sInitComplete)
        return;

#ifdef FSL_GM_PLAYER
    registerFactory_l(new OMXPlayerFactory(), OMX_PLAYER);
#endif
    registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
    registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
    registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
    registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);

    sInitComplete = true;
}

android中是通过一个KeyedVector来保存这些player的,在registerFactory_l函数中,通过sFactoryMap.add来将对应的Player添加到这个vector中。

下面来简单说明一下,为什么每一个工厂类都需要去实现scoreFactory和createPlayer两个虚函数。

这个简单的应用是,在MediaPlayerService.cpp中的MediaPlayerService::Client::setDataSource函数中,通过如下的语句:

player_type playerType = MediaPlayerFactory::getPlayerType(this,
                                                               fd,
                                                               offset,
                                                               length);

来获取想要使用的Player类型。

这个函数是MediaPlayerFactory中实现的:

player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
                                              int fd,
                                              int64_t offset,
                                              int64_t length) {
    GET_PLAYER_TYPE_IMPL(client, fd, offset, length, bestScore);
}

在这个GET_PLAYER_TYPE_IMPL宏中,会去遍历sFactoryMap这个vector中的每一项,在上面我们已经知道,vector中包含各个IFactory,怎么选择最合适的一个IFactory呢?就是通过遍历sFactoryMap这个vector中的每一项,分别调用各个IFactory各自实现的scoreFactory,需要读取文件的内容,判断文件的格式,看这个格式自己是否支持播放,如果支持那么就可以返回1(最高得分),或者返回0(最低得分)。得分最高的一个IFactory就是最合适的。

#define GET_PLAYER_TYPE_IMPL(a...)                      \
    Mutex::Autolock lock_(&sLock);                      \
                                                        \
    player_type ret = STAGEFRIGHT_PLAYER;               \
    float bestScore = 0.0;                              \
                                                        \
    for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
                                                        \
        IFactory* v = sFactoryMap.valueAt(i);           \
        float thisScore;                                \
        CHECK(v != NULL);                               \
        thisScore = v->scoreFactory(a);      \
        if (thisScore > bestScore) {                    \
            ret = sFactoryMap.keyAt(i);                 \
            bestScore = thisScore;                      \
        }                                               \
    }                                                   \
                                                        \
    if (0.0 == bestScore) {                             \
        ret = getDefaultPlayerType();                   \
    }                                                   \
                                                        \
    return ret;

那么各个工厂类的得分情况是什么样呢?大致如下:

bestScore = 0.0

StagefrightPlayer : ogg文件的话,得分为1.0, 其他为0.0

NuPlayer : 0.8

OMXPlayer : 1.0

所以,基本情况下都会使用OMXPlayer工厂类。

(这里传入的参数a还有问题,没有研究透彻,a是哪一个参数,是如何根据a判断的?以后有时间的话再深究)

这个文件中有许多种类型的播放器工厂,可以创建出不同的播放器,如果厂商要定制自己的播放器,就可以在这里面做文章,创建自己的工厂类,实现createPlayer方法,然后修改scoreFactory返回得分值为一个较大的数值,在注册进sFactoryMap变量,或者直接修改GET_PLAYER_TYPE宏和getDefaultPlayerType方法的规则,下面也给出了FSL的OMXPlayer的实现过程。

在FSL的代码中,OMXPlayer也只是一个皮包公司,真正做事的是GMPlayer,下面给出这一步步的额实现过程:

(1)mediaserver, a daemon running in android, started by zygote, called: MediaPlayerFactory::createPlayer(playerType, this, notify); (/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp)

同样,在创建Player时,需要根据文件获取对应的playerType后,再去创建,所以先调用

 player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */, 
                                                   fd, offset, length);

(2)之后跳转到MediaPlayerFactory::createPlayer中,

MediaPlayerFactory, called: return new OMXPlayer();  (/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp)

函数调用流程如下:

factory = sFactoryMap.valueFor(playerType); //获取得分最高的一个工厂类,此时为OMXPlayer

p = factory->createPlayer(); //调用得分最高工厂类里面的createPlayer函数。

virtual sp<MediaPlayerBase> createPlayer() {

ALOGV(" create OMXPlayer");

return new OMXPlayer();

}

(3)new OMXPlayer()时,就会调用这个类的构造函数,构造函数OMXPlayer::OMXPlayer(int nMediaType),这时就创建好OMXPlayer了,在构造函数中,创建了真正干活的GMPlayer:

called: gm = OMX_GraphManagerCreate();  (/external/fsl_imx_omx/Android/OMXPlayer.cpp)

(4)同样,在OMX_GraphManager* OMX_GraphManagerCreate()函数中,

called: Player = FSL_NEW(GMPlayer, ());, (/external/fsl_imx_omx/OpenMAXIL/src/client/GMPlayerWrapper.cpp)

之后调用

Player->Init();

来完成对这个GMPlayer的初始化,至此,GMPlayer也创建完成了。

猜你喜欢

转载自blog.csdn.net/yanbixing123/article/details/88927013