2 Copyright (c) 2012, Broadcom Europe Ltd
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "interface/vchi/vchi.h"
35 #include "interface/vcos/vcos_dlfcn.h"
36 #include "interface/vmcs_host/khronos/IL/OMX_Component.h"
37 #include "interface/vmcs_host/khronos/IL/OMX_ILCS.h"
38 #include "interface/vmcs_host/vc_ilcs_defs.h"
39 #include "interface/vmcs_host/vcilcs.h"
40 #include "interface/vmcs_host/vcilcs_common.h"
41 #include "interface/vcos/vcos_dlfcn.h"
43 static VC_PRIVATE_PORT_T *find_port(VC_PRIVATE_COMPONENT_T *comp, OMX_U32 nPortIndex)
46 while (i<comp->numPorts && comp->port[i].port != nPortIndex)
49 if (i < comp->numPorts)
50 return &comp->port[i];
56 static int is_valid_hostside_buffer(OMX_BUFFERHEADERTYPE *pBuf)
62 if ((unsigned long)pBuf->pBuffer < 0x100)
63 return 0; // not believable
68 static OMX_ERRORTYPE vcil_out_ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent)
70 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
71 VC_PRIVATE_COMPONENT_T *comp;
72 IL_EXECUTE_HEADER_T exe;
73 IL_RESPONSE_HEADER_T resp;
75 int rlen = sizeof(resp);
78 return OMX_ErrorBadParameter;
80 st = pComp->pApplicationPrivate;
81 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
83 exe.reference = comp->reference;
85 if(ilcs_execute_function(st->ilcs, IL_COMPONENT_DEINIT, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp) ||
86 resp.err == OMX_ErrorNone)
88 // remove from list, assuming that we successfully managed to deinit
89 // this component, or that ilcs has returned an error. The assumption
90 // here is that if the component has managed to correctly signal an
91 // error, it still exists, but if the transport has failed then we might
92 // as well try and cleanup
93 VC_PRIVATE_COMPONENT_T *list, *prev;
95 vcos_semaphore_wait(&st->component_lock);
97 list = st->component_list;
100 while (list != NULL && list != comp)
106 // failing to find this component is not a good sign.
107 if(vcos_verify(list))
110 st->component_list = list->next;
112 prev->next = list->next;
115 vcos_semaphore_post(&st->component_lock);
122 static OMX_ERRORTYPE vcil_out_GetComponentVersion(OMX_IN OMX_HANDLETYPE hComponent,
123 OMX_OUT OMX_STRING pComponentName,
124 OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
125 OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
126 OMX_OUT OMX_UUIDTYPE* pComponentUUID)
128 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
129 VC_PRIVATE_COMPONENT_T *comp;
130 IL_EXECUTE_HEADER_T exe;
131 IL_GET_VERSION_RESPONSE_T resp;
133 int rlen = sizeof(resp);
135 if (!(pComp && pComponentName && pComponentVersion && pSpecVersion && pComponentUUID))
136 return OMX_ErrorBadParameter;
138 st = pComp->pApplicationPrivate;
139 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
141 exe.reference = comp->reference;
143 if(ilcs_execute_function(st->ilcs, IL_GET_COMPONENT_VERSION, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
144 return OMX_ErrorHardware;
146 strncpy(pComponentName, resp.name, 128);
147 pComponentName[127] = 0;
148 *pComponentVersion = resp.component_version;
149 *pSpecVersion = resp.spec_version;
150 memcpy(pComponentUUID, resp.uuid, sizeof(OMX_UUIDTYPE));
155 static OMX_ERRORTYPE vcil_out_SetCallbacks(OMX_IN OMX_HANDLETYPE hComponent,
156 OMX_IN OMX_CALLBACKTYPE* pCallbacks,
157 OMX_IN OMX_PTR pAppData)
159 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
160 VC_PRIVATE_COMPONENT_T *comp;
161 IL_SET_CALLBACKS_EXECUTE_T exe;
162 IL_RESPONSE_HEADER_T resp;
164 int rlen = sizeof(resp);
166 if(!(pComp && pCallbacks))
167 return OMX_ErrorBadParameter;
169 st = pComp->pApplicationPrivate;
170 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
172 comp->callbacks = *pCallbacks;
173 comp->callback_state = pAppData;
175 exe.reference = comp->reference;
176 exe.pAppData = pComp;
178 if(ilcs_execute_function(st->ilcs, IL_SET_CALLBACKS, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
179 return OMX_ErrorHardware;
184 static OMX_ERRORTYPE vcil_out_GetState(OMX_IN OMX_HANDLETYPE hComponent,
185 OMX_OUT OMX_STATETYPE* pState)
187 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
188 VC_PRIVATE_COMPONENT_T *comp;
189 IL_EXECUTE_HEADER_T exe;
190 IL_GET_STATE_RESPONSE_T resp;
192 int rlen = sizeof(resp);
194 if (!(pComp && pState))
195 return OMX_ErrorBadParameter;
197 st = pComp->pApplicationPrivate;
198 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
200 exe.reference = comp->reference;
202 if(ilcs_execute_function(st->ilcs, IL_GET_STATE, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
203 return OMX_ErrorHardware;
205 *pState = resp.state;
210 static OMX_ERRORTYPE vcil_out_get(OMX_IN OMX_HANDLETYPE hComponent,
211 OMX_IN OMX_INDEXTYPE nParamIndex,
212 OMX_INOUT OMX_PTR pComponentParameterStructure,
215 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
216 VC_PRIVATE_COMPONENT_T *comp;
217 IL_GET_EXECUTE_T exe;
218 IL_GET_RESPONSE_T resp;
221 int rlen = sizeof(resp);
223 if (!(pComp && pComponentParameterStructure))
224 return OMX_ErrorBadParameter;
226 st = pComp->pApplicationPrivate;
227 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
229 exe.reference = comp->reference;
230 exe.index = nParamIndex;
232 size = *((OMX_U32 *) pComponentParameterStructure);
234 if(size > VC_ILCS_MAX_PARAM_SIZE)
235 return OMX_ErrorHardware;
237 memcpy(exe.param, pComponentParameterStructure, size);
239 if(ilcs_execute_function(st->ilcs, func, &exe, size + IL_GET_EXECUTE_HEADER_SIZE, &resp, &rlen) < 0 || rlen > sizeof(resp))
240 return OMX_ErrorHardware;
242 memcpy(pComponentParameterStructure, resp.param, size);
247 static OMX_ERRORTYPE vcil_out_set(OMX_IN OMX_HANDLETYPE hComponent,
248 OMX_IN OMX_INDEXTYPE nParamIndex,
249 OMX_IN OMX_PTR pComponentParameterStructure,
252 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
253 VC_PRIVATE_COMPONENT_T *comp;
254 IL_SET_EXECUTE_T exe;
255 IL_RESPONSE_HEADER_T resp;
258 int rlen = sizeof(resp);
260 if (!(pComp && pComponentParameterStructure))
261 return OMX_ErrorBadParameter;
263 st = pComp->pApplicationPrivate;
264 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
266 exe.reference = comp->reference;
267 exe.index = nParamIndex;
269 size = *((OMX_U32 *) pComponentParameterStructure);
271 if(size > VC_ILCS_MAX_PARAM_SIZE)
272 return OMX_ErrorHardware;
274 memcpy(exe.param, pComponentParameterStructure, size);
276 if(ilcs_execute_function(st->ilcs, func, &exe, size + IL_SET_EXECUTE_HEADER_SIZE, &resp, &rlen) < 0 || rlen != sizeof(resp))
277 return OMX_ErrorHardware;
282 static OMX_ERRORTYPE vcil_out_GetParameter(OMX_IN OMX_HANDLETYPE hComponent,
283 OMX_IN OMX_INDEXTYPE nParamIndex,
284 OMX_INOUT OMX_PTR pComponentParameterStructure)
286 return vcil_out_get(hComponent, nParamIndex, pComponentParameterStructure, IL_GET_PARAMETER);
289 static OMX_ERRORTYPE vcil_out_SetParameter(OMX_IN OMX_HANDLETYPE hComponent,
290 OMX_IN OMX_INDEXTYPE nParamIndex,
291 OMX_IN OMX_PTR pComponentParameterStructure)
293 return vcil_out_set(hComponent, nParamIndex, pComponentParameterStructure, IL_SET_PARAMETER);
296 static OMX_ERRORTYPE vcil_out_GetConfig(OMX_IN OMX_HANDLETYPE hComponent,
297 OMX_IN OMX_INDEXTYPE nParamIndex,
298 OMX_INOUT OMX_PTR pComponentParameterStructure)
300 return vcil_out_get(hComponent, nParamIndex, pComponentParameterStructure, IL_GET_CONFIG);
303 static OMX_ERRORTYPE vcil_out_SetConfig(OMX_IN OMX_HANDLETYPE hComponent,
304 OMX_IN OMX_INDEXTYPE nParamIndex,
305 OMX_IN OMX_PTR pComponentParameterStructure)
307 return vcil_out_set(hComponent, nParamIndex, pComponentParameterStructure, IL_SET_CONFIG);
310 static OMX_ERRORTYPE vcil_out_SendCommand(OMX_IN OMX_HANDLETYPE hComponent,
311 OMX_IN OMX_COMMANDTYPE Cmd,
312 OMX_IN OMX_U32 nParam1,
313 OMX_IN OMX_PTR pCmdData)
315 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
316 VC_PRIVATE_COMPONENT_T *comp;
317 IL_SEND_COMMAND_EXECUTE_T exe;
318 IL_RESPONSE_HEADER_T resp;
320 int rlen = sizeof(resp);
323 return OMX_ErrorBadParameter;
325 st = pComp->pApplicationPrivate;
326 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
328 exe.reference = comp->reference;
332 if (Cmd == OMX_CommandMarkBuffer)
334 exe.mark = *((OMX_MARKTYPE *) pCmdData);
338 exe.mark.hMarkTargetComponent = 0;
339 exe.mark.pMarkData = 0;
342 if(ilcs_execute_function(st->ilcs, IL_SEND_COMMAND, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
343 return OMX_ErrorHardware;
348 // Called to pass a buffer from the host-side across the interface to videcore.
350 static OMX_ERRORTYPE vcil_out_addBuffer(OMX_IN OMX_HANDLETYPE hComponent,
351 OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
352 OMX_IN OMX_U32 nPortIndex,
353 OMX_IN OMX_PTR pAppPrivate,
354 OMX_IN OMX_U32 nSizeBytes,
355 OMX_IN OMX_U8* pBuffer,
356 OMX_IN void *eglImage,
359 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
360 VC_PRIVATE_COMPONENT_T *comp;
361 IL_ADD_BUFFER_EXECUTE_T exe;
362 IL_ADD_BUFFER_RESPONSE_T resp;
363 OMX_BUFFERHEADERTYPE *pHeader;
364 VC_PRIVATE_PORT_T *port;
366 int rlen = sizeof(resp);
368 if (!(pComp && ppBufferHdr))
369 return OMX_ErrorBadParameter;
371 st = pComp->pApplicationPrivate;
372 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
374 port = find_port(comp, nPortIndex);
375 if (!port) // bad port index
376 return OMX_ErrorBadPortIndex;
378 if (port->numBuffers > 0 && port->func != func)
380 // inconsistent use of usebuffer/allocatebuffer/eglimage
381 // all ports must receive all buffers by exactly one of these methods
382 vc_assert(port->func != func);
383 return OMX_ErrorInsufficientResources;
387 if (!VCHI_BULK_ALIGNED(pBuffer))
389 // cannot transfer this buffer across the host interface
390 return OMX_ErrorBadParameter;
393 pHeader = vcos_malloc(sizeof(*pHeader), "vcout buffer header");
396 return OMX_ErrorInsufficientResources;
398 if (func == IL_ALLOCATE_BUFFER)
400 pBuffer = vcos_malloc_aligned(nSizeBytes, ILCS_ALIGN, "vcout mapping buffer");
404 return OMX_ErrorInsufficientResources;
408 exe.reference = comp->reference;
409 exe.bufferReference = pHeader;
410 exe.port = nPortIndex;
411 exe.size = nSizeBytes;
412 exe.eglImage = eglImage;
414 if(ilcs_execute_function(st->ilcs, func, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
415 resp.err = OMX_ErrorHardware;
417 if (resp.err == OMX_ErrorNone)
419 memcpy(pHeader, &resp.bufferHeader, sizeof(OMX_BUFFERHEADERTYPE));
420 if (port->dir == OMX_DirOutput)
421 pHeader->pOutputPortPrivate = resp.reference;
423 pHeader->pInputPortPrivate = resp.reference;
425 if (func == IL_USE_EGL_IMAGE)
427 pHeader->pBuffer = (OMX_U8*)eglImage;
428 port->bEGL = OMX_TRUE;
432 pHeader->pBuffer = pBuffer;
433 port->bEGL = OMX_FALSE;
436 pHeader->pAppPrivate = pAppPrivate;
437 *ppBufferHdr = pHeader;
442 if (func == IL_ALLOCATE_BUFFER)
450 static VCOS_ONCE_T loaded_eglIntOpenMAXILDoneMarker = VCOS_ONCE_INIT;
451 static int (*local_eglIntOpenMAXILDoneMarker) (void* component_handle, void *egl_image) = NULL;
453 static void load_eglIntOpenMAXILDoneMarker(void)
457 /* First try to load from the current process, this will succeed
458 * if something that is linked to libEGL is already loaded or
459 * something explicitly loaded libEGL with RTLD_GLOBAL
461 handle = vcos_dlopen(NULL, VCOS_DL_GLOBAL);
462 local_eglIntOpenMAXILDoneMarker = (void * )vcos_dlsym(handle, "eglIntOpenMAXILDoneMarker");
463 if (local_eglIntOpenMAXILDoneMarker == NULL)
465 vcos_dlclose(handle);
466 /* If that failed try to load libEGL.so explicitely */
467 handle = vcos_dlopen("libEGL.so", VCOS_DL_LAZY | VCOS_DL_LOCAL);
468 vc_assert(handle != NULL);
469 local_eglIntOpenMAXILDoneMarker = (void * )vcos_dlsym(handle, "eglIntOpenMAXILDoneMarker");
470 vc_assert(local_eglIntOpenMAXILDoneMarker != NULL);
474 static OMX_ERRORTYPE vcil_out_UseEGLImage(OMX_IN OMX_HANDLETYPE hComponent,
475 OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
476 OMX_IN OMX_U32 nPortIndex,
477 OMX_IN OMX_PTR pAppPrivate,
478 OMX_IN void* eglImage)
480 /* Load eglIntOpenMAXILDoneMarker() and libEGL here, it will be needed later */
481 vcos_once(&loaded_eglIntOpenMAXILDoneMarker, load_eglIntOpenMAXILDoneMarker);
483 return vcil_out_addBuffer(hComponent, ppBufferHdr, nPortIndex, pAppPrivate, 0, NULL, eglImage, IL_USE_EGL_IMAGE);
486 static OMX_ERRORTYPE vcil_out_UseBuffer(OMX_IN OMX_HANDLETYPE hComponent,
487 OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
488 OMX_IN OMX_U32 nPortIndex,
489 OMX_IN OMX_PTR pAppPrivate,
490 OMX_IN OMX_U32 nSizeBytes,
491 OMX_IN OMX_U8* pBuffer)
493 return vcil_out_addBuffer(hComponent, ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes, pBuffer, NULL, IL_USE_BUFFER);
496 static OMX_ERRORTYPE vcil_out_AllocateBuffer(OMX_IN OMX_HANDLETYPE hComponent,
497 OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
498 OMX_IN OMX_U32 nPortIndex,
499 OMX_IN OMX_PTR pAppPrivate,
500 OMX_IN OMX_U32 nSizeBytes)
502 return vcil_out_addBuffer(hComponent, ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes, NULL, NULL, IL_ALLOCATE_BUFFER);
505 static OMX_ERRORTYPE vcil_out_FreeBuffer(OMX_IN OMX_HANDLETYPE hComponent,
506 OMX_IN OMX_U32 nPortIndex,
507 OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr)
509 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
510 VC_PRIVATE_COMPONENT_T *comp;
511 IL_FREE_BUFFER_EXECUTE_T exe;
512 IL_RESPONSE_HEADER_T resp;
513 VC_PRIVATE_PORT_T *port;
515 int rlen = sizeof(resp);
517 if (!(pComp && pBufferHdr))
518 return OMX_ErrorBadParameter;
520 st = pComp->pApplicationPrivate;
521 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
523 port = find_port(comp, nPortIndex);
525 return OMX_ErrorBadPortIndex;
527 if (port->numBuffers == 0)
528 return OMX_ErrorIncorrectStateTransition;
530 exe.reference = comp->reference;
531 exe.port = nPortIndex;
532 if (port->dir == OMX_DirOutput)
533 exe.bufferReference = pBufferHdr->pOutputPortPrivate;
535 exe.bufferReference = pBufferHdr->pInputPortPrivate;
536 exe.func = port->func;
537 exe.inputPrivate = NULL;
538 exe.outputPrivate = NULL;
540 if(ilcs_execute_function(st->ilcs, IL_FREE_BUFFER, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
541 return OMX_ErrorHardware;
543 if (resp.err == OMX_ErrorNone)
545 if (port->func == IL_ALLOCATE_BUFFER)
546 vcos_free(pBufferHdr->pBuffer);
547 vcos_free(pBufferHdr);
554 // Called on host-side to pass a buffer to VideoCore to be emptied
555 static OMX_ERRORTYPE vcil_out_EmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent,
556 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
558 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
559 VC_PRIVATE_COMPONENT_T *comp;
562 if (!(pComp && pBuffer))
563 return (OMX_ErrorBadParameter);
565 st = pComp->pApplicationPrivate;
566 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
568 return ilcs_pass_buffer(st->ilcs, IL_EMPTY_THIS_BUFFER, comp->reference, pBuffer);
571 // Called from ril_top as OMX_FillThisBuffer().
572 // ->pBuffer field is expected to be a memory handle.
574 static OMX_ERRORTYPE vcil_out_FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent,
575 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
578 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
579 VC_PRIVATE_COMPONENT_T *comp;
580 VC_PRIVATE_PORT_T *port;
583 if (!(pComp && pBuffer))
584 return (OMX_ErrorBadParameter);
586 st = pComp->pApplicationPrivate;
587 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
589 port = find_port(comp, pBuffer->nOutputPortIndex);
591 return OMX_ErrorBadPortIndex;
593 if(pBuffer->pBuffer == 0)
594 return OMX_ErrorIncorrectStateOperation;
596 vcos_assert(pComp != NULL && comp != NULL && port != NULL && st != NULL);
598 // The lower layers will attempt to transfer the bytes specified if we don't
599 // clear these - callers should ideally do this themselves, but it is not
600 // mandated in the specification.
601 pBuffer->nFilledLen = 0;
604 vc_assert(port->bEGL == OMX_TRUE || is_valid_hostside_buffer(pBuffer));
606 err = ilcs_pass_buffer(st->ilcs, IL_FILL_THIS_BUFFER, comp->reference, pBuffer);
608 if (err == OMX_ErrorNone && port->bEGL == OMX_TRUE)
610 // If an output port is marked as an EGL port, we request EGL to notify the IL component
611 // when it's allowed to render into the buffer/EGLImage.
612 vc_assert(local_eglIntOpenMAXILDoneMarker != NULL);
613 local_eglIntOpenMAXILDoneMarker(comp->reference, pBuffer->pBuffer);
619 static OMX_ERRORTYPE vcil_out_ComponentTunnelRequest(OMX_IN OMX_HANDLETYPE hComponent,
620 OMX_IN OMX_U32 nPort,
621 OMX_IN OMX_HANDLETYPE hTunneledComp,
622 OMX_IN OMX_U32 nTunneledPort,
623 OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup)
625 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
626 VC_PRIVATE_COMPONENT_T *comp;
627 IL_TUNNEL_REQUEST_EXECUTE_T exe;
628 IL_TUNNEL_REQUEST_RESPONSE_T resp;
629 VC_PRIVATE_COMPONENT_T *list;
631 int rlen = sizeof(resp);
634 return OMX_ErrorBadParameter;
636 st = pComp->pApplicationPrivate;
637 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
639 exe.reference = comp->reference;
641 exe.tunnel_port = nTunneledPort;
643 exe.setup = *pTunnelSetup;
645 // the other component may be on the host or on VC. Look through our list
646 // so we can tell, and tell ILCS on VC the details.
647 vcos_semaphore_wait(&st->component_lock);
649 list = st->component_list;
650 while (list != NULL && list->comp != (void *) hTunneledComp)
653 vcos_semaphore_post(&st->component_lock);
657 exe.tunnel_ref = hTunneledComp;
658 exe.tunnel_host = OMX_TRUE;
662 exe.tunnel_ref = list->reference;
663 exe.tunnel_host = OMX_FALSE;
666 if(ilcs_execute_function(st->ilcs, IL_COMPONENT_TUNNEL_REQUEST, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
667 return OMX_ErrorHardware;
670 *pTunnelSetup = resp.setup;
674 static OMX_ERRORTYPE vcil_out_GetExtensionIndex(OMX_IN OMX_HANDLETYPE hComponent,
675 OMX_IN OMX_STRING cParameterName,
676 OMX_OUT OMX_INDEXTYPE* pIndexType)
678 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
679 VC_PRIVATE_COMPONENT_T *comp;
680 IL_GET_EXTENSION_EXECUTE_T exe;
681 IL_GET_EXTENSION_RESPONSE_T resp;
683 int rlen = sizeof(resp);
685 if (!(pComp && cParameterName && pIndexType))
686 return OMX_ErrorBadParameter;
688 st = pComp->pApplicationPrivate;
689 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
691 exe.reference = comp->reference;
692 strncpy(exe.name, cParameterName, 128);
695 if(ilcs_execute_function(st->ilcs, IL_GET_EXTENSION_INDEX, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
696 return OMX_ErrorHardware;
698 *pIndexType = resp.index;
702 static OMX_ERRORTYPE vcil_out_ComponentRoleEnum(OMX_IN OMX_HANDLETYPE hComponent,
703 OMX_OUT OMX_U8 *cRole,
704 OMX_IN OMX_U32 nIndex)
706 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
707 VC_PRIVATE_COMPONENT_T *comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
708 IL_COMPONENT_ROLE_ENUM_EXECUTE_T exe;
709 IL_COMPONENT_ROLE_ENUM_RESPONSE_T resp;
710 ILCS_COMMON_T *st = pComp->pApplicationPrivate;
711 int rlen = sizeof(resp);
713 exe.reference = comp->reference;
716 if(ilcs_execute_function(st->ilcs, IL_COMPONENT_ROLE_ENUM, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
717 return OMX_ErrorHardware;
719 strncpy((char *) cRole, (char *) resp.role, 128);
724 OMX_ERRORTYPE vcil_out_component_name_enum(ILCS_COMMON_T *st, OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex)
726 IL_COMPONENT_NAME_ENUM_EXECUTE_T exe;
727 IL_COMPONENT_NAME_ENUM_RESPONSE_T resp;
728 int rlen = sizeof(resp);
732 if(ilcs_execute_function(st->ilcs, IL_COMPONENT_NAME_ENUM, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
733 return OMX_ErrorHardware;
735 if (sizeof(resp.name) < nNameLength)
736 nNameLength = sizeof(resp.name);
738 strncpy((char *)cComponentName, (char *) resp.name, nNameLength);
739 cComponentName[127] = 0;
743 OMX_ERRORTYPE vcil_out_get_debug_information(ILCS_COMMON_T *st, OMX_STRING debugInfo, OMX_S32 *pLen)
745 IL_GET_DEBUG_INFORMATION_EXECUTE_T exe;
749 if(ilcs_execute_function(st->ilcs, IL_GET_DEBUG_INFORMATION, &exe, sizeof(exe), debugInfo, (int *) pLen) < 0)
750 return OMX_ErrorHardware;
752 return OMX_ErrorNone;
755 // Called on the host side to create an OMX component.
756 OMX_ERRORTYPE vcil_out_create_component(ILCS_COMMON_T *st, OMX_HANDLETYPE hComponent, OMX_STRING component_name)
758 OMX_COMPONENTTYPE *pComp = (OMX_COMPONENTTYPE *) hComponent;
759 IL_CREATE_COMPONENT_EXECUTE_T exe;
760 IL_CREATE_COMPONENT_RESPONSE_T resp;
761 VC_PRIVATE_COMPONENT_T *comp;
763 int rlen = sizeof(resp);
765 if (strlen(component_name) >= sizeof(exe.name))
766 return OMX_ErrorInvalidComponent;
768 strcpy(exe.name, component_name);
771 if(ilcs_execute_function(st->ilcs, IL_CREATE_COMPONENT, &exe, sizeof(exe), &resp, &rlen) < 0 || rlen != sizeof(resp))
772 return OMX_ErrorHardware;
774 if (resp.err != OMX_ErrorNone)
777 comp = vcos_malloc(sizeof(VC_PRIVATE_COMPONENT_T) + (sizeof(VC_PRIVATE_PORT_T) * resp.numPorts), "ILCS Host Comp");
780 IL_EXECUTE_HEADER_T dexe;
781 IL_RESPONSE_HEADER_T dresp;
782 int dlen = sizeof(dresp);
784 dexe.reference = resp.reference;
786 ilcs_execute_function(st->ilcs, IL_COMPONENT_DEINIT, &dexe, sizeof(dexe), &dresp, &dlen);
787 return OMX_ErrorInsufficientResources;
790 memset(comp, 0, sizeof(VC_PRIVATE_COMPONENT_T) + (sizeof(VC_PRIVATE_PORT_T) * resp.numPorts));
792 comp->reference = resp.reference;
794 comp->numPorts = resp.numPorts;
795 comp->port = (VC_PRIVATE_PORT_T *) ((unsigned char *) comp + sizeof(VC_PRIVATE_COMPONENT_T));
797 for (i=0; i<comp->numPorts; i++)
801 IL_GET_EXECUTE_T gexe;
802 IL_GET_RESPONSE_T gresp;
803 OMX_PARAM_PORTSUMMARYTYPE *summary;
804 int glen = sizeof(gresp);
806 gexe.reference = comp->reference;
807 gexe.index = OMX_IndexParamPortSummary;
809 summary = (OMX_PARAM_PORTSUMMARYTYPE *) &gexe.param;
810 summary->nSize = sizeof(OMX_PARAM_PORTSUMMARYTYPE);
811 summary->nVersion.nVersion = OMX_VERSION;
812 summary->reqSet = i>>5;
814 ilcs_execute_function(st->ilcs, IL_GET_PARAMETER, &gexe,
815 sizeof(OMX_PARAM_PORTSUMMARYTYPE)+IL_GET_EXECUTE_HEADER_SIZE,
818 summary = (OMX_PARAM_PORTSUMMARYTYPE *) &gresp.param;
819 resp.portDir = summary->portDir;
820 memcpy(resp.portIndex, summary->portIndex, sizeof(OMX_U32) * 32);
823 comp->port[i].port = resp.portIndex[i&0x1f];
824 comp->port[i].dir = ((resp.portDir >> (i&0x1f)) & 1) ? OMX_DirOutput : OMX_DirInput;
827 vcos_semaphore_wait(&st->component_lock);
828 // insert into head of list
829 comp->next = st->component_list;
830 st->component_list = comp;
831 vcos_semaphore_post(&st->component_lock);
833 pComp->pComponentPrivate = comp;
834 pComp->pApplicationPrivate = st;
836 pComp->GetComponentVersion = vcil_out_GetComponentVersion;
837 pComp->ComponentDeInit = vcil_out_ComponentDeInit;
838 pComp->SetCallbacks = vcil_out_SetCallbacks;
839 pComp->GetState = vcil_out_GetState;
840 pComp->GetParameter = vcil_out_GetParameter;
841 pComp->SetParameter = vcil_out_SetParameter;
842 pComp->GetConfig = vcil_out_GetConfig;
843 pComp->SetConfig = vcil_out_SetConfig;
844 pComp->SendCommand = vcil_out_SendCommand;
845 pComp->UseBuffer = vcil_out_UseBuffer;
846 pComp->AllocateBuffer = vcil_out_AllocateBuffer;
847 pComp->FreeBuffer = vcil_out_FreeBuffer;
848 pComp->EmptyThisBuffer = vcil_out_EmptyThisBuffer;
849 pComp->FillThisBuffer = vcil_out_FillThisBuffer;
850 pComp->ComponentTunnelRequest = vcil_out_ComponentTunnelRequest;
851 pComp->GetExtensionIndex = vcil_out_GetExtensionIndex;
852 pComp->UseEGLImage = vcil_out_UseEGLImage;
853 pComp->ComponentRoleEnum = vcil_out_ComponentRoleEnum;
860 void vcil_out_event_handler(ILCS_COMMON_T *st, void *call, int clen, void *resp, int *rlen)
862 IL_EVENT_HANDLER_EXECUTE_T *exe = call;
863 OMX_COMPONENTTYPE *pComp = exe->reference;
864 VC_PRIVATE_COMPONENT_T *comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
868 vcos_assert(comp->callbacks.EventHandler);
869 comp->callbacks.EventHandler(pComp, comp->callback_state, exe->event, exe->data1, exe->data2, exe->eventdata);
872 // Called on host side via RPC in response to empty buffer completing
873 void vcil_out_empty_buffer_done(ILCS_COMMON_T *st, void *call, int clen, void *resp, int *rlen)
875 IL_PASS_BUFFER_EXECUTE_T *exe = call;
876 OMX_COMPONENTTYPE *pComp = exe->reference;
877 VC_PRIVATE_COMPONENT_T *comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
878 OMX_BUFFERHEADERTYPE *pHeader = exe->bufferHeader.pOutputPortPrivate;
879 OMX_U8 *pBuffer = pHeader->pBuffer;
880 OMX_PTR *pAppPrivate = pHeader->pAppPrivate;
881 OMX_PTR *pPlatformPrivate = pHeader->pPlatformPrivate;
882 OMX_PTR *pInputPortPrivate = pHeader->pInputPortPrivate;
883 OMX_PTR *pOutputPortPrivate = pHeader->pOutputPortPrivate;
885 memcpy(pHeader, &exe->bufferHeader, sizeof(OMX_BUFFERHEADERTYPE));
887 pHeader->pBuffer = pBuffer;
888 pHeader->pAppPrivate = pAppPrivate;
889 pHeader->pPlatformPrivate = pPlatformPrivate;
890 pHeader->pInputPortPrivate = pInputPortPrivate;
891 pHeader->pOutputPortPrivate = pOutputPortPrivate;
895 vcos_assert(comp->callbacks.EmptyBufferDone);
896 comp->callbacks.EmptyBufferDone(pComp, comp->callback_state, pHeader);
899 // Called on host side via RPC in response to a fill-buffer completing
900 // on the VideoCore side. ->pBuffer is a real pointer.
901 void vcil_out_fill_buffer_done(ILCS_COMMON_T *st, void *call, int clen, void *resp, int *rlen)
903 OMX_COMPONENTTYPE *pComp;
904 VC_PRIVATE_COMPONENT_T *comp;
905 OMX_BUFFERHEADERTYPE *pHeader;
907 pHeader = ilcs_receive_buffer(st->ilcs, call, clen, &pComp);
912 comp = (VC_PRIVATE_COMPONENT_T *) pComp->pComponentPrivate;
914 vc_assert(comp->callbacks.FillBufferDone);
915 comp->callbacks.FillBufferDone(pComp, comp->callback_state, pHeader);