继前一篇文章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数据流