Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2116850
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: Android平台

2015-02-09 16:58:33

0.1继上一篇 android应用开发---11.MediaPlayer实现音乐播放的demo 发现android播放音频文件只需要下面几步
  1. mediaPlayer = new MediaPlayer();               //1
  2. mediaPlayer.setDataSource(File_Path);          //2
  3. mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  4. mediaPlayer.prepareAsync();       //异步的方式加载音乐文件
  5. mediaPlayer.start();             //准备好之后才能start
0.2 stageFright的框架如下所示:


下面就逐个分析一下这个过程

.new MediaPlayer的过程
  1. ./frameworks/base/media/java/android/media/MediaPlayer.java
  2. public MediaPlayer() {
  3.    //调用jni中的native_setup   
  4.    native_setup(new WeakReference<MediaPlayer>(this));
  5. }
1.1 jni的native_setup
  1. ./frameworks/base/media/jni/android_media_MediaPlayer.cpp
  2. android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
  3. {
  4.     sp<MediaPlayer> mp = new MediaPlayer();
  5.     sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
  6.     mp->setListener(listener);
  7.     setMediaPlayer(env, thiz, mp);    //把mp保存起来
  8. }


二. setDataSource的过程
  1. 在./frameworks/base/media/java/android/media/MediaPlayer.java中
  2. public void setDataSource(String path) {
  3.     //打开path的文件,转为fd
  4.     //调用jni的_setDataSource
  5. }
2.1 jni中的setDataSource
  1. ./frameworks/base/media/jni/android_media_MediaPlayer.cpp
  2. android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
  3. {
  4.     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);             //获取第1步保存的mp
  5.     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
  6.     process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
  7. }
2.2
  1. ./frameworks/av/media/libmedia/mediaplayer.cpp
  2. status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
  3. {
  4.     const sp<IMediaPlayerService>& service(getMediaPlayerService());    //获取MediaPlayerService
  5.     sp<IMediaPlayer> player(service->create(this, mAudioSessionId));    //2.2.1通过MediaPlayerService创建player
  6.     player->setDataSource(fd, offset, length)));                        //2.2.2
  7.     attachNewPlayer(player);
  8.     return err;
  9. }
通过下面的2.3可知service->create实际上是创建了一个::Client>
引自《Android多媒体开发【4】-- 上层mediaPlayer 是如何调到Stagefright的【2】【图解】》
“MediaPlayerService会为每个client应用进程创建一个相应的MediaPlayerService::Client的实例,来提供服务”
2.2.1
  1. ./frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
  2. sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client, int audioSessionId)
  3. {
  4.     pid_t pid = IPCThreadState::self()->getCallingPid();
  5.     int32_t connId = android_atomic_inc(&mNextConnId);

  6.     sp<Client> c = new Client(this, pid, connId, client, audioSessionId, IPCThreadState::self()->getCallingUid());

  7.     wp<Client> w = c;
  8.     {
  9.         Mutex::Autolock lock(mLock);
  10.         mClients.add(w);               //添加到成员数组中
  11.     }
  12.     return c;
  13. }
2.2.2
知道了player是一个::Client>,那么player->setDataSource(fd, offset, length)));也就好理解了
setDataSource主要是调用createPlayer,其过程如下
MediaPlayerService::Client::setDataSource
  --> MediaPlayerService::Client::setDataSource_pre
    --> MediaPlayerService::Client::createPlayer
      --> MediaPlayerFactory::createPlayer
        --> MediaPlayerFactory::StagefrightPlayerFactory::createPlayer
  1. ./frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
  2. status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
  3. {
  4.     int ret = fstat(fd, &sb);
  5.     //MediaPlayerFactory中通过读取file中的内容来判断是下面的哪种类型
  6.     //在STAGEFRIGHT_PLAYER, NU_PLAYER, SONIVOX_PLAYER, TEST_PLAYER
  7.     //默认是STAGEFRIGHT_PLAYER
  8.     player_type playerType = MediaPlayerFactory::getPlayerType(this,fd, offset, length); 
  9.     sp<MediaPlayerBase> p = setDataSource_pre(playerType);       //创建player并设置output
  10.     //这儿实际上是创建了一个StagefrightPlayer,所以下面的p->setDataSourc
  11.     //就是调用StagefrightPlayer::setDataSource
  12.     setDataSource_post(p, p->setDataSource(fd, offset, length));  //第2步--> 2.2.3
  13.     return mStatus;
  14. }

  15. sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(player_type playerType)
  16. {
  17.     sp<MediaPlayerBase> p = createPlayer(playerType);     //先创建player,这儿实际上是创建了一个StagefrightPlayer
  18.     if (!p->hardwareOutput()) {
  19.         mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid());
  20.         static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
  21.     }
  22.     return p;
  23. }

  24. sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
  25. {
  26.     sp<MediaPlayerBase> p = mPlayer;
  27.     p = MediaPlayerFactory::createPlayer(playerType, this, notify);  //返回一个StagefrightPlayer
  28.     return p;
  29. }
在MediaPlayerFactory
  1. ./frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
  2. sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(player_type playerType, ...) {
  3.     sp<MediaPlayerBase> p;
  4.     factory = sFactoryMap.valueFor(playerType);
  5.     p = factory->createPlayer();     //默认是创建StagefrightPlayer();
  6.     return p;
  7. }

  8. virtual sp<MediaPlayerBase> createPlayer() {
  9.     return new StagefrightPlayer();     //最终new了一个StagefrightPlayer
  10. }
2.2.3
//这儿实际上是创建了一个StagefrightPlayer,所以下面的p->setDataSourc  
//就是调用StagefrightPlayer::setDataSource

    setDataSource_post(p, p->setDataSource(fd, offset, length));
  1. ./frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp
  2. StagefrightPlayer::setDataSource
  3. AwesomePlayer::setDataSource(int fd, int64_t offset, int64_t length)
  4.     --> setDataSource_l(const sp<DataSource> &dataSource)
  5.         --> extractor = MediaExtractor::Create(dataSource); //这儿会调用sniff检测文件的类型,并根据文件类型创建相应的解码器
  6.                                                             //:WAV会new WAVExtractor, mp3会new MP3Extractor
  7.         --> setDataSource_l(extractor);

三. prepare的过程


. start的过程
1. 近似的认为:MediaPlayer.java是StagefrightPlayer的java层的调用,这样就很好理解了
  1. mediaPlayer = new MediaPlayer(); --> new StagefrightPlayer
  2. mediaPlayer.setDataSource(File_Path); --> StagefrightPlayer::setDataSource
  3. mediaPlayer.prepareAsync(); --> StagefrightPlayer::prepareAsync
  4. mediaPlayer.start(); --> StagefrightPlayer::start
但是StagefrightPlayer只是一个空壳,它是调用了AwesomePlayer,所以进一步:
  1. mediaPlayer = new MediaPlayer --> new StagefrightPlayer        --> mPlayer(new AwesomePlayer)
  2. mediaPlayer.setDataSource --> StagefrightPlayer::setDataSource --> mPlayer->setDataSource
  3. mediaPlayer.prepareAsync  --> StagefrightPlayer::prepareAsync  --> mPlayer->prepareAsync
  4. mediaPlayer.start();      --> StagefrightPlayer::start         --> mPlayer->play()



四. 数据的读取

  1. frameworks/av/media/libstagefright/DataSource.cpp
  2. status_t AwesomePlayer::setDataSource(int fd, int64_t offset, int64_t length) {
  3.     sp<DataSource> dataSource;
  4.     sp<DataSource> fileSource = new FileSource(fd, offset, length);     //new了一个FileSource,里面的内容是open
  5.     dataSource = new NuCachedSource2(fileSource);
  6.     
  7.     MediaExtractor::Create(dataSource);
  8.       --> source->sniff(&tmp, &confidence, &meta)                       //调用了DataSource的sniff过程
  9.         --> mSniffer->sniff(this, mimeType, confidence, meta);          //this 就是刚刚new的fileSource
  10.           --> (*it)(source, &newMimeType, &newConfidence, &newMeta)     //调用Extractor的sniffer的过程
  11.             --> source->readAt(0, header, sizeof(header)                //数据读取的过程
  12. }
下面就看一下数据读取的真正过程
  1. ./frameworks/av/media/libstagefright/FileSource.cpp
    FileSource有两个构造函数,如果传的是文件名,则调用open打开,获取fd; 如果是fd,则保存在成员变量中
  2. FileSource::FileSource(const char *filename)
  3. {
  4.     mFd = open(filename, O_LARGEFILE | O_RDONLY);  //open:必然要调用系统接口的
  5.     mLength = lseek64(mFd, 0, SEEK_END);
  6. }

  7. FileSource::FileSource(int fd, int64_t offset, int64_t length)
  8.     : mFd(fd),                                 //传的是fd,则直接保存起来
  9.       mOffset(offset),
  10.       mLength(length)
  11. }
  12. //真正的读取过程,还是调用系统的read,没有什么神秘的
  13. ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
  14.     lseek64(mFd, offset + mOffset, SEEK_SET);
  15.     read(mFd, data, size);                              //read:
  16. }




参考文章:
Android多媒体开发【4】-- 上层mediaPlayer 是如何调到Stagefright的【2】【图解】
http://blog.csdn.net/tx3344/article/details/8024489
阅读(1714) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~