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.
28 #include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h"
30 #include "mmalomx_commands.h"
31 #include "mmalomx_roles.h"
32 #include "mmalomx_registry.h"
33 #include "mmalomx_buffer.h"
34 #include "mmalomx_parameters.h"
35 #include "mmalomx_logging.h"
37 #include <util/mmal_util.h>
38 #include <util/mmal_util_params.h>
42 #define MAX_CMD_BUFFERS 5
44 #define PARAM_GET_PORT(port, component, index) \
45 if (index >= component->ports_num) return OMX_ErrorBadPortIndex; \
46 port = &component->ports[index]
48 static void *mmalomx_cmd_thread_func(void *arg);
49 #define MMALOMX_ZERO_COPY_THRESHOLD 256
51 /*****************************************************************************/
52 OMX_ERRORTYPE mmalomx_callback_event_handler(
53 MMALOMX_COMPONENT_T *component,
59 LOG_DEBUG("component %p, eEvent %i, nData1 %u, nData2 %u, pEventData %p",
60 component, (int)eEvent, (unsigned int)nData1, (unsigned int)nData2, pEventData);
61 return component->callbacks.EventHandler((OMX_HANDLETYPE)&component->omx,
62 component->callbacks_data, eEvent, nData1, nData2, pEventData);
65 /*****************************************************************************/
66 static OMX_ERRORTYPE mmalomx_ComponentGetComponentVersion(
67 OMX_HANDLETYPE hComponent,
68 OMX_STRING pComponentName,
69 OMX_VERSIONTYPE* pComponentVersion,
70 OMX_VERSIONTYPE* pSpecVersion,
71 OMX_UUIDTYPE* pComponentUUID)
73 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
74 const char *short_name, *prefix;
76 LOG_TRACE("hComponent %p, componentName %p, componentVersion %p, "
77 "pSpecVersion %p, componentUUID %p",
78 hComponent, pComponentName, pComponentVersion, pSpecVersion,
83 return OMX_ErrorInvalidComponent;
84 if (component->state == OMX_StateInvalid)
85 return OMX_ErrorInvalidState;
86 if (!pComponentName || !pComponentVersion || !pSpecVersion || !pComponentUUID )
87 return OMX_ErrorBadParameter;
89 short_name = mmalomx_registry_component_name(component->registry_id, &prefix);
91 snprintf(pComponentName, OMX_MAX_STRINGNAME_SIZE, "%s%s", short_name, prefix);
92 pComponentVersion->nVersion = 0;
93 pSpecVersion->nVersion = OMX_VERSION;
94 snprintf((char *)(*pComponentUUID), sizeof(OMX_UUIDTYPE), "%s", pComponentName);
99 /*****************************************************************************/
100 static OMX_ERRORTYPE mmalomx_ComponentSendCommand(
101 OMX_HANDLETYPE hComponent,
106 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
107 OMX_ERRORTYPE status = OMX_ErrorNone;
109 LOG_TRACE("hComponent %p, Cmd %i (%s), nParam1 %i (%s), pCmdData %p",
110 hComponent, Cmd, mmalomx_cmd_to_string(Cmd), (int)nParam1,
111 Cmd == OMX_CommandStateSet ? mmalomx_state_to_string((OMX_STATETYPE)nParam1) : "",
116 return OMX_ErrorInvalidComponent;
117 if (component->state == OMX_StateInvalid)
118 return OMX_ErrorInvalidState;
120 /* Sanity check port index */
121 if (Cmd == OMX_CommandFlush || Cmd == OMX_CommandMarkBuffer ||
122 Cmd == OMX_CommandPortEnable || Cmd == OMX_CommandPortDisable)
124 if (nParam1 != OMX_ALL && nParam1 >= component->ports_num)
125 return OMX_ErrorBadPortIndex;
128 if (Cmd == OMX_CommandStateSet ||
129 Cmd == OMX_CommandFlush ||
130 Cmd == OMX_CommandPortEnable ||
131 Cmd == OMX_CommandPortDisable)
133 status = mmalomx_command_queue(component, Cmd, nParam1);
135 else if (Cmd == OMX_CommandMarkBuffer)
137 status = mmalomx_command_port_mark(hComponent, nParam1, pCmdData);
141 status = OMX_ErrorNotImplemented;
147 /*****************************************************************************/
148 static MMAL_STATUS_T mmalomx_get_port_settings(MMALOMX_PORT_T *port, OMX_PARAM_PORTDEFINITIONTYPE *def)
150 MMAL_STATUS_T status = MMAL_SUCCESS;
151 MMAL_PORT_T *mmal = port->mmal;
153 def->eDomain = mmalil_es_type_to_omx_domain(mmal->format->type);
154 def->eDir = OMX_DirInput;
155 if (mmal->type == MMAL_PORT_TYPE_OUTPUT)
156 def->eDir = OMX_DirOutput;
158 if (def->eDomain == OMX_PortDomainVideo)
160 def->format.video.eColorFormat = OMX_COLOR_FormatUnused;
161 def->format.video.eCompressionFormat = mmalil_encoding_to_omx_video_coding(mmal->format->encoding);
162 if (def->format.video.eCompressionFormat == OMX_VIDEO_CodingUnused)
163 def->format.video.eColorFormat = mmalil_encoding_to_omx_color_format(mmal->format->encoding);
165 def->format.video.nBitrate = mmal->format->bitrate;
166 def->format.video.nFrameWidth = mmal->format->es->video.width;
167 if (mmal->format->es->video.crop.width)
168 def->format.video.nFrameWidth = mmal->format->es->video.crop.width;
169 def->format.video.nStride = mmal->format->es->video.width;
170 if (port->no_cropping)
171 def->format.video.nFrameWidth = def->format.video.nStride;
172 def->format.video.nStride =
173 mmal_encoding_width_to_stride(mmal->format->encoding, def->format.video.nStride);
174 def->format.video.nFrameHeight = mmal->format->es->video.height;
175 if (mmal->format->es->video.crop.height)
176 def->format.video.nFrameHeight = mmal->format->es->video.crop.height;
177 def->format.video.nSliceHeight = mmal->format->es->video.height;
178 if (port->no_cropping)
179 def->format.video.nFrameHeight = def->format.video.nSliceHeight;
180 if (mmal->format->es->video.frame_rate.den)
181 def->format.video.xFramerate = (((int64_t)mmal->format->es->video.frame_rate.num) << 16) /
182 mmal->format->es->video.frame_rate.den;
184 def->format.video.xFramerate = 0;
186 else if (def->eDomain == OMX_PortDomainImage)
188 def->format.image.eColorFormat = OMX_COLOR_FormatUnused;
189 def->format.image.eCompressionFormat = mmalil_encoding_to_omx_image_coding(mmal->format->encoding);
190 if (def->format.image.eCompressionFormat == OMX_IMAGE_CodingUnused)
191 def->format.image.eColorFormat = mmalil_encoding_to_omx_color_format(mmal->format->encoding);
192 if (mmal->format->encoding == MMAL_ENCODING_UNKNOWN)
193 def->format.image.eCompressionFormat = OMX_IMAGE_CodingAutoDetect;
194 def->format.image.nFrameWidth = mmal->format->es->video.width;
195 if (mmal->format->es->video.crop.width)
196 def->format.image.nFrameWidth = mmal->format->es->video.crop.width;
197 def->format.image.nStride = mmal->format->es->video.width;
198 if (port->no_cropping)
199 def->format.image.nFrameWidth = def->format.image.nStride;
200 def->format.image.nStride =
201 mmal_encoding_width_to_stride(mmal->format->encoding, def->format.image.nStride);
202 def->format.image.nFrameHeight = mmal->format->es->video.height;
203 if (mmal->format->es->video.crop.height)
204 def->format.image.nFrameHeight = mmal->format->es->video.crop.height;
205 def->format.image.nSliceHeight = mmal->format->es->video.height;
206 if (port->no_cropping)
207 def->format.image.nFrameHeight = def->format.image.nSliceHeight;
209 else if(def->eDomain == OMX_PortDomainAudio)
211 def->format.audio.eEncoding = mmalil_encoding_to_omx_audio_coding(mmal->format->encoding);
215 LOG_ERROR("%s: unsupported domain (%u)", mmal->name, def->eDomain);
216 status = MMAL_EINVAL;
220 def->nBufferAlignment = mmal->buffer_alignment_min;
221 def->nBufferCountActual = mmal->buffer_num;
222 def->nBufferCountMin = mmal->buffer_num_min;
223 def->nBufferSize = mmal->buffer_size;
224 if (def->nBufferSize < mmal->buffer_size_min)
225 def->nBufferSize = mmal->buffer_size_min;
226 def->bEnabled = port->enabled;
227 def->bPopulated = port->populated;
233 /*****************************************************************************/
234 static OMX_ERRORTYPE mmalomx_ComponentGetParameter(
235 OMX_HANDLETYPE hComponent,
236 OMX_INDEXTYPE nParamIndex,
239 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
240 MMALOMX_PORT_T *port = NULL;
242 LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
243 hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
247 return OMX_ErrorInvalidComponent;
249 return OMX_ErrorBadParameter;
250 if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
251 return OMX_ErrorBadParameter;
252 if (component->state == OMX_StateInvalid)
253 return OMX_ErrorInvalidState;
257 case OMX_IndexParamAudioInit:
258 case OMX_IndexParamVideoInit:
259 case OMX_IndexParamImageInit:
260 case OMX_IndexParamOtherInit:
262 OMX_PORT_PARAM_TYPE *param = (OMX_PORT_PARAM_TYPE *)pParam;
263 param->nStartPortNumber = 0;
264 param->nPorts = component->ports_domain_num[OMX_PortDomainAudio];
265 if (nParamIndex == OMX_IndexParamAudioInit)
266 return OMX_ErrorNone;
267 param->nStartPortNumber += param->nPorts;
268 param->nPorts = component->ports_domain_num[OMX_PortDomainVideo];
269 if (nParamIndex == OMX_IndexParamVideoInit)
270 return OMX_ErrorNone;
271 param->nStartPortNumber += param->nPorts;
272 param->nPorts = component->ports_domain_num[OMX_PortDomainImage];
273 if (nParamIndex == OMX_IndexParamImageInit)
274 return OMX_ErrorNone;
275 param->nStartPortNumber += param->nPorts;
276 param->nPorts = component->ports_domain_num[OMX_PortDomainOther];
278 return OMX_ErrorNone;
280 case OMX_IndexParamPortDefinition:
282 OMX_PARAM_PORTDEFINITIONTYPE *param = (OMX_PARAM_PORTDEFINITIONTYPE *)pParam;
283 PARAM_GET_PORT(port, component, param->nPortIndex);
284 return mmalil_error_to_omx(mmalomx_get_port_settings(port, param));
286 return OMX_ErrorNone;
288 case OMX_IndexParamCompBufferSupplier:
290 OMX_PARAM_BUFFERSUPPLIERTYPE *param = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParam;
291 PARAM_GET_PORT(port, component, param->nPortIndex);
292 param->eBufferSupplier = OMX_BufferSupplyUnspecified;
294 return OMX_ErrorNone;
296 case OMX_IndexParamPriorityMgmt:
298 OMX_PRIORITYMGMTTYPE *param = (OMX_PRIORITYMGMTTYPE *)pParam;
299 param->nGroupPriority = component->group_priority;
300 param->nGroupID = component->group_id;
302 return OMX_ErrorNone;
304 case OMX_IndexParamVideoPortFormat:
305 case OMX_IndexParamAudioPortFormat:
307 OMX_VIDEO_PARAM_PORTFORMATTYPE *param = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pParam;
308 PARAM_GET_PORT(port, component, param->nPortIndex);
310 /* Populate our internal list of encodings the first time around */
311 if (!port->encodings_num)
313 port->encodings_header.id = MMAL_PARAMETER_SUPPORTED_ENCODINGS;
314 port->encodings_header.size = sizeof(port->encodings_header) + sizeof(port->encodings);
315 if (mmal_port_parameter_get(port->mmal, &port->encodings_header) == MMAL_SUCCESS)
317 port->encodings_num = (port->encodings_header.size - sizeof(port->encodings_header)) /
318 sizeof(port->encodings[0]);
320 if (!port->encodings_num)
322 port->encodings_num = 1;
323 port->encodings[0] = port->mmal->format->encoding;
327 if (param->nIndex >= port->encodings_num)
328 return OMX_ErrorNoMore;
330 if (nParamIndex == OMX_IndexParamVideoPortFormat)
332 param->eColorFormat = OMX_COLOR_FormatUnused;
333 param->eCompressionFormat =
334 mmalil_encoding_to_omx_video_coding(port->encodings[param->nIndex]);
335 if (param->eCompressionFormat == OMX_VIDEO_CodingUnused)
336 param->eColorFormat =
337 mmalil_encoding_to_omx_color_format(port->encodings[param->nIndex]);
338 param->xFramerate = 0;
342 OMX_AUDIO_PARAM_PORTFORMATTYPE *aparam =
343 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pParam;
345 mmalil_encoding_to_omx_audio_coding(port->encodings[param->nIndex]);
347 return OMX_ErrorNone;
350 case OMX_IndexParamImagePortFormat:
351 case OMX_IndexParamOtherPortFormat:
353 case OMX_IndexParamStandardComponentRole:
355 OMX_PARAM_COMPONENTROLETYPE *param = (OMX_PARAM_COMPONENTROLETYPE *)pParam;
356 const char *role = mmalomx_role_to_name(component->role);
358 role = component->name;
359 snprintf((char *)param->cRole, sizeof(param->cRole), "%s", role);
361 return OMX_ErrorNone;
363 return mmalomx_parameter_get(component, nParamIndex, pParam);
366 return OMX_ErrorNotImplemented;
369 /*****************************************************************************/
370 static MMAL_STATUS_T mmalomx_set_port_settings(MMALOMX_PORT_T *mmalomx_port,
371 OMX_PARAM_PORTDEFINITIONTYPE *def)
373 MMAL_PORT_T *port = mmalomx_port->mmal;
374 uint32_t buffer_size_min = port->buffer_size_min;
375 MMAL_STATUS_T status;
377 port->format->type = mmalil_omx_domain_to_es_type(def->eDomain);
378 port->format->encoding_variant = 0;
380 if(def->eDomain == OMX_PortDomainVideo)
382 if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused)
383 port->format->encoding = mmalil_omx_video_coding_to_encoding(def->format.video.eCompressionFormat);
385 port->format->encoding = mmalil_omx_color_format_to_encoding(def->format.video.eColorFormat);
387 port->format->bitrate = def->format.video.nBitrate;
388 port->format->es->video.width = def->format.video.nFrameWidth;
389 if (!mmalomx_port->no_cropping)
390 port->format->es->video.crop.width = port->format->es->video.width;
391 if (mmal_encoding_stride_to_width(port->format->encoding, def->format.video.nStride))
392 port->format->es->video.width =
393 mmal_encoding_stride_to_width(port->format->encoding, def->format.video.nStride);
394 port->format->es->video.height = def->format.video.nFrameHeight;
395 if (!mmalomx_port->no_cropping)
396 port->format->es->video.crop.height = port->format->es->video.height;
397 if (def->format.video.nSliceHeight > def->format.video.nFrameHeight)
398 port->format->es->video.height = def->format.video.nSliceHeight;
399 port->format->es->video.frame_rate.num = def->format.video.xFramerate;
400 port->format->es->video.frame_rate.den = (1<<16);
402 else if(def->eDomain == OMX_PortDomainImage)
404 if (def->format.image.eCompressionFormat != OMX_IMAGE_CodingUnused)
405 port->format->encoding = mmalil_omx_image_coding_to_encoding(def->format.image.eCompressionFormat);
407 port->format->encoding = mmalil_omx_color_format_to_encoding(def->format.image.eColorFormat);
409 port->format->es->video.width = def->format.image.nFrameWidth;
410 if (!mmalomx_port->no_cropping)
411 port->format->es->video.crop.width = port->format->es->video.width;
412 if (mmal_encoding_stride_to_width(port->format->encoding, def->format.image.nStride))
413 port->format->es->video.width =
414 mmal_encoding_stride_to_width(port->format->encoding, def->format.image.nStride);
415 port->format->es->video.height = def->format.image.nFrameHeight;
416 if (!mmalomx_port->no_cropping)
417 port->format->es->video.crop.height = port->format->es->video.height;
418 if (def->format.image.nSliceHeight > def->format.image.nFrameHeight)
419 port->format->es->video.height = def->format.image.nSliceHeight;
421 else if(def->eDomain == OMX_PortDomainAudio)
423 port->format->encoding = mmalil_omx_audio_coding_to_encoding(def->format.audio.eEncoding);
427 port->format->encoding = MMAL_ENCODING_UNKNOWN;
430 port->buffer_num = def->nBufferCountActual;
431 port->buffer_size = def->nBufferSize;
432 if (port->buffer_size < port->buffer_size_min)
433 port->buffer_size = port->buffer_size_min;
435 status = mmal_port_format_commit(port);
436 if (status != MMAL_SUCCESS)
439 /* Acknowledge any ongoing port format changed event */
440 mmalomx_port->format_changed = MMAL_FALSE;
442 /* The minimum buffer size only changes when the format significantly changes
443 * and in that case we want to advertise the new requirement to the client. */
444 if (port->buffer_size_min != buffer_size_min)
445 port->buffer_size = port->buffer_size_min;
450 /*****************************************************************************/
451 static OMX_ERRORTYPE mmalomx_ComponentSetParameter(
452 OMX_HANDLETYPE hComponent,
453 OMX_INDEXTYPE nParamIndex,
456 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
457 MMALOMX_PORT_T *port = NULL;
459 LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
460 hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
464 return OMX_ErrorInvalidComponent;
466 return OMX_ErrorBadParameter;
467 if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
468 return OMX_ErrorBadParameter;
469 if (component->state == OMX_StateInvalid)
470 return OMX_ErrorInvalidState;
474 case OMX_IndexParamPortDefinition:
476 OMX_PARAM_PORTDEFINITIONTYPE *param = (OMX_PARAM_PORTDEFINITIONTYPE *)pParam;
477 PARAM_GET_PORT(port, component, param->nPortIndex);
478 return mmalil_error_to_omx(mmalomx_set_port_settings(port, param));
480 return OMX_ErrorNone;
482 case OMX_IndexParamCompBufferSupplier:
484 OMX_PARAM_BUFFERSUPPLIERTYPE *param = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParam;
485 PARAM_GET_PORT(port, component, param->nPortIndex);
486 //param->eBufferSupplier = OMX_BufferSupplyUnspecified;
488 return OMX_ErrorNone;
490 case OMX_IndexParamPriorityMgmt:
492 OMX_PRIORITYMGMTTYPE *param = (OMX_PRIORITYMGMTTYPE *)pParam;
494 if (component->state != OMX_StateLoaded)
495 return OMX_ErrorIncorrectStateOperation;
497 component->group_priority = param->nGroupPriority;
498 component->group_id = param->nGroupID;
500 return OMX_ErrorNone;
502 case OMX_IndexParamAudioPortFormat:
504 OMX_AUDIO_PARAM_PORTFORMATTYPE *param = (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pParam;
505 PARAM_GET_PORT(port, component, param->nPortIndex);
506 port->mmal->format->encoding = mmalil_omx_audio_coding_to_encoding(param->eEncoding);
507 port->mmal->format->encoding_variant = 0;
508 if (mmal_port_format_commit(port->mmal) != MMAL_SUCCESS)
509 LOG_ERROR("OMX_IndexParamAudioPortFormat commit failed");
510 return OMX_ErrorNone;
513 case OMX_IndexParamVideoPortFormat:
515 OMX_VIDEO_PARAM_PORTFORMATTYPE *param = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pParam;
516 PARAM_GET_PORT(port, component, param->nPortIndex);
517 if (param->eCompressionFormat != OMX_VIDEO_CodingUnused)
518 port->mmal->format->encoding = mmalil_omx_video_coding_to_encoding(param->eCompressionFormat);
520 port->mmal->format->encoding = mmalil_omx_color_format_to_encoding(param->eColorFormat);
521 port->mmal->format->encoding_variant = 0;
523 if (mmal_port_format_commit(port->mmal) != MMAL_SUCCESS)
524 LOG_ERROR("OMX_IndexParamAudioPortFormat commit failed");
525 return OMX_ErrorNone;
528 case OMX_IndexParamImagePortFormat:
529 case OMX_IndexParamOtherPortFormat:
531 case OMX_IndexParamStandardComponentRole:
533 OMX_PARAM_COMPONENTROLETYPE *param = (OMX_PARAM_COMPONENTROLETYPE *)pParam;
534 return mmalomx_role_set(component, (const char *)param->cRole);
539 OMX_ERRORTYPE status = mmalomx_parameter_set(component, nParamIndex, pParam);
541 /* Keep track of the zero-copy state */
542 if (status == OMX_ErrorNone && nParamIndex == OMX_IndexParamBrcmZeroCopy)
544 PARAM_GET_PORT(port, component, ((OMX_CONFIG_PORTBOOLEANTYPE *)pParam)->nPortIndex);
545 port->zero_copy = ((OMX_CONFIG_PORTBOOLEANTYPE *)pParam)->bEnabled;
552 return OMX_ErrorNotImplemented;
555 /*****************************************************************************/
556 static OMX_ERRORTYPE mmalomx_ComponentGetConfig(
557 OMX_HANDLETYPE hComponent,
558 OMX_INDEXTYPE nParamIndex,
561 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
563 LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
564 hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
568 return OMX_ErrorInvalidComponent;
570 return OMX_ErrorBadParameter;
571 if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
572 return OMX_ErrorBadParameter;
573 if (component->state == OMX_StateInvalid)
574 return OMX_ErrorInvalidState;
576 return mmalomx_parameter_get(component, nParamIndex, pParam);
579 /*****************************************************************************/
580 static OMX_ERRORTYPE mmalomx_ComponentSetConfig(
581 OMX_HANDLETYPE hComponent,
582 OMX_INDEXTYPE nParamIndex,
585 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
587 LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p",
588 hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam);
592 return OMX_ErrorInvalidComponent;
594 return OMX_ErrorBadParameter;
595 if (*(OMX_U32 *)pParam < sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))
596 return OMX_ErrorBadParameter;
597 if (component->state == OMX_StateInvalid)
598 return OMX_ErrorInvalidState;
600 return mmalomx_parameter_set(component, nParamIndex, pParam);
603 /*****************************************************************************/
604 static OMX_ERRORTYPE mmalomx_ComponentGetExtensionIndex(
605 OMX_HANDLETYPE hComponent,
606 OMX_STRING cParameterName,
607 OMX_INDEXTYPE* pIndexType)
609 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
611 LOG_TRACE("hComponent %p, cParameterName %s, pIndexType %p",
612 hComponent, cParameterName, pIndexType);
616 return OMX_ErrorInvalidComponent;
617 if (component->state == OMX_StateInvalid)
618 return OMX_ErrorInvalidState;
620 return mmalomx_parameter_extension_index_get(cParameterName, pIndexType);
623 /*****************************************************************************/
624 static OMX_ERRORTYPE mmalomx_ComponentGetState(
625 OMX_HANDLETYPE hComponent,
626 OMX_STATETYPE* pState)
628 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
629 MMAL_PARAM_UNUSED(component);
631 LOG_TRACE("hComponent %p, pState, %p", hComponent, pState);
635 return OMX_ErrorInvalidComponent;
637 return OMX_ErrorBadParameter;
639 *pState = component->state;
640 return OMX_ErrorNone;
643 /*****************************************************************************/
644 static OMX_ERRORTYPE mmalomx_ComponentTunnelRequest(
645 OMX_HANDLETYPE hComponent,
647 OMX_HANDLETYPE hTunneledComp,
648 OMX_U32 nTunneledPort,
649 OMX_TUNNELSETUPTYPE* pTunnelSetup)
651 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
652 MMAL_PARAM_UNUSED(component);
654 LOG_TRACE("hComponent %p, nPort %i, hTunneledComp %p, nTunneledPort %i, "
655 "pTunnelSetup %p", hComponent, (int)nPort, hTunneledComp,
656 (int)nTunneledPort, pTunnelSetup);
660 return OMX_ErrorInvalidComponent;
661 if (component->state == OMX_StateInvalid)
662 return OMX_ErrorInvalidState;
663 if (nPort >= component->ports_num)
664 return OMX_ErrorBadPortIndex;
665 if (component->state != OMX_StateLoaded && component->ports[nPort].enabled)
666 return OMX_ErrorIncorrectStateOperation;
667 if (hTunneledComp && !pTunnelSetup)
668 return OMX_ErrorBadParameter;
671 return OMX_ErrorNone;
672 return OMX_ErrorNotImplemented;
675 /*****************************************************************************/
676 static OMX_ERRORTYPE mmalomx_ComponentUseBuffer(
677 OMX_HANDLETYPE hComponent,
678 OMX_BUFFERHEADERTYPE** ppBuffer,
684 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
685 OMX_ERRORTYPE status = OMX_ErrorNone;
686 MMAL_BOOL_T populated = MMAL_FALSE;
687 OMX_BUFFERHEADERTYPE *buffer;
688 MMALOMX_PORT_T *port;
690 LOG_TRACE("hComponent %p, ppBufferHdr %p, nPortIndex %i, pAppPrivate %p,"
691 " nSizeBytes %i, pBuffer %p", hComponent, ppBuffer,
692 (int)nPortIndex, pAppPrivate, (int)nSizeBytes, pBuffer);
696 return OMX_ErrorInvalidComponent;
698 return OMX_ErrorBadParameter;
699 if (component->state == OMX_StateInvalid)
700 return OMX_ErrorInvalidState;
701 if (nPortIndex >= component->ports_num)
702 return OMX_ErrorBadPortIndex;
704 /* Make sure any previous command has been processed.
705 * This is not ideal since done inline but in practice the actual
706 * notification to the client will not be done as part of this call. */
707 mmalomx_commands_actions_check(component);
709 port = &component->ports[nPortIndex];
710 MMALOMX_LOCK_PORT(component, port);
712 if (!(port->actions & MMALOMX_ACTION_CHECK_ALLOCATED))
713 status = OMX_ErrorIncorrectStateOperation;
715 status = OMX_ErrorIncorrectStateOperation;
716 if (status != OMX_ErrorNone)
719 /* Check for mismatched calls to UseBuffer/AllocateBuffer */
720 if (port->buffers && port->buffers_allocated)
722 status = OMX_ErrorBadParameter;
726 /* Sanity check buffer size */
727 if (nSizeBytes < port->mmal->buffer_size_min)
729 LOG_ERROR("buffer size too small (%i/%i)", (int)nSizeBytes,
730 (int)port->mmal->buffer_size_min);
731 status = OMX_ErrorBadParameter;
735 port->mmal->buffer_size = nSizeBytes;
736 if (nSizeBytes > port->mmal->buffer_size)
738 LOG_ERROR("buffer size too big (%i/%i)", (int)nSizeBytes,
739 (int)port->mmal->buffer_size);
740 status = OMX_ErrorBadParameter;
744 buffer = calloc( 1, sizeof(*buffer) );
747 status = OMX_ErrorInsufficientResources;
751 buffer->nSize = sizeof(*buffer);
752 buffer->nVersion.nVersion = OMX_VERSION;
753 buffer->nAllocLen = nSizeBytes;
754 buffer->pBuffer = pBuffer;
755 buffer->pAppPrivate = pAppPrivate;
756 if (port->direction == OMX_DirInput)
758 buffer->nInputPortIndex = nPortIndex;
759 buffer->pOutputPortPrivate = pAppPrivate;
763 buffer->nOutputPortIndex = nPortIndex;
764 buffer->pInputPortPrivate = pAppPrivate;
769 port->buffers_allocated = MMAL_FALSE;
770 port->populated = populated = port->buffers == port->mmal->buffer_num;
772 MMALOMX_UNLOCK_PORT(component, port);
774 LOG_DEBUG("allocated %i/%i buffers", port->buffers, port->mmal->buffer_num);
777 mmalomx_commands_actions_signal(component);
779 return OMX_ErrorNone;
782 MMALOMX_UNLOCK_PORT(component, port);
786 /*****************************************************************************/
787 static OMX_ERRORTYPE mmalomx_ComponentAllocateBuffer(
788 OMX_HANDLETYPE hComponent,
789 OMX_BUFFERHEADERTYPE** ppBuffer,
794 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
795 OMX_ERRORTYPE status = OMX_ErrorNone;
796 MMAL_BOOL_T populated = MMAL_FALSE;
797 OMX_BUFFERHEADERTYPE *buffer = 0;
798 MMALOMX_PORT_T *port;
800 LOG_TRACE("hComponent %p, ppBuffer %p, nPortIndex %i, pAppPrivate %p, "
801 "nSizeBytes %i", hComponent, ppBuffer, (int)nPortIndex,
802 pAppPrivate, (int)nSizeBytes);
806 return OMX_ErrorInvalidComponent;
808 return OMX_ErrorBadParameter;
809 if (component->state == OMX_StateInvalid)
810 return OMX_ErrorInvalidState;
811 if (nPortIndex >= component->ports_num)
812 return OMX_ErrorBadPortIndex;
814 /* Make sure any previous command has been processed.
815 * This is not ideal since done inline but in practice the actual
816 * notification to the client will not be done as part of this call. */
817 mmalomx_commands_actions_check(component);
819 port = &component->ports[nPortIndex];
820 MMALOMX_LOCK_PORT(component, port);
822 if (!(port->actions & MMALOMX_ACTION_CHECK_ALLOCATED))
823 status = OMX_ErrorIncorrectStateOperation;
825 status = OMX_ErrorIncorrectStateOperation;
826 if (status != OMX_ErrorNone)
829 /* Check for mismatched calls to UseBuffer/AllocateBuffer */
830 if (!status && port->buffers && !port->buffers_allocated)
832 status = OMX_ErrorBadParameter;
836 /* Sanity check buffer size */
837 if (nSizeBytes < port->mmal->buffer_size_min)
839 LOG_ERROR("buffer size too small (%i/%i)", (int)nSizeBytes,
840 (int)port->mmal->buffer_size_min);
841 status = OMX_ErrorBadParameter;
845 port->mmal->buffer_size = nSizeBytes;
846 if (nSizeBytes > port->mmal->buffer_size)
848 LOG_ERROR("buffer size too big (%i/%i)", (int)nSizeBytes,
849 (int)port->mmal->buffer_size);
850 status = OMX_ErrorBadParameter;
854 /* Set the zero-copy mode */
855 if (!port->buffers_allocated && nSizeBytes > MMALOMX_ZERO_COPY_THRESHOLD &&
858 MMAL_STATUS_T status = mmal_port_parameter_set_boolean(port->mmal,
859 MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
860 if (status != MMAL_SUCCESS && status != MMAL_ENOSYS)
861 LOG_ERROR("failed to enable zero copy on %s", port->mmal->name);
864 buffer = calloc( 1, sizeof(*buffer) );
867 status = OMX_ErrorInsufficientResources;
871 buffer->pBuffer = mmal_port_payload_alloc(port->mmal, nSizeBytes);
872 if (!buffer->pBuffer)
874 status = OMX_ErrorInsufficientResources;
878 buffer->nSize = sizeof(*buffer);
879 buffer->nVersion.nVersion = OMX_VERSION;
880 buffer->nAllocLen = nSizeBytes;
881 buffer->pAppPrivate = pAppPrivate;
882 if (port->direction == OMX_DirInput)
884 buffer->nInputPortIndex = nPortIndex;
885 buffer->pOutputPortPrivate = pAppPrivate;
889 buffer->nOutputPortIndex = nPortIndex;
890 buffer->pInputPortPrivate = pAppPrivate;
892 /* Keep an unmodified copy of the pointer for when we come to free it */
893 buffer->pPlatformPrivate = (OMX_PTR)buffer->pBuffer;
897 port->buffers_allocated = MMAL_TRUE;
898 port->populated = populated = port->buffers == port->mmal->buffer_num;
900 MMALOMX_UNLOCK_PORT(component, port);
902 LOG_DEBUG("allocated %i/%i buffers", port->buffers, port->mmal->buffer_num);
905 mmalomx_commands_actions_signal(component);
907 return OMX_ErrorNone;
910 if (!port->buffers_allocated && !port->zero_copy)
911 mmal_port_parameter_set_boolean(port->mmal, MMAL_PARAMETER_ZERO_COPY, MMAL_FALSE);
913 MMALOMX_UNLOCK_PORT(component, port);
914 LOG_ERROR("failed to allocate %i/%i buffers", port->buffers, port->mmal->buffer_num);
920 /*****************************************************************************/
921 static OMX_ERRORTYPE mmalomx_ComponentFreeBuffer(
922 OMX_HANDLETYPE hComponent,
924 OMX_BUFFERHEADERTYPE* pBuffer)
926 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
927 OMX_ERRORTYPE status = OMX_ErrorNone;
928 MMAL_BOOL_T unpopulated, allocated;
929 MMALOMX_PORT_T *port;
930 unsigned int buffers;
932 LOG_TRACE("hComponent %p, nPortIndex %i, pBuffer %p",
933 hComponent, (int)nPortIndex, pBuffer);
937 return OMX_ErrorInvalidComponent;
939 return OMX_ErrorBadParameter;
940 if (nPortIndex >= component->ports_num)
941 return OMX_ErrorBadPortIndex;
943 /* Make sure any previous command has been processed.
944 * This is not ideal since done inline but in practice the actual
945 * notification to the client will not be done as part of this call. */
946 mmalomx_commands_actions_check(component);
948 port = &component->ports[nPortIndex];
949 MMALOMX_LOCK_PORT(component, port);
953 status = OMX_ErrorBadParameter;
957 buffers = --port->buffers;
958 port->populated = MMAL_FALSE;
959 unpopulated = !(port->actions & MMALOMX_ACTION_CHECK_DEALLOCATED);
960 allocated = port->buffers_allocated;
962 MMALOMX_UNLOCK_PORT(component, port);
964 if (allocated) /* Free the unmodified pointer */
965 mmal_port_payload_free(port->mmal, pBuffer->pPlatformPrivate);
968 if (allocated && !port->zero_copy) /* Reset the zero-copy status */
969 mmal_port_parameter_set_boolean(port->mmal, MMAL_PARAMETER_ZERO_COPY, MMAL_FALSE);
971 LOG_DEBUG("freed %i/%i buffers", port->mmal->buffer_num - port->buffers, port->mmal->buffer_num);
974 mmalomx_callback_event_handler(component, OMX_EventError, OMX_ErrorPortUnpopulated, 0, NULL);
977 mmalomx_commands_actions_signal(component);
979 return OMX_ErrorNone;
982 MMALOMX_UNLOCK_PORT(component, port);
986 /*****************************************************************************/
987 static OMX_ERRORTYPE mmalomx_ComponentEmptyThisBuffer(
988 OMX_HANDLETYPE hComponent,
989 OMX_BUFFERHEADERTYPE* pBuffer)
991 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
993 if (ENABLE_MMAL_EXTRA_LOGGING)
994 LOG_TRACE("hComponent %p, port %i, pBuffer %p", hComponent,
995 pBuffer ? (int)pBuffer->nInputPortIndex : -1, pBuffer);
997 return mmalomx_buffer_send(component, pBuffer, OMX_DirInput);
1000 /*****************************************************************************/
1001 static OMX_ERRORTYPE mmalomx_ComponentFillThisBuffer(
1002 OMX_HANDLETYPE hComponent,
1003 OMX_BUFFERHEADERTYPE* pBuffer)
1005 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
1007 if (ENABLE_MMAL_EXTRA_LOGGING)
1008 LOG_TRACE("hComponent %p, port %i, pBuffer %p", hComponent,
1009 pBuffer ? (int)pBuffer->nOutputPortIndex : -1, pBuffer);
1011 return mmalomx_buffer_send(component, pBuffer, OMX_DirOutput);
1014 /*****************************************************************************/
1015 static OMX_ERRORTYPE mmalomx_ComponentSetCallbacks(
1016 OMX_HANDLETYPE hComponent,
1017 OMX_CALLBACKTYPE* pCallbacks,
1020 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
1021 MMAL_PARAM_UNUSED(component);
1023 LOG_TRACE("hComponent %p, pCallbacks %p, pAppData %p",
1024 hComponent, pCallbacks, pAppData);
1028 return OMX_ErrorInvalidComponent;
1030 return OMX_ErrorBadParameter;
1031 if (component->state == OMX_StateInvalid)
1032 return OMX_ErrorInvalidState;
1034 if (component->state != OMX_StateLoaded)
1035 return OMX_ErrorInvalidState;
1037 component->callbacks = *pCallbacks;
1038 component->callbacks_data = pAppData;
1039 return OMX_ErrorNone;
1042 /*****************************************************************************/
1043 static OMX_ERRORTYPE mmalomx_ComponentDeInit(
1044 OMX_HANDLETYPE hComponent)
1046 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
1047 MMAL_PARAM_UNUSED(component);
1049 LOG_TRACE("hComponent %p", hComponent);
1053 return OMX_ErrorInvalidComponent;
1055 return OMX_ErrorNone;
1058 /*****************************************************************************/
1059 static OMX_ERRORTYPE mmalomx_ComponentUseEGLImage(
1060 OMX_HANDLETYPE hComponent,
1061 OMX_BUFFERHEADERTYPE** ppBufferHdr,
1063 OMX_PTR pAppPrivate,
1066 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
1067 MMAL_PARAM_UNUSED(component);
1069 LOG_TRACE("hComponent %p, ppBufferHdr %p, nPortIndex %i, pAppPrivate %p,"
1070 " eglImage %p", hComponent, ppBufferHdr, (int)nPortIndex,
1071 pAppPrivate, eglImage);
1075 return OMX_ErrorInvalidComponent;
1076 if (component->state == OMX_StateInvalid)
1077 return OMX_ErrorInvalidState;
1079 return OMX_ErrorNotImplemented;
1082 /*****************************************************************************/
1083 static OMX_ERRORTYPE mmalomx_ComponentRoleEnum(
1084 OMX_HANDLETYPE hComponent,
1088 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
1089 MMALOMX_ROLE_T role;
1091 LOG_TRACE("hComponent %p, cRole %p, nIndex %i",
1092 hComponent, cRole, (int)nIndex);
1096 return OMX_ErrorInvalidComponent;
1097 if (component->state == OMX_StateInvalid)
1098 return OMX_ErrorInvalidState;
1100 role = mmalomx_registry_component_roles(component->registry_id, nIndex);
1102 return OMX_ErrorNoMore;
1103 if (!mmalomx_role_to_name(role))
1104 return OMX_ErrorNoMore;
1106 strcpy((char *)cRole, mmalomx_role_to_name(role));
1107 return OMX_ErrorNone;
1110 /*****************************************************************************/
1111 OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_Init)(void)
1113 mmalomx_logging_init();
1115 return OMX_ErrorNone;
1118 /*****************************************************************************/
1119 OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_Deinit)(void)
1121 LOG_TRACE("Deinit");
1122 mmalomx_logging_deinit();
1123 return OMX_ErrorNone;
1126 /*****************************************************************************/
1127 OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_ComponentNameEnum)(
1128 OMX_STRING cComponentName,
1129 OMX_U32 nNameLength,
1132 const char *prefix, *name;
1133 name = mmalomx_registry_component_name(nIndex, &prefix);
1135 LOG_TRACE("cComponentName %p, nNameLength %i, nIndex %i",
1136 cComponentName, (int)nNameLength, (int)nIndex);
1138 /* Sanity checking */
1139 if (!cComponentName)
1140 return OMX_ErrorBadParameter;
1142 return OMX_ErrorNoMore;
1143 if (nNameLength <= strlen(name) + strlen(prefix))
1144 return OMX_ErrorBadParameter;
1146 sprintf(cComponentName, "%s%s", prefix, name);
1147 LOG_TRACE("cComponentName: %s", cComponentName);
1148 return OMX_ErrorNone;
1151 /*****************************************************************************/
1152 static void mmalomx_buffer_cb_control(
1154 MMAL_BUFFER_HEADER_T *buffer)
1156 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)port->userdata;
1158 LOG_DEBUG("received event %4.4s on port %s", (char *)&buffer->cmd, port->name);
1160 if (buffer->cmd == MMAL_EVENT_ERROR)
1162 mmalomx_callback_event_handler(component, OMX_EventError,
1163 mmalil_error_to_omx(*(MMAL_STATUS_T *)buffer->data), 0, NULL);
1165 else if (buffer->cmd == MMAL_EVENT_EOS &&
1166 buffer->length == sizeof(MMAL_EVENT_END_OF_STREAM_T))
1168 MMAL_EVENT_END_OF_STREAM_T *eos = (MMAL_EVENT_END_OF_STREAM_T *)buffer->data;
1169 if (eos->port_index < port->component->input_num)
1171 MMALOMX_PORT_T *omx_port = (MMALOMX_PORT_T *)
1172 port->component->input[eos->port_index]->userdata;
1173 LOG_DEBUG("send EOS on %i", omx_port->index);
1174 mmalomx_callback_event_handler(component, OMX_EventBufferFlag,
1175 omx_port->index, OMX_BUFFERFLAG_EOS, NULL);
1179 mmal_buffer_header_release(buffer);
1182 /*****************************************************************************/
1183 OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_GetHandle)(
1184 OMX_HANDLETYPE* pHandle,
1185 OMX_STRING cComponentName,
1187 OMX_CALLBACKTYPE* pCallBacks)
1189 OMX_ERRORTYPE status = OMX_ErrorInsufficientResources;
1190 MMALOMX_COMPONENT_T *component = 0;
1191 MMAL_COMPONENT_T *mmal_component = 0;
1192 MMAL_STATUS_T mmal_status;
1193 unsigned int i, ports_num;
1194 OMX_PORTDOMAINTYPE domain;
1195 const char *mmal_name;
1198 LOG_TRACE("pHandle %p, cComponentName %s, pAppData %p, pCallBacks %p",
1199 pHandle, cComponentName, pAppData, pCallBacks);
1201 /* Sanity check params */
1202 if (!pHandle || !cComponentName || !pCallBacks)
1203 return OMX_ErrorBadParameter;
1205 /* Find component */
1206 registry_id = mmalomx_registry_find_component(cComponentName);
1207 if (registry_id < 0)
1208 return OMX_ErrorComponentNotFound;
1210 /* create and setup component */
1211 mmal_name = mmalomx_registry_component_mmal(registry_id);
1212 mmal_status = mmal_component_create(mmal_name, &mmal_component);
1213 if (mmal_status != MMAL_SUCCESS)
1215 LOG_ERROR("could not create mmal component %s", mmal_name);
1216 return mmalil_error_to_omx(mmal_status);
1218 mmal_status = mmal_port_enable(mmal_component->control, mmalomx_buffer_cb_control);
1219 if (mmal_status != MMAL_SUCCESS)
1221 LOG_ERROR("could not enable %s", mmal_component->control->name);
1222 mmal_component_destroy(mmal_component);
1223 return mmalil_error_to_omx(mmal_status);
1226 ports_num = mmal_component->port_num - 1;
1228 component = calloc(1, sizeof(*component) + ports_num * sizeof(*component->ports));
1231 mmal_component_destroy(mmal_component);
1232 return OMX_ErrorInsufficientResources;
1235 if (vcos_mutex_create(&component->lock, "mmalomx lock") != VCOS_SUCCESS)
1237 mmal_component_destroy(mmal_component);
1239 return OMX_ErrorInsufficientResources;
1241 if (vcos_mutex_create(&component->lock_port, "mmalomx port lock") != VCOS_SUCCESS)
1243 vcos_mutex_delete(&component->lock);
1244 mmal_component_destroy(mmal_component);
1246 return OMX_ErrorInsufficientResources;
1249 component->omx.nSize = sizeof(component->omx);
1250 component->omx.nVersion.nVersion = OMX_VERSION;
1251 component->mmal = mmal_component;
1252 component->state = OMX_StateLoaded;
1253 component->callbacks = *pCallBacks;
1254 component->callbacks_data = pAppData;
1255 component->ports = (MMALOMX_PORT_T *)&component[1];
1256 component->registry_id = registry_id;
1257 component->name = mmalomx_registry_component_name(registry_id, 0);
1258 component->role = mmalomx_registry_component_roles(registry_id, 0);
1260 // FIXME: make this configurable
1261 component->cmd_thread_used = MMAL_TRUE;
1263 /* Sort the ports into separate OMX domains */
1264 for (domain = OMX_PortDomainAudio; domain < OMX_PortDomainOther; domain++)
1266 for (i = 1; i < mmal_component->port_num; i++)
1268 if (domain == mmalil_es_type_to_omx_domain(mmal_component->port[i]->format->type))
1270 component->ports[component->ports_num].mmal = mmal_component->port[i];
1271 component->ports_domain_num[domain]++;
1272 component->ports_num++;
1276 LOG_DEBUG("ports: %i audio, %i video",
1277 component->ports_domain_num[OMX_PortDomainAudio],
1278 component->ports_domain_num[OMX_PortDomainVideo]);
1280 /* Setup our ports */
1281 for (i = 0; i < component->ports_num; i++)
1283 component->ports[i].component = component;
1284 if (component->ports[i].mmal->type == MMAL_PORT_TYPE_OUTPUT)
1285 component->ports[i].direction = OMX_DirOutput;
1286 component->ports[i].index = i;
1287 component->ports[i].enabled = MMAL_TRUE;
1288 component->ports[i].pool =
1289 mmal_port_pool_create(component->ports[i].mmal, 0, 0);
1290 if (!component->ports[i].pool)
1292 component->ports[i].mmal->userdata = (struct MMAL_PORT_USERDATA_T *)&component->ports[i];
1294 mmal_component->control->userdata = (struct MMAL_PORT_USERDATA_T *)component;
1296 /* Create our OMX commands queue */
1297 component->cmd_queue = mmal_queue_create();
1298 if (!component->cmd_queue)
1300 component->cmd_pool = mmal_pool_create(MAX_CMD_BUFFERS, 0);
1301 if (!component->cmd_pool)
1304 if (component->cmd_thread_used &&
1305 vcos_semaphore_create(&component->cmd_sema,
1306 "mmalomx sema", 0) != VCOS_SUCCESS)
1308 component->cmd_thread_used = MMAL_FALSE;
1312 if (component->cmd_thread_used &&
1313 vcos_thread_create(&component->cmd_thread, component->name, NULL,
1314 mmalomx_cmd_thread_func, component) != VCOS_SUCCESS)
1316 vcos_semaphore_delete(&component->cmd_sema);
1317 component->cmd_thread_used = MMAL_FALSE;
1321 /* Set the function pointer for the component's interface */
1322 component->omx.GetComponentVersion = mmalomx_ComponentGetComponentVersion;
1323 component->omx.SendCommand = mmalomx_ComponentSendCommand;
1324 component->omx.GetParameter = mmalomx_ComponentGetParameter;
1325 component->omx.SetParameter = mmalomx_ComponentSetParameter;
1326 component->omx.GetConfig = mmalomx_ComponentGetConfig;
1327 component->omx.SetConfig = mmalomx_ComponentSetConfig;
1328 component->omx.GetExtensionIndex = mmalomx_ComponentGetExtensionIndex;
1329 component->omx.GetState = mmalomx_ComponentGetState;
1330 component->omx.ComponentTunnelRequest = mmalomx_ComponentTunnelRequest;
1331 component->omx.UseBuffer = mmalomx_ComponentUseBuffer;
1332 component->omx.AllocateBuffer = mmalomx_ComponentAllocateBuffer;
1333 component->omx.FreeBuffer = mmalomx_ComponentFreeBuffer;
1334 component->omx.EmptyThisBuffer = mmalomx_ComponentEmptyThisBuffer;
1335 component->omx.FillThisBuffer = mmalomx_ComponentFillThisBuffer;
1336 component->omx.SetCallbacks = mmalomx_ComponentSetCallbacks;
1337 component->omx.ComponentDeInit = mmalomx_ComponentDeInit;
1338 component->omx.UseEGLImage = mmalomx_ComponentUseEGLImage;
1339 component->omx.ComponentRoleEnum = mmalomx_ComponentRoleEnum;
1340 *pHandle = (OMX_HANDLETYPE)&component->omx;
1342 return OMX_ErrorNone;
1345 MMALOMX_IMPORT(OMX_FreeHandle)((OMX_HANDLETYPE)&component->omx);
1349 /*****************************************************************************/
1350 OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_FreeHandle)(
1351 OMX_HANDLETYPE hComponent)
1353 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent;
1354 OMX_ERRORTYPE status;
1357 LOG_TRACE("hComponent %p", hComponent);
1361 return OMX_ErrorInvalidComponent;
1363 if (component->omx.ComponentDeInit)
1365 status = component->omx.ComponentDeInit(hComponent);
1366 if (status != OMX_ErrorNone)
1368 LOG_ERROR("ComponentDeInit failed");
1373 if (component->cmd_thread_used)
1375 component->cmd_thread_used = MMAL_FALSE;
1376 vcos_semaphore_post(&component->cmd_sema);
1377 vcos_thread_join(&component->cmd_thread, NULL);
1380 mmal_component_destroy(component->mmal);
1381 for (i = 0; i < component->ports_num; i++)
1382 if (component->ports[i].pool)
1383 mmal_pool_destroy(component->ports[i].pool);
1385 if (component->cmd_pool)
1386 mmal_pool_destroy(component->cmd_pool);
1387 if (component->cmd_queue)
1388 mmal_queue_destroy(component->cmd_queue);
1389 if (component->cmd_thread_used)
1390 vcos_semaphore_delete(&component->cmd_sema);
1391 vcos_mutex_delete(&component->lock_port);
1392 vcos_mutex_delete(&component->lock);
1394 return OMX_ErrorNone;
1397 /*****************************************************************************/
1398 OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetRolesOfComponent)(
1399 OMX_STRING compName,
1403 OMX_U32 i, num_roles;
1404 MMALOMX_ROLE_T role;
1407 LOG_TRACE("compName %s, pNumRoles %p, roles %p", compName, pNumRoles, roles);
1410 if (!compName || !pNumRoles)
1411 return OMX_ErrorBadParameter;
1413 if (!roles || *pNumRoles > MMALOMX_MAX_ROLES)
1414 num_roles = MMALOMX_MAX_ROLES;
1416 num_roles = *pNumRoles;
1419 /* Find component */
1420 registry_id = mmalomx_registry_find_component(compName);
1421 if (registry_id < 0)
1422 return OMX_ErrorComponentNotFound;
1424 /* Enumerate Roles */
1425 for (i = 0; i < num_roles; i++)
1427 role = mmalomx_registry_component_roles(registry_id, i);
1428 if (!role || !mmalomx_role_to_name(role))
1433 strncpy((char *)roles[i], mmalomx_role_to_name(role), OMX_MAX_STRINGNAME_SIZE);
1434 LOG_DEBUG("found role: %s", roles[i]);
1437 LOG_DEBUG("found %i roles", (int)i);
1440 return OMX_ErrorNone;
1443 /*****************************************************************************/
1444 OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetComponentsOfRole)(
1449 OMX_ERRORTYPE status;
1450 OMX_HANDLETYPE handle;
1451 OMX_COMPONENTTYPE *comp;
1452 OMX_U8 name[OMX_MAX_STRINGNAME_SIZE], compRole[OMX_MAX_STRINGNAME_SIZE];
1453 OMX_U32 nNameLength = OMX_MAX_STRINGNAME_SIZE, nIndex = 0;
1454 OMX_U32 nRoles, nIndexRoles, nComps = 0;
1455 OMX_CALLBACKTYPE callbacks = {0,0,0};
1457 LOG_TRACE("role %s, pNumComps %p, compNames %p", role, pNumComps, compNames);
1460 if (!role || !pNumComps)
1461 return OMX_ErrorBadParameter;
1463 /* Enumerates components */
1464 while ((status = OMX_ComponentNameEnum((OMX_STRING)name, nNameLength,
1465 nIndex++)) == OMX_ErrorNone)
1467 /* Find component */
1468 status = MMALOMX_IMPORT(OMX_GetHandle)(&handle, (OMX_STRING)name, 0, &callbacks);
1469 if(status != OMX_ErrorNone) continue;
1470 comp = (OMX_COMPONENTTYPE *)handle;
1472 /* Enumerate Roles */
1473 status = MMALOMX_IMPORT(OMX_GetRolesOfComponent)((OMX_STRING)name, &nRoles, 0);
1474 if(status != OMX_ErrorNone) continue;
1476 for (nIndexRoles = 0; nIndexRoles < nRoles; nIndexRoles++)
1478 status = comp->ComponentRoleEnum(handle, compRole, nIndexRoles);
1479 if(status != OMX_ErrorNone) break;
1481 if(!strncmp((char *)role, (char *)compRole, OMX_MAX_STRINGNAME_SIZE))
1486 if(!compNames) break;
1488 /* Check if enough space was provided for all the component names */
1489 if(nComps > *pNumComps) return OMX_ErrorBadParameter;
1491 strncpy((char *)compNames[nComps-1], (char *)name, OMX_MAX_STRINGNAME_SIZE);
1493 LOG_DEBUG("found component: %s", name);
1497 MMALOMX_IMPORT(OMX_FreeHandle)(handle);
1499 LOG_DEBUG("found %i components", (int)nComps);
1500 *pNumComps = nComps;
1502 return OMX_ErrorNone;
1505 /*****************************************************************************/
1506 OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_SetupTunnel)(
1507 OMX_HANDLETYPE hOutput,
1508 OMX_U32 nPortOutput,
1509 OMX_HANDLETYPE hInput,
1512 OMX_TUNNELSETUPTYPE tunnel_setup = {0, OMX_BufferSupplyUnspecified};
1513 OMX_ERRORTYPE status = OMX_ErrorNone;
1515 LOG_TRACE("hOutput %p, nPortOutput %d, hInput %p, nPortInput %d",
1516 hOutput, (int)nPortOutput, hInput, (int)nPortInput);
1519 if (!hOutput && !hInput)
1520 return OMX_ErrorBadParameter;
1524 status = ((OMX_COMPONENTTYPE *)hOutput)->ComponentTunnelRequest(
1525 hOutput, nPortOutput, hInput, nPortInput, &tunnel_setup);
1526 if (status != OMX_ErrorNone)
1527 LOG_DEBUG("OMX_SetupTunnel failed on output port (%i)", status);
1530 if (status == OMX_ErrorNone && hInput)
1532 status = ((OMX_COMPONENTTYPE *)hInput)->ComponentTunnelRequest(
1533 hInput, nPortInput, hOutput, nPortOutput, &tunnel_setup);
1534 if (status != OMX_ErrorNone)
1536 LOG_DEBUG("OMX_SetupTunnel failed on input port (%i)", status);
1537 /* Cancel request on output port */
1539 ((OMX_COMPONENTTYPE *)hOutput)->ComponentTunnelRequest(
1540 hOutput, nPortOutput, NULL, 0, NULL);
1547 OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetContentPipe)(
1548 OMX_HANDLETYPE *hPipe,
1551 MMAL_PARAM_UNUSED(hPipe);
1552 MMAL_PARAM_UNUSED(szURI);
1554 LOG_TRACE("hPipe %p, szURI %s", hPipe, szURI);
1556 return OMX_ErrorNotImplemented;
1559 /*****************************************************************************
1561 *****************************************************************************/
1562 static void *mmalomx_cmd_thread_func(void *arg)
1564 MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)arg;
1565 VCOS_STATUS_T status;
1567 while (component->cmd_thread_used)
1569 status = vcos_semaphore_wait(&component->cmd_sema);
1570 if (status == VCOS_EAGAIN)
1572 mmalomx_commands_actions_check(component);