.创建实例(AwesomePlayer调用SetDataSource())
.调用OMXCodec:Create()
.findMatchingCodecs()
.InstantiateSoftwareDecoder()
.omx->allocateNode()
.如果成功后,new OMXCodec()初始化OMXCodec,设置mState为LOADED
.setComponentRole()->调用omx->setParameter(OMX_IndexParamStandardComponentRole)
.configureCodec(),调用setVideoOutputFormat()
.对InputPort做mOMX->getParameter(OMX_IndexParamPortDefinition)后修改宽、高、压缩比、颜色格式后mOMX->setParameter(OMX_IndexParamPortDefinition)
.对OutputPort做mOMX->getParameter(OMX_IndexParamPortDefinition)后修改宽、高后mOMX->setParameter(OMX_IndexParamPortDefinition)
.预备解码(AwesomePlayer调用play()中的initVideoDecoder())
.调用OMXCodec:start()
.如果是在paused的状态,则:(如果是硬解码,当前mState必须为PAUSED状态。mOMX-sendCommand(set,Executing),并setState(IDLE_TO_EXECUTING),并等待至mState变成EXECUTING或者ERROR,然后drainInputBuffers();如果是软解码,则直接drainInputBuffers()),并return
.否则默认mState当前必须是LOADED状态,调用压缩数据源DataSource->start()
.调用OMXCodec:init()
.调用mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle),并设置mState为LOADED_TO_IDLE
.调用allocateBuffers(),先mOMX->getParameter(OMX_IndexParamPortDefinition)读取port信息,再根据port定义的buffer size去mOMX->allocateBuffer()申请内存,然后将申请好的内存放在mPortBuffers[portIndex]里
.一直忙等直到mState变为Executing或Error,这期间会收到下层消息并调用onStateChange(OMX_StateIdle),mOMX->sendCommand(Set, OMX_StateExecuting)并设置mState为IDLE_TO_EXECUTING,再收到onStateChange(OMX_StateExecuting),并将mState设置为EXECUTING
.开始解码(AwesomePlayer调用play()中的postVideoEvent_l()后激活onVideoEvent())
.调用OMXCodec:read()
.先读取ReadOptions看看是不是seek
.如果不是seek,则当前mState必须是EXECUTING或者RECONFIGURING
.如果是提交的第一帧,先调用drainInputBuffers()
.执行drainInputBuffers()必须是在mState为EXECUTING,RECONFIGURING和FLUSHING的状态。
.从mPortBuffers[input]里循环取出每个BufferInfo,并对每个info->mStatus等于OWNED_BY_US的buffer调用drainInputBuffer(info)
.drainInputBuffer(BufferInfo)要求buffer必须是OWNED_BY_US
.如果有未处理的mCodecSpecificData则先mOMX->emptyBuffer(info->Buffer,OMX_BUFFERFLAG_CODECCONFIG)处理这些配置数据
.如果mSignalledEOS或者mPaused为true则停止drain并return false
.循环调用mSource->read()读取压缩源srcBuffer,读取失败的话则设置mSignalledEOS为true,如果成功则将其copy进info->mData里去
.结果是info->mData里装着从mSource中多次读取出来的数据总和,并将timestampUs设为第一块数据的kKeyTime值
.设置flags为OMX_BUFFERFLAG_ENDOFFRAME,如果刚才遇到EOS则再并一个OMX_BUFFERFLAG_EOS
.调用mOMX->emptyBuffer(mNode, info->mBuffer, 0, offset,flags, timestampUs);
.如果emptyBuffer返回OK,则设置info->mStatus为OWNED_BY_COMPONENT并return true,否则设置mState为ERROR并返回false
.再调用fillOutputBuffers()
.执行fillOutputBuffers()必须是在mState为EXECUTING,FLUSHING的状态
.从mPortBuffers[output]里循环取出每个BufferInfo,并对每个info->mStatus等于OWNED_BY_US的buffer调用fillOutputBuffer(info)
.如果mNoMoreOutputData为true则return
.如果info->mMediaBuffer不为空,则取出其中的GraphicBuffer,并调用mNativeWindow->lockBuffer(mNativeWindow,graphicBuffer)来锁定该buffer,出错则设置mState为ERROR
.调用mOMX->fillBuffer(mNode, info->mBuffer)
.如果emptyBuffer返回OK,则设置info->mStatus为OWNED_BY_COMPONENT,否则设置mState为ERROR,最后return
.如果mState不为ERROR,并且mNoMoreOutputData为false,并且mFilledBuffers为空,并且mOutputPortSettingsChangedPending为false的情况下,则调用waitForBufferFilled_l(),让mBufferFilled去wait lock
.从waitForBufferFilled_l()释放出来后,判断mFilledBuffers为空的话,如果mOutputPortSettingsChangedPending为true则去调用之前延迟执行的onPortSettingsChanged(),否则return EOS
.取出mFilledBuffers的第一个buffer,该buffer的mStatus此时必须为OWNED_BY_US。
.然后设置其为OWNED_BY_CLIENT,给该buffer的mMediaBuffer->add_ref()增加一个引用,并把该mMediaBuffer赋值给buffer并返回给AwesomePlayer
. 暂停解码(AwesomePlayer调用pause()。本地播放只有audio会pause;而video只会clear "OnVideoEvent“, 只有在http streaming时才会调用pause)
.调用OMXCodec::pause()
.mState必须是EXECUTING状态,否则返回ERROR。如果当前是“中间状态“则waitlock。
.如果当前是qcom解码器,则调用mOMX->sendCommand(Set, OMX_StatePause),并设置mState为PAUSING,设置mPaused为true。然后waitlock直到mState变成PAUSED或者ERROR
.下层执行完毕后调用omCmdComplete(),然后进入onStateChange(OMX_StatePause),断定当前mState必须是PAUSING,然后将其设置为PAUSED
.如果不是qcom解码器则只设置mPaused为true并return
. 恢复解码(AwesomePlayer调用play(),onVideoEvent()恢复执行,AudioPlayer会调用resume())
.调用OMXCodec:start() (只有audio会调用,video的会直接调用read())
.当在paused的状态,则:(如果是硬解码,当前mState必须为PAUSED状态。mOMX-sendCommand(set,Executing),并setState(IDLE_TO_EXECUTING),并等待至mState变成EXECUTING或者ERROR,然后drainInputBuffers();如果是软解码,则直接drainInputBuffers()),并return
.调用drainInputBuffers()-> drainInputBuffer(BufferInfo *info)......(同之前的drainInputBuffer()描述)
. Seek操作(AwesomePlayer调用seekTo方法)
.从ReadOptions中取出seekTimeUs, seekMode,并设置seeking为true
.如果当前seeking为true,并且mState为PAUSING或者PAUSED,并且解码器是qcom的,则:
.如果mState是PAUSING,则waitlock,等到其为PAUSED,且必须为PAUSED
.发送mOMX->sendCommand(Set, OMX_StateExecuting),并设置mState为IDLE_TO_EXECUTING,mPaused为false,并等待Executing状态设置成功后,执行drainInputBuffers()
.如果当前mState不是EXECUTING或者RECONFIGURING的话,则直接返回UNKNOWN_ERROR
.如果当前seeking为true,则:
.当mState为RECONFIGURING,则一直忙等执行waitForBufferFilled_l(),即mBufferFilled一直waitlock,直到mState不为RECONFIGURING
.如果mState不为EXECUTING,则return UNKNOWN_ERROR
.设置mSignalledEOS为false,并清空mFilledBuffer
.设置当前mState为FLUSHING
.分别对output port和input port做flushPortAsync()
.flushPortAsync()执行时mState必须是EXECUTING 或者 RECONFIGURING 或者 EXECUTING_TO_IDLE 或者 FLUSHING
.断定当前mPortStatus[portIndex]必须是ENABLED,然后将mPortStatus设成SHUTTING_DOWN
.发送mOMX->sendCommand(OMX_CommandFlush, portIndex)
.当mSeekTimeUs大于等于0,则waitForBufferFilled_l()直到mSeekTimeUs小于0;如果出错,并且当时mState为FLUSHING,则设置mState为EXECUTING
.如果mState不为ERROR,并且mNoMoreOutputData为false,并且mFilledBuffers为空,并且mOutputPortSettingsChangedPending为false的情况下,则调用waitForBufferFilled_l(),让mBufferFilled去waitlock
.如果seeking为true,则断定当前mState为FLUSHING,然后将其设置为EXECUTING
.取出mFilledBuffers的第一个buffer,该buffer的mStatus此时必须为OWNED_BY_US。
.然后设置其为OWNED_BY_CLIENT,给该buffer的mMediaBuffer->add_ref()增加一个引用,并把该mMediaBuffer赋值给buffer并返回给AwesomePlayer
. 停止解码(AwesomePlayer调用shutdownVideoDecoder_l())
.调用OMXCodec:stop(),如果当前mState是中间状态,则waitlock等待
.设置isError和forceFlush为false
.如果当前mState状态为LOADED,则break
.如果当前mState状态为ERROR,则:
.如果当前的mPortStatus[output]为ENABLING,则freeBuffersOnPort(portIndex,onlyThoseWeOwn)去释放尽可能多的buffer,为保证析构能正常释放实例避免assert crash,设置mStatus为LOADED,并break
.如果不是ENABLING,则mOMX->getState()获取当前状态,如果state不是Executing或者Pause的话,则设置forceFlush为true,并break,否则设置isError为true并fall through到下面来
.如果当前mState状态为PAUSED或者EXECUTING,则:
.设置mState为EXECUTING_TO_IDLE
.设置mPortStatus[input/output]为SHUTTING_DOWN,并发送mOMX->sendCommand(Set, OMX_StateIdle),并waitlock直到mState为LOADED或ERROR
.底层通知onStateChange(Idle)成功,并断定当前mState为EXECUTING_TO_IDLE,并断定countBufferWeOwn()必须是mPortBuffers.size()
.发送mOMX->sendCommand(Set, OMX_StateLoaded),同时freeBuffersOnPort(in/out),设置mPortStatus[in/out]为ENABLED,并设置mState为IDLE_TO_LOADED
.freeBuffersOnPort()会循环断定每个buffer的mStatus必须为OWNED_BY_US或者OWNED_BY_NATIVE_WINDOW,或者OWNED_BY_COMPONENT但参数onlyThoseWeOwn为true
.freeBuffer()调用mOMX->freeBuffer(portIndex, info->mBuffer),并断定info->mMediaBuffer->refcount()为0,调用cancelBufferToNativeWindow(),并info->mMediaBuffer->release(),这将触发signalBufferReturned()
.收到onStateChange(Loaded),断定mState为IDLE_TO_LOADED,设置mState为LOADED
.如果mState是ERROR,则设置forceFlush为true;如果isError为true,则设置mState为ERROR
.如果forceFlush()为true,则调用flushBuffersOnError()
.通过mOMX->getState()返回OK断定component还活着,设置mPortStatus[in/out]为ENABLED,设置mState为EXCUTING_TO_IDLE
.flushPortAsync(in/out),设置mState为ERROR以滤掉所有EBD/FBD,然后循环15次查看mPortBuffers是否被收回
.将所有mStatus为OWNED_BY_US的buffer都执行一遍cancelBufferToNativeWindow()
.最后将压缩源mSource->stop(),并return OK
. 注销实例(AwesomePlayer调用shutdownVideoDecoder_l())
.断定当前mState必须为LOADED,ERROR或者LOADED_TO_IDLE
.调用mOMX->freeNode()
.releaseMediaBuffersOn(input/output)
.设置mState为DEAD
.清除mCodecSpecificData
. 底层通知on_message() -> omx_message::EMPTY_BUFFER_DONE
.根据buffer_id获取对应的BufferInfo, 设置info->mStatus为OWNED_BY_US
.如果info->mMediaBuffer不为空,则调用info->mMediaBuffer->release(),其会调用signalBufferReturned()
.signalBufferReturned()首先断定mPortStatus[output]为ENABLED,并且info->mStatus为OWNED_BY_CLIENT, 然后设置info->mStatus为OWNED_BY_US
.如果buffer的graphicBuffer为空并且mOutputPortSettingsChangedPending是false的话,则fillOutputBuffer()
.否则获取kKeyRendered,如果为false则cancelBufferToNativeWindow(),设置info->mStatus为OWNED_BY_NATIVE_WINDOW
.如果mOutputPortSettingsChangedPending为false的话,dequeueBufferFromNativeWindow()获取下一个buffer,然后fillOutputBuffer(nextBufInfo)
.否则调用onPortSettingsChanged(ouput)
.如果当前mPortStatus[input]为DISABLING,则调用freeBuffer()
.或者如果mState不为ERROR,并且mPortStatus[input]不为SHUTTING_DOWN的话,断定mPortStatus[input]为ENABLED,并且drainInputBuffer()
. 底层通知on_message() -> omx_message::FILL_BUFFER_DONE
.根据buffer_id获取对应的BufferInfo, 设置info->mStatus为OWNED_BY_US
.如果当前mPortStatus[output]为DISABLING,则调用freeBuffer()
.或者如果mPortStatus[output]不为SHUTTING_DOWN的话
.断定mPortStatus[input]为ENABLED
.如果info->mMediaBuffer为空的话,则
.断定mOMXLivesLocally为true,mQuirks包含kRequiresAllocateBufferOnOutputPorts和kDefersOutputBufferAllocation
.info->mMediaBuffer=new MediaBuffer(),并且设置info->mMediaBuffer->setObserver为当前的OMXCodec实例
.设置一堆info->mMediaBuffer的meta后,如果mTargetTimeUs大于等于0并且info的timestamp小于mTargetTimeUs的话,则skip这个buffer,调用fillOutputBuffer(info)后break;否则mFilledBuffers.push_back该buffer,然后mBufferFilled.signal()
. 底层通知on_message() -> onEvent() -> OMX_EventPortSettingsChanged
.OMXCodec:onEvent(OMX_EventPortSettingsChanged)被调用,如果当前mState不是EXECUTING则忽略
.如果port是ouput并且mFilledBuffers不为空则mDeferReason或上一个FILLED_BUFFERS_PRESENT,或者如果countOutputBuffers(OWNED_BY_CLIENT)>0则mDeferReason或上一个BUFFER_WITH_CLIENT,则设置mOutputPortSettingsChangedPending为true
.如果mDeferReason不为空,则调用mBufferFilled.signal()激活waitforbufferfilled();如果为空,则调用onPortSettingsChanged()
.onPortSettingsChanged首先断定mState为EXECUTING,port是output,并且mOutputPortSettingsChangedPending为false
.如果mPortStatus[output]不是ENABLED,则延迟port setting change,设置mOutputPortSettingsChangedPending为ture并return
.否则设置mState为RECONFIGURING,并调用disablePortAsync(portIndex)
.disablePortAsync()断定当前mState必须为EXECUTING或者RECONFIGURING,并且mPortStatus[portIndex]必须为ENABLED
.设置mPortStatus为DISABLING,并发送mOMX->sendCommand(OMX_CommandPortDisable),并调用freeBuffersOnPort(portIndex,onThoseWeOwn)
.收到底层onCmdComplete(OMX_CommandPortDisable)的消息
.断定mState为EXECUTING或者RECONFIGURING,断定mPortStatus为DISABLING,断定mPortBuffers.size()必须为0
.设置mPortStatus为DISABLED
.如果mState为RECONFIGURING,则调用initOutputFormat(),通过mOMX->getParameter/setParameter重新初始化参数
.调用enablePortAsync()
.断定mState为EXECUTING或RECONFIGURING,断定mPortStatus为DISABLED,再设置其为ENABLING
.发送mOMX->sendCommand(OMX_CommandPortEnable)
.收到底层onCmdComplete(OMX_CommandPortEnable),断定mState为EXECUTING或者RECONFIGURING,断定mPortStatus为ENABLING,然后设置mPortStatus为ENABLED
.如果mState是RECONFIGURING,则设置mState为EXECUTING,并执行fillOutputBuffers()
.如果enablePortAsync()返回OK,则allocateBuffersOnPort(),否则设置mState为ERROR
. 底层通知on_message() -> onEvent() -> onCmdComplete() -> OMX_CommandFlush
.断定mPortStatus[index]为SHUTTING_DOWN,然后设置mPortStatus[index]为ENABLED
.断定countBufferWeOwn()必须为mPortBuffers.size()
.如果当前mState是RECONFIGURING,则调用disablePortAsync()
.或者如果当前mState是EXECUTING_TO_IDLE,并且mPortStatus[in/out]都为ENABLED,则设置mPortStatus[in/out]为SHUTTING_DOWN,并发送mOMX->sendCommand(Set, OMX_StateIdle)
.否则,当前应该是为seeking做准备而flush所有port(mState当前应该是FLUSHING)
.如果mPort[in/out]都是ENABLED,则设置mPaused为false,并drainInputBuffers()和fillOutputBuffers()
.如果mOutputPortSettingsChangedPending为true,则设置mOutputPortSettingsChangedPending为false
.如果countOutputBuffers(OWNED_BY_CLIENT) > 0则设置mOutputPortSettingsChangedPending为true,并mDeferReason或一个BUFFER_WITH_CLIENT后break
.否则断定mFilledBuffers为空,并且调用onPortSettingsChanged(kPortIndexOutput)