frameworks/base/media/java/android/media/MediaPlayer.java
/**
* Prepares the player for playback, asynchronously.
*
* After setting the datasource and the display surface, you need to either
* call prepare() or prepareAsync(). For streams, you should call prepareAsync(),
* which returns immediately, rather than blocking until enough data has been
* buffered.
*
* @throws IllegalStateException if it is called in an invalid state
*/
public native void prepareAsync() throws IllegalStateException;
MediaPlayer.java 没有任何流程,直接调用了jni。从注释可以了解到,设置完datasource和 display surface就需要调用prepare或prepareAsync。prepare是阻塞的接口,prepareAsync是异步的接口。
/home/llm/project/rk/8.1/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
{
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);
process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
}
首先重新设置了display surface,从注释看setDisplay接口可以在setDataSource之前被调用。接着调用到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()
{
if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
if (mAudioAttributesParcel != NULL) {
mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
} else {
mPlayer->setAudioStreamType(mStreamType);
}
mCurrentState = MEDIA_PLAYER_PREPARING;
return mPlayer->prepareAsync();
}
ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
return INVALID_OPERATION;
}
首先是对audio的设置,这部分笔者也没研究。
其次是将播放器的状态置为MEDIA_PLAYER_PREPARING
最后调用服务端的prepareAsync
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
status_t MediaPlayerService::Client::prepareAsync()
{
ALOGV("[%d] prepareAsync", mConnId);
mMaybeVideoAlive = (mConnectedWindow.get() != NULL);
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
status_t ret = p->prepareAsync();
#if CALLBACK_ANTAGONIZER
ALOGD("start Antagonizer");
if (ret == NO_ERROR) mAntagonizer->start();
#endif
return ret;
}prepare
留下两个知识盲点:mConnectedWindow,CALLBACK_ANTAGONIZER
主要是直接调用到NuPlayer的prepareAsync.NuPlayer处理完后会通过notify回调函数通知java层,流程大概如下
NuPlayer -->MediaPlayerService::Client::notify--> MediaPlayer::notify--> JNIMediaPlayerListener::notify -->postEventFromNative(java)
根据MediaPlayer的状态图,MeidiaPlayer在执行往prepareAsync后会将状态置为prepared,这个操作是在MediaPlayer::notify处理的
void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
case MEDIA_PREPARED:
ALOGV("MediaPlayer::notify() prepared");
mCurrentState = MEDIA_PLAYER_PREPARED;
if (mPrepareSync) {
ALOGV("signal application thread");
mPrepareSync = false;
mPrepareStatus = NO_ERROR;
mSignal.signal();
}
break;
}
mSignal.signal();是一种信号量的通讯方式,其他调用了mSignal.wait的地方会阻塞等待,当收到signal的信号后就可以继续往下执行。我们知道MediaPlayer prepare方法是阻塞的,实际上prepare就是调用mSignal.wait进行等待,其他地方跟prepareAsync的流程是差不多的
status_t MediaPlayer::prepare()
{
ALOGV("prepare");
Mutex::Autolock _l(mLock);
mLockThreadId = getThreadId();
if (mPrepareSync) {
mLockThreadId = 0;
return -EALREADY;
}
mPrepareSync = true;
status_t ret = prepareAsync_l();
if (ret != NO_ERROR) {
mLockThreadId = 0;
return ret;
}
if (mPrepareSync) {
mSignal.wait(mLock); // wait for prepare done
mPrepareSync = false;
}
ALOGV("prepare complete - status=%d", mPrepareStatus);
mLockThreadId = 0;
return mPrepareStatus;
}
网友评论