1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON 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
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#include <stdio.h>
28#include <stdarg.h>
29
30//includes
31#include <memory.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include "interface/vmcs_host/khronos/IL/OMX_Component.h"
37#include "interface/vmcs_host/vcilcs.h"
38#include "interface/vmcs_host/vchost.h"
39#include "interface/vmcs_host/vcilcs_common.h"
40
41#include "host_ilcore.h"
42
43
44#ifdef WANT_OMX_NAME_MANGLE
45#define OMX_Deinit host_OMX_Deinit
46#define OMX_Init host_OMX_Init
47#define OMX_SetupTunnel host_OMX_SetupTunnel
48#define OMX_FreeHandle host_OMX_FreeHandle
49#define OMX_GetHandle host_OMX_GetHandle
50#define OMX_GetRolesOfComponent host_OMX_GetRolesOfComponent
51#define OMX_GetComponentsOfRole host_OMX_GetComponentsOfRole
52#define OMX_ComponentNameEnum host_OMX_ComponentNameEnum
53#define OMX_GetDebugInformation host_OMX_GetDebugInformation
54#endif
55
56#ifdef WANT_LOCAL_OMX
57 // xxx: we need to link to local OpenMAX IL core as well
58 OMX_API OMX_ERRORTYPE OMX_APIENTRY vc_OMX_Init(void);
59 OMX_API OMX_ERRORTYPE OMX_APIENTRY vc_OMX_Deinit(void);
60 OMX_API OMX_ERRORTYPE OMX_APIENTRY vc_OMX_GetHandle(
61 OMX_OUT OMX_HANDLETYPE* pHandle,
62 OMX_IN OMX_STRING cComponentName,
63 OMX_IN OMX_PTR pAppData,
64 OMX_IN OMX_CALLBACKTYPE* pCallBacks);
65 OMX_API OMX_ERRORTYPE OMX_APIENTRY vc_OMX_FreeHandle(
66 OMX_IN OMX_HANDLETYPE hComponent);
67#endif
68
69static int coreInit = 0;
70static int nActiveHandles = 0;
71static ILCS_SERVICE_T *ilcs_service = NULL;
72static VCOS_MUTEX_T lock;
73static VCOS_ONCE_T once = VCOS_ONCE_INIT;
74
75/* Atomic creation of lock protecting shared state */
76static void initOnce(void)
77{
78 VCOS_STATUS_T status;
79 status = vcos_mutex_create(&lock, VCOS_FUNCTION);
80 vcos_demand(status == VCOS_SUCCESS);
81}
82
83/* OMX_Init */
84OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
85{
86 VCOS_STATUS_T status;
87 OMX_ERRORTYPE err = OMX_ErrorNone;
88
89 status = vcos_once(&once, initOnce);
90 vcos_demand(status == VCOS_SUCCESS);
91
92 vcos_mutex_lock(&lock);
93
94#ifdef WANT_LOCAL_OMX
95 vc_OMX_Init(); // initialise local core first
96#endif
97
98 if(coreInit == 0)
99 {
100 // we need to connect via an ILCS connection to VideoCore
101 VCHI_INSTANCE_T initialise_instance;
102 VCHI_CONNECTION_T *connection;
103 ILCS_CONFIG_T config;
104
105 vc_host_get_vchi_state(&initialise_instance, &connection);
106
107 vcilcs_config(&config);
108#ifdef USE_VCHIQ_ARM
109 ilcs_service = ilcs_init((VCHIQ_INSTANCE_T) initialise_instance, (void **) &connection, &config, 0);
110#else
111 ilcs_service = ilcs_init((VCHIQ_STATE_T *) initialise_instance, (void **) &connection, &config, 0);
112#endif
113
114 if(ilcs_service == NULL)
115 {
116 err = OMX_ErrorHardware;
117 goto end;
118 }
119
120 coreInit = 1;
121 }
122#ifdef USE_VCHIQ_ARM
123 else
124 coreInit++;
125#endif
126
127end:
128 vcos_mutex_unlock(&lock);
129 return err;
130}
131
132/* OMX_Deinit */
133OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
134{
135 if(coreInit == 0) // || (coreInit == 1 && nActiveHandles > 0))
136 return OMX_ErrorNotReady;
137
138 vcos_mutex_lock(&lock);
139
140#ifdef USE_VCHIQ_ARM
141 coreInit--;
142#endif
143
144 if(coreInit == 0)
145 {
146 // we need to teardown the ILCS connection to VideoCore
147 ilcs_deinit(ilcs_service);
148 ilcs_service = NULL;
149 }
150
151#ifdef WANT_LOCAL_OMX
152 vc_OMX_Deinit(); // deinitialise local core as well
153#endif
154
155 vcos_mutex_unlock(&lock);
156
157 return OMX_ErrorNone;
158}
159
160
161/* OMX_ComponentNameEnum */
162OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
163 OMX_OUT OMX_STRING cComponentName,
164 OMX_IN OMX_U32 nNameLength,
165 OMX_IN OMX_U32 nIndex)
166{
167 if(ilcs_service == NULL)
168 return OMX_ErrorBadParameter;
169
170 return vcil_out_component_name_enum(ilcs_get_common(ilcs_service), cComponentName, nNameLength, nIndex);
171}
172
173
174/* OMX_GetHandle */
175OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
176 OMX_OUT OMX_HANDLETYPE* pHandle,
177 OMX_IN OMX_STRING cComponentName,
178 OMX_IN OMX_PTR pAppData,
179 OMX_IN OMX_CALLBACKTYPE* pCallBacks)
180{
181 OMX_ERRORTYPE eError;
182 OMX_COMPONENTTYPE *pComp;
183 OMX_HANDLETYPE hHandle = 0;
184
185 if (pHandle == NULL || cComponentName == NULL || pCallBacks == NULL || ilcs_service == NULL)
186 {
187 if(pHandle)
188 *pHandle = NULL;
189 return OMX_ErrorBadParameter;
190 }
191
192#if defined(WANT_LOCAL_OMX) && 0
193 if ((eError = vc_OMX_GetHandle(pHandle, cComponentName, pAppData, pCallBacks)) != OMX_ErrorNone)
194#endif
195 {
196 pComp = (OMX_COMPONENTTYPE *)malloc(sizeof(OMX_COMPONENTTYPE));
197 if (!pComp)
198 {
199 vcos_assert(0);
200 return OMX_ErrorInsufficientResources;
201 }
202 memset(pComp, 0, sizeof(OMX_COMPONENTTYPE));
203 hHandle = (OMX_HANDLETYPE)pComp;
204 pComp->nSize = sizeof(OMX_COMPONENTTYPE);
205 pComp->nVersion.nVersion = OMX_VERSION;
206 eError = vcil_out_create_component(ilcs_get_common(ilcs_service), hHandle, cComponentName);
207
208 if (eError == OMX_ErrorNone) {
209 // Check that all function pointers have been filled in.
210 // All fields should be non-zero.
211 int i;
212 uint32_t *p = (uint32_t *) pComp;
213 for(i=0; i<sizeof(OMX_COMPONENTTYPE)>>2; i++)
214 if(*p++ == 0)
215 eError = OMX_ErrorInvalidComponent;
216
217 if(eError != OMX_ErrorNone && pComp->ComponentDeInit)
218 pComp->ComponentDeInit(hHandle);
219 }
220
221 if (eError == OMX_ErrorNone) {
222 eError = pComp->SetCallbacks(hHandle,pCallBacks,pAppData);
223 if (eError != OMX_ErrorNone)
224 pComp->ComponentDeInit(hHandle);
225 }
226 if (eError == OMX_ErrorNone) {
227 *pHandle = hHandle;
228 }
229 else {
230 *pHandle = NULL;
231 free(pComp);
232 }
233 }
234
235 if (eError == OMX_ErrorNone) {
236 vcos_mutex_lock(&lock);
237 nActiveHandles++;
238 vcos_mutex_unlock(&lock);
239 }
240
241 return eError;
242}
243
244/* OMX_FreeHandle */
245OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
246 OMX_IN OMX_HANDLETYPE hComponent)
247{
248 OMX_ERRORTYPE eError = OMX_ErrorNone;
249 OMX_COMPONENTTYPE *pComp;
250
251 if (hComponent == NULL || ilcs_service == NULL)
252 return OMX_ErrorBadParameter;
253
254 pComp = (OMX_COMPONENTTYPE*)hComponent;
255
256#ifdef WANT_LOCAL_OMX
257 // xxx: a bit of a bodge, we rely on knowing that
258 // the local core doesn't make use of this field but
259 // ILCS does...
260 if (pComp->pApplicationPrivate == NULL)
261 return vc_OMX_FreeHandle(hComponent);
262#endif
263
264 if (ilcs_service == NULL)
265 return OMX_ErrorBadParameter;
266
267 eError = (pComp->ComponentDeInit)(hComponent);
268 if (eError == OMX_ErrorNone) {
269 vcos_mutex_lock(&lock);
270 --nActiveHandles;
271 vcos_mutex_unlock(&lock);
272 free(pComp);
273 }
274
275 vcos_assert(nActiveHandles >= 0);
276
277 return eError;
278}
279
280/* OMX_SetupTunnel */
281OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
282 OMX_IN OMX_HANDLETYPE hOutput,
283 OMX_IN OMX_U32 nPortOutput,
284 OMX_IN OMX_HANDLETYPE hInput,
285 OMX_IN OMX_U32 nPortInput)
286{
287 OMX_ERRORTYPE eError = OMX_ErrorNone;
288 OMX_COMPONENTTYPE *pCompIn, *pCompOut;
289 OMX_TUNNELSETUPTYPE oTunnelSetup;
290
291 if ((hOutput == NULL && hInput == NULL) || ilcs_service == NULL)
292 return OMX_ErrorBadParameter;
293
294 oTunnelSetup.nTunnelFlags = 0;
295 oTunnelSetup.eSupplier = OMX_BufferSupplyUnspecified;
296
297 pCompOut = (OMX_COMPONENTTYPE*)hOutput;
298
299 if (hOutput){
300 eError = pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, hInput, nPortInput, &oTunnelSetup);
301 }
302
303 if (eError == OMX_ErrorNone && hInput) {
304 pCompIn = (OMX_COMPONENTTYPE*)hInput;
305 eError = pCompIn->ComponentTunnelRequest(hInput, nPortInput, hOutput, nPortOutput, &oTunnelSetup);
306
307 if (eError != OMX_ErrorNone && hOutput) {
308 /* cancel tunnel request on output port since input port failed */
309 pCompOut->ComponentTunnelRequest(hOutput, nPortOutput, NULL, 0, NULL);
310 }
311 }
312 return eError;
313}
314
315/* OMX_GetComponentsOfRole */
316OMX_ERRORTYPE OMX_GetComponentsOfRole (
317 OMX_IN OMX_STRING role,
318 OMX_INOUT OMX_U32 *pNumComps,
319 OMX_INOUT OMX_U8 **compNames)
320{
321 OMX_ERRORTYPE eError = OMX_ErrorNone;
322
323 *pNumComps = 0;
324 return eError;
325}
326
327/* OMX_GetRolesOfComponent */
328OMX_ERRORTYPE OMX_GetRolesOfComponent (
329 OMX_IN OMX_STRING compName,
330 OMX_INOUT OMX_U32 *pNumRoles,
331 OMX_OUT OMX_U8 **roles)
332{
333 OMX_ERRORTYPE eError = OMX_ErrorNone;
334
335 *pNumRoles = 0;
336 return eError;
337}
338
339/* OMX_GetDebugInformation */
340OMX_ERRORTYPE OMX_GetDebugInformation (
341 OMX_OUT OMX_STRING debugInfo,
342 OMX_INOUT OMX_S32 *pLen)
343{
344 if(ilcs_service == NULL)
345 return OMX_ErrorBadParameter;
346
347 return vcil_out_get_debug_information(ilcs_get_common(ilcs_service), debugInfo, pLen);
348}
349
350
351
352/* File EOF */
353
354