4. Android MultiMedia框架完全解析 - MediaPlayerFactory中OMX_Player的實現

這裏的實現,可以參照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也創建完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章