前段時間接到任務,探究一下MediaPlayer在Android系統中是如何實現的。到現在為止終於有些眉目了,在調查代碼時候雖然有些吃力,但是還算是有所得的。今天把自己對MediaPlayer的粗淺理解拿出來,一來作為筆記備份;一來和大家分享。以下代碼都是以Android4.2代碼為基礎的,歡迎大家指正,共同學習。
為了有一個完整的閱讀代碼的脈絡和思路,我是以一個非常簡單的Java應用程序開始。程序非常簡單,代碼如下:
1 MediaPlayer mediaPlayer = new MediaPlayer(); 2 mediaPlayer.setDataSource("/sdcard/test.mp3"); 3 mediaPlayer.prepare(); 4 mediaPlayer.start(); 5 mediaPlayer.stop();
創建MediaPlayer對象
從第一行代碼開始看:
MediaPlayer mediaPlayer = new MediaPlayer();
這行代碼是在Java應用程序中,功能是新建一個對象。既然如此,我們就看看MediaPlayer這個類在Java層的構造函數,如下:
[/frameworks/base/media/java/android/media/MediaPlayer.java]
1 public MediaPlayer() { 2 3 Looper looper; 4 if ((looper = Looper.myLooper()) != null) { 5 mEventHandler = new EventHandler(this, looper); 6 } else if ((looper = Looper.getMainLooper()) != null) { 7 mEventHandler = new EventHandler(this, looper); 8 } else { 9 mEventHandler = null; 10 } 11 12 /* Native setup requires a weak reference to our object. 13 * It's easier to create it here than in C++. 14 */ 15 native_setup(new WeakReference<MediaPlayer>(this)); 16 }
在這個構造函數中,較為重要的就是native_setup(). 這個函數在之前的聲明中包含native,說明這是一個native函數。也就是說native_setup()函數實在native層實現的。接下來我們要做的就是根據JNI找到這個函數是如何實現的。native函數實現所在的文件的文件名都是如下命名的,把包名中的"."替換為"_"+類名。所以我們要找文件就是android_media_MediaPlayer.cpp.在這個文件中我們有個重要的數組,如下:
【/frameworks/base/media/jni/android_media_MediaPlayer.cpp】
1 static JNINativeMethod gMethods[] = { 2 { 3 "_setDataSource", 4 "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", 5 (void *)android_media_MediaPlayer_setDataSourceAndHeaders 6 }, 7 8 {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, 9 {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface}, 10 {"prepare", "()V", (void *)android_media_MediaPlayer_prepare}, 11 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, 12 {"_start", "()V", (void *)android_media_MediaPlayer_start}, 13 {"_stop", "()V", (void *)android_media_MediaPlayer_stop}, 14 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth}, 15 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight}, 16 {"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo}, 17 {"_pause", "()V", (void *)android_media_MediaPlayer_pause}, 18 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying}, 19 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition}, 20 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration}, 21 {"_release", "()V", (void *)android_media_MediaPlayer_release}, 22 {"_reset", "()V", (void *)android_media_MediaPlayer_reset}, 23 {"setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType}, 24 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping}, 25 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping}, 26 {"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume}, 27 {"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt}, 28 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke}, 29 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter}, 30 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata}, 31 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init}, 32 {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup}, 33 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize}, 34 {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id}, 35 {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id}, 36 {"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel}, 37 {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect}, 38 {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData}, 39 {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter}, 40 {"getParameter", "(ILandroid/os/Parcel;)V", (void *)android_media_MediaPlayer_getParameter}, 41 {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint}, 42 {"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer}, 43 };
在這個數組中,第一列表示的是Java層中函數名,第二列是Java層函數對應的參數以及返回值類型,第三列就是對應在Native層的函數名。從這個數組中,我們可以找到native_setup(),對應的函數名是android_media_MediaPlayer_native_setup,接下來我們就看看這個函數的實現:
【/frameworks/base/media/jni/android_media_MediaPlayer.cpp】
1 static void 2 android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) 3 { 4 ALOGV("native_setup"); 5 sp<MediaPlayer> mp = new MediaPlayer(); 6 if (mp == NULL) { 7 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 8 return; 9 } 10 11 // create new listener and give it to MediaPlayer 12 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); 13 mp->setListener(listener); 14 15 // Stow our new C++ MediaPlayer in an opaque field in the Java object. 16 setMediaPlayer(env, thiz, mp); 17 }
在本文中,對於分析MediaPlayer流程較為重要的函數,我都會用紅色字體標識出來。這不是說沒有標紅的就不重要,在程序里沒有無用的代碼,只是對於我們這次的流程分析不太重要而已。先看第5行
sp<MediaPlayer> mp = new MediaPlayer();
這行代碼的功能就是創建一個MediaPlayer類的對象,不過這個對象是Native層的對象,也就是說這個Native層的MediaPlayer類是使用C++代碼實現的。我們先往下看下面一句較為重要的代碼,然后在后頭分析Native層MediaPlayer對象的構造函數。
16 setMediaPlayer(env, thiz, mp);
這行代碼的功能就是把我們新創建的Native層的MediaPlayer對象保存到Java層。也就是說將來我們通過getMediaplayer()的時候獲取到的就是這個對象。接下來,我就開始分析Native層的MediaPlayer的構造函數,代碼如下:
1 MediaPlayer::MediaPlayer() 2 { 3 ALOGV("constructor"); 4 mListener = NULL; 5 mCookie = NULL; 6 mStreamType = AUDIO_STREAM_MUSIC; 7 mCurrentPosition = -1; 8 mSeekPosition = -1; 9 mCurrentState = MEDIA_PLAYER_IDLE; 10 mPrepareSync = false; 11 mPrepareStatus = NO_ERROR; 12 mLoop = false; 13 mLeftVolume = mRightVolume = 1.0; 14 mVideoWidth = mVideoHeight = 0; 15 mLockThreadId = 0; 16 mAudioSessionId = AudioSystem::newAudioSessionId(); 17 AudioSystem::acquireAudioSessionId(mAudioSessionId); 18 mSendLevel = 0; 19 mRetransmitEndpointValid = false; 20 }
在構造Native層的MediaPlayer對象的時候,也會構造父類的對象。只不過在這些對象構造過程中,對於我們分析MediaPlayer流程並沒有特別重要的東西。但是我們要了解的一點就是在MediaPlayer的父類IMediaDeathNotifier中有個很重要的方法getMediaPlayerService(),對於這個方法我們在之后的分析過程中還會用到,到時候在詳細介紹。
到這里為止,這一小節基本結束。總結一下,在MediaPlayer的初始化過程中,就是創建了MediaPlayer的對象。
重要的函數setDataSource()
在寫這篇blog之前,已經對MediaPlayer的流程有了大概的了解。現在回頭再看,發現這個函數真的非常重要。在這個函數中,MediaPlayer和MediaPlayerService建立了聯系,MediaPlayerService和Stagefright或者OpenCore也建立了聯系。 我們繼續RFCD,在Java層,我們使用的方法如下:
mediaPlayer.setDataSource("/sdcard/test.mp3");
在Java層這個函數代碼如下:
【/frameworks/base/media/java/android/media/MediaPlayer.java】
1 public void setDataSource(String path) 2 throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 3 setDataSource(path, null, null); 4 } 5 調用setDataSource()的重載方法,之后的重載調用過程我們就略過,最終會調用到如下方法: 6 public void setDataSource(FileDescriptor fd) 7 throws IOException, IllegalArgumentException, IllegalStateException { 8 // intentionally less than LONG_MAX 9 setDataSource(fd, 0, 0x7ffffffffffffffL); 10 } 11 public native void setDataSource(FileDescriptor fd, long offset, long length) 12 throws IOException, IllegalArgumentException, IllegalStateException;
所以這個函數最終還是調用到類Native層。在之后的過程中,我們都會跳過對於JNI層的尋找過程,直接進入Native層的MediaPlayer對象尋找相應的方法。在Native層中setDataSource()對應的代碼如下:
【/frameworks/av/media/libmedia/mediaplayer.cpp】
1 status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) 2 { 3 ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 4 status_t err = UNKNOWN_ERROR; 5 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 6 if (service != 0) { 7 sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId)); 8 if ((NO_ERROR != doSetRetransmitEndpoint(player)) || 9 (NO_ERROR != player->setDataSource(fd, offset, length))) { 10 player.clear(); 11 } 12 err = attachNewPlayer(player); 13 } 14 return err; 15 }
上面這段代碼重點地方有三個,都已經標示出來。先看第一個,getMediaPlayerService(),這個函數從其名字上看是獲取MediaPlayerService。因此
5 const sp<IMediaPlayerService>& service(getMediaPlayerService());
的功能就是獲取MediaPlayerService並且把返回值賦值給service。關於getMediaPlayerService函數,我們在前面說過一次,這個方法是MediaPlayer的父類IMediaDeathNotifier的一個方法,關系到MediaPlayer和MediaPlayerService之間的通信。下面我們就看看這個方法的代碼:
[/frameworks/av/media/libmedia/IMediaDeathNotifier.cpp]
1 // establish binder interface to MediaPlayerService 2 /*static*/const sp<IMediaPlayerService>& 3 IMediaDeathNotifier::getMediaPlayerService() 4 { 5 ALOGV("getMediaPlayerService"); 6 Mutex::Autolock _l(sServiceLock); 7 if (sMediaPlayerService == 0) { 8 sp<IServiceManager> sm = defaultServiceManager(); 9 sp<IBinder> binder; 10 do { 11 binder = sm->getService(String16("media.player")); 12 if (binder != 0) { 13 break; 14 } 15 ALOGW("Media player service not published, waiting..."); 16 usleep(500000); // 0.5 s 17 } while (true); 18 19 if (sDeathNotifier == NULL) { 20 sDeathNotifier = new DeathNotifier(); 21 } 22 binder->linkToDeath(sDeathNotifier); 23 sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); 24 } 25 ALOGE_IF(sMediaPlayerService == 0, "no media player service!?"); 26 return sMediaPlayerService; 27 }
在getMediaPlayerService()函數中,重點內容有三處,不過都是為了最后獲取MediaPlayerService服務的。第8行是獲取ServiceManager;第11行是從ServiceManager中獲取到我們所需要的一個對象,這個對象是BpBinder類型,為我們最后取得MediaPlayerService作准備。第23行是獲取MediaPlayerService,不過最終獲得這個對象是BpMediaPlayerService類型。我們獲取到得這個BpMediaPlayerService,這個對象的所有操作最終都會由真正的MediaPlayerService對象來完成,因此完全可以看做是MediaPlayerService。這個過程和Binder通信相關,不是我們這次探討的重點,這里不再贅述。
到這里,我們分析完成了getMediaPlayerService方法,獲得了返回值,並把它賦值給了service。接下來我們就要看看MediaPlayer使用這個service都做了些什么事情。從代碼中看,總共有兩件事情,分別是:
1)根據進程ID,對象本身,AudioSessionId這三個參數,在server端創建了一個Player對象並返回給MediaPlayer端的player。這個Player也是具有進程間通信能力的。
7 sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
2)為server端的Player設置播放資源
player->setDataSource(fd, offset, length)
我們開始看看第一件事情時如何完成的,以及在Server段創建player的時候都做了那些工作。這個Create操作最終會在Server端執行,所以我們就去MediaPlayerService段在這個過程中都做了些什么,代碼如下:
[/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp]
1 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, 2 int audioSessionId) 3 { 4 int32_t connId = android_atomic_inc(&mNextConnId); 5 6 sp<Client> c = new Client( 7 this, pid, connId, client, audioSessionId, 8 IPCThreadState::self()->getCallingUid()); 9 10 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid, 11 IPCThreadState::self()->getCallingUid()); 12 13 wp<Client> w = c; 14 { 15 Mutex::Autolock lock(mLock); 16 mClients.add(w); 17 } 18 return c; 19 }
從代碼中,我們可以看出,在Server端,我們新建的對象是Client,是MediaPlayerService的內部類。但是這個Client執行了MediaPlayerService的絕大部分操作。同樣我們將來傳輸過來的數據也都是會交給內部類Client進行處理的。到這里,在Server端的對象就創建完成了。
接下來就是要做第二件事情了,就是在MediaPlayer中調用player->setDataSource();,這件事還是要在Server完成的,代碼如下:
[/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp]
1 status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length) 2 { 3 ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length); 4 struct stat sb; 5 int ret = fstat(fd, &sb); 6 if (ret != 0) { 7 ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 8 return UNKNOWN_ERROR; 9 } 10 11 ALOGV("st_dev = %llu", sb.st_dev); 12 ALOGV("st_mode = %u", sb.st_mode); 13 ALOGV("st_uid = %lu", sb.st_uid); 14 ALOGV("st_gid = %lu", sb.st_gid); 15 ALOGV("st_size = %llu", sb.st_size); 16 17 if (offset >= sb.st_size) { 18 ALOGE("offset error"); 19 ::close(fd); 20 return UNKNOWN_ERROR; 21 } 22 if (offset + length > sb.st_size) { 23 length = sb.st_size - offset; 24 ALOGV("calculated length = %lld", length); 25 } 26 27 player_type playerType = MediaPlayerFactory::getPlayerType(this, 28 fd, 29 offset, 30 length); 31 sp<MediaPlayerBase> p = setDataSource_pre(playerType); 32 if (p == NULL) { 33 return NO_INIT; 34 } 35 36 // now set data source 37 setDataSource_post(p, p->setDataSource(fd, offset, length)); 38 return mStatus; 39 }
上面這段代碼作用就是獲取一個PlayerType,然后一這個PlayerType作為參數傳遞到setDataSource _pre(),在這個方法中根據playerType做一些事情。關於PlayerType是如何獲取的,以及我們傳入的文件test.mp3,對應什么類型的playerType,我就不再介紹了。之所以不介紹是因為牽涉到資源的一些特有的參數和屬性判斷的,我不太了解。不過我們可以從代碼中找到在Android中一共又幾種這樣的Type,如下:
/frameworks/av/include/media/MediaPlayerInterface.h
1 enum player_type { 2 PV_PLAYER = 1, 3 SONIVOX_PLAYER = 2, 4 STAGEFRIGHT_PLAYER = 3, 5 NU_PLAYER = 4, 6 // Test players are available only in the 'test' and 'eng' builds. 7 // The shared library with the test player is passed passed as an 8 // argument to the 'test:' url in the setDataSource call. 9 TEST_PLAYER = 5, 10 };
一種有五種type,但是PV_PLAYER好像是從Android2.3之后就取消了,因為PVPlayer是和Opencore相關的,自從OpenCore從Android2.3中移出之后,這個type對應的Player就沒有了。所以在Android4.2中只剩下
四種type了。這些type和他們對應的player都會以鍵值對的形式放入一個數據結構中,以備后用。在后面我們在使用這些type的時候,就會發現這些鍵值對是存放在sFactoryMap中的,而sFactoryMap 是tFactoryMap型的,
也就是就是KeyVector。貌似KeyVector是android定義的數據結構吧,類似Hashmap。而把這些type和player鍵值對添加入sFactorymap中過程如下:
[/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp]
1 void MediaPlayerFactory::registerBuiltinFactories() { 2 Mutex::Autolock lock_(&sLock); 3 4 if (sInitComplete) 5 return; 6 7 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER); 8 registerFactory_l(new NuPlayerFactory(), NU_PLAYER); 9 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER); 10 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER); 11 12 sInitComplete = true; 13 }
看看上面這兩段代碼還是有好處的,最起碼讓我們明白事情的來龍去脈。如果我們想要在Android中擴展,使用新的解碼工具,可以直接繼承MediaPlayerFactory類,然后在這里注冊所需要的type就行了。
接着上面的說,假設我們mp3對應的時defaultType,也就是STAGEFRIGHT_PLAYER,那么這個數據就會作為setDataSource_pre()的參數使用。我們就看看這個函數是如何利用Type參數創建新的對象的,代碼如下:
【/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp】
1 sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( 2 player_type playerType) 3 { 4 ALOGV("player type = %d", playerType); 5 6 // create the right type of player 7 sp<MediaPlayerBase> p = createPlayer(playerType); 8 if (p == NULL) { 9 return p; 10 } 11 12 if (!p->hardwareOutput()) { 13 mAudioOutput = new AudioOutput(mAudioSessionId); 14 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); 15 } 16 17 return p; 18 }
先說明一下,上面的紅色代碼都是很重要的,不過13和14行代碼在setDataSource()暫時還是用不上,要等到start()的時候,和AudioFlinger建立聯系的時候才能用到。現在先標記下,有個印象。我們繼續我們的工作,分析createPlayer()方法,代碼如下:
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
1 sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType) 2 { 3 // determine if we have the right player type 4 sp<MediaPlayerBase> p = mPlayer; 5 if ((p != NULL) && (p->playerType() != playerType)) { 6 ALOGV("delete player"); 7 p.clear(); 8 } 9 if (p == NULL) { 10 p = MediaPlayerFactory::createPlayer(playerType, this, notify); 11 } 12 13 if (p != NULL) { 14 p->setUID(mUID); 15 } 16 17 return p; 18 }
看紅色代碼標識的第10行代碼,這里使用的設計模式中的--Factory模式,大家可以參考學習下。Android系統時一個如此龐大復雜的系統,為了良好的擴展性使用了很多設計模式。無論是學習計算機哪方面內容,Android源碼都是一份不錯的教材。還是繼續看我們的任務,接着看代碼,在MediaPlayerFactory::createPlayer()的代碼如下:
[/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp]
1 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( 2 player_type playerType, 3 void* cookie, 4 notify_callback_f notifyFunc) { 5 sp<MediaPlayerBase> p; 6 IFactory* factory; 7 status_t init_result; 8 Mutex::Autolock lock_(&sLock); 9 10 if (sFactoryMap.indexOfKey(playerType) < 0) { 11 ALOGE("Failed to create player object of type %d, no registered" 12 " factory", playerType); 13 return p; 14 } 15 16 factory = sFactoryMap.valueFor(playerType); 17 CHECK(NULL != factory); 18 p = factory->createPlayer(); 19 20 if (p == NULL) { 21 ALOGE("Failed to create player object of type %d, create failed", 22 playerType); 23 return p; 24 } 25 26 init_result = p->initCheck(); 27 if (init_result == NO_ERROR) { 28 p->setNotifyCallback(cookie, notifyFunc); 29 } else { 30 ALOGE("Failed to create player object of type %d, initCheck failed" 31 " (res = %d)", playerType, init_result); 32 p.clear(); 33 } 34 35 return p; 36 }
我們通過playerType獲取到得是IFactory對象,然后使用這個對象進行createPlayer。對於這一點的理解和Factory模式有關,如果不明白的話,抽出一點點時間看看Factory模式肯定是會有好處的。根據
playerType,我們這里的factory應該是StageFrightPlayerFactory的對象,然后調用它的的createPlayer函數。createPlayer()的實現如下:
[/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp]
1 virtual sp<MediaPlayerBase> createPlayer() { 2 ALOGV(" create StagefrightPlayer"); 3 return new StagefrightPlayer(); 4 }
從這里StageFrightPlayerFactory的createPlayer中我們獲得的返回值是一個新的對象--StagefrightPlayer的實例。到這里,我們就算是進入stagefright了,我們代碼調查到這兒也基本快要結束了。
我們還是接着看看這個新的對象的構造方法,代碼如下:
[/frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp]
1 StagefrightPlayer::StagefrightPlayer() 2 : mPlayer(new AwesomePlayer) { 3 ALOGV("StagefrightPlayer"); 4 5 mPlayer->setListener(this); 6 }
在這個構造函數中,有個很容易忽視的地方,就是構造函數的屬性賦值的方式,在C++中經常使用,叫做構造函數的初始化列表。乍一看,這個構造函數什么也沒有,其實重點內容就在構造函數的初始化列表中,在這里我們又
創建了一個對象AwesomPlayer. 我覺得我們進行到這兒,也可以告一段落了,因為我們已經接觸到了Stagefright,再向下調查代碼的話就應該是單獨研究stagefright的工作了。以后,在調查過stagefrigh后,我會
再補上一篇博客說說stagefright的。
好了,騷年們,讓我們像函數調用結束時一樣,一步一步return吧,直到能夠繼續向下執行的地方。我們一直調查到這兒,是在分析MediaPlayerService中要做的兩件事中的第二件事情:setDataSource()。我們剛剛結束
分析的地方是:sp<MediaPlayerBase> p = setDataSource_pre(playerType);讓我們先總結一下我們剛剛都做了哪些事情,其實挺簡單的就是創建了一個對象StagefrightPlayer,並把這個對象保存到p中。StagefrightPlayer
對象在創建的過程中,我們也設置了一些參數,比如p->setAudioSink(),還創建了AwesomePlayer對象,保存在StagefrightPlayer對象中的mPlayer屬性中。既然setDataSource_pre()已經調查結束,那么我們就要開始下一步
操作了,就是下面已經用紅色代碼標示出來的部分:
[/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp]
1 status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length) 2 { 3 ... 4 player_type playerType = MediaPlayerFactory::getPlayerType(this, 5 fd, 6 offset, 7 length); 8 sp<MediaPlayerBase> p = setDataSource_pre(playerType); 9 ... 10 // now set data source 11 setDataSource_post(p, p->setDataSource(fd, offset, length)); 12 return mStatus; 13 }
其實函數setDataSource_post()對於我們分析MediaPlayer流程的作用不太大,可能是要設置MediaPlayer的一些功能的屬性吧,我們這次重點關注的是這個方法中的第二個參數。由上面的分析,我們知道p指向的對象是一個StagefrightPlayer
對象,所以p->setDataSource()的實現,我們就應該去StagefrightPlayer類中尋找。找到相應的代碼如下:
[/frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp]
1 status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 2 ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 3 return mPlayer->setDataSource(dup(fd), offset, length); 4 }
原來是使用StagefrightPlayer的屬性mPlayer去實現的,前面我們也說到了stagefrightPlayer.mPlayer指向的是AwesomePlayer.到這兒我們到此為止吧。
到這里,在MediaPlayerService端的的setDataSource()的工作也結束了,總結一下就是:從Java應用程序中的MediaPlayer的setDataSource()會傳遞到Native層中的MediaPlayer的setDataSource()去執行,而MediaPlayer會把這個方法交給MediaPlayerservice去執行。MediaPlayerService的是使用stagefrightPlayer實現的,最后,最后,我們的setdataSource還是交給了AwesomePlayer去執行了。這個流程把MediaPlayer和MediaPlayerService之間的聯系建立起來,同時又把MediaPlayerService是如何使用stagefright實現的關系建立了起來。到這里,我們的分析MediaPlayer的流程的目的也算是基本達到了。如果再繼續分析MediaPlayer的話,我們可以分為兩個方向了,一個是分析stagefright是如何解碼的;一個是分析MediaPlayer與AudioTrack,AudioFlinger之間的關系了。由此看來,將來的任務和道路還是任重道遠的。