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是給應用層提供的接口,通過jni調用native層,native層又采用C/S框架,通過binder調用到service端, servcie端最終調用到本地播放器NuPlayer。
Binder是android普遍采用的架構,這里應該主要也是為了對資源和client進行統一管理。不過筆者不太明白為什么不跟其他模塊一樣在java層使用binder通訊呢
NuPlayer是andriod原生的播放器,芯片廠家一般會替換成自己的播放器。MediaPlayerService實際上持有的是MediaPlayerFactory, NuPlayer通過MediaPlayerFactory創建出來的,是典型的工廠設計模式
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<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
{
// determine if we have the right player type
sp<MediaPlayerBase> 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