// receive a buffer from VideoCore either from the message bytes // or by a bulk transfer receieve OMX_BUFFERHEADERTYPE *vc_ilcs_receive_buffer(void *call, int clen, OMX_COMPONENTTYPE **pComp) { IL_PASS_BUFFER_EXECUTE_T *exe = call; OMX_BUFFERHEADERTYPE *pHeader = exe->bufferHeader.pInputPortPrivate; OMX_U8 *pBuffer = pHeader->pBuffer; OMX_PTR *pAppPrivate = pHeader->pAppPrivate; OMX_PTR *pPlatformPrivate = pHeader->pPlatformPrivate; OMX_PTR *pInputPortPrivate = pHeader->pInputPortPrivate; OMX_PTR *pOutputPortPrivate = pHeader->pOutputPortPrivate; vc_assert(pHeader); memcpy(pHeader, &exe->bufferHeader, sizeof(OMX_BUFFERHEADERTYPE)); *pComp = exe->reference; pHeader->pBuffer = pBuffer; pHeader->pAppPrivate = pAppPrivate; pHeader->pPlatformPrivate = pPlatformPrivate; pHeader->pInputPortPrivate = pInputPortPrivate; pHeader->pOutputPortPrivate = pOutputPortPrivate; if(exe->method == IL_BUFFER_BULK) { vc_assert(VCHI_BULK_ALIGNED(pHeader->pBuffer)); IL_BUFFER_BULK_T *fixup = (IL_BUFFER_BULK_T *) (exe+1); // bulk transfer from videocore to host uint8_t *start = pHeader->pBuffer + pHeader->nOffset; uint8_t *end = start + pHeader->nFilledLen; int32_t bulk_len = pHeader->nFilledLen - fixup->headerlen - fixup->trailerlen; int32_t result; vc_assert(clen == sizeof(IL_PASS_BUFFER_EXECUTE_T) + sizeof(IL_BUFFER_BULK_T)); result = vchi_bulk_queue_receive( vc_ilcsg.vchi_handle, start + fixup->headerlen, bulk_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED | VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL ); vc_assert(result == 0); if (fixup->headerlen) memcpy(start, fixup->header, fixup->headerlen); if (fixup->trailerlen) memcpy(end-fixup->trailerlen, fixup->trailer, fixup->trailerlen); } else if(exe->method == IL_BUFFER_INLINE) { IL_BUFFER_INLINE_T *buffer = (IL_BUFFER_INLINE_T *) (exe+1); vc_assert(clen == sizeof(IL_PASS_BUFFER_EXECUTE_T) + pHeader->nFilledLen); memcpy(pBuffer+pHeader->nOffset, buffer->buffer, pHeader->nFilledLen); } else if(exe->method == IL_BUFFER_NONE) { vc_assert(clen == sizeof(IL_PASS_BUFFER_EXECUTE_T)); } else if(exe->method == IL_BUFFER_MAX) { vc_assert(0); } return pHeader; }
static OMX_ERRORTYPE vcil_out_addBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes, OMX_IN OMX_U8* pBuffer, OMX_IN void *eglImage, IL_FUNCTION_T func) { OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent; VC_PRIVATE_COMPONENT_T *comp; IL_ADD_BUFFER_EXECUTE_T exe; IL_ADD_BUFFER_RESPONSE_T resp; OMX_BUFFERHEADERTYPE *pHeader; VC_PRIVATE_PORT_T *port; ILCS_COMMON_T *st; int rlen = sizeof(resp); if (!(pComp && ppBufferHdr)) return OMX_ErrorBadParameter; st = pComp->pApplicationPrivate; comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate; port = find_port(comp, nPortIndex); if (!port) // bad port index return OMX_ErrorBadPortIndex; if (port->numBuffers > 0 && port->func != func) { // inconsistent use of usebuffer/allocatebuffer/eglimage // all ports must receive all buffers by exactly one of these methods vc_assert(port->func != func); return OMX_ErrorInsufficientResources; } port->func = func; if (!VCHI_BULK_ALIGNED(pBuffer)) { // cannot transfer this buffer across the host interface return OMX_ErrorBadParameter; } pHeader = vcos_malloc(sizeof(*pHeader), "vcout buffer header"); if (!pHeader) return OMX_ErrorInsufficientResources; if (func == IL_ALLOCATE_BUFFER) { pBuffer = vcos_malloc_aligned(nSizeBytes, ILCS_ALIGN, "vcout mapping buffer"); if (!pBuffer) { vcos_free(pHeader); return OMX_ErrorInsufficientResources; } } exe.reference = comp->reference; exe.bufferReference = pHeader; exe.port = nPortIndex; exe.size = nSizeBytes; exe.eglImage = eglImage; if(ilcs_execute_function(st->ilcs, func, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp)) resp.err = OMX_ErrorHardware; if (resp.err == OMX_ErrorNone) { memcpy(pHeader, &resp.bufferHeader, sizeof(OMX_BUFFERHEADERTYPE)); if (port->dir == OMX_DirOutput) pHeader->pOutputPortPrivate = resp.reference; else pHeader->pInputPortPrivate = resp.reference; if (func == IL_USE_EGL_IMAGE) { pHeader->pBuffer = (OMX_U8*)eglImage; port->bEGL = OMX_TRUE; } else { pHeader->pBuffer = pBuffer; port->bEGL = OMX_FALSE; } pHeader->pAppPrivate = pAppPrivate; *ppBufferHdr = pHeader; port->numBuffers++; } else { if (func == IL_ALLOCATE_BUFFER) vcos_free(pBuffer); vcos_free(pHeader); } return resp.err; }