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