MediaPlayer(七)--prepareAsync

作者: llm_5243 | 来源:发表于2020-04-18 14:55 被阅读0次

    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;
    }
    
    

    相关文章

      网友评论

        本文标题:MediaPlayer(七)--prepareAsync

        本文链接:https://www.haomeiwen.com/subject/faotphtx.html