前言
前文中分析了MediaPlayer的设置数据源和设置显示控件的流程,那么完成这些设置流程以后,MediaPlayer还需要一个prepare即数据准备的流程才能进行播放。
MediaPlayer提供了两个数据准备的方法,prepareAsync和prepare。
//同步prepare
mMediaPlayer.prepare();
//设置prepareAsync回调
mMediaPlayer.setOnPreparedListener(mOnPreparedListener);
//异步prepare
mMediaPlayer.prepareAsync();
prepareAsync和prepare 两者的流程基本一致,而prepareAsync可以通过setOnPreparedListener方法设置一个回调,最终调用onPrepared方法通知APP prepare流程执行完成。
完成数据准备工作之后,就可以开始播放了。
mMediaPlayer.start();
prepareAsync流程分析
首先来分析一下MediaPlayer.java的prepareAsync方法,prepareAsync就是一个native方法,直接调用到Jni层。
// frameworks/base/media/java/android/media/MediaPlayer.java
public native void prepareAsync() throws IllegalStateException;
通过Jni的动态注册, prepareAsync调用到android_media_MediaPlayer_prepareAsync方法
// frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
{
// 获取之前缓存的C++层的MediaPlayer对象
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
// Handle the case where the display surface was set before the mp was
// initialized. We try again to make it stick.
// 再次设置显示控件
sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
mp->setVideoSurfaceTexture(st);
// mp->prepareAsync() 调用C++层MediaPlayer的prepareAsync方法, 如果异常则通过process_media_player_call抛给Java层处理
process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
}
再来分析MediaPlayer.cpp中的prepareAsync方法
// frameworks/av/media/libmedia/mediaplayer.cpp
status_t MediaPlayer::prepareAsync()
{
ALOGV("prepareAsync");
//加锁操作
Mutex::Autolock _l(mLock);
return prepareAsync_l();
}
// must call with lock held
status_t MediaPlayer::prepareAsync_l()
{
// 判断当前状态是否是INITIALIZED或STOP状态
if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
if (mAudioAttributesParcel != NULL) {
// 设置音频属性参数
mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
} else {
// 设置音频流类型信息
mPlayer->setAudioStreamType(mStreamType);
}
// 设置当前状态为正在prepare流程状态
mCurrentState = MEDIA_PLAYER_PREPARING;
// 调用IMediaPlayer的prepareAsync方法
return mPlayer->prepareAsync();
}
ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
return INVALID_OPERATION;
}
上面代码可以看出,prepareAsync方法最终还是会通过IMediaPlayer对象,最终调用到MediaPlayerService中的播放器对象的prepareAsync,这一部分我们在分析MediaPlayerService和播放器的源码时再详细分析。
到这里,我们客户端的MediaPlayer的prepare流程就完成了,那么它又是如何接收到prepare流程的回调通知呢?
其实我们在第一篇文章中就已经分析了这一部分流程,简单来说就是,MediaPlayerService通过IMediaPlayerClient对象持有客户端的MediaPlayer.cpp对象的接口代理对象,通过notify方法来给客户端发送消息。
而客户端接收到消息以后,最终通过 MediaPlayer.cpp —> android_media_MediaPlayer.cpp —> MediaPlayer.java 一层一层向上传给给APP端。
start流程分析
当所有准备工作都已经就绪以后,MediaPlayer的状态应当为MEDIA_PLAYER_PREPARED,此时我们就可以开始播放了。
// frameworks/base/media/java/android/media/MediaPlayer.java
public void start() throws IllegalStateException {
//FIXME use lambda to pass startImpl to superclass
//获取延时事件
final int delay = getStartDelayMs();
if (delay == 0) {
//不需要延时,直接start
startImpl();
} else {
new Thread() {
public void run() {
//休眠延时时间
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
//重置延时时间
baseSetStartDelayMs(0);
try {
//开始start
startImpl();
} catch (IllegalStateException e) {
// fail silently for a state exception when it is happening after
// a delayed start, as the player state could have changed between the
// call to start() and the execution of startImpl()
}
}
}.start();
}
}
private void startImpl() {
//更新播放状态
baseStart();
//唤醒锁处理
stayAwake(true);
//调用JNI层的start
_start();
}
private native void _start() throws IllegalStateException;
上面代码可以看到,start之前,需要先处理休眠时间、更新播放状态、唤醒锁处理,最后才调用到JNI层的_start()。
// frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
{
ALOGV("start");
// 获取之前缓存的C++层的MediaPlayer对象
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
// mp->start() 调用C++层MediaPlayer的start方法, 如果异常则通过process_media_player_call抛给Java层处理
process_media_player_call( env, thiz, mp->start(), NULL, NULL );
}
与之前的几个步骤基本相同,先获取创建好的C++层的MediaPlayer对象,再调用它的start()方法,如果异常则通过process_media_player_call抛给Java层处理。
// frameworks/av/media/libmedia/mediaplayer.cpp
status_t MediaPlayer::start()
{
ALOGV("start");
//加锁操作
status_t ret = NO_ERROR;
Mutex::Autolock _l(mLock);
mLockThreadId = getThreadId();
if (mCurrentState & MEDIA_PLAYER_STARTED) {
ret = NO_ERROR;
// 如果当前状态
} else if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
mPlayer->setLooping(mLoop);
//设置左右声的音量
mPlayer->setVolume(mLeftVolume, mRightVolume);
//设置音效增益等级
mPlayer->setAuxEffectSendLevel(mSendLevel);
//设置当前状态为开始播放状态
mCurrentState = MEDIA_PLAYER_STARTED;
//调用IMediaPlayer的start方法
ret = mPlayer->start();
if (ret != NO_ERROR) {
mCurrentState = MEDIA_PLAYER_STATE_ERROR;
} else {
if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
ALOGV("playback completed immediately following start()");
}
}
} else {
ALOGE("start called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
ret = INVALID_OPERATION;
}
mLockThreadId = 0;
return ret;
}
与之前几个步骤相同,start方法最终也是会通过IMediaPlayer对象,调用到MediaPlayerService中的播放器对象的start。
到此,MediaPlayer的播放流程基本上分析完成。