1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
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. |
15 | |
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. |
26 | */ |
27 | |
28 | #include "interface/vmcs_host/khronos/IL/OMX_Broadcom.h" |
29 | #include "mmalomx.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" |
36 | |
37 | #include <util/mmal_util.h> |
38 | #include <util/mmal_util_params.h> |
39 | #include <string.h> |
40 | #include <stdio.h> |
41 | |
42 | #define MAX_CMD_BUFFERS 5 |
43 | |
44 | #define PARAM_GET_PORT(port, component, index) \ |
45 | if (index >= component->ports_num) return OMX_ErrorBadPortIndex; \ |
46 | port = &component->ports[index] |
47 | |
48 | static void *mmalomx_cmd_thread_func(void *arg); |
49 | #define MMALOMX_ZERO_COPY_THRESHOLD 256 |
50 | |
51 | /*****************************************************************************/ |
52 | OMX_ERRORTYPE mmalomx_callback_event_handler( |
53 | MMALOMX_COMPONENT_T *component, |
54 | OMX_EVENTTYPE eEvent, |
55 | OMX_U32 nData1, |
56 | OMX_U32 nData2, |
57 | OMX_PTR pEventData) |
58 | { |
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); |
63 | } |
64 | |
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) |
72 | { |
73 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
74 | const char *short_name, *prefix; |
75 | |
76 | LOG_TRACE("hComponent %p, componentName %p, componentVersion %p, " |
77 | "pSpecVersion %p, componentUUID %p" , |
78 | hComponent, pComponentName, pComponentVersion, pSpecVersion, |
79 | pComponentUUID); |
80 | |
81 | /* Sanity checks */ |
82 | if (!hComponent) |
83 | return OMX_ErrorInvalidComponent; |
84 | if (component->state == OMX_StateInvalid) |
85 | return OMX_ErrorInvalidState; |
86 | if (!pComponentName || !pComponentVersion || !pSpecVersion || !pComponentUUID ) |
87 | return OMX_ErrorBadParameter; |
88 | |
89 | short_name = mmalomx_registry_component_name(component->registry_id, &prefix); |
90 | |
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); |
95 | |
96 | return OMX_ErrorNone; |
97 | } |
98 | |
99 | /*****************************************************************************/ |
100 | static OMX_ERRORTYPE mmalomx_ComponentSendCommand( |
101 | OMX_HANDLETYPE hComponent, |
102 | OMX_COMMANDTYPE Cmd, |
103 | OMX_U32 nParam1, |
104 | OMX_PTR pCmdData) |
105 | { |
106 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
107 | OMX_ERRORTYPE status = OMX_ErrorNone; |
108 | |
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) : "" , |
112 | pCmdData); |
113 | |
114 | /* Sanity checks */ |
115 | if (!hComponent) |
116 | return OMX_ErrorInvalidComponent; |
117 | if (component->state == OMX_StateInvalid) |
118 | return OMX_ErrorInvalidState; |
119 | |
120 | /* Sanity check port index */ |
121 | if (Cmd == OMX_CommandFlush || Cmd == OMX_CommandMarkBuffer || |
122 | Cmd == OMX_CommandPortEnable || Cmd == OMX_CommandPortDisable) |
123 | { |
124 | if (nParam1 != OMX_ALL && nParam1 >= component->ports_num) |
125 | return OMX_ErrorBadPortIndex; |
126 | } |
127 | |
128 | if (Cmd == OMX_CommandStateSet || |
129 | Cmd == OMX_CommandFlush || |
130 | Cmd == OMX_CommandPortEnable || |
131 | Cmd == OMX_CommandPortDisable) |
132 | { |
133 | status = mmalomx_command_queue(component, Cmd, nParam1); |
134 | } |
135 | else if (Cmd == OMX_CommandMarkBuffer) |
136 | { |
137 | status = mmalomx_command_port_mark(hComponent, nParam1, pCmdData); |
138 | } |
139 | else |
140 | { |
141 | status = OMX_ErrorNotImplemented; |
142 | } |
143 | |
144 | return status; |
145 | } |
146 | |
147 | /*****************************************************************************/ |
148 | static MMAL_STATUS_T mmalomx_get_port_settings(MMALOMX_PORT_T *port, OMX_PARAM_PORTDEFINITIONTYPE *def) |
149 | { |
150 | MMAL_STATUS_T status = MMAL_SUCCESS; |
151 | MMAL_PORT_T *mmal = port->mmal; |
152 | |
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; |
157 | |
158 | if (def->eDomain == OMX_PortDomainVideo) |
159 | { |
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); |
164 | |
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; |
183 | else |
184 | def->format.video.xFramerate = 0; |
185 | } |
186 | else if (def->eDomain == OMX_PortDomainImage) |
187 | { |
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; |
208 | } |
209 | else if(def->eDomain == OMX_PortDomainAudio) |
210 | { |
211 | def->format.audio.eEncoding = mmalil_encoding_to_omx_audio_coding(mmal->format->encoding); |
212 | } |
213 | else |
214 | { |
215 | LOG_ERROR("%s: unsupported domain (%u)" , mmal->name, def->eDomain); |
216 | status = MMAL_EINVAL; |
217 | goto finish; |
218 | } |
219 | |
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; |
228 | |
229 | finish: |
230 | return status; |
231 | } |
232 | |
233 | /*****************************************************************************/ |
234 | static OMX_ERRORTYPE mmalomx_ComponentGetParameter( |
235 | OMX_HANDLETYPE hComponent, |
236 | OMX_INDEXTYPE nParamIndex, |
237 | OMX_PTR pParam) |
238 | { |
239 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
240 | MMALOMX_PORT_T *port = NULL; |
241 | |
242 | LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p" , |
243 | hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam); |
244 | |
245 | /* Sanity checks */ |
246 | if (!hComponent) |
247 | return OMX_ErrorInvalidComponent; |
248 | if (!pParam) |
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; |
254 | |
255 | switch(nParamIndex) |
256 | { |
257 | case OMX_IndexParamAudioInit: |
258 | case OMX_IndexParamVideoInit: |
259 | case OMX_IndexParamImageInit: |
260 | case OMX_IndexParamOtherInit: |
261 | { |
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]; |
277 | } |
278 | return OMX_ErrorNone; |
279 | break; |
280 | case OMX_IndexParamPortDefinition: |
281 | { |
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)); |
285 | } |
286 | return OMX_ErrorNone; |
287 | break; |
288 | case OMX_IndexParamCompBufferSupplier: |
289 | { |
290 | OMX_PARAM_BUFFERSUPPLIERTYPE *param = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParam; |
291 | PARAM_GET_PORT(port, component, param->nPortIndex); |
292 | param->eBufferSupplier = OMX_BufferSupplyUnspecified; |
293 | } |
294 | return OMX_ErrorNone; |
295 | break; |
296 | case OMX_IndexParamPriorityMgmt: |
297 | { |
298 | OMX_PRIORITYMGMTTYPE *param = (OMX_PRIORITYMGMTTYPE *)pParam; |
299 | param->nGroupPriority = component->group_priority; |
300 | param->nGroupID = component->group_id; |
301 | } |
302 | return OMX_ErrorNone; |
303 | break; |
304 | case OMX_IndexParamVideoPortFormat: |
305 | case OMX_IndexParamAudioPortFormat: |
306 | { |
307 | OMX_VIDEO_PARAM_PORTFORMATTYPE *param = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pParam; |
308 | PARAM_GET_PORT(port, component, param->nPortIndex); |
309 | |
310 | /* Populate our internal list of encodings the first time around */ |
311 | if (!port->encodings_num) |
312 | { |
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) |
316 | { |
317 | port->encodings_num = (port->encodings_header.size - sizeof(port->encodings_header)) / |
318 | sizeof(port->encodings[0]); |
319 | } |
320 | if (!port->encodings_num) |
321 | { |
322 | port->encodings_num = 1; |
323 | port->encodings[0] = port->mmal->format->encoding; |
324 | } |
325 | } |
326 | |
327 | if (param->nIndex >= port->encodings_num) |
328 | return OMX_ErrorNoMore; |
329 | |
330 | if (nParamIndex == OMX_IndexParamVideoPortFormat) |
331 | { |
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; |
339 | } |
340 | else |
341 | { |
342 | OMX_AUDIO_PARAM_PORTFORMATTYPE *aparam = |
343 | (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pParam; |
344 | aparam->eEncoding = |
345 | mmalil_encoding_to_omx_audio_coding(port->encodings[param->nIndex]); |
346 | } |
347 | return OMX_ErrorNone; |
348 | } |
349 | break; |
350 | case OMX_IndexParamImagePortFormat: |
351 | case OMX_IndexParamOtherPortFormat: |
352 | break; |
353 | case OMX_IndexParamStandardComponentRole: |
354 | { |
355 | OMX_PARAM_COMPONENTROLETYPE *param = (OMX_PARAM_COMPONENTROLETYPE *)pParam; |
356 | const char *role = mmalomx_role_to_name(component->role); |
357 | if (!role) |
358 | role = component->name; |
359 | snprintf((char *)param->cRole, sizeof(param->cRole), "%s" , role); |
360 | } |
361 | return OMX_ErrorNone; |
362 | default: |
363 | return mmalomx_parameter_get(component, nParamIndex, pParam); |
364 | } |
365 | |
366 | return OMX_ErrorNotImplemented; |
367 | } |
368 | |
369 | /*****************************************************************************/ |
370 | static MMAL_STATUS_T mmalomx_set_port_settings(MMALOMX_PORT_T *mmalomx_port, |
371 | OMX_PARAM_PORTDEFINITIONTYPE *def) |
372 | { |
373 | MMAL_PORT_T *port = mmalomx_port->mmal; |
374 | uint32_t buffer_size_min = port->buffer_size_min; |
375 | MMAL_STATUS_T status; |
376 | |
377 | port->format->type = mmalil_omx_domain_to_es_type(def->eDomain); |
378 | port->format->encoding_variant = 0; |
379 | |
380 | if(def->eDomain == OMX_PortDomainVideo) |
381 | { |
382 | if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused) |
383 | port->format->encoding = mmalil_omx_video_coding_to_encoding(def->format.video.eCompressionFormat); |
384 | else |
385 | port->format->encoding = mmalil_omx_color_format_to_encoding(def->format.video.eColorFormat); |
386 | |
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); |
401 | } |
402 | else if(def->eDomain == OMX_PortDomainImage) |
403 | { |
404 | if (def->format.image.eCompressionFormat != OMX_IMAGE_CodingUnused) |
405 | port->format->encoding = mmalil_omx_image_coding_to_encoding(def->format.image.eCompressionFormat); |
406 | else |
407 | port->format->encoding = mmalil_omx_color_format_to_encoding(def->format.image.eColorFormat); |
408 | |
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; |
420 | } |
421 | else if(def->eDomain == OMX_PortDomainAudio) |
422 | { |
423 | port->format->encoding = mmalil_omx_audio_coding_to_encoding(def->format.audio.eEncoding); |
424 | } |
425 | else |
426 | { |
427 | port->format->encoding = MMAL_ENCODING_UNKNOWN; |
428 | } |
429 | |
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; |
434 | |
435 | status = mmal_port_format_commit(port); |
436 | if (status != MMAL_SUCCESS) |
437 | return status; |
438 | |
439 | /* Acknowledge any ongoing port format changed event */ |
440 | mmalomx_port->format_changed = MMAL_FALSE; |
441 | |
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; |
446 | |
447 | return MMAL_SUCCESS; |
448 | } |
449 | |
450 | /*****************************************************************************/ |
451 | static OMX_ERRORTYPE mmalomx_ComponentSetParameter( |
452 | OMX_HANDLETYPE hComponent, |
453 | OMX_INDEXTYPE nParamIndex, |
454 | OMX_PTR pParam) |
455 | { |
456 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
457 | MMALOMX_PORT_T *port = NULL; |
458 | |
459 | LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p" , |
460 | hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam); |
461 | |
462 | /* Sanity checks */ |
463 | if (!hComponent) |
464 | return OMX_ErrorInvalidComponent; |
465 | if (!pParam) |
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; |
471 | |
472 | switch(nParamIndex) |
473 | { |
474 | case OMX_IndexParamPortDefinition: |
475 | { |
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)); |
479 | } |
480 | return OMX_ErrorNone; |
481 | break; |
482 | case OMX_IndexParamCompBufferSupplier: |
483 | { |
484 | OMX_PARAM_BUFFERSUPPLIERTYPE *param = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParam; |
485 | PARAM_GET_PORT(port, component, param->nPortIndex); |
486 | //param->eBufferSupplier = OMX_BufferSupplyUnspecified; |
487 | } |
488 | return OMX_ErrorNone; |
489 | break; |
490 | case OMX_IndexParamPriorityMgmt: |
491 | { |
492 | OMX_PRIORITYMGMTTYPE *param = (OMX_PRIORITYMGMTTYPE *)pParam; |
493 | |
494 | if (component->state != OMX_StateLoaded) |
495 | return OMX_ErrorIncorrectStateOperation; |
496 | |
497 | component->group_priority = param->nGroupPriority; |
498 | component->group_id = param->nGroupID; |
499 | } |
500 | return OMX_ErrorNone; |
501 | break; |
502 | case OMX_IndexParamAudioPortFormat: |
503 | { |
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; |
511 | } |
512 | break; |
513 | case OMX_IndexParamVideoPortFormat: |
514 | { |
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); |
519 | else |
520 | port->mmal->format->encoding = mmalil_omx_color_format_to_encoding(param->eColorFormat); |
521 | port->mmal->format->encoding_variant = 0; |
522 | |
523 | if (mmal_port_format_commit(port->mmal) != MMAL_SUCCESS) |
524 | LOG_ERROR("OMX_IndexParamAudioPortFormat commit failed" ); |
525 | return OMX_ErrorNone; |
526 | } |
527 | break; |
528 | case OMX_IndexParamImagePortFormat: |
529 | case OMX_IndexParamOtherPortFormat: |
530 | break; |
531 | case OMX_IndexParamStandardComponentRole: |
532 | { |
533 | OMX_PARAM_COMPONENTROLETYPE *param = (OMX_PARAM_COMPONENTROLETYPE *)pParam; |
534 | return mmalomx_role_set(component, (const char *)param->cRole); |
535 | } |
536 | break; |
537 | default: |
538 | { |
539 | OMX_ERRORTYPE status = mmalomx_parameter_set(component, nParamIndex, pParam); |
540 | |
541 | /* Keep track of the zero-copy state */ |
542 | if (status == OMX_ErrorNone && nParamIndex == OMX_IndexParamBrcmZeroCopy) |
543 | { |
544 | PARAM_GET_PORT(port, component, ((OMX_CONFIG_PORTBOOLEANTYPE *)pParam)->nPortIndex); |
545 | port->zero_copy = ((OMX_CONFIG_PORTBOOLEANTYPE *)pParam)->bEnabled; |
546 | } |
547 | |
548 | return status; |
549 | } |
550 | } |
551 | |
552 | return OMX_ErrorNotImplemented; |
553 | } |
554 | |
555 | /*****************************************************************************/ |
556 | static OMX_ERRORTYPE mmalomx_ComponentGetConfig( |
557 | OMX_HANDLETYPE hComponent, |
558 | OMX_INDEXTYPE nParamIndex, |
559 | OMX_PTR pParam) |
560 | { |
561 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
562 | |
563 | LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p" , |
564 | hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam); |
565 | |
566 | /* Sanity checks */ |
567 | if (!hComponent) |
568 | return OMX_ErrorInvalidComponent; |
569 | if (!pParam) |
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; |
575 | |
576 | return mmalomx_parameter_get(component, nParamIndex, pParam); |
577 | } |
578 | |
579 | /*****************************************************************************/ |
580 | static OMX_ERRORTYPE mmalomx_ComponentSetConfig( |
581 | OMX_HANDLETYPE hComponent, |
582 | OMX_INDEXTYPE nParamIndex, |
583 | OMX_PTR pParam) |
584 | { |
585 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
586 | |
587 | LOG_TRACE("hComponent %p, nParamIndex 0x%x (%s), pParam %p" , |
588 | hComponent, nParamIndex, mmalomx_param_to_string(nParamIndex), pParam); |
589 | |
590 | /* Sanity checks */ |
591 | if (!hComponent) |
592 | return OMX_ErrorInvalidComponent; |
593 | if (!pParam) |
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; |
599 | |
600 | return mmalomx_parameter_set(component, nParamIndex, pParam); |
601 | } |
602 | |
603 | /*****************************************************************************/ |
604 | static OMX_ERRORTYPE mmalomx_ComponentGetExtensionIndex( |
605 | OMX_HANDLETYPE hComponent, |
606 | OMX_STRING cParameterName, |
607 | OMX_INDEXTYPE* pIndexType) |
608 | { |
609 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
610 | |
611 | LOG_TRACE("hComponent %p, cParameterName %s, pIndexType %p" , |
612 | hComponent, cParameterName, pIndexType); |
613 | |
614 | /* Sanity checks */ |
615 | if (!hComponent) |
616 | return OMX_ErrorInvalidComponent; |
617 | if (component->state == OMX_StateInvalid) |
618 | return OMX_ErrorInvalidState; |
619 | |
620 | return mmalomx_parameter_extension_index_get(cParameterName, pIndexType); |
621 | } |
622 | |
623 | /*****************************************************************************/ |
624 | static OMX_ERRORTYPE mmalomx_ComponentGetState( |
625 | OMX_HANDLETYPE hComponent, |
626 | OMX_STATETYPE* pState) |
627 | { |
628 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
629 | MMAL_PARAM_UNUSED(component); |
630 | |
631 | LOG_TRACE("hComponent %p, pState, %p" , hComponent, pState); |
632 | |
633 | /* Sanity checks */ |
634 | if (!hComponent) |
635 | return OMX_ErrorInvalidComponent; |
636 | if (!pState) |
637 | return OMX_ErrorBadParameter; |
638 | |
639 | *pState = component->state; |
640 | return OMX_ErrorNone; |
641 | } |
642 | |
643 | /*****************************************************************************/ |
644 | static OMX_ERRORTYPE mmalomx_ComponentTunnelRequest( |
645 | OMX_HANDLETYPE hComponent, |
646 | OMX_U32 nPort, |
647 | OMX_HANDLETYPE hTunneledComp, |
648 | OMX_U32 nTunneledPort, |
649 | OMX_TUNNELSETUPTYPE* pTunnelSetup) |
650 | { |
651 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
652 | MMAL_PARAM_UNUSED(component); |
653 | |
654 | LOG_TRACE("hComponent %p, nPort %i, hTunneledComp %p, nTunneledPort %i, " |
655 | "pTunnelSetup %p" , hComponent, (int)nPort, hTunneledComp, |
656 | (int)nTunneledPort, pTunnelSetup); |
657 | |
658 | /* Sanity checks */ |
659 | if (!hComponent) |
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; |
669 | |
670 | if (!hTunneledComp) |
671 | return OMX_ErrorNone; |
672 | return OMX_ErrorNotImplemented; |
673 | } |
674 | |
675 | /*****************************************************************************/ |
676 | static OMX_ERRORTYPE mmalomx_ComponentUseBuffer( |
677 | OMX_HANDLETYPE hComponent, |
678 | OMX_BUFFERHEADERTYPE** ppBuffer, |
679 | OMX_U32 nPortIndex, |
680 | OMX_PTR pAppPrivate, |
681 | OMX_U32 nSizeBytes, |
682 | OMX_U8* pBuffer) |
683 | { |
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; |
689 | |
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); |
693 | |
694 | /* Sanity checks */ |
695 | if (!hComponent) |
696 | return OMX_ErrorInvalidComponent; |
697 | if (!ppBuffer) |
698 | return OMX_ErrorBadParameter; |
699 | if (component->state == OMX_StateInvalid) |
700 | return OMX_ErrorInvalidState; |
701 | if (nPortIndex >= component->ports_num) |
702 | return OMX_ErrorBadPortIndex; |
703 | |
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); |
708 | |
709 | port = &component->ports[nPortIndex]; |
710 | MMALOMX_LOCK_PORT(component, port); |
711 | |
712 | if (!(port->actions & MMALOMX_ACTION_CHECK_ALLOCATED)) |
713 | status = OMX_ErrorIncorrectStateOperation; |
714 | if (port->populated) |
715 | status = OMX_ErrorIncorrectStateOperation; |
716 | if (status != OMX_ErrorNone) |
717 | goto error; |
718 | |
719 | /* Check for mismatched calls to UseBuffer/AllocateBuffer */ |
720 | if (port->buffers && port->buffers_allocated) |
721 | { |
722 | status = OMX_ErrorBadParameter; |
723 | goto error; |
724 | } |
725 | |
726 | /* Sanity check buffer size */ |
727 | if (nSizeBytes < port->mmal->buffer_size_min) |
728 | { |
729 | LOG_ERROR("buffer size too small (%i/%i)" , (int)nSizeBytes, |
730 | (int)port->mmal->buffer_size_min); |
731 | status = OMX_ErrorBadParameter; |
732 | goto error; |
733 | } |
734 | if (!port->buffers) |
735 | port->mmal->buffer_size = nSizeBytes; |
736 | if (nSizeBytes > port->mmal->buffer_size) |
737 | { |
738 | LOG_ERROR("buffer size too big (%i/%i)" , (int)nSizeBytes, |
739 | (int)port->mmal->buffer_size); |
740 | status = OMX_ErrorBadParameter; |
741 | goto error; |
742 | } |
743 | |
744 | buffer = calloc( 1, sizeof(*buffer) ); |
745 | if (!buffer) |
746 | { |
747 | status = OMX_ErrorInsufficientResources; |
748 | goto error; |
749 | } |
750 | |
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) |
757 | { |
758 | buffer->nInputPortIndex = nPortIndex; |
759 | buffer->pOutputPortPrivate = pAppPrivate; |
760 | } |
761 | else |
762 | { |
763 | buffer->nOutputPortIndex = nPortIndex; |
764 | buffer->pInputPortPrivate = pAppPrivate; |
765 | } |
766 | |
767 | *ppBuffer = buffer; |
768 | port->buffers++; |
769 | port->buffers_allocated = MMAL_FALSE; |
770 | port->populated = populated = port->buffers == port->mmal->buffer_num; |
771 | |
772 | MMALOMX_UNLOCK_PORT(component, port); |
773 | |
774 | LOG_DEBUG("allocated %i/%i buffers" , port->buffers, port->mmal->buffer_num); |
775 | |
776 | if (populated) |
777 | mmalomx_commands_actions_signal(component); |
778 | |
779 | return OMX_ErrorNone; |
780 | |
781 | error: |
782 | MMALOMX_UNLOCK_PORT(component, port); |
783 | return status; |
784 | } |
785 | |
786 | /*****************************************************************************/ |
787 | static OMX_ERRORTYPE mmalomx_ComponentAllocateBuffer( |
788 | OMX_HANDLETYPE hComponent, |
789 | OMX_BUFFERHEADERTYPE** ppBuffer, |
790 | OMX_U32 nPortIndex, |
791 | OMX_PTR pAppPrivate, |
792 | OMX_U32 nSizeBytes) |
793 | { |
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; |
799 | |
800 | LOG_TRACE("hComponent %p, ppBuffer %p, nPortIndex %i, pAppPrivate %p, " |
801 | "nSizeBytes %i" , hComponent, ppBuffer, (int)nPortIndex, |
802 | pAppPrivate, (int)nSizeBytes); |
803 | |
804 | /* Sanity checks */ |
805 | if (!hComponent) |
806 | return OMX_ErrorInvalidComponent; |
807 | if (!ppBuffer) |
808 | return OMX_ErrorBadParameter; |
809 | if (component->state == OMX_StateInvalid) |
810 | return OMX_ErrorInvalidState; |
811 | if (nPortIndex >= component->ports_num) |
812 | return OMX_ErrorBadPortIndex; |
813 | |
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); |
818 | |
819 | port = &component->ports[nPortIndex]; |
820 | MMALOMX_LOCK_PORT(component, port); |
821 | |
822 | if (!(port->actions & MMALOMX_ACTION_CHECK_ALLOCATED)) |
823 | status = OMX_ErrorIncorrectStateOperation; |
824 | if (port->populated) |
825 | status = OMX_ErrorIncorrectStateOperation; |
826 | if (status != OMX_ErrorNone) |
827 | goto error; |
828 | |
829 | /* Check for mismatched calls to UseBuffer/AllocateBuffer */ |
830 | if (!status && port->buffers && !port->buffers_allocated) |
831 | { |
832 | status = OMX_ErrorBadParameter; |
833 | goto error; |
834 | } |
835 | |
836 | /* Sanity check buffer size */ |
837 | if (nSizeBytes < port->mmal->buffer_size_min) |
838 | { |
839 | LOG_ERROR("buffer size too small (%i/%i)" , (int)nSizeBytes, |
840 | (int)port->mmal->buffer_size_min); |
841 | status = OMX_ErrorBadParameter; |
842 | goto error; |
843 | } |
844 | if (!port->buffers) |
845 | port->mmal->buffer_size = nSizeBytes; |
846 | if (nSizeBytes > port->mmal->buffer_size) |
847 | { |
848 | LOG_ERROR("buffer size too big (%i/%i)" , (int)nSizeBytes, |
849 | (int)port->mmal->buffer_size); |
850 | status = OMX_ErrorBadParameter; |
851 | goto error; |
852 | } |
853 | |
854 | /* Set the zero-copy mode */ |
855 | if (!port->buffers_allocated && nSizeBytes > MMALOMX_ZERO_COPY_THRESHOLD && |
856 | !port->zero_copy) |
857 | { |
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); |
862 | } |
863 | |
864 | buffer = calloc( 1, sizeof(*buffer) ); |
865 | if (!buffer) |
866 | { |
867 | status = OMX_ErrorInsufficientResources; |
868 | goto error; |
869 | } |
870 | |
871 | buffer->pBuffer = mmal_port_payload_alloc(port->mmal, nSizeBytes); |
872 | if (!buffer->pBuffer) |
873 | { |
874 | status = OMX_ErrorInsufficientResources; |
875 | goto error; |
876 | } |
877 | |
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) |
883 | { |
884 | buffer->nInputPortIndex = nPortIndex; |
885 | buffer->pOutputPortPrivate = pAppPrivate; |
886 | } |
887 | else |
888 | { |
889 | buffer->nOutputPortIndex = nPortIndex; |
890 | buffer->pInputPortPrivate = pAppPrivate; |
891 | } |
892 | /* Keep an unmodified copy of the pointer for when we come to free it */ |
893 | buffer->pPlatformPrivate = (OMX_PTR)buffer->pBuffer; |
894 | |
895 | *ppBuffer = buffer; |
896 | port->buffers++; |
897 | port->buffers_allocated = MMAL_TRUE; |
898 | port->populated = populated = port->buffers == port->mmal->buffer_num; |
899 | |
900 | MMALOMX_UNLOCK_PORT(component, port); |
901 | |
902 | LOG_DEBUG("allocated %i/%i buffers" , port->buffers, port->mmal->buffer_num); |
903 | |
904 | if (populated) |
905 | mmalomx_commands_actions_signal(component); |
906 | |
907 | return OMX_ErrorNone; |
908 | |
909 | error: |
910 | if (!port->buffers_allocated && !port->zero_copy) |
911 | mmal_port_parameter_set_boolean(port->mmal, MMAL_PARAMETER_ZERO_COPY, MMAL_FALSE); |
912 | |
913 | MMALOMX_UNLOCK_PORT(component, port); |
914 | LOG_ERROR("failed to allocate %i/%i buffers" , port->buffers, port->mmal->buffer_num); |
915 | if (buffer) |
916 | free(buffer); |
917 | return status; |
918 | } |
919 | |
920 | /*****************************************************************************/ |
921 | static OMX_ERRORTYPE mmalomx_ComponentFreeBuffer( |
922 | OMX_HANDLETYPE hComponent, |
923 | OMX_U32 nPortIndex, |
924 | OMX_BUFFERHEADERTYPE* pBuffer) |
925 | { |
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; |
931 | |
932 | LOG_TRACE("hComponent %p, nPortIndex %i, pBuffer %p" , |
933 | hComponent, (int)nPortIndex, pBuffer); |
934 | |
935 | /* Sanity checks */ |
936 | if (!hComponent) |
937 | return OMX_ErrorInvalidComponent; |
938 | if (!pBuffer) |
939 | return OMX_ErrorBadParameter; |
940 | if (nPortIndex >= component->ports_num) |
941 | return OMX_ErrorBadPortIndex; |
942 | |
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); |
947 | |
948 | port = &component->ports[nPortIndex]; |
949 | MMALOMX_LOCK_PORT(component, port); |
950 | |
951 | if (!port->buffers) |
952 | { |
953 | status = OMX_ErrorBadParameter; |
954 | goto error; |
955 | } |
956 | |
957 | buffers = --port->buffers; |
958 | port->populated = MMAL_FALSE; |
959 | unpopulated = !(port->actions & MMALOMX_ACTION_CHECK_DEALLOCATED); |
960 | allocated = port->buffers_allocated; |
961 | |
962 | MMALOMX_UNLOCK_PORT(component, port); |
963 | |
964 | if (allocated) /* Free the unmodified pointer */ |
965 | mmal_port_payload_free(port->mmal, pBuffer->pPlatformPrivate); |
966 | free(pBuffer); |
967 | |
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); |
970 | |
971 | LOG_DEBUG("freed %i/%i buffers" , port->mmal->buffer_num - port->buffers, port->mmal->buffer_num); |
972 | |
973 | if (unpopulated) |
974 | mmalomx_callback_event_handler(component, OMX_EventError, OMX_ErrorPortUnpopulated, 0, NULL); |
975 | |
976 | if (!buffers) |
977 | mmalomx_commands_actions_signal(component); |
978 | |
979 | return OMX_ErrorNone; |
980 | |
981 | error: |
982 | MMALOMX_UNLOCK_PORT(component, port); |
983 | return status; |
984 | } |
985 | |
986 | /*****************************************************************************/ |
987 | static OMX_ERRORTYPE mmalomx_ComponentEmptyThisBuffer( |
988 | OMX_HANDLETYPE hComponent, |
989 | OMX_BUFFERHEADERTYPE* pBuffer) |
990 | { |
991 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
992 | |
993 | if (ENABLE_MMAL_EXTRA_LOGGING) |
994 | LOG_TRACE("hComponent %p, port %i, pBuffer %p" , hComponent, |
995 | pBuffer ? (int)pBuffer->nInputPortIndex : -1, pBuffer); |
996 | |
997 | return mmalomx_buffer_send(component, pBuffer, OMX_DirInput); |
998 | } |
999 | |
1000 | /*****************************************************************************/ |
1001 | static OMX_ERRORTYPE mmalomx_ComponentFillThisBuffer( |
1002 | OMX_HANDLETYPE hComponent, |
1003 | OMX_BUFFERHEADERTYPE* pBuffer) |
1004 | { |
1005 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
1006 | |
1007 | if (ENABLE_MMAL_EXTRA_LOGGING) |
1008 | LOG_TRACE("hComponent %p, port %i, pBuffer %p" , hComponent, |
1009 | pBuffer ? (int)pBuffer->nOutputPortIndex : -1, pBuffer); |
1010 | |
1011 | return mmalomx_buffer_send(component, pBuffer, OMX_DirOutput); |
1012 | } |
1013 | |
1014 | /*****************************************************************************/ |
1015 | static OMX_ERRORTYPE mmalomx_ComponentSetCallbacks( |
1016 | OMX_HANDLETYPE hComponent, |
1017 | OMX_CALLBACKTYPE* pCallbacks, |
1018 | OMX_PTR pAppData) |
1019 | { |
1020 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
1021 | MMAL_PARAM_UNUSED(component); |
1022 | |
1023 | LOG_TRACE("hComponent %p, pCallbacks %p, pAppData %p" , |
1024 | hComponent, pCallbacks, pAppData); |
1025 | |
1026 | /* Sanity checks */ |
1027 | if (!hComponent) |
1028 | return OMX_ErrorInvalidComponent; |
1029 | if (!pCallbacks) |
1030 | return OMX_ErrorBadParameter; |
1031 | if (component->state == OMX_StateInvalid) |
1032 | return OMX_ErrorInvalidState; |
1033 | |
1034 | if (component->state != OMX_StateLoaded) |
1035 | return OMX_ErrorInvalidState; |
1036 | |
1037 | component->callbacks = *pCallbacks; |
1038 | component->callbacks_data = pAppData; |
1039 | return OMX_ErrorNone; |
1040 | } |
1041 | |
1042 | /*****************************************************************************/ |
1043 | static OMX_ERRORTYPE mmalomx_ComponentDeInit( |
1044 | OMX_HANDLETYPE hComponent) |
1045 | { |
1046 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
1047 | MMAL_PARAM_UNUSED(component); |
1048 | |
1049 | LOG_TRACE("hComponent %p" , hComponent); |
1050 | |
1051 | /* Sanity checks */ |
1052 | if (!hComponent) |
1053 | return OMX_ErrorInvalidComponent; |
1054 | |
1055 | return OMX_ErrorNone; |
1056 | } |
1057 | |
1058 | /*****************************************************************************/ |
1059 | static OMX_ERRORTYPE mmalomx_ComponentUseEGLImage( |
1060 | OMX_HANDLETYPE hComponent, |
1061 | OMX_BUFFERHEADERTYPE** ppBufferHdr, |
1062 | OMX_U32 nPortIndex, |
1063 | OMX_PTR pAppPrivate, |
1064 | void* eglImage) |
1065 | { |
1066 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
1067 | MMAL_PARAM_UNUSED(component); |
1068 | |
1069 | LOG_TRACE("hComponent %p, ppBufferHdr %p, nPortIndex %i, pAppPrivate %p," |
1070 | " eglImage %p" , hComponent, ppBufferHdr, (int)nPortIndex, |
1071 | pAppPrivate, eglImage); |
1072 | |
1073 | /* Sanity checks */ |
1074 | if (!hComponent) |
1075 | return OMX_ErrorInvalidComponent; |
1076 | if (component->state == OMX_StateInvalid) |
1077 | return OMX_ErrorInvalidState; |
1078 | |
1079 | return OMX_ErrorNotImplemented; |
1080 | } |
1081 | |
1082 | /*****************************************************************************/ |
1083 | static OMX_ERRORTYPE mmalomx_ComponentRoleEnum( |
1084 | OMX_HANDLETYPE hComponent, |
1085 | OMX_U8 *cRole, |
1086 | OMX_U32 nIndex) |
1087 | { |
1088 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
1089 | MMALOMX_ROLE_T role; |
1090 | |
1091 | LOG_TRACE("hComponent %p, cRole %p, nIndex %i" , |
1092 | hComponent, cRole, (int)nIndex); |
1093 | |
1094 | /* Sanity checks */ |
1095 | if (!hComponent) |
1096 | return OMX_ErrorInvalidComponent; |
1097 | if (component->state == OMX_StateInvalid) |
1098 | return OMX_ErrorInvalidState; |
1099 | |
1100 | role = mmalomx_registry_component_roles(component->registry_id, nIndex); |
1101 | if (!role) |
1102 | return OMX_ErrorNoMore; |
1103 | if (!mmalomx_role_to_name(role)) |
1104 | return OMX_ErrorNoMore; |
1105 | |
1106 | strcpy((char *)cRole, mmalomx_role_to_name(role)); |
1107 | return OMX_ErrorNone; |
1108 | } |
1109 | |
1110 | /*****************************************************************************/ |
1111 | OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_Init)(void) |
1112 | { |
1113 | mmalomx_logging_init(); |
1114 | LOG_TRACE("Init" ); |
1115 | return OMX_ErrorNone; |
1116 | } |
1117 | |
1118 | /*****************************************************************************/ |
1119 | OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_Deinit)(void) |
1120 | { |
1121 | LOG_TRACE("Deinit" ); |
1122 | mmalomx_logging_deinit(); |
1123 | return OMX_ErrorNone; |
1124 | } |
1125 | |
1126 | /*****************************************************************************/ |
1127 | OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_ComponentNameEnum)( |
1128 | OMX_STRING cComponentName, |
1129 | OMX_U32 nNameLength, |
1130 | OMX_U32 nIndex) |
1131 | { |
1132 | const char *prefix, *name; |
1133 | name = mmalomx_registry_component_name(nIndex, &prefix); |
1134 | |
1135 | LOG_TRACE("cComponentName %p, nNameLength %i, nIndex %i" , |
1136 | cComponentName, (int)nNameLength, (int)nIndex); |
1137 | |
1138 | /* Sanity checking */ |
1139 | if (!cComponentName) |
1140 | return OMX_ErrorBadParameter; |
1141 | if (!name) |
1142 | return OMX_ErrorNoMore; |
1143 | if (nNameLength <= strlen(name) + strlen(prefix)) |
1144 | return OMX_ErrorBadParameter; |
1145 | |
1146 | sprintf(cComponentName, "%s%s" , prefix, name); |
1147 | LOG_TRACE("cComponentName: %s" , cComponentName); |
1148 | return OMX_ErrorNone; |
1149 | } |
1150 | |
1151 | /*****************************************************************************/ |
1152 | static void mmalomx_buffer_cb_control( |
1153 | MMAL_PORT_T *port, |
1154 | MMAL_BUFFER_HEADER_T *buffer) |
1155 | { |
1156 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)port->userdata; |
1157 | |
1158 | LOG_DEBUG("received event %4.4s on port %s" , (char *)&buffer->cmd, port->name); |
1159 | |
1160 | if (buffer->cmd == MMAL_EVENT_ERROR) |
1161 | { |
1162 | mmalomx_callback_event_handler(component, OMX_EventError, |
1163 | mmalil_error_to_omx(*(MMAL_STATUS_T *)buffer->data), 0, NULL); |
1164 | } |
1165 | else if (buffer->cmd == MMAL_EVENT_EOS && |
1166 | buffer->length == sizeof(MMAL_EVENT_END_OF_STREAM_T)) |
1167 | { |
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) |
1170 | { |
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); |
1176 | } |
1177 | } |
1178 | |
1179 | mmal_buffer_header_release(buffer); |
1180 | } |
1181 | |
1182 | /*****************************************************************************/ |
1183 | OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_GetHandle)( |
1184 | OMX_HANDLETYPE* pHandle, |
1185 | OMX_STRING cComponentName, |
1186 | OMX_PTR pAppData, |
1187 | OMX_CALLBACKTYPE* pCallBacks) |
1188 | { |
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; |
1196 | int registry_id; |
1197 | |
1198 | LOG_TRACE("pHandle %p, cComponentName %s, pAppData %p, pCallBacks %p" , |
1199 | pHandle, cComponentName, pAppData, pCallBacks); |
1200 | |
1201 | /* Sanity check params */ |
1202 | if (!pHandle || !cComponentName || !pCallBacks) |
1203 | return OMX_ErrorBadParameter; |
1204 | |
1205 | /* Find component */ |
1206 | registry_id = mmalomx_registry_find_component(cComponentName); |
1207 | if (registry_id < 0) |
1208 | return OMX_ErrorComponentNotFound; |
1209 | |
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) |
1214 | { |
1215 | LOG_ERROR("could not create mmal component %s" , mmal_name); |
1216 | return mmalil_error_to_omx(mmal_status); |
1217 | } |
1218 | mmal_status = mmal_port_enable(mmal_component->control, mmalomx_buffer_cb_control); |
1219 | if (mmal_status != MMAL_SUCCESS) |
1220 | { |
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); |
1224 | } |
1225 | |
1226 | ports_num = mmal_component->port_num - 1; |
1227 | |
1228 | component = calloc(1, sizeof(*component) + ports_num * sizeof(*component->ports)); |
1229 | if (!component) |
1230 | { |
1231 | mmal_component_destroy(mmal_component); |
1232 | return OMX_ErrorInsufficientResources; |
1233 | } |
1234 | |
1235 | if (vcos_mutex_create(&component->lock, "mmalomx lock" ) != VCOS_SUCCESS) |
1236 | { |
1237 | mmal_component_destroy(mmal_component); |
1238 | free(component); |
1239 | return OMX_ErrorInsufficientResources; |
1240 | } |
1241 | if (vcos_mutex_create(&component->lock_port, "mmalomx port lock" ) != VCOS_SUCCESS) |
1242 | { |
1243 | vcos_mutex_delete(&component->lock); |
1244 | mmal_component_destroy(mmal_component); |
1245 | free(component); |
1246 | return OMX_ErrorInsufficientResources; |
1247 | } |
1248 | |
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); |
1259 | |
1260 | // FIXME: make this configurable |
1261 | component->cmd_thread_used = MMAL_TRUE; |
1262 | |
1263 | /* Sort the ports into separate OMX domains */ |
1264 | for (domain = OMX_PortDomainAudio; domain < OMX_PortDomainOther; domain++) |
1265 | { |
1266 | for (i = 1; i < mmal_component->port_num; i++) |
1267 | { |
1268 | if (domain == mmalil_es_type_to_omx_domain(mmal_component->port[i]->format->type)) |
1269 | { |
1270 | component->ports[component->ports_num].mmal = mmal_component->port[i]; |
1271 | component->ports_domain_num[domain]++; |
1272 | component->ports_num++; |
1273 | } |
1274 | } |
1275 | } |
1276 | LOG_DEBUG("ports: %i audio, %i video" , |
1277 | component->ports_domain_num[OMX_PortDomainAudio], |
1278 | component->ports_domain_num[OMX_PortDomainVideo]); |
1279 | |
1280 | /* Setup our ports */ |
1281 | for (i = 0; i < component->ports_num; i++) |
1282 | { |
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) |
1291 | goto error; |
1292 | component->ports[i].mmal->userdata = (struct MMAL_PORT_USERDATA_T *)&component->ports[i]; |
1293 | } |
1294 | mmal_component->control->userdata = (struct MMAL_PORT_USERDATA_T *)component; |
1295 | |
1296 | /* Create our OMX commands queue */ |
1297 | component->cmd_queue = mmal_queue_create(); |
1298 | if (!component->cmd_queue) |
1299 | goto error; |
1300 | component->cmd_pool = mmal_pool_create(MAX_CMD_BUFFERS, 0); |
1301 | if (!component->cmd_pool) |
1302 | goto error; |
1303 | |
1304 | if (component->cmd_thread_used && |
1305 | vcos_semaphore_create(&component->cmd_sema, |
1306 | "mmalomx sema" , 0) != VCOS_SUCCESS) |
1307 | { |
1308 | component->cmd_thread_used = MMAL_FALSE; |
1309 | goto error; |
1310 | } |
1311 | |
1312 | if (component->cmd_thread_used && |
1313 | vcos_thread_create(&component->cmd_thread, component->name, NULL, |
1314 | mmalomx_cmd_thread_func, component) != VCOS_SUCCESS) |
1315 | { |
1316 | vcos_semaphore_delete(&component->cmd_sema); |
1317 | component->cmd_thread_used = MMAL_FALSE; |
1318 | goto error; |
1319 | } |
1320 | |
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; |
1341 | |
1342 | return OMX_ErrorNone; |
1343 | |
1344 | error: |
1345 | MMALOMX_IMPORT(OMX_FreeHandle)((OMX_HANDLETYPE)&component->omx); |
1346 | return status; |
1347 | } |
1348 | |
1349 | /*****************************************************************************/ |
1350 | OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_FreeHandle)( |
1351 | OMX_HANDLETYPE hComponent) |
1352 | { |
1353 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)hComponent; |
1354 | OMX_ERRORTYPE status; |
1355 | unsigned int i; |
1356 | |
1357 | LOG_TRACE("hComponent %p" , hComponent); |
1358 | |
1359 | /* Sanity check */ |
1360 | if (!hComponent) |
1361 | return OMX_ErrorInvalidComponent; |
1362 | |
1363 | if (component->omx.ComponentDeInit) |
1364 | { |
1365 | status = component->omx.ComponentDeInit(hComponent); |
1366 | if (status != OMX_ErrorNone) |
1367 | { |
1368 | LOG_ERROR("ComponentDeInit failed" ); |
1369 | return status; |
1370 | } |
1371 | } |
1372 | |
1373 | if (component->cmd_thread_used) |
1374 | { |
1375 | component->cmd_thread_used = MMAL_FALSE; |
1376 | vcos_semaphore_post(&component->cmd_sema); |
1377 | vcos_thread_join(&component->cmd_thread, NULL); |
1378 | } |
1379 | |
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); |
1384 | |
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); |
1393 | free(component); |
1394 | return OMX_ErrorNone; |
1395 | } |
1396 | |
1397 | /*****************************************************************************/ |
1398 | OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetRolesOfComponent)( |
1399 | OMX_STRING compName, |
1400 | OMX_U32 *pNumRoles, |
1401 | OMX_U8 **roles) |
1402 | { |
1403 | OMX_U32 i, num_roles; |
1404 | MMALOMX_ROLE_T role; |
1405 | int registry_id; |
1406 | |
1407 | LOG_TRACE("compName %s, pNumRoles %p, roles %p" , compName, pNumRoles, roles); |
1408 | |
1409 | /* Sanity checks */ |
1410 | if (!compName || !pNumRoles) |
1411 | return OMX_ErrorBadParameter; |
1412 | |
1413 | if (!roles || *pNumRoles > MMALOMX_MAX_ROLES) |
1414 | num_roles = MMALOMX_MAX_ROLES; |
1415 | else |
1416 | num_roles = *pNumRoles; |
1417 | *pNumRoles = 0; |
1418 | |
1419 | /* Find component */ |
1420 | registry_id = mmalomx_registry_find_component(compName); |
1421 | if (registry_id < 0) |
1422 | return OMX_ErrorComponentNotFound; |
1423 | |
1424 | /* Enumerate Roles */ |
1425 | for (i = 0; i < num_roles; i++) |
1426 | { |
1427 | role = mmalomx_registry_component_roles(registry_id, i); |
1428 | if (!role || !mmalomx_role_to_name(role)) |
1429 | break; |
1430 | |
1431 | if(roles) |
1432 | { |
1433 | strncpy((char *)roles[i], mmalomx_role_to_name(role), OMX_MAX_STRINGNAME_SIZE); |
1434 | LOG_DEBUG("found role: %s" , roles[i]); |
1435 | } |
1436 | } |
1437 | LOG_DEBUG("found %i roles" , (int)i); |
1438 | *pNumRoles = i; |
1439 | |
1440 | return OMX_ErrorNone; |
1441 | } |
1442 | |
1443 | /*****************************************************************************/ |
1444 | OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetComponentsOfRole)( |
1445 | OMX_STRING role, |
1446 | OMX_U32 *pNumComps, |
1447 | OMX_U8 **compNames) |
1448 | { |
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}; |
1456 | |
1457 | LOG_TRACE("role %s, pNumComps %p, compNames %p" , role, pNumComps, compNames); |
1458 | |
1459 | /* Sanity checks */ |
1460 | if (!role || !pNumComps) |
1461 | return OMX_ErrorBadParameter; |
1462 | |
1463 | /* Enumerates components */ |
1464 | while ((status = OMX_ComponentNameEnum((OMX_STRING)name, nNameLength, |
1465 | nIndex++)) == OMX_ErrorNone) |
1466 | { |
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; |
1471 | |
1472 | /* Enumerate Roles */ |
1473 | status = MMALOMX_IMPORT(OMX_GetRolesOfComponent)((OMX_STRING)name, &nRoles, 0); |
1474 | if(status != OMX_ErrorNone) continue; |
1475 | |
1476 | for (nIndexRoles = 0; nIndexRoles < nRoles; nIndexRoles++) |
1477 | { |
1478 | status = comp->ComponentRoleEnum(handle, compRole, nIndexRoles); |
1479 | if(status != OMX_ErrorNone) break; |
1480 | |
1481 | if(!strncmp((char *)role, (char *)compRole, OMX_MAX_STRINGNAME_SIZE)) |
1482 | { |
1483 | /* Found one */ |
1484 | nComps++; |
1485 | |
1486 | if(!compNames) break; |
1487 | |
1488 | /* Check if enough space was provided for all the component names */ |
1489 | if(nComps > *pNumComps) return OMX_ErrorBadParameter; |
1490 | |
1491 | strncpy((char *)compNames[nComps-1], (char *)name, OMX_MAX_STRINGNAME_SIZE); |
1492 | |
1493 | LOG_DEBUG("found component: %s" , name); |
1494 | } |
1495 | } |
1496 | |
1497 | MMALOMX_IMPORT(OMX_FreeHandle)(handle); |
1498 | } |
1499 | LOG_DEBUG("found %i components" , (int)nComps); |
1500 | *pNumComps = nComps; |
1501 | |
1502 | return OMX_ErrorNone; |
1503 | } |
1504 | |
1505 | /*****************************************************************************/ |
1506 | OMX_API OMX_ERRORTYPE OMX_APIENTRY MMALOMX_EXPORT(OMX_SetupTunnel)( |
1507 | OMX_HANDLETYPE hOutput, |
1508 | OMX_U32 nPortOutput, |
1509 | OMX_HANDLETYPE hInput, |
1510 | OMX_U32 nPortInput) |
1511 | { |
1512 | OMX_TUNNELSETUPTYPE tunnel_setup = {0, OMX_BufferSupplyUnspecified}; |
1513 | OMX_ERRORTYPE status = OMX_ErrorNone; |
1514 | |
1515 | LOG_TRACE("hOutput %p, nPortOutput %d, hInput %p, nPortInput %d" , |
1516 | hOutput, (int)nPortOutput, hInput, (int)nPortInput); |
1517 | |
1518 | /* Sanity checks */ |
1519 | if (!hOutput && !hInput) |
1520 | return OMX_ErrorBadParameter; |
1521 | |
1522 | if (hOutput) |
1523 | { |
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); |
1528 | } |
1529 | |
1530 | if (status == OMX_ErrorNone && hInput) |
1531 | { |
1532 | status = ((OMX_COMPONENTTYPE *)hInput)->ComponentTunnelRequest( |
1533 | hInput, nPortInput, hOutput, nPortOutput, &tunnel_setup); |
1534 | if (status != OMX_ErrorNone) |
1535 | { |
1536 | LOG_DEBUG("OMX_SetupTunnel failed on input port (%i)" , status); |
1537 | /* Cancel request on output port */ |
1538 | if (hOutput) |
1539 | ((OMX_COMPONENTTYPE *)hOutput)->ComponentTunnelRequest( |
1540 | hOutput, nPortOutput, NULL, 0, NULL); |
1541 | } |
1542 | } |
1543 | |
1544 | return status; |
1545 | } |
1546 | |
1547 | OMX_API OMX_ERRORTYPE MMALOMX_EXPORT(OMX_GetContentPipe)( |
1548 | OMX_HANDLETYPE *hPipe, |
1549 | OMX_STRING szURI) |
1550 | { |
1551 | MMAL_PARAM_UNUSED(hPipe); |
1552 | MMAL_PARAM_UNUSED(szURI); |
1553 | |
1554 | LOG_TRACE("hPipe %p, szURI %s" , hPipe, szURI); |
1555 | |
1556 | return OMX_ErrorNotImplemented; |
1557 | } |
1558 | |
1559 | /***************************************************************************** |
1560 | * Processing thread |
1561 | *****************************************************************************/ |
1562 | static void *mmalomx_cmd_thread_func(void *arg) |
1563 | { |
1564 | MMALOMX_COMPONENT_T *component = (MMALOMX_COMPONENT_T *)arg; |
1565 | VCOS_STATUS_T status; |
1566 | |
1567 | while (component->cmd_thread_used) |
1568 | { |
1569 | status = vcos_semaphore_wait(&component->cmd_sema); |
1570 | if (status == VCOS_EAGAIN) |
1571 | continue; |
1572 | mmalomx_commands_actions_check(component); |
1573 | } |
1574 | |
1575 | return 0; |
1576 | } |
1577 | |
1578 | |