您的位置:首页 > 其它

ICS4.0.3创建NuPlayer的处理流程

2012-03-16 10:39 274 查看
ICS4.0.3中播放RTSP流媒体使用的播放器框架是NuPlayer,现在就分析创建NuPlayer的处理流程。

1.创建Nulayer所做的处理

在NuPlayerDriver::NuPlayerDriver()构造函数中:

1.1 创建了ALooper对象mLooper,并调用了 mLooper->start函数,优先级为PRIORITY_AUDIO。

在ALooper::start函数中循环执行ALooper::loop()函数,在loop函数中调用gLooperRoster.deliverMessage函数,

然后在ALooperRoster::deliverMessag函数中调用handler->onMessageReceived函数,最终执行了AHandler的子struct中的onMessageReceived函数,

处理具体消息;例如MyHandler的onMessageReceived函数,用于处理rtsp的消息。

1.2 创建了NuPlayer对象mPlayer,并调用 mLooper->registerHandler,把mPlayer注册到全局变量gLooperRoster的mHandlers成员vector中。

所有的AHandler对象都需要注册到全局变量gLooperRoster的mHandlers成员中。

2. NuPlayer::start处理的流程为以下顺序

2.1 MediaPlayer::start() -> MediaPlayerService::Client::start() ->

2.2 NuPlayerDriver::start()

在NuPlayerDriver::setDataSource中mState被设置为STOPPED状态,所以在start函数中执行了mPlayer->start(),调用到NuPlayer::start()函数

2.3 NuPlayer::start()

发送kWhatStart消息

2.4 NuPlayer::onMessageReceived对kWhatStart消息的处理

2.4.1 接收到kWhatStart消息后,先对一些变量赋初始值,并调用mSource->start()函数,对于rtsp流来说,即调用NuPlayer::RTSPSource::start()函数

2.4.1.1 NuPlayer::RTSPSource::start()

(1)创建了ALooper对象mLooper,并调用了mLooper->setName("rtsp")和mLooper->start()函数。

(2)创建了AHandlerReflector<RTSPSource>对象mReflector,并通过调用mLooper->registerHandler,把mReflector注册到全局变量gLooperRoster的mHandlers成员中

AHandlerReflector的作用暂时还不清楚,貌似是指定RTSPSource接收消息

(3)创建消息kWhatNotify,并做为MyHandler的参数,在NuPlayer::RTSPSource::onMessageReceived函数中处理了kWhatNotify消息

(4)创建MyHandler对象mHandler,并注册到gLooperRoster的mHandlers成员中

(5)执行mHandler->connect(),链接到服务器,并把mState设置为CONNECTING状态

调用ARTSPConnection的connect函数,进行链接服务器的处理。

2.4.2 新建Renderer对象mRenderer,并发送kWhatRendererNotify消息,把mRenderer注册到全局变量gLooperRoster的mHandlers成员中

Renderer构造函数只是简单的对变量赋默认值,并没有做其他处理

2.4.3 调用postScanSources()函数,进行初始化audio/video的解码器decoder

(1)NuPlayer::postScanSources()函数中发送了kWhatScanSources消息

2.5 NuPlayer::onMessageReceived对kWhatScanSources消息的处理

2.5.1 调用instantiateDecoder函数执行初始化video和audio解码器

instantiateDecoder(false, &mVideoDecoder);

    if (mAudioSink != NULL) {
        instantiateDecoder(true, &mAudioDecoder);
    }
2.5.2 NuPlayer::instantiateDecoder

(1)当初始化audio解码器时,发送kWhatAudioNotify消息

当初始化video解码器时,发送kWhatVideoNotify消息

(2)初始解码器Decoder对象decoder,并注册到全局变量gLooperRoster的mHandlers成员中

*decoder = audio ? new Decoder(notify) :
                       new Decoder(notify, mNativeWindow); // video时,设置NativeWindowWrapper参数
    looper()->registerHandler(*decoder);

    (*decoder)->configure(meta); // 调用decoder的configure方法,初始化ACodec解码器
2.5.3 NuPlayer::Decoder::configure

(1)创建消息kWhatCodecNotify,用于ACodec对象mCodec的通知消息

(2)调用makeFormat函数,根据meta类型,创建对应的message format

(3)创建ACodec对象mCodec,

(4)video解码时,创建ALooper对象mCodecLooper,用于释放主消息event队列,并注册到全局变量gLooperRoster的mHandlers成员中

mCodecLooper的name设置为"NuPlayerDecoder"

2.6 NuPlayer::onMessageReceived

case kWhatVideoNotify:

case kWhatAudioNotify:

取得AMessage消息"codec-request"对应的"what"值,分别对以下情况处理

2.6.1 ACodec::kWhatFillThisBuffer

执行feedDecoderInputData函数,取得一个有效的buffer

2.6.2 ACodec::kWhatEOS

向render发送EOS消息

mRenderer->queueEOS(audio, err);

2.6.3 ACodec::kWhatFlushCompleted

(1)把mFlushingAudio或mFlushingVideo设置为FLUSHED或者SHUTTING_DOWN_DECODER状态

(2)调用finishFlushIfPossible()函数,执行一些flush后的操作,例如:

mRenderer->signalTimeDiscontinuity();

mAudioDecoder->signalResume();

mVideoDecoder->signalResume();

finishReset();

如果mAudioDecoder == NULL || mVideoDecoder == NULL,则会执行postScanSources()函数,进行初始化audio/video的解码器decoder

2.6.4 ACodec::kWhatOutputFormatChanged

2.6.5 ACodec::kWhatShutdownCompleted

2.6.6 ACodec::kWhatError

2.6.7 ACodec::kWhatDrainThisBuffer // 在ACodec::BaseState::onOMXFillBufferDone中发送的

调用renderBuffer(audio, codecRequest), 把需要解码的数据放入render队列

2.7 NuPlayer::renderBuffer

先做一些检查,丢弃需要跳过的数据

调用mRenderer->queueBuffer(audio, buffer, reply);,把真正需要解码的数据放入renderer队列

2.8 NuPlayer::Renderer::queueBuffer

发送kWhatQueueBuffer消息

sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
    msg->setInt32("audio", static_cast<int32_t>(audio));
    msg->setObject("buffer", buffer);
    msg->setMessage("notifyConsumed", notifyConsumed);
    msg->post();
2.9 NuPlayer::Renderer::onMessageReceived

case kWhatQueueBuffer:

--->

NuPlayer::Renderer::onQueueBuffer

在video时,调用postDrainVideoQueue函数

--->

NuPlayer::Renderer::postDrainVideoQueue()

发送kWhatDrainVideoQueue消息,消息延迟时间为delayUs。

+++++++++++++++变量注解+++++++++++++++

mAnchorTimeMediaUs表示audio的媒体时间mediaTimeUs,初始值为-1
        mAnchorTimeMediaUs = mediaTimeUs;

            int64_t realTimeOffsetUs =
                (mAudioSink->latency() / 2  /* XXX */
                    + numFramesPendingPlayout
                        * mAudioSink->msecsPerFrame()) * 1000ll;

            // LOGI("realTimeOffsetUs = %lld us", realTimeOffsetUs);

            mAnchorTimeRealUs =
                ALooper::GetNowUs() + realTimeOffsetUs;
        mAnchorTimeRealUs表示audio的已经处理完(包括已经播放和正要播放)的数据的时间。如果没有audio,则为当前系统时间
            mAnchorTimeRealUs = ALooper::GetNowUs();
++++++++++++++++++++++++++++++

--->

NuPlayer::Renderer::onMessageReceived

case kWhatDrainVideoQueue:

调用onDrainVideoQueue()处理

继续调用postDrainVideoQueue函数,循环处理下一个buffer

--->

NuPlayer::Renderer::onDrainVideoQueue()
// 发送消息表示此buffer已经处理
    entry->mNotifyConsumed->setInt32("render", !tooLate);
    entry->mNotifyConsumed->post();
    mVideoQueue.erase(mVideoQueue.begin());
    entry = NULL;

    notifyPosition();
--------------------------------------------------------------------------------------------------

**************** 发送kWhatDrainThisBuffer消息的处理流程 Start ****************

NuPlayer::instantiateDecoder

创建Decoder对象,然后调用

(*decoder)->configure(meta);

--->

NuPlayer::Decoder::configure

调用mCodec->initiateSetup(format);

--->

ACodec::initiateSetup

发送kWhatSetup消息

--->

ACodec::UninitializedState::onMessageReceived

case ACodec::kWhatSetup:

调用onSetup(msg);

--->

ACodec::UninitializedState::onSetup
status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
--->

OMX::allocateNode

创建了OMXNodeInstance对象,并注册了OMXNodeInstance::kCallbacks回调

--->

// static
OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone // 注册了回调函数OnFillBufferDone
};
--->

OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
        OMX_IN OMX_HANDLETYPE hComponent,
        OMX_IN OMX_PTR pAppData,
        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
    OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
    if (instance->mDying) {
        return OMX_ErrorNone;
    }
    return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer); // OMXNodeInstance含有OMX成员变量OMX *mOwner;
}
--->

OMX::OnFillBufferDone

设置msg.type = omx_message::FILL_BUFFER_DONE;并发送

--->

ACodec::BaseState::onOMXMessage
    case omx_message::FILL_BUFFER_DONE:
        return onOMXFillBufferDone(
                            bufferID,
                            (size_t)rangeOffset, (size_t)rangeLength,
                            (OMX_U32)flags,
                            timeUs,
                            platformPrivate,
                            dataPtr);
--->

ACodec::BaseState::onOMXFillBufferDone
    PortMode mode = getPortMode(kPortIndexOutput);

    switch (mode) {
        case KEEP_BUFFERS:
            break;

        case RESUBMIT_BUFFERS:
        设置发送消息notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
**************** 发送kWhatDrainThisBuffer消息的处理流程 End ****************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: