0.1继上一篇
android应用开发---11.MediaPlayer实现音乐播放的demo 发现android播放音频文件只需要下面几步
-
mediaPlayer = new MediaPlayer(); //1
-
mediaPlayer.setDataSource(File_Path); //2
-
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-
mediaPlayer.prepareAsync(); //异步的方式加载音乐文件
-
mediaPlayer.start(); //准备好之后才能start
0.2 stageFright的框架如下所示:
下面就逐个分析一下这个过程
一.new MediaPlayer的过程
-
./frameworks/base/media/java/android/media/MediaPlayer.java
-
public MediaPlayer() {
-
//调用jni中的native_setup
-
native_setup(new WeakReference<MediaPlayer>(this));
-
}
1.1 jni的native_setup
-
./frameworks/base/media/jni/android_media_MediaPlayer.cpp
-
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
-
{
-
sp<MediaPlayer> mp = new MediaPlayer();
-
sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
-
mp->setListener(listener);
-
setMediaPlayer(env, thiz, mp); //把mp保存起来
-
}
二. setDataSource的过程
-
在./frameworks/base/media/java/android/media/MediaPlayer.java中
-
public void setDataSource(String path) {
-
//打开path的文件,转为fd
-
//调用jni的_setDataSource
-
}
2.1 jni中的setDataSource
-
./frameworks/base/media/jni/android_media_MediaPlayer.cpp
-
android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
-
{
-
sp<MediaPlayer> mp = getMediaPlayer(env, thiz); //获取第1步保存的mp
-
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
-
}
2.2
-
./frameworks/av/media/libmedia/mediaplayer.cpp
-
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
-
{
-
const sp<IMediaPlayerService>& service(getMediaPlayerService()); //获取MediaPlayerService
-
sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); //2.2.1通过MediaPlayerService创建player
-
player->setDataSource(fd, offset, length))); //2.2.2
-
attachNewPlayer(player);
-
return err;
-
}
通过下面的2.3可知service->create实际上是创建了一个
::Client>
引自《Android多媒体开发【4】-- 上层mediaPlayer 是如何调到Stagefright的【2】【图解】》
“MediaPlayerService会为每个client应用进程创建一个相应的MediaPlayerService::Client的实例,来提供服务”
2.2.1
-
./frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
-
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client, int audioSessionId)
-
{
-
pid_t pid = IPCThreadState::self()->getCallingPid();
-
int32_t connId = android_atomic_inc(&mNextConnId);
-
-
sp<Client> c = new Client(this, pid, connId, client, audioSessionId, IPCThreadState::self()->getCallingUid());
-
-
wp<Client> w = c;
-
{
-
Mutex::Autolock lock(mLock);
-
mClients.add(w); //添加到成员数组中
-
}
-
return c;
-
}
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
-
./frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
-
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
-
{
-
int ret = fstat(fd, &sb);
-
//MediaPlayerFactory中通过读取file中的内容来判断是下面的哪种类型
-
//在STAGEFRIGHT_PLAYER, NU_PLAYER, SONIVOX_PLAYER, TEST_PLAYER
-
//默认是STAGEFRIGHT_PLAYER
-
player_type playerType = MediaPlayerFactory::getPlayerType(this,fd, offset, length);
-
sp<MediaPlayerBase> p = setDataSource_pre(playerType); //创建player并设置output
-
//这儿实际上是创建了一个StagefrightPlayer,所以下面的p->setDataSourc
-
//就是调用StagefrightPlayer::setDataSource
-
setDataSource_post(p, p->setDataSource(fd, offset, length)); //第2步--> 2.2.3
-
return mStatus;
-
}
-
-
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(player_type playerType)
-
{
-
sp<MediaPlayerBase> p = createPlayer(playerType); //先创建player,这儿实际上是创建了一个StagefrightPlayer
-
if (!p->hardwareOutput()) {
-
mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid());
-
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
-
}
-
return p;
-
}
-
-
sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
-
{
-
sp<MediaPlayerBase> p = mPlayer;
-
p = MediaPlayerFactory::createPlayer(playerType, this, notify); //返回一个StagefrightPlayer
-
return p;
-
}
在MediaPlayerFactory中
-
./frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
-
sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(player_type playerType, ...) {
-
sp<MediaPlayerBase> p;
-
factory = sFactoryMap.valueFor(playerType);
-
p = factory->createPlayer(); //默认是创建StagefrightPlayer();
-
return p;
-
}
-
-
virtual sp<MediaPlayerBase> createPlayer() {
-
return new StagefrightPlayer(); //最终new了一个StagefrightPlayer
-
}
2.2.3
//这儿实际上是创建了一个StagefrightPlayer,所以下面的p->setDataSourc
//就是调用StagefrightPlayer::setDataSource
setDataSource_post(p, p->setDataSource(fd, offset, length));
-
./frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp
-
StagefrightPlayer::setDataSource
-
AwesomePlayer::setDataSource(int fd, int64_t offset, int64_t length)
-
--> setDataSource_l(const sp<DataSource> &dataSource)
-
--> extractor = MediaExtractor::Create(dataSource); //这儿会调用sniff检测文件的类型,并根据文件类型创建相应的解码器
-
//如:WAV会new WAVExtractor, mp3会new MP3Extractor
-
--> setDataSource_l(extractor);
三. prepare的过程
三. start的过程
1. 近似的认为:MediaPlayer.java是StagefrightPlayer的java层的调用,这样就很好理解了
-
mediaPlayer = new MediaPlayer(); --> new StagefrightPlayer
-
mediaPlayer.setDataSource(File_Path); --> StagefrightPlayer::setDataSource
-
mediaPlayer.prepareAsync(); --> StagefrightPlayer::prepareAsync
-
mediaPlayer.start(); --> StagefrightPlayer::start
但是StagefrightPlayer只是一个空壳,它是调用了AwesomePlayer,所以进一步:
-
mediaPlayer = new MediaPlayer --> new StagefrightPlayer --> mPlayer(new AwesomePlayer)
-
mediaPlayer.setDataSource --> StagefrightPlayer::setDataSource --> mPlayer->setDataSource
-
mediaPlayer.prepareAsync --> StagefrightPlayer::prepareAsync --> mPlayer->prepareAsync
-
mediaPlayer.start(); --> StagefrightPlayer::start --> mPlayer->play()
四. 数据的读取
-
frameworks/av/media/libstagefright/DataSource.cpp
-
status_t AwesomePlayer::setDataSource(int fd, int64_t offset, int64_t length) {
-
sp<DataSource> dataSource;
-
sp<DataSource> fileSource = new FileSource(fd, offset, length); //new了一个FileSource,里面的内容是open
-
dataSource = new NuCachedSource2(fileSource);
-
-
MediaExtractor::Create(dataSource);
-
--> source->sniff(&tmp, &confidence, &meta) //调用了DataSource的sniff过程
-
--> mSniffer->sniff(this, mimeType, confidence, meta); //this 就是刚刚new的fileSource
-
--> (*it)(source, &newMimeType, &newConfidence, &newMeta) //调用Extractor的sniffer的过程
-
--> source->readAt(0, header, sizeof(header) //数据读取的过程
-
}
下面就看一下数据读取的真正过程
-
./frameworks/av/media/libstagefright/FileSource.cpp
FileSource有两个构造函数,如果传的是文件名,则调用open打开,获取fd; 如果是fd,则保存在成员变量中
-
FileSource::FileSource(const char *filename)
-
{
-
mFd = open(filename, O_LARGEFILE | O_RDONLY); //open:必然要调用系统接口的
-
mLength = lseek64(mFd, 0, SEEK_END);
-
}
-
-
FileSource::FileSource(int fd, int64_t offset, int64_t length)
-
: mFd(fd), //传的是fd,则直接保存起来
-
mOffset(offset),
-
mLength(length)
-
}
-
//真正的读取过程,还是调用系统的read,没有什么神秘的
-
ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
-
lseek64(mFd, offset + mOffset, SEEK_SET);
-
read(mFd, data, size); //read:隐藏的很深
-
}
参考文章:
Android多媒体开发【4】-- 上层mediaPlayer 是如何调到Stagefright的【2】【图解】
http://blog.csdn.net/tx3344/article/details/8024489
阅读(1790) | 评论(0) | 转发(0) |