博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android MediaCodec OMX_FillThisBuffer流程分析
阅读量:3730 次
发布时间:2019-05-22

本文共 7005 字,大约阅读时间需要 23 分钟。

OMX_FillThisBuffer

#define OMX_FillThisBuffer (hComponent,pBuffer)((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer(hComponent,pBuffer)

作用:向组件的输出端口发送空白buffer

allocateOutputBuffersFromNativeWindow

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]进行填充

fillBuffer

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);}

xxx_OMX_FillThisBuffer

pOMXComponent->FillThisBuffer  = &xxx_OMX_FillThisBuffer;

在对应的插件中实现此函数

转载地址:http://obzin.baihongyu.com/

你可能感兴趣的文章
Allegro PCB更改摆放好的元器件
查看>>
Allegro PCB设置差分对
查看>>
Cadence PCB敷铜注意事项
查看>>
Allegro丝印修改
查看>>
Allegro PCB输出光绘文件
查看>>
leetcode(一)--- 树
查看>>
MyBatis的多表操作
查看>>
MyBatis注解开发
查看>>
点击复制内容到手机粘贴板(简洁易懂-只需五步)
查看>>
在vue项目中使用字体图标(精简易懂)(配图)
查看>>
flex布局详解(配图-简洁易懂)
查看>>
生成随机密码(长度自定义)
查看>>
前端生成并导出表格+样式修改(只需一个插件,无需修改源码)
查看>>
rem项目踩到的坑
查看>>
前端解析zip压缩包 --- vue、react等等通用
查看>>
大文件断点续传/切片上传(react、vue通用)
查看>>
打包&配置&优化--备忘录
查看>>
vue项目CDN引入
查看>>
Nonde+MongoDB基础创建及增删改查
查看>>
前端模块化详解(包含各种导入导出及输出结果)
查看>>