AwesomePlayer的启动工作



http://blog.csdn.net/myarrow/article/details/7108393

继前一篇文章AwesomePlayer的准备工作,本文主要描述当Java调用mp.start();时,AwesomePlayer做了些什么...

1. AwesomePlayer::play_l

  其调用流程如下:

    StagefrightPlayer::start->

       AwesomePlayer::play->

         AwesomePlayer::play_l

    AwesomePlayer::play_l主要代码如下:

 

  1. status_t AwesomePlayer::play_l() {  
  2.     modifyFlags(SEEK_PREVIEW, CLEAR);  
  3.   
  4.     modifyFlags(PLAYING, SET);  
  5.     modifyFlags(FIRST_FRAME, SET);  
  6.       
  7.     // 创建AudioPlayer  
  8.     if (mAudioSource != NULL) {  
  9.         if (mAudioPlayer == NULL) {  
  10.             if (mAudioSink != NULL) {  
  11.                 mAudioPlayer = new AudioPlayer(mAudioSink, this);  
  12.                 mAudioPlayer->setSource(mAudioSource);  
  13.   
  14.                 mTimeSource = mAudioPlayer;  
  15.   
  16.                 // If there was a seek request before we ever started,  
  17.                 // honor the request now.  
  18.                 // Make sure to do this before starting the audio player  
  19.                 // to avoid a race condition.  
  20.                 seekAudioIfNecessary_l();  
  21.             }  
  22.         }  
  23.   
  24.         CHECK(!(mFlags & AUDIO_RUNNING));  
  25.           
  26.         //如果只播放音频,则启动AudioPlayer  
  27.         if (mVideoSource == NULL) {  
  28.             // We don't want to post an error notification at this point,  
  29.             // the error returned from MediaPlayer::start() will suffice.  
  30.   
  31.             status_t err = startAudioPlayer_l(  
  32.                     false /* sendErrorNotification */);  
  33.   
  34.             if (err != OK) {  
  35.                 delete mAudioPlayer;  
  36.                 mAudioPlayer = NULL;  
  37.   
  38.                 modifyFlags((PLAYING | FIRST_FRAME), CLEAR);  
  39.   
  40.                 if (mDecryptHandle != NULL) {  
  41.                     mDrmManagerClient->setPlaybackStatus(  
  42.                             mDecryptHandle, Playback::STOP, 0);  
  43.                 }  
  44.   
  45.                 return err;  
  46.             }  
  47.         }  
  48.     }  
  49.   
  50.     if (mTimeSource == NULL && mAudioPlayer == NULL) {  
  51.         mTimeSource = &mSystemTimeSource;  
  52.     }  
  53.   
  54.     // 启动视频回放  
  55.     if (mVideoSource != NULL) {  
  56.         // Kick off video playback  
  57.         postVideoEvent_l();  
  58.   
  59.         if (mAudioSource != NULL && mVideoSource != NULL) {  
  60.             postVideoLagEvent_l();  
  61.         }  
  62.     }  
  63.   
  64.     ...  
  65.   
  66.     return OK;  
  67. }  
status_t AwesomePlayer::play_l() {
    modifyFlags(SEEK_PREVIEW, CLEAR);

    modifyFlags(PLAYING, SET);
    modifyFlags(FIRST_FRAME, SET);
    
    // 创建AudioPlayer
    if (mAudioSource != NULL) {
        if (mAudioPlayer == NULL) {
            if (mAudioSink != NULL) {
                mAudioPlayer = new AudioPlayer(mAudioSink, this);
                mAudioPlayer->setSource(mAudioSource);

                mTimeSource = mAudioPlayer;

                // If there was a seek request before we ever started,
                // honor the request now.
                // Make sure to do this before starting the audio player
                // to avoid a race condition.
                seekAudioIfNecessary_l();
            }
        }

        CHECK(!(mFlags & AUDIO_RUNNING));
        
        //如果只播放音频,则启动AudioPlayer
        if (mVideoSource == NULL) {
            // We don't want to post an error notification at this point,
            // the error returned from MediaPlayer::start() will suffice.

            status_t err = startAudioPlayer_l(
                    false /* sendErrorNotification */);

            if (err != OK) {
                delete mAudioPlayer;
                mAudioPlayer = NULL;

                modifyFlags((PLAYING | FIRST_FRAME), CLEAR);

                if (mDecryptHandle != NULL) {
                    mDrmManagerClient->setPlaybackStatus(
                            mDecryptHandle, Playback::STOP, 0);
                }

                return err;
            }
        }
    }

    if (mTimeSource == NULL && mAudioPlayer == NULL) {
        mTimeSource = &mSystemTimeSource;
    }

    // 启动视频回放
    if (mVideoSource != NULL) {
        // Kick off video playback
        postVideoEvent_l();

        if (mAudioSource != NULL && mVideoSource != NULL) {
            postVideoLagEvent_l();
        }
    }

    ...

    return OK;
}


1.1 创建AudioPlayer

      创建AudioPlayer,创建之后,如果只播放音频,则调用AwesomePlayer::startAudioPlayer_l启动音频播放,在启动音频播放时,主要调用以下启动工作:

     AudioPlayer::start->

          mSource->start

          mSource->read

          mAudioSink->open

          mAudioSink->start

1.2 启动视频回放

      调用AwesomePlayer::postVideoEvent_l启动视频回放。此函数代码如下:

 

  1. void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {  
  2.     if (mVideoEventPending) {  
  3.         return;  
  4.     }  
  5.   
  6.     mVideoEventPending = true;  
  7.     mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);  
  8. }  
void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
    if (mVideoEventPending) {
        return;
    }

    mVideoEventPending = true;
    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
}


    前面已经讲过, mQueue.postEventWithDelay发送一个事件到队列中,最终执行事件的fire函数。这些事件的初始化在AwesomePlayer::AwesomePlayer中进行。

 

  1. AwesomePlayer::AwesomePlayer()  
  2.     : mQueueStarted(false),  
  3.       mUIDValid(false),  
  4.       mTimeSource(NULL),  
  5.       mVideoRendererIsPreview(false),  
  6.       mAudioPlayer(NULL),  
  7.       mDisplayWidth(0),  
  8.       mDisplayHeight(0),  
  9.       mFlags(0),  
  10.       mExtractorFlags(0),  
  11.       mVideoBuffer(NULL),  
  12.       mDecryptHandle(NULL),  
  13.       mLastVideoTimeUs(-1),  
  14.       mTextPlayer(NULL) {  
  15.     CHECK_EQ(mClient.connect(), (status_t)OK);  
  16.   
  17.     DataSource::RegisterDefaultSniffers();  
  18.   
  19.     mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);  
  20.     mVideoEventPending = false;  
  21.     mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);  
  22.     mStreamDoneEventPending = false;  
  23.     mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);  
  24.     mBufferingEventPending = false;  
  25.     mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);  
  26.     mVideoEventPending = false;  
  27.   
  28.     mCheckAudioStatusEvent = new AwesomeEvent(  
  29.             this, &AwesomePlayer::onCheckAudioStatus);  
  30.   
  31.     mAudioStatusEventPending = false;  
  32.   
  33.     reset();  
  34. }  
AwesomePlayer::AwesomePlayer()
    : mQueueStarted(false),
      mUIDValid(false),
      mTimeSource(NULL),
      mVideoRendererIsPreview(false),
      mAudioPlayer(NULL),
      mDisplayWidth(0),
      mDisplayHeight(0),
      mFlags(0),
      mExtractorFlags(0),
      mVideoBuffer(NULL),
      mDecryptHandle(NULL),
      mLastVideoTimeUs(-1),
      mTextPlayer(NULL) {
    CHECK_EQ(mClient.connect(), (status_t)OK);

    DataSource::RegisterDefaultSniffers();

    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
    mVideoEventPending = false;
    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
    mStreamDoneEventPending = false;
    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
    mBufferingEventPending = false;
    mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
    mVideoEventPending = false;

    mCheckAudioStatusEvent = new AwesomeEvent(
            this, &AwesomePlayer::onCheckAudioStatus);

    mAudioStatusEventPending = false;

    reset();
}


      现在明白了,对于mVideoEnent,最终将执行函数AwesomePlayer::onVideoEvent,一层套一层,再继续向下看看... 

1.2.1 AwesomePlayer::onVideoEvent

相关简化代码如下:

  1. <span style="font-size: 10px;">void AwesomePlayer::postVideoEvent_l(int64_t delayUs)  
  2. {  
  3.   mQueue.postEventWithDelay(mVideoEvent, delayUs);  
  4. }  
  5.   
  6. void AwesomePlayer::onVideoEvent()  
  7. {  
  8.   mVideoSource->read(&mVideoBuffer,&options);  //获取解码后的YUV数据  
  9.   [Check Timestamp]                        //进行AV同步  
  10.   mVideoRenderer->render(mVideoBuffer);   //显示解码后的YUV数据  
  11.   
  12.   postVideoEvent_l();    //进行下一帧的显示  
  13. }  
  14. </span>  
<span style="font-size: 10px;">void AwesomePlayer::postVideoEvent_l(int64_t delayUs)
{
  mQueue.postEventWithDelay(mVideoEvent, delayUs);
}

void AwesomePlayer::onVideoEvent()
{
  mVideoSource->read(&mVideoBuffer,&options);  //获取解码后的YUV数据
  [Check Timestamp]                        //进行AV同步
  mVideoRenderer->render(mVideoBuffer);   //显示解码后的YUV数据

  postVideoEvent_l();    //进行下一帧的显示
}
</span>

 

1)调用OMXCodec::read创建mVideoBuffer

2)调用AwesomePlayer::initRenderer_l初始化mVideoRender

 

  1. if (USE_SURFACE_ALLOC  //硬件解码  
  2.         && !strncmp(component, "OMX.", 4)  
  3.         && strncmp(component, "OMX.google.", 11)) {  
  4.     // Hardware decoders avoid the CPU color conversion by decoding  
  5.     // directly to ANativeBuffers, so we must use a renderer that  
  6.     // just pushes those buffers to the ANativeWindow.  
  7.     mVideoRenderer =  
  8.         new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);  
  9. else {  //软件解码  
  10.     // Other decoders are instantiated locally and as a consequence  
  11.     // allocate their buffers in local address space.  This renderer  
  12.     // then performs a color conversion and copy to get the data  
  13.     // into the ANativeBuffer.  
  14.     mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);  
  15. }  
    if (USE_SURFACE_ALLOC  //硬件解码
            && !strncmp(component, "OMX.", 4)
            && strncmp(component, "OMX.google.", 11)) {
        // Hardware decoders avoid the CPU color conversion by decoding
        // directly to ANativeBuffers, so we must use a renderer that
        // just pushes those buffers to the ANativeWindow.
        mVideoRenderer =
            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
    } else {  //软件解码
        // Other decoders are instantiated locally and as a consequence
        // allocate their buffers in local address space.  This renderer
        // then performs a color conversion and copy to get the data
        // into the ANativeBuffer.
        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
    }


3)调用AwesomePlayer::startAudioPlayer_l启动音频播放

4)然后再循环调用postVideoEvent_l来post mVideoEvent事件,以循环工作。

 其主要对象及关系如下图所示:

 

 

 2. AwesomePlayer数据流

 

 

 

 

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值