本文共 7005 字,大约阅读时间需要 23 分钟。
#define OMX_FillThisBuffer (hComponent,pBuffer)((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer(hComponent,pBuffer)
作用:向组件的输出端口发送空白buffer
status_t ACodec::allocateOutputBuffersFromNativeWindow() { // This method only handles the non-metadata mode (or simulating legacy // mode with metadata, which is transparent to ACodec). CHECK(!storingMetadataInDecodedBuffers()); OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers; status_t err = configureOutputBuffersFromNativeWindow( &bufferCount, &bufferSize, &minUndequeuedBuffers, true /* preregister */); if (err != 0) return err; mNumUndequeuedBuffers = minUndequeuedBuffers; static_cast(mNativeWindow.get()) ->getIGraphicBufferProducer()->allowAllocation(true); ALOGV("[%s] Allocating %u buffers from a native window of size %u on " "output port", mComponentName.c_str(), bufferCount, bufferSize); // Dequeue buffers and send them to OMX for (OMX_U32 i = 0; i < bufferCount; i++) { ANativeWindowBuffer *buf; int fenceFd; err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf, &fenceFd); if (err != 0) { ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err); break; } sp graphicBuffer(GraphicBuffer::from(buf)); BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_US; info.mFenceFd = fenceFd; info.mIsReadFence = false; info.mRenderInfo = NULL; info.mGraphicBuffer = graphicBuffer; info.mNewGraphicBuffer = false; info.mDequeuedAt = mDequeueCounter; // TODO: We shouln't need to create MediaCodecBuffer. In metadata mode // OMX doesn't use the shared memory buffer, but some code still // access info.mData. Create an ABuffer as a placeholder. info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize)); info.mCodecData = info.mData; mBuffers[kPortIndexOutput].push(info); IOMX::buffer_id bufferId; err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId); if (err != 0) { ALOGE("registering GraphicBuffer %u with OMX IL component failed: " "%d", i, err); break; } mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId; ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)", mComponentName.c_str(), bufferId, graphicBuffer.get()); } OMX_U32 cancelStart; OMX_U32 cancelEnd; if (err != OK) { // If an error occurred while dequeuing we need to cancel any buffers // that were dequeued. Also cancel all if we're in legacy metadata mode. cancelStart = 0; cancelEnd = mBuffers[kPortIndexOutput].size(); } else { // Return the required minimum undequeued buffers to the native window. cancelStart = bufferCount - minUndequeuedBuffers; cancelEnd = bufferCount; } for (OMX_U32 i = cancelStart; i < cancelEnd; i++) { BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); if (info->mStatus == BufferInfo::OWNED_BY_US) { status_t error = cancelBufferToNativeWindow(info); if (err == 0) { err = error; } } } static_cast (mNativeWindow.get()) ->getIGraphicBufferProducer()->allowAllocation(false); return err;}
从显示那边拿到buffer后对mBuffers[kPortIndexOutput]进行填充
status_t ACodec::fillBuffer(BufferInfo *info) { status_t err; // Even in dynamic ANW buffer mode, if the graphic buffer is not changing, // send sPreset instead of the same graphic buffer, so that OMX server // side doesn't update the meta. In theory it should make no difference, // however when the same buffer is parcelled again, a new handle could be // created on server side, and some decoder doesn't recognize the handle // even if it's the same buffer. if (!storingMetadataInDecodedBuffers() || !info->mNewGraphicBuffer) { err = mOMXNode->fillBuffer( info->mBufferID, OMXBuffer::sPreset, info->mFenceFd); } else { err = mOMXNode->fillBuffer( info->mBufferID, info->mGraphicBuffer, info->mFenceFd); } info->mNewGraphicBuffer = false; info->mFenceFd = -1; if (err == OK) { info->mStatus = BufferInfo::OWNED_BY_COMPONENT; } return err;}
status_t OMXNodeInstance::fillBuffer( IOMX::buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) { Mutex::Autolock autoLock(mLock); if (mHandle == NULL) { return DEAD_OBJECT; } OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer, kPortIndexOutput); if (header == NULL) { ALOGE("b/25884056"); return BAD_VALUE; } if (omxBuffer.mBufferType == OMXBuffer::kBufferTypeANWBuffer) { status_t err = updateGraphicBufferInMeta_l( kPortIndexOutput, omxBuffer.mGraphicBuffer, buffer, header); if (err != OK) { CLOG_ERROR(fillBuffer, err, FULL_BUFFER( (intptr_t)header->pBuffer, header, fenceFd)); return err; } } else if (omxBuffer.mBufferType != OMXBuffer::kBufferTypePreset) { return BAD_VALUE; } header->nFilledLen = 0; header->nOffset = 0; header->nFlags = 0; // meta now owns fenceFd status_t res = storeFenceInMeta_l(header, fenceFd, kPortIndexOutput); if (res != OK) { CLOG_ERROR(fillBuffer::storeFenceInMeta, res, EMPTY_BUFFER(buffer, header, fenceFd)); return res; } { Mutex::Autolock _l(mDebugLock); mOutputBuffersWithCodec.add(header); CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header, fenceFd))); } OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header); if (err != OMX_ErrorNone) { CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header, fenceFd)); Mutex::Autolock _l(mDebugLock); mOutputBuffersWithCodec.remove(header); } return StatusFromOMXError(err);}
pOMXComponent->FillThisBuffer = &xxx_OMX_FillThisBuffer;
在对应的插件中实现此函数
转载地址:http://obzin.baihongyu.com/