1. Android MultiMedia框架解析

前言

在之前文章中说到mediaplayer最终会利用工场模式通过打分选择Nuplayer。

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

定制

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

核心就是这个class MediaPlayerFactory。
每个工厂类都继承自这个IFactory基类,如

class OMXPlayerFactory : public MediaPlayerFactory::IFactory
class NuPlayerFactory : public MediaPlayerFactory::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 float scoreFactory(const sp<IMediaPlayer>& /*client*/,
                                const sp<DataSource> &/*source*/,
                                float /*curScore*/) { return 0.0; }
     virtual sp<MediaPlayerBase> createPlayer() = 0;
 };

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

创建OMXPlayerFactory工厂类与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 NuPlayerFactory(), NU_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
NuPlayer : 0.8
OMXPlayer : 1.0

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

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值