static void omx_buffer_fixup(IL_PASS_BUFFER_EXECUTE_T* data, void**data2, int*len2,IL_BUFFER_BULK_T *fixup) { OMX_BUFFERHEADERTYPE* headptr; void* uaddr; vc_malloc_t desc; OMX_BUFFERHEADERTYPE *pBuffer; IL_RESPONSE_HEADER_T *resp; *data2 = NULL; *len2 = 0; if(NULL==data || NULL == data->bufferHeader.pBuffer) { OMX_DEBUG("error: invalid / corrupt memory\n"); return; } headptr = &data->bufferHeader; uaddr = (void*)headptr->pBuffer; uaddr -= sizeof(desc); memcpy(&desc, uaddr, sizeof(desc)); // if(desc.key != VC_MAGIC || NULL == desc.kaddr || NULL == desc.addr) { OMX_DEBUG("error: invalid / corrupt memory\n"); return; } headptr->pPlatformPrivate = headptr->pBuffer; headptr->pBuffer = desc.kaddr + sizeof(desc); #if 0 vchi_bulk_queue_transmit(vc_ilcs_vchi_handle(), headptr->pBuffer + headptr->nOffset, headptr->nFilledLen, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); #else pBuffer = headptr; if(pBuffer->nFilledLen) { if(pBuffer->nFilledLen + sizeof(IL_PASS_BUFFER_EXECUTE_T) <= VC_ILCS_MAX_INLINE) { data->method = IL_BUFFER_INLINE; *data2 = pBuffer->pBuffer + pBuffer->nOffset; *len2 = pBuffer->nFilledLen; } else { const uint8_t *start = pBuffer->pBuffer + pBuffer->nOffset; const uint8_t *end = start + pBuffer->nFilledLen; const uint8_t *round_start = (const OMX_U8*)VCHI_BULK_ROUND_UP(start); const uint8_t *round_end = (const OMX_U8*)VCHI_BULK_ROUND_DOWN(end); int bulk_len = round_end-round_start; int32_t result; data->method = IL_BUFFER_BULK; result = vchi_bulk_queue_transmit( vc_ilcsg.vchi_handle, round_start, round_end-round_start, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); // when IL_EMPTY_THIS_BUFFER executes on videocore, there is a // corresponding vchi_bulk_queue_receive, which blocks until // complete (at which point, the above vchi_bulk_queue_transmit // must by definition have completed) vc_assert(result == 0); if((fixup->headerlen = round_start - start) > 0) memcpy(fixup->header, start, fixup->headerlen); if((fixup->trailerlen = end - round_end) > 0) memcpy(fixup->trailer, round_end, fixup->trailerlen); *data2 = fixup; *len2 = sizeof(IL_BUFFER_BULK_T); } } else { data->method = IL_BUFFER_NONE; } #endif }
// send a buffer to VideoCore either by writing the buffer data in a control // message or by sending an aligned bulk transfer with fixup information in the // control message. OMX_ERRORTYPE vc_ilcs_pass_buffer(IL_FUNCTION_T func, void *reference, OMX_BUFFERHEADERTYPE *pBuffer) { IL_PASS_BUFFER_EXECUTE_T exe; IL_BUFFER_BULK_T fixup; IL_RESPONSE_HEADER_T resp; void *data2 = NULL; int len2 = 0; if ((func == IL_EMPTY_THIS_BUFFER && pBuffer->pInputPortPrivate == NULL) || (func == IL_FILL_THIS_BUFFER && pBuffer->pOutputPortPrivate == NULL)) { // return this to pass conformance // the actual error is using a buffer that hasn't be registered with usebuffer/allocatebuffer return OMX_ErrorIncorrectStateOperation; } exe.reference = reference; memcpy(&exe.bufferHeader, pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); if(pBuffer->nFilledLen) { if(pBuffer->nFilledLen + sizeof(IL_PASS_BUFFER_EXECUTE_T) <= VC_ILCS_MAX_INLINE) { exe.method = IL_BUFFER_INLINE; data2 = pBuffer->pBuffer + pBuffer->nOffset; len2 = pBuffer->nFilledLen; } else { const uint8_t *start = pBuffer->pBuffer + pBuffer->nOffset; const uint8_t *end = start + pBuffer->nFilledLen; const uint8_t *round_start = (const OMX_U8*)VCHI_BULK_ROUND_UP(start); const uint8_t *round_end = (const OMX_U8*)VCHI_BULK_ROUND_DOWN(end); int bulk_len = round_end-round_start; int32_t result; exe.method = IL_BUFFER_BULK; result = vchi_bulk_queue_transmit( vc_ilcsg.vchi_handle, round_start, round_end-round_start, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); // when IL_EMPTY_THIS_BUFFER executes on videocore, there is a // corresponding vchi_bulk_queue_receive, which blocks until // complete (at which point, the above vchi_bulk_queue_transmit // must by definition have completed) vc_assert(result == 0); if((fixup.headerlen = round_start - start) > 0) memcpy(fixup.header, start, fixup.headerlen); if((fixup.trailerlen = end - round_end) > 0) memcpy(fixup.trailer, round_end, fixup.trailerlen); data2 = &fixup; len2 = sizeof(IL_BUFFER_BULK_T); } } else { exe.method = IL_BUFFER_NONE; } vc_ilcs_execute_function(func, &exe, sizeof(IL_PASS_BUFFER_EXECUTE_T), data2, len2, &resp, sizeof(resp)); return resp.err; }
OMX_ERRORTYPE vc_ilcs_pass_buffer(IL_FUNCTION_T func, void *reference, OMX_BUFFERHEADERTYPE *pBuffer) { IL_PASS_BUFFER_EXECUTE_T exe; IL_BUFFER_BULK_T fixup; IL_RESPONSE_HEADER_T resp; void *data2 = NULL; int len2 = 0; void *bulk = NULL; int bulk_len = 0; if ((func == IL_EMPTY_THIS_BUFFER && pBuffer->pInputPortPrivate == NULL) || (func == IL_FILL_THIS_BUFFER && pBuffer->pOutputPortPrivate == NULL)) { // return this to pass conformance // the actual error is using a buffer that hasn't be registered with usebuffer/allocatebuffer return OMX_ErrorIncorrectStateOperation; } exe.reference = reference; memcpy(&exe.bufferHeader, pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); exe.bufferLen = pBuffer->nFilledLen; if(pBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { OMX_U8 *ptr = pBuffer->pBuffer + pBuffer->nOffset + pBuffer->nFilledLen + 3; OMX_OTHER_EXTRADATATYPE *extra = (OMX_OTHER_EXTRADATATYPE *) (((uint32_t) ptr) & ~3); while(extra->eType != OMX_ExtraDataNone) extra = (OMX_OTHER_EXTRADATATYPE *) (((uint8_t *) extra) + extra->nSize); exe.bufferLen = (((uint8_t *) extra) + extra->nSize) - (pBuffer->pBuffer + pBuffer->nOffset); } if(exe.bufferLen) { if(exe.bufferLen + sizeof(IL_PASS_BUFFER_EXECUTE_T) <= VC_ILCS_MAX_INLINE) { exe.method = IL_BUFFER_INLINE; data2 = pBuffer->pBuffer + pBuffer->nOffset; len2 = exe.bufferLen; } else { const uint8_t *start = pBuffer->pBuffer + pBuffer->nOffset; const uint8_t *end = start + exe.bufferLen; const uint8_t *round_start = (const OMX_U8*)VCHI_BULK_ROUND_UP(start); const uint8_t *round_end = (const OMX_U8*)VCHI_BULK_ROUND_DOWN(end); exe.method = IL_BUFFER_BULK; bulk = (void *) round_start; bulk_len = round_end - round_start; if((fixup.headerlen = round_start - start) > 0) memcpy(fixup.header, start, fixup.headerlen); if((fixup.trailerlen = end - round_end) > 0) memcpy(fixup.trailer, round_end, fixup.trailerlen); data2 = &fixup; len2 = sizeof(IL_BUFFER_BULK_T); } } else { exe.method = IL_BUFFER_NONE; } if(vc_ilcs_execute_function(func, &exe, sizeof(IL_PASS_BUFFER_EXECUTE_T), data2, len2, bulk, bulk_len, &resp) < 0) return OMX_ErrorHardware; return resp.err; }