东莞网站开发哪里找,网站推广方法和策略,现在大家做电商网站用什么源码,齐博网站模板之前的章节中我们解了 input buffer 是如何传递给 OMX 的#xff0c;以及Output buffer 是如何分配并且注册给 OMX 的。这一节我们就来看ACodec是如何处理OMX的Callback的。 1、OMXNodeInstance Callback
这一节我们只大致记录Callback是如何传递给ACodec的。在之前的学习中我… 之前的章节中我们解了 input buffer 是如何传递给 OMX 的以及Output buffer 是如何分配并且注册给 OMX 的。这一节我们就来看ACodec是如何处理OMX的Callback的。 1、OMXNodeInstance Callback
这一节我们只大致记录Callback是如何传递给ACodec的。在之前的学习中我们了解到OMXNodeInstance中会有一个专门的线程来处理OMX的callback这个线程的作用是把Callback按照时间顺序回传给ACodec。
CallbackDispatcher中维护了一个list将消息回传给ACodec时并不是将list中的消息一条一条回传的而是将list中所有的消息一次性回传这也就是为什么ACodec处理OMXNodeInstance的消息时会有循环遍历。
在调用CodecObserver做消息上抛之前会调用OMXNodeInstance::handleMessage 对消息做预处理这里的预处里包括是否要将buffer做拷贝等等。
2、onOMXEmptyBufferDone
OMX使用完input buffer后消息上抛到ACodec层ACodec 会调用onOMXEmptyBufferDone再处理input buffer。
bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID, int fenceFd) {ALOGV([%s] onOMXEmptyBufferDone %u,mCodec-mComponentName.c_str(), bufferID);BufferInfo *info mCodec-findBufferByID(kPortIndexInput, bufferID);BufferInfo::Status status BufferInfo::getSafeStatus(info);// 检查 Buffer 状态if (status ! BufferInfo::OWNED_BY_COMPONENT) {ALOGE(Wrong ownership in EBD: %s(%d) buffer #%u, _asString(status), status, bufferID);mCodec-dumpBuffers(kPortIndexInput);if (fenceFd 0) {::close(fenceFd);}return false;}// input buffer 回到 ACodecinfo-mStatus BufferInfo::OWNED_BY_US;// input buffers cannot take fences, so wait for any fence now(void)mCodec-waitForFence(fenceFd, onOMXEmptyBufferDone);fenceFd -1;// still save fence for completenessinfo-setWriteFence(fenceFd, onOMXEmptyBufferDone);// Were in store-metadata-in-buffers mode, the underlying// OMX component had access to data thats implicitly refcounted// by this MediaBuffer object. Now that the OMX component has// told us that its done with the input buffer, we can decrement// the mediaBuffers reference count.info-mData-meta()-setObject(mediaBufferHolder, spMediaBufferHolder(nullptr));// 获取当前的 PortModePortMode mode getPortMode(kPortIndexInput);switch (mode) {case KEEP_BUFFERS:break;case RESUBMIT_BUFFERS:postFillThisBuffer(info);break;case FREE_BUFFERS:default:ALOGE(SHOULD NOT REACH HERE: cannot free empty output buffers);return false;}return true;
}对input buffer的处理很简单检查当前ACodec处在的状态并作出反应如果处在 ExecutingState 则调用 postFillThisBuffer 将 Buffer 提交给 MediaCodec同时清除 ACodec 存储的 mData。其他状态下则持有 input buffer 不会将其回传给 MediaCodec。
2、onOMXFillBufferDone
ACodec 处理 output buffer 的代码比较长但是也不难接下来就做分解学习
首先有个 debug log我们可以打开宏TRACK_BUFFER_TIMING来使用这部分内容把input buffer写给 OMX 时会将pts以及调用时间做记录在output buffer回传回来时检查pts打印出解码该帧消耗的时间。
#if TRACK_BUFFER_TIMINGindex mCodec-mBufferStats.indexOfKey(timeUs);if (index 0) {ACodec::BufferStats *stats mCodec-mBufferStats.editValueAt(index);stats-mFillBufferDoneTimeUs ALooper::GetNowUs();ALOGI(frame PTS %lld: %lld,timeUs,stats-mFillBufferDoneTimeUs - stats-mEmptyBufferTimeUs);mCodec-mBufferStats.removeItemsAt(index);stats NULL;}
#endif记录output BufferInfo是在第几帧被使用mDequeueCounter可以看作是当前解码的帧数。 info-mDequeuedAt mCodec-mDequeueCounter;info-mStatus BufferInfo::OWNED_BY_US;2.1 Executing
在 Executing 状态下会检查output buffer flag 和 size
output buffer size为0flag 不是 OMX_BUFFERFLAG_EOS说明没有解出有效数据重新回传给 OMX 使用output buffer size为0flag 是 OMX_BUFFERFLAG_EOSACodec 已经收到 EOS重新把 buffer 交给 OMX其他情况说明数据有效或者是flag是 OMX_BUFFERFLAG_EOS需要把output buffer回传给上层。 case RESUBMIT_BUFFERS:{// 如果output buffer长度为0flag 不是 OMX_BUFFERFLAG_EOS// 如果output buffer长度为0已将收到 EOS// 重新把 output buffer 提交给 OMXif (rangeLength 0 (!(flags OMX_BUFFERFLAG_EOS)|| mCodec-mPortEOS[kPortIndexOutput])) {ALOGV([%s] calling fillBuffer %u,mCodec-mComponentName.c_str(), info-mBufferID);err mCodec-fillBuffer(info);if (err ! OK) {mCodec-signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));return true;}break;}spMediaCodecBuffer buffer info-mData;// ......// 设定 ptsbuffer-meta()-setInt64(timeUs, timeUs);// 解除 ACodec 引用info-mData.clear();// 调用 drainThisBuffermCodec-mBufferChannel-drainThisBuffer(info-mBufferID, flags);info-mStatus BufferInfo::OWNED_BY_DOWNSTREAM;// 如果 flag 为 OMX_BUFFERFLAG_EOS将PortEOS置为trueif (flags OMX_BUFFERFLAG_EOS) {ALOGV([%s] saw output EOS, mCodec-mComponentName.c_str());mCodec-mCallback-onEos(mCodec-mInputEOSResult);mCodec-mPortEOS[kPortIndexOutput] true;}break;}2.2 OutputPortSettingsChangedState
ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(OMX_U32 portIndex) {if (portIndex kPortIndexOutput) {return FREE_BUFFERS;}CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);return RESUBMIT_BUFFERS;
}