安卓mediacodec是啥,Android6.0之前版本(AwesomePlayer)OMXCodec執行流程細節

 2023-11-30 阅读 20 评论 0

摘要:?原址 .創建實例(AwesomePlayer調用SetDataSource()).調用OMXCodec:Create().findMatchingCodecs().InstantiateSoftwareDecoder().omx->allocateNode().如果成功后,new OMXCodec()初始化OMXCodec,設置mState為LOADED.setCompon

?原址

.創建實例(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)

?

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/185608.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息