MediaPlayer函数调用(二)

分析完setDataSource之后,分析prepare和start

prepare()

Prepares the player for playback, synchronously.
After setting the datasource and the display surface, you need to either
call prepare() or prepareAsync(). For files, it is OK to call prepare(),
which blocks until MediaPlayer is ready for playback.

在设置完setDataSource之后,调用prepare()或者prepareAsync(),分别为同步,异步准备。
在prepare()中,调用了本地函数。

 public void prepare() throws IOException, IllegalStateException {
        _prepare();  /*call native _prepare*/
        scanInternalSubtitleTracks();
    }
  • jni的函数名为 android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)

这个地方和setDataSource一样,得到MediaPlay -》 mp.prepare(),

MediaPlay.cpp

源码地址 /home/android/frameworks/av/media/libmedia/mediaplayer.cpp

status_t MediaPlayer::prepare()
{
    ALOGI("[snake_xing_MediaPlayer.cpp]======================>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;
}

status_t MediaPlayer::prepareAsync()
{
    ALOGV("prepareAsync");
    Mutex::Autolock _l(mLock);
    return prepareAsync_l();
}

可以看到,在准备的时候,同步和异步最终调用的都是prepareAsync_l();
并且在同步调用的时候等待准备结束,才能继续执行。

/ must call with lock held
status_t MediaPlayer::prepareAsync_l()
{
    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
        mPlayer->setAudioStreamType(mStreamType);
        if (mAudioAttributesParcel != NULL) {
            mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
        }
        mCurrentState = MEDIA_PLAYER_PREPARING;
        return mPlayer->prepareAsync(); /*sp   mPlayer; */
    }
    ALOGE("[snake_xing_MediaPlayer]=================>prepareAsync called in state %d", mCurrentState);
    return INVALID_OPERATION;
}

中介

1 追了MediaPlay的prepare 和 start
在设置完setDataSource()之后,分别可以call prepare()或者 prepareAsync()
prepare() -》 本地函数_prepare()
也就是 android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)两个参数分别本地类和java类
-> getMediaPlayer(env, thiz); 根据两个参数获取MeidiaPlay
->MediaPlay.prepare() //MediaPlayer::prepare()
->prepareAsync_l() 在这发现,调用了异步的准备,也就是上层的同步和异步准备,在MediaPlay中都是call prepareAsync_l(),
->mSignal.wait(mLock); // wait for prepare done 等待准备,就达到了同步的效果。
->MediaPlayer::prepareAsync_l()
a. ->mPlayer(IMediaPlayer)->prepareAsync(); 调用了接口类IMediaPlayer
在IMediaPlayer中定义了 BpMediaPlayer 和 BnMediaPlayer
在 BpMediaPlayer中的 prepareAsync()中,调用了transact(PREPARE_ASYNC, data, &reply)和 server通信,返回结果 ,第一个参数 代表准备的命令,第二个参数 要传递的值 ,第三个是server回传的值
在BnMediaPlayer 实现了 onTransact() 并且给replay赋值。

start()的调用步骤和prepare 类似。

在打log的时候,MediaPlayerService::instantiate() 是注册服务的函数 
            -> addService(String16("media.player"), new MediaPlayerService());  第一个是服务的名称,第二个是服务类
同样就有      MediaPlayerService::create() 创建client 
            -> binder = sm->getService(String16("media.player"));
            返回IMediaPlayer也就是client
          
         通过IMediaPlayer来调用 prepareAsync()也就是上面的a.

遇到的问题 1 在jni 和 av/media/ 下打log发现,ALOGV()在logcat中并不显示,原因:在debug模式下,ALOGV()被关闭,使用ALOGI()可以。
2 binder的架构不理解,下午主要看了binder模板写法,
service:
在service中 addservice(“XXXX”)
jonithread作为服务。
定义Bnservice
实现 ontransat() 和 业务函数比如 start()

Client:
getservice(“xxx”)  获得 Iservie调用 start()

定义类Bpservice
实现业务函数 start(){
transat(); 和service通信,获得service返回数据reply
}

你可能感兴趣的:(MediaPlayer函数调用(二))