android多媒体本地播放流程video playback--base on jellybean (四)

上一篇我们讲了mediaplayer播放的第一步骤setdataSource,下面我们来讲解preparesync的流程,在prepare前我们还有setDisplay这一步,即获取surfacetexture来进行画面的展示

setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive)

{

    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);

………

    sp<ISurfaceTexture> new_st;

    if (jsurface) {

        sp<Surface> surface(Surface_getSurface(env, jsurface));

        if (surface != NULL) {

            new_st = surface->getSurfaceTexture();

            ---通过surface获取surfaceTexture

            new_st->incStrong(thiz);

……….

    }………….

    mp->setVideoSurfaceTexture(new_st);

}

 

为什么用surfaceTexture不用surface来展示呢?ICS之前都用的是surfaceview来展示video或者openGL的内容,surfacaview rendersurface上,textureview rendersurfaceTexturetextureviewsurfaceview 这两者有什么区别呢?surfaceview跟应用的视窗不是同一个视窗,它自己new了一个window来展示openGL或者video的内容,这样做有一个好处就是不用重绘应用的视窗,本身就可以不停的更新,但这也带来一些局限性,surfaceview不是依附在应用视窗中,也就不能移动、缩放、旋转,应用ListView或者 ScrollView就比较费劲。Textureview就很好的解决了这些问题。它拥有surfaceview的一切特性外,它也拥有view的一切行为,可以当个view使用。

 

获取完surfaceTexture,我们就可以prepare/prepareAsync了,先给大伙看个大体时序图吧:

 

JNI的部分我们跳过,直接进入libmedia下的mediaplayer.cpp prepareAsync_l方法,prepare是个同步的过程,所以要加锁,prepareAsync_l后缀加_l就是表面是同步的过程。

status_t MediaPlayer::prepareAsync_l()

{

    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {

        mPlayer->setAudioStreamType(mStreamType);

        mCurrentState = MEDIA_PLAYER_PREPARING;

        return mPlayer->prepareAsync();

    }

    ALOGE("prepareAsync called in state %d", mCurrentState);

    return INVALID_OPERATION;

}

 

在上面的代码中,我们看到有个mPlayer,看过前一章的朋友都会记得,就是我们从Mediaplayerservice获得的BpMediaplayer.通过BpMediaplayer我们就可以长驱直入,直捣Awesomeplayer这条干实事的黄龙,前方的mediaplayerserviceclientstagefrightplayer都是些通风报信的料,不值得我们去深入研究,无非是些接口而已。进入了prepareAsync_l方法,我们的播放器所处的状态就是MEDIA_PLAYER_PREPARING了。好了,我们就来看看Awesomeplayer到底做了啥吧.

代码定位于:frameworks/av/media/libstagefright/Awesomeplayer.cpp

先看下prepareAsync_l吧:

status_t AwesomePlayer::prepareAsync_l() {

    if (mFlags & PREPARING) {

        return UNKNOWN_ERROR;  // async prepare already pending

    }

 

    if (!mQueueStarted) {

        mQueue.start();

        mQueueStarted = true;

    }

 

    modifyFlags(PREPARING, SET);

    mAsyncPrepareEvent = new AwesomeEvent(

            this, &AwesomePlayer::onPrepareAsyncEvent);

 

    mQueue.postEvent(mAsyncPrepareEvent);

 

    return OK;

}

 

  这里我们涉及到了TimeEventQueue,即时间事件队列模型,Awesomeplayer里面类似Handler的东西,它的实现方式是把事件响应时间和事件本身封装成一个queueItem,通过postEvent 插入队列,时间到了就会根据事件id进行相应的处理。

  首先我们来看下TimeEventQueue的start(mQueue.start();)方法都干了什么:

frameworks/av/media/libstagefright/TimedEventQueue.cpp

void TimedEventQueue::start() {

    if (mRunning) {

        return;

    }

……..

 

    pthread_create(&mThread, &attr, ThreadWrapper, this);

 

………

}

 

目的很明显就是在主线程创建一个子线程,可能很多没有写过C/C++的人对ptread_create这个创建线程的方法有点陌生,我们就来分析下:

int pthread_create(pthread_t *thread, pthread_addr_t *arr,

           void* (*start_routine)(void *), void *arg);

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值