AwesomePlayer的准备工作,本文主要描述当Java调用mp.start();时,AwesomePlayer做了些什么... 1. AwesomePlayer::play_l 其调用流程如下: StagefrightPlayer::start-> AwesomePlayer::play-> AwesomePlayer::play_l AwesomePlayer::play_l主要代码如下:

               

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

1. AwesomePlayer::play_l

  其调用流程如下:

    StagefrightPlayer::start->

       AwesomePlayer::play->

         AwesomePlayer::play_l

    AwesomePlayer::play_l主要代码如下:

 

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启动视频回放。此函数代码如下:

 

void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {    if (mVideoEventPending) {        return;    }    mVideoEventPending = true;    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);}


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

 

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

相关简化代码如下:

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();    //进行下一帧的显示}

 

1)调用OMXCodec::read创建mVideoBuffer

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

    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数据流

 

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/hddghhfd/article/details/87858131