​Android 的多媒体框架(一)

      最近在学习Android的多媒体框架,omx,Stagefright,awesomeplayer等知识,稍微有了一点了解,也参考了很多网上的资料,现从上而下(Java层到kernel层)梳理一下~。
    Java层:
  
  
  1. 1 MediaPlayer mediaPlayer = new MediaPlayer();
  2. 2 mediaPlayer.setDataSource("/sdcard/test.mp3");
  3. 3 mediaPlayer.prepare();
  4. 4 mediaPlayer.start();
  5. 5 mediaPlayer.stop();
    Java层调用多媒体播放器很简单,由上面几条语句便可实现,贴一段用videoview实现的源码:
   
   
  1. http://blog.csdn.net/tx3344/article/details/8016049
main.xml:
   
   
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <SurfaceView
  6. android:id="@+id/surfaceView1"
  7. android:layout_width="wrap_content"
  8. android:layout_height="360dp"
  9. android:layout_alignParentLeft="true"
  10. android:layout_alignParentRight="true"
  11. android:layout_alignParentTop="true" />
  12. </RelativeLayout>
   
   
  1. package com.example.surfacemediaplayer;
  2. import android.media.MediaPlayer;
  3. import android.os.Bundle;
  4. import android.os.Environment;
  5. import android.app.Activity;
  6. import android.view.Menu;
  7. import android.view.SurfaceHolder;
  8. import android.view.SurfaceView;
  9. import android.view.SurfaceHolder.Callback;
  10. public class SurfaceMediaPlayer extends Activity {
  11. SurfaceView surfaceView;
  12. MediaPlayer mediaPlayer;
  13. @Override
  14. public void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_surface_media_player);
  17. mediaPlayer=new MediaPlayer();
  18. surfaceView=(SurfaceView) this.findViewById(R.id.surfaceView1);
  19. surfaceView.getHolder().addCallback(new Callback() {
  20. @Override
  21. public void surfaceDestroyed(SurfaceHolder holder) {
  22. }
  23. @Override
  24. public void surfaceCreated(SurfaceHolder holder) {
  25. //开始播放
  26. play();
  27. }
  28. @Override
  29. public void surfaceChanged(SurfaceHolder holder, int format, int width,
  30. int height) {
  31. }
  32. });
  33. }
  34. private void play() {
  35. try {
  36. String path = Environment.getExternalStorageDirectory().getPath()+"/Movies/run_to_you.3gp";
  37. mediaPlayer.setDataSource(path);
  38. //把视频画面输出到SurfaceView
  39. mediaPlayer.setDisplay(surfaceView.getHolder());
  40. mediaPlayer.prepare();
  41. //开始播放
  42. mediaPlayer.start();
  43. } catch (Exception e) {
  44. // TODO: handle exception
  45. }
  46. }
  47. @Override
  48. public boolean onCreateOptionsMenu(Menu menu) {
  49. getMenuInflater().inflate(R.menu.activity_surface_media_player, menu);
  50. return true;
  51. }
  52. }
MediaPlayer 类的实现:
   
   
  1. /frameworks/base/media/java/android/media/MediaPlayer.java
构造函数:
   
   
  1. public MediaPlayer() {
  2. Looper looper;
  3. if ((looper = Looper.myLooper()) != null) {
  4. mEventHandler = new EventHandler(this, looper);
  5. } else if ((looper = Looper.getMainLooper()) != null) {
  6. mEventHandler = new EventHandler(this, looper);
  7. } else {
  8. mEventHandler = null;
  9. }
  10. mTimeProvider = new TimeProvider(this);
  11. mOpenSubtitleSources = new Vector<InputStream>();
  12. IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
  13. mAppOps = IAppOpsService.Stub.asInterface(b);
  14. /* Native setup requires a weak reference to our object.
  15. * It's easier to create it here than in C++.
  16. */
  17. native_setup(new WeakReference<MediaPlayer>(this));
  18. }
     在这个构造函数中,较为重要的就是native_setup(). 这个函数在之前的声明中包含native,说明这是一个native函数。也就是说native_setup()函数实在native层实现的。接下来我们要做的就是根据JNI找到这个函数是如何实现的。native函数实现所在的文件的文件名都是如下命名的,把包名中的"."替换为"_"+类名。所以我们要找文件就是android_media_MediaPlayer.cpp.在这个文件中我们有个重要的数组。

    JNI层:
    
    
  1. /frameworks/base/media/jni/android_media_MediaPlayer.cpp
     
     
  1. static JNINativeMethod gMethods[] = {
  2. {
  3. "nativeSetDataSource",
  4. "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
  5. "[Ljava/lang/String;)V",
  6. (void *)android_media_MediaPlayer_setDataSourceAndHeaders
  7. },
  8. {"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
  9. {"_setDataSource", "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
  10. {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface},
  11. {"_prepare", "()V", (void *)android_media_MediaPlayer_prepare},
  12. {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
  13. {"_start", "()V", (void *)android_media_MediaPlayer_start},
  14. {"_stop", "()V", (void *)android_media_MediaPlayer_stop},
  15. {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
  16. {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
  17. {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
  18. {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
  19. {"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer_setSyncParams},
  20. {"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer_getSyncParams},
  21. {"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo},
  22. {"_pause", "()V", (void *)android_media_MediaPlayer_pause},
  23. {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying},
  24. {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition},
  25. {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration},
  26. {"_release", "()V", (void *)android_media_MediaPlayer_release},
  27. {"_reset", "()V", (void *)android_media_MediaPlayer_reset},
  28. {"_setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType},
  29. {"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer_getAudioStreamType},
  30. {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter},
  31. {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping},
  32. {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping},
  33. {"_setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume},
  34. {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
  35. {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
  36. {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
  37. {"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
  38. {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
  39. {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
  40. {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
  41. {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
  42. {"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
  43. {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
  44. {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
  45. {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint},
  46. {"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer},
  47. };
          在这个数组中,第一列表示的是Java层中函数名,第二列是Java层函数对应的参数以及返回值类型,第三列就是对应在Native层的函数名。从这个数组中,我们可以找到native_setup(),对应的函数名是android_media_MediaPlayer_native_setup,接下来我们就看看这个函数的实现:
   
   
  1. /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. // create new listener and give it to MediaPlayer
  11. sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
  12. mp->setListener(listener);
  13. // Stow our new C++ MediaPlayer in an opaque field in the Java object.
  14. setMediaPlayer(env, thiz, mp);
  15. }
   
   
  1. sp<MediaPlayer> mp = new MediaPlayer();
这行代码的功能就是创建一个MediaPlayer类的对象,不过这个对象是Native层的对象,也就是说这个Native层的MediaPlayer类是使用C++代码实现的。我们先往下看下面一句较为重要的代码,然后在后头分析Native层MediaPlayer对象的构造函数。
   
   
  1. setMediaPlayer(env, thiz, mp);
这行代码的功能就是把我们新创建的Native层的MediaPlayer对象保存到Java层。也就是说将来我们通过getMediaplayer()的时候获取到的就是这个对象。接下来,我就开始分析Native层的MediaPlayer的构造函数,代码如下:
  
  
  1. frameworks\base\media\java\android\media\mediaplayer.cpp
   
   
  1. MediaPlayer::MediaPlayer()
  2. {
  3. ALOGV("constructor");
  4. mListener = NULL;
  5. mCookie = NULL;
  6. mStreamType = AUDIO_STREAM_MUSIC;
  7. mAudioAttributesParcel = NULL;
  8. mCurrentPosition = -1;
  9. mSeekPosition = -1;
  10. mCurrentState = MEDIA_PLAYER_IDLE;
  11. mPrepareSync = false;
  12. mPrepareStatus = NO_ERROR;
  13. mLoop = false;
  14. mLeftVolume = mRightVolume = 1.0;
  15. mVideoWidth = mVideoHeight = 0;
  16. mLockThreadId = 0;
  17. mAudioSessionId = AudioSystem::newAudioUniqueId();
  18. AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
  19. mSendLevel = 0;
  20. mRetransmitEndpointValid = false;
  21. }
该函数主要是做一些初始化。下面重点来看:
  
  
  1. mediaPlayer.setDataSource("/sdcard/test.mp3");
在写这篇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. }
  调用setDataSource()的重载方法,之后的重载调用过程我们就略过,最终会调用到如下方法:
    
    
  1. public void setDataSource(FileDescriptor fd)
  2. throws IOException, IllegalArgumentException, IllegalStateException {
  3. // intentionally less than LONG_MAX
  4. setDataSource(fd, 0, 0x7ffffffffffffffL);
  5. }
    
    
  1. public native void setDataSource(FileDescriptor fd, long offset, long length)
  2. throws IOException, IllegalArgumentException, IllegalStateException;
 所以这个函数最终还是调用到类Native层。在之后的过程中,我们都会跳过对于JNI层的寻找过程,直接进入Native层的MediaPlayer对象寻找相应的方法。在Native层中setDataSource()对应的代码如下:


    
    
  1. /frameworks/av/media/libmedia/mediaplayer.cpp
    
    
  1. status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
  2. {
  3. ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", 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(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。
(定义一个“sp<IMediaPlayerService>const”类型的引用 “&service” 它是getMediaPlayerService()结果值的别名)
因此
    
    
  1. const sp<IMediaPlayerService>& service(getMediaPlayerService());
的功能就是获取MediaPlayerService并且把返回值赋值给service。关于getMediaPlayerService函数,我们在前面说过一次,这个方法是MediaPlayer的父类IMediaDeathNotifier的一个方法,关系到MediaPlayer和MediaPlayerService之间的通信。下面我们就看看这个方法的代码:
    
    
  1. /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. if (sDeathNotifier == NULL) {
  19. sDeathNotifier = new DeathNotifier();
  20. }
  21. binder->linkToDeath(sDeathNotifier);
  22. sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
  23. }
  24. ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
  25. return sMediaPlayerService;
  26. }
          在getMediaPlayerService()函数中,重点内容有三处,不过都是为了最后获取MediaPlayerService服务的。第8行是获取ServiceManager;第11行是从ServiceManager中获取到我们所需要的一个对象,这个对象是BpBinder类型,为我们最后取得MediaPlayerService作准备。第23行是获取MediaPlayerService,不过最终获得这个对象是BpMediaPlayerService类型。我们获取到得这个BpMediaPlayerService,这个对象的所有操作最终都会由真正的MediaPlayerService对象来完成,因此完全可以看做是MediaPlayerService。这个过程和Binder通信相关,不是我们这次探讨的重点,这里不再赘述。

MediaPlayerService 层:
    
    
  1. /frameworks/av/media/libmediaplayerservice/MediaPlayerService
     
     
  1. sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
  2. int audioSessionId)
  3. {
  4. pid_t pid = IPCThreadState::self()->getCallingPid();
  5. int32_t connId = android_atomic_inc(&mNextConnId);
  6. sp<Client> c = new Client(
  7. this, pid, connId, client, audioSessionId,
  8. IPCThreadState::self()->getCallingUid());
  9. ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
  10. IPCThreadState::self()->getCallingUid());
  11. wp<Client> w = c;
  12. {
  13. Mutex::Autolock lock(mLock);
  14. mClients.add(w);
  15. }
  16. return c;
  17. }
创建MediaPlayerService的内部类client。但是这个Client执行了MediaPlayerService的绝大部分操作。同样我们将来传输过来的数据也都是会交给内部类Client进行处理的。到这里,在Server端的对象就创建完成了。
接下来就是要做第二件事情了,就是在MediaPlayer中调用player->setDataSource();,这件事还是要在Server完成的,代码如下:
    
    
  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. ALOGV("st_dev = %llu", static_cast<uint64_t>(sb.st_dev));
  11. ALOGV("st_mode = %u", sb.st_mode);
  12. ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
  13. ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
  14. ALOGV("st_size = %llu", sb.st_size);
  15. if (offset >= sb.st_size) {
  16. ALOGE("offset error");
  17. ::close(fd);
  18. return UNKNOWN_ERROR;
  19. }
  20. if (offset + length > sb.st_size) {
  21. length = sb.st_size - offset;
  22. ALOGV("calculated length = %lld", length);
  23. }
  24. player_type playerType = MediaPlayerFactory::getPlayerType(this,
  25. fd,
  26. offset,
  27. length);
  28. sp<MediaPlayerBase> p = setDataSource_pre(playerType);
  29. if (p == NULL) {
  30. return NO_INIT;
  31. }
  32. // now set data source
  33. setDataSource_post(p, p->setDataSource(fd, offset, length));
  34. return mStatus;
  35. }
上面这段代码作用就是获取一个PlayerType,然后一这个PlayerType作为参数传递到setDataSource _pre(),在这个方法中根据playerType做一些事情。关于PlayerType是如何获取的,以及我们传入的文件test.mp3,对应什么类型的playerType,我就不再介绍了。之所以不介绍是因为牵涉到资源的一些特有的参数和属性判断的,我不太了解。不过我们可以从代码中找到在Android中一共又几种这样的Type,如下:
     
     
    1. enum player_type {
  1. STAGEFRIGHT_PLAYER = 3,
  2. NU_PLAYER = 4,
  3. // Test players are available only in the 'test' and 'eng' builds.
  4. // The shared library with the test player is passed passed as an
  5. // argument to the 'test:' url in the setDataSource call.
  6. TEST_PLAYER = 5,
  7. REALTEK_PLAYER = 6,
  8. PHOTO_PLAYER = 7,
  9. SKYMEDIA_PLAYER = 20,
  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中过程如下:
     
     
  1. /frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
      
      
  1. 1 void MediaPlayerFactory::registerBuiltinFactories() {
  2. 2 Mutex::Autolock lock_(&sLock);
  3. 3
  4. 4 if (sInitComplete)
  5. 5 return;
  6. 6
  7. 7 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
  8. 8 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
  9. 9 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
  10. 10 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
  11. 11
  12. 12 sInitComplete = true;
  13. 13 }
看看上面这两段代码还是有好处的,最起码让我们明白事情的来龙去脉。如果我们想要在Android中扩展,使用新的解码工具,可以直接继承MediaPlayerFactory类,然后在这里注册所需要的type就行了。

接着上面的说,假设我们mp3对应的时defaultType,也就是STAGEFRIGHT_PLAYER,那么这个数据就会作为setDataSource_pre()的参数使用。我们就看看这个函数是如何利用Type参数创建新的对象的,代码如下:
    
    
  1. /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. // create the right type of player
  6. sp<MediaPlayerBase> p = createPlayer(playerType);
  7. if (p == NULL) {
  8. return p;
  9. }
  10. if (!p->hardwareOutput()) {
  11. Mutex::Autolock l(mLock);
  12. mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
  13. mPid, mAudioAttributes);
  14. static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
  15. }
  16. return p;
  17. }
先说明一下,上面的红色代码都是很重要的,不过13和14行代码在setDataSource()暂时还是用不上,要等到start()的时候,和AudioFlinger建立联系的时候才能用到。现在先标记下,有个印象。我们继续我们的工作,分析createPlayer()方法,代码如下:
     
     
  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, mPid);
  11. }
  12. if (p != NULL) {
  13. p->setUID(mUID);
  14. }
  15. return p;
  16. }
看红色代码标识的第10行代码,这里使用的设计模式中的--Factory模式,大家可以参考学习下。Android系统时一个如此庞大复杂的系统,为了良好的扩展性使用了很多设计模式。无论是学习计算机哪方面内容,Android源码都是一份不错的教材。还是继续看我们的任务,接着看代码,在MediaPlayerFactory::createPlayer()的代码如下:
     
     
  1. /frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
      
      
  1. sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
  2. player_type playerType,
  3. void* cookie,
  4. notify_callback_f notifyFunc,
  5. pid_t pid) {
  6. sp<MediaPlayerBase> p;
  7. IFactory* factory;
  8. status_t init_result;
  9. Mutex::Autolock lock_(&sLock);
  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. factory = sFactoryMap.valueFor(playerType);
  16. CHECK(NULL != factory);
  17. p = factory->createPlayer(pid);
  18. if (p == NULL) {
  19. ALOGE("Failed to create player object of type %d, create failed",
  20. playerType);
  21. return p;
  22. }
  23. init_result = p->initCheck();
  24. if (init_result == NO_ERROR) {
  25. p->setNotifyCallback(cookie, notifyFunc);
  26. } else {
  27. ALOGE("Failed to create player object of type %d, initCheck failed"
  28. " (res = %d)", playerType, init_result);
  29. p.clear();
  30. }
  31. return p;
  32. }
我们通过playerType获取到得是IFactory对象,然后使用这个对象进行createPlayer。对于这一点的理解和Factory模式有关,如果不明白的话,抽出一点点时间看看Factory模式肯定是会有好处的。根据 playerType,我们这里的factory应该是StageFrightPlayerFactory的对象,然后调用它的的createPlayer函数。createPlayer()的实现如下:
      
      
  1. /frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
       
       
  1. virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
  2. ALOGV(" create StagefrightPlayer");
  3. return new StagefrightPlayer();
  4. }
       
       
  1. virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
  2. ALOGV("Create RtkPlayer");
  3. return new RtkPlayerDriver(pid);
  4. }
从这里StageFrightPlayerFactory的createPlayer中我们获得的返回值是一个新的对象--StagefrightPlayer的实例。到这里,我们就算是进入stagefright了,我们代码调查到这儿也基本快要结束了。
我们还是接着看看这个新的对象的构造方法,代码如下:
    
    
  1. /frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp
     
     
  1. StagefrightPlayer::StagefrightPlayer()
  2. : mPlayer(new AwesomePlayer) {
  3. ALOGV("StagefrightPlayer");
  4. mPlayer->setListener(this);
  5. }
在这个构造函数中,有个很容易忽视的地方,就是构造函数的属性赋值的方式,在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()已经调查结束,那么我们就要开始下一步 操作了,就是下面已经用红色代码标示出来的部分:
其实函数setDataSource_post()对于我们分析MediaPlayer流程的作用不太大,可能是要设置MediaPlayer的一些功能的属性吧,我们这次重点关注的是这个方法中的第二个参数。由上面的分析,我们知道p指向的对象是一个StagefrightPlayer
对象,所以p->setDataSource()的实现,我们就应该去StagefrightPlayer类中寻找。找到相应的代码如下:
     
     
  1. /frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp
      
      
  1. 1 status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
  2. 2 ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
  3. 3 return mPlayer->setDataSource(dup(fd), offset, length);
  4. 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之间的关系了。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值