Android4.0中MediaPlayer 和 MediaPlayerService


  前段時間接到任務,探究一下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之間的關系了。由此看來,將來的任務和道路還是任重道遠的。

 

 
        

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM