• 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之间的关系了。由此看来,将来的任务和道路还是任重道远的。

    
    
    
    
    
  • 相关阅读:
    leetcode第14题最长公共前缀
    什么是神经网络
    获取url "?" 后面的字符串
    第一天
    C#和.Ne学习第九天
    C#和.Ne学习第八天
    格式化输出
    C#和.Ne学习
    C#和.Ne学习第七天
    C#类型转换
  • 原文地址:https://www.cnblogs.com/haiming/p/2948730.html
Copyright © 2020-2023  润新知