标签:des style blog http color io os ar strong
- status_t AwesomePlayer::play() {
- ……
- return play_l();
- }
-
- status_t AwesomePlayer::play_l() {
- ……
- if (mAudioSource != NULL) {
- if (mAudioPlayer == NULL) {
- createAudioPlayer_l();
- }
-
- if (mVideoSource == NULL) {
- status_t err = startAudioPlayer_l(
- false
- ……;
- }
- }
-
- if (mVideoSource != NULL) {
-
- postVideoEvent_l();
-
- if (mAudioSource != NULL && mVideoSource != NULL) {
- postVideoLagEvent_l();
- }
- }
- ……
- }
如果是播放AVI、MP4等视频文件,则m_AudioSource和mVideoSource都不为null,如果是播放MP3文件,则m_AudioSource不为null而mVideoSource为null。现在按照播放视频文件的流程来分析。
先看createAudioPlayer_1();
- void AwesomePlayer::createAudioPlayer_l()
- {
- ……
- mAudioPlayer = new AudioPlayer(mAudioSink, flags, this);
- mAudioPlayer->setSource(mAudioSource);
- ……
- }
可以看到,创建了audioPlayer,且把mAudioSource传给了创建的mAudioPlayer。
接着看postVideoEvent_l
- void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
- ATRACE_CALL();
-
- if (mVideoEventPending) {
- return;
- }
-
- mVideoEventPending = true;
- mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
- }
有关TimedEventQueue的介绍,在上一篇TimedEventQueue分析。mVideoEvent在AwesomePlayer的构造函数中定义,如下:
mVideoEvent = new AwesomeEvent(this,&AwesomePlayer::onVideoEvent);
所以,mQueue.postEventWithDelay()后,将会执行到onVideoEvent
- void AwesomePlayer::onVideoEvent() {
- ……
- if (!mVideoBuffer) {
- ……
- for (;;) {
- status_t err = mVideoSource->read(&mVideoBuffer, &options);
- ……
- if (mVideoBuffer->range_length() == 0) {
- mVideoBuffer->release();
- mVideoBuffer = NULL;
- continue;
- }
- break;
- }
-
- {
- Mutex::Autolock autoLock(mStatsLock);
- ++mStats.mNumVideoFramesDecoded;
- }
- }
-
- ……
- if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
- status_t err = startAudioPlayer_l();
- }
-
- if ((mFlags & TEXTPLAYER_INITIALIZED)
- && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
- mTextDriver->start();
- modifyFlags(TEXT_RUNNING, SET);
- }
- ……
-
- if ((mNativeWindow != NULL)
- && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
- mVideoRendererIsPreview = false;
-
- initRenderer_l();
- }
-
- if (mVideoRenderer != NULL) {
- mSinceLastDropped++;
- mVideoRenderer->render(mVideoBuffer);
- if (!mVideoRenderingStarted) {
- mVideoRenderingStarted = true;
- notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
- }
-
- if (mFlags & PLAYING) {
- notifyIfMediaStarted_l();
- }
- }
- ……
- postVideoEvent_l();
- }
接下来分步分析
step1 : status_t err= mVideoSource->read(&mVideoBuffer, &options); 这个方法的作用就是从数据源读取数据,然后将数据送给解码器解码,最后解码器将解码好的数据输出,并通过输出参数buffer传出,为后面的render 所用。
- status_t OMXCodec::read(
- MediaBuffer **buffer, const ReadOptions *options) {
- ……
- if (mInitialBufferSubmit) {
- mInitialBufferSubmit = false;
- ……
- drainInputBuffers();
-
- if (mState == EXECUTING) {
-
-
- fillOutputBuffers();
- }
- }
- ……
- while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
- if ((err = waitForBufferFilled_l()) != OK) {
- return err;
- }
- }
- ……
- *buffer = info->mMediaBuffer;
- return OK;
- }
drainInputBuffers()和fillOutputBuffers()这两个函数后面再分析,先接着看onVideoEvent里面的step2 : status_t err = startAudioPlayer_l();
- status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
- ……
- err = mAudioPlayer->start(
- true
- ……
- return err;
- }
- status_t AudioPlayer::start(bool sourceAlreadyStarted) {
- ……
- mAudioTrack = new AudioTrack(AUDIO_STREAM_MUSIC,
- mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
- 0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
- ……
- mAudioTrack->start();
- ……
- return OK;
- }
- void AudioPlayer::AudioCallback(int event, void *info) {
- switch (event) {
- case AudioTrack::EVENT_MORE_DATA:
- {
- AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
-
- size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
- buffer->size = numBytesWritten;
- }
- break;
-
- case AudioTrack::EVENT_STREAM_END:
- mReachedEOS = true;
- notifyAudioEOS();
- break;
- }
- }
Step3 : initRenderer_l() 创建render
- void AwesomePlayer::initRenderer_l() {
- ……
- if (USE_SURFACE_ALLOC
- && !strncmp(component, "OMX.", 4)
- && strncmp(component, "OMX.google.", 11)) {
-
-
-
-
- mVideoRenderer =
- new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
- } else {
-
-
-
-
-
- mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
- }
- }
Step4 : mVideoRenderer->render(mVideoBuffer);
就是将mVideoBuffer的内容输出到屏幕
到现在为止,onVideoEvent流程分析完成,接下来详细分析drainInputBuffers和fillOutputBuffers,这两个函数都是通过OMX和解码器通讯的函数。
- bool OMXCodec::drainInputBuffer(BufferInfo *info) {
- ……
- err = mSource->read(&srcBuffer);
- ……
- err = mOMX->emptyBuffer(
- mNode, info->mBuffer, 0, offset,
- flags, timestampUs);
-
- info->mStatus = OWNED_BY_COMPONENT;
-
- return true;
- }
- void OMXCodec::fillOutputBuffer(BufferInfo *info) {
-
- status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
-
- info->mStatus = OWNED_BY_COMPONENT;
- }
貌似很简单,其实调用解码器的这个流程还是蛮复杂的,下面以emptyBuffer为例来梳理一下:
首先,mOMX为OMX的Bp端,其Bn端的实现在OMX.cpp里面
- status_t OMX::emptyBuffer(
- node_id node,
- buffer_id buffer,
- OMX_U32 range_offset, OMX_U32 range_length,
- OMX_U32 flags, OMX_TICKS timestamp) {
- return findInstance(node)->emptyBuffer(
- buffer, range_offset, range_length, flags, timestamp);
- }
再看findInstance(node),node是prepare时调用OMX的allocateNode方法得到的,findInstance将会根据这个node值返回之前创建的OMXNodeInstance对象,其emptyBuffer定义如下:
- status_t OMXNodeInstance::emptyBuffer(
- OMX::buffer_id buffer,
- OMX_U32 rangeOffset, OMX_U32 rangeLength,
- OMX_U32 flags, OMX_TICKS timestamp) {
- Mutex::Autolock autoLock(mLock);
-
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
- header->nFilledLen = rangeLength;
- header->nOffset = rangeOffset;
- header->nFlags = flags;
- header->nTimeStamp = timestamp;
-
- BufferMeta *buffer_meta =
- static_cast<BufferMeta *>(header->pAppPrivate);
- buffer_meta->CopyToOMX(header);
-
- OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
-
- return StatusFromOMXError(err);
- }
-
- #define OMX_EmptyThisBuffer( \
- hComponent, \
- pBuffer) \
- ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer( \
- hComponent, \
- pBuffer)
从
代码中,我们可以看出实际上是调用了mHandle的EmptyThisBuffer方法,mHandle是什么呢?在prepare过程中,我们调用了
OMX的allocateNode方法,在这个方法里面,我们通过调用OMXNodeInstance的setHandle方法设置了其值。再回顾一下其
实现:
- status_t OMX::allocateNode(
- const char *name, const sp<IOMXObserver> &observer, node_id *node) {
- Mutex::Autolock autoLock(mLock);
-
- *node = 0;
-
-
- OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
-
-
- OMX_COMPONENTTYPE *handle;
- OMX_ERRORTYPE err = mMaster->makeComponentInstance(
- name, &OMXNodeInstance::kCallbacks,
- instance, &handle);
-
- if (err != OMX_ErrorNone) {
- ALOGV("FAILED to allocate omx component ‘%s‘", name);
-
- instance->onGetHandleFailed();
-
- return UNKNOWN_ERROR;
- }
-
- *node = makeNodeID(instance);
- mDispatchers.add(*node, new CallbackDispatcher(instance));
-
- instance->setHandle(*node, handle);
-
- mLiveNodes.add(observer->asBinder(), instance);
- observer->asBinder()->linkToDeath(this);
-
- return OK;
- }
-
- void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
- CHECK(mHandle == NULL);
- mNodeID = node_id;
- mHandle = handle;
- }
OK,至此整个发送数据到解码器的流程就跑通了,但是前面也说了,在OMXCodec的read方法中,drainInputBuffers方法只会执行一次,之后要再往解码器送数据该怎么弄呢?就要靠回调了。一起来看一下这个回调的流程是怎么弄的吧?
在OMX的allocateNode方法中
- OMX_COMPONENTTYPE *handle;
- OMX_ERRORTYPE err = mMaster->makeComponentInstance(
- name, &OMXNodeInstance::kCallbacks,
- instance, &handle);
创建解码器时,就注册了回调函数
- OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
- &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
- };
当解码器将原始数据全部解码完成后,就会调用OMXNodeInstance 的OnEmptyBufferDone方法
- OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
- 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()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
- }
Instance->owner()实际上就是OMX,再看OMX的OnEmptyBufferDone
- OMX_ERRORTYPE OMX::OnEmptyBufferDone(
- node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
- ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
-
- omx_message msg;
- msg.type = omx_message::EMPTY_BUFFER_DONE;
- msg.node = node;
- msg.u.buffer_data.buffer = pBuffer;
-
- findDispatcher(node)->post(msg);
-
- return OMX_ErrorNone;
- }
findDispatcher
返回CallbackDispatcher对象,是OMX的内部类,也是在OMX的allocate方法中创建的,CallbackDispatcher
在创建时启动了一个线程,不断的获取消息,然后调用dispatch方法执行之,看dispatch方法:
- void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
- if (mOwner == NULL) {
- ALOGV("Would have dispatched a message to a node that‘s already gone.");
- return;
- }
- mOwner->onMessage(msg);
- }
mOwner为OMXNodeInstance对象,所以看OMXNodeInstance的onMessage方法。
- void OMXNodeInstance::onMessage(const omx_message &msg) {
- ……
- mObserver->onMessage(msg);
- }
mObserver为OMXCodecObserver对象,是在prepare时在OMXCodec::Create中创建,下面看其onMessage方法实现
- virtual void onMessage(const omx_message &msg) {
- sp<OMXCodec> codec = mTarget.promote();
-
- if (codec.get() != NULL) {
- Mutex::Autolock autoLock(codec->mLock);
- codec->on_message(msg);
- codec.clear();
- }
- }
codec的值为OMXCodec对象,看其on_message的实现
- void OMXCodec::on_message(const omx_message &msg) {
- ……
- switch (msg.type) {
- ……
- case omx_message::EMPTY_BUFFER_DONE:
- {
- ……
- if (mPortStatus[kPortIndexInput] == DISABLING) {
- ……
- } else if (mState != ERROR
- && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
- CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED);
-
- if (mFlags & kUseSecureInputBuffers) {
- drainAnyInputBuffer();
- } else {
-
- drainInputBuffer(&buffers->editItemAt(i));
- }
- break;
- }
-
- case omx_message::FILL_BUFFER_DONE:
- {
-
-
- ……
- }
- }
- }
MediaPlayer本地播放流程解析(三)
标签:des style blog http color io os ar strong
原文地址:http://www.cnblogs.com/yido9932/p/3987426.html