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_parameters.h" |
31 | #include "mmalomx_util_params.h" |
32 | #include "mmalomx_roles.h" |
33 | #include "mmalomx_registry.h" |
34 | #include "mmalomx_logging.h" |
35 | #include <util/mmal_util.h> |
36 | #include <util/mmal_util_params.h> |
37 | #include <util/mmal_util_rational.h> |
38 | |
39 | #define PARAM_GET_PORT(port, component, index) \ |
40 | if (index >= component->ports_num) return OMX_ErrorBadPortIndex; \ |
41 | port = &component->ports[index] |
42 | |
43 | #define MMALOMX_PARAM_GENERIC_MAX 256 |
44 | |
45 | /** A structure capable of holding any OMX parameter that contains a port */ |
46 | typedef struct MMALOMX_PARAM_OMX_GENERIC_T |
47 | { |
48 | MMALOMX_PARAM_OMX_HEADER_T ; |
49 | uint8_t data[MMALOMX_PARAM_GENERIC_MAX]; |
50 | } MMALOMX_PARAM_OMX_GENERIC_T; |
51 | |
52 | /** A structure capable of holding any OMX parameter that doesn't contain a port */ |
53 | typedef struct MMALOMX_PARAM_OMX_GENERIC_PORTLESS_T |
54 | { |
55 | MMALOMX_PARAM_OMX_HEADER_PORTLESS_T hdr; |
56 | uint8_t data[MMALOMX_PARAM_GENERIC_MAX]; |
57 | } MMALOMX_PARAM_OMX_GENERIC_PORTLESS_T; |
58 | |
59 | /** A structure capable of holding any MMAL parameter */ |
60 | typedef struct MMALOMX_PARAM_MMAL_GENERIC_T |
61 | { |
62 | MMAL_PARAMETER_HEADER_T ; |
63 | uint8_t data[MMALOMX_PARAM_GENERIC_MAX]; |
64 | } MMALOMX_PARAM_MMAL_GENERIC_T; |
65 | |
66 | static OMX_ERRORTYPE mmalomx_parameter_set_xlat(MMALOMX_COMPONENT_T *component, |
67 | OMX_INDEXTYPE nParamIndex, OMX_PTR pParam) |
68 | { |
69 | const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_omx_id(nParamIndex); |
70 | MMALOMX_PARAM_OMX_HEADER_T * = (MMALOMX_PARAM_OMX_HEADER_T *)pParam; |
71 | MMALOMX_PARAM_MMAL_GENERIC_T mmal_generic; |
72 | MMAL_PARAMETER_HEADER_T * = &mmal_generic.header; |
73 | MMAL_PORT_T *mmal_port = component->mmal->control; |
74 | MMAL_STATUS_T status; |
75 | |
76 | if (!xlat) |
77 | { |
78 | LOG_DEBUG("no translation for omx id 0x%08x" , nParamIndex); |
79 | return OMX_ErrorNotImplemented; |
80 | } |
81 | |
82 | if (!xlat->portless) |
83 | { |
84 | if (omx_header->nSize < sizeof(*omx_header)) |
85 | return OMX_ErrorBadParameter; |
86 | if (omx_header->nPortIndex >= component->ports_num) |
87 | return OMX_ErrorBadPortIndex; |
88 | mmal_port = component->ports[omx_header->nPortIndex].mmal; |
89 | } |
90 | |
91 | if (omx_header->nSize < xlat->omx_size) |
92 | return OMX_ErrorBadParameter; |
93 | |
94 | /* Handle the direct case first */ |
95 | if (xlat->type == MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT) |
96 | { |
97 | mmal_header = (MMAL_PARAMETER_HEADER_T *)(((uint8_t *)pParam) + (xlat->portless ? 0 : 4)); |
98 | mmal_generic.header = *mmal_header; |
99 | mmal_header->size = omx_header->nSize - (xlat->portless ? 0 : 4); |
100 | mmal_header->id = xlat->mmal_id; |
101 | status = mmal_port_parameter_set(mmal_port, mmal_header); |
102 | *mmal_header = mmal_generic.header; |
103 | return mmalil_error_to_omx(status); |
104 | } |
105 | |
106 | if (!xlat->fn.generic && !xlat->fn.simple) |
107 | { |
108 | // FIXME |
109 | return OMX_ErrorNotImplemented; |
110 | } |
111 | |
112 | // FIXME: check size of mmal_generic is sufficient |
113 | if (sizeof(mmal_generic) < xlat->mmal_size) |
114 | return OMX_ErrorBadParameter; |
115 | |
116 | mmal_header->size = xlat->mmal_size; |
117 | mmal_header->id = xlat->mmal_id; |
118 | if (xlat->fn.generic) |
119 | status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_MMAL, xlat, mmal_header, pParam, mmal_port); |
120 | else |
121 | status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_MMAL, mmal_header, pParam); |
122 | if (status != MMAL_SUCCESS) |
123 | goto error; |
124 | |
125 | status = mmal_port_parameter_set(mmal_port, mmal_header); |
126 | |
127 | error: |
128 | return mmalil_error_to_omx(status); |
129 | } |
130 | |
131 | static OMX_ERRORTYPE mmalomx_parameter_get_xlat(MMALOMX_COMPONENT_T *component, |
132 | OMX_INDEXTYPE nParamIndex, OMX_PTR pParam) |
133 | { |
134 | const MMALOMX_PARAM_TRANSLATION_T *xlat = mmalomx_find_parameter_from_omx_id(nParamIndex); |
135 | MMALOMX_PARAM_OMX_HEADER_T * = (MMALOMX_PARAM_OMX_HEADER_T *)pParam; |
136 | MMALOMX_PARAM_MMAL_GENERIC_T mmal_generic; |
137 | MMAL_PARAMETER_HEADER_T * = &mmal_generic.header; |
138 | MMAL_PORT_T *mmal_port = component->mmal->control; |
139 | MMAL_STATUS_T status = MMAL_SUCCESS; |
140 | |
141 | if (!xlat) |
142 | return OMX_ErrorNotImplemented; |
143 | |
144 | if (!xlat->portless) |
145 | { |
146 | if (omx_header->nSize < sizeof(*omx_header)) |
147 | return OMX_ErrorBadParameter; |
148 | if (omx_header->nPortIndex >= component->ports_num) |
149 | return OMX_ErrorBadPortIndex; |
150 | mmal_port = component->ports[omx_header->nPortIndex].mmal; |
151 | } |
152 | |
153 | if (omx_header->nSize < xlat->omx_size) |
154 | return OMX_ErrorBadParameter; |
155 | |
156 | /* Handle the direct case first */ |
157 | if (xlat->type == MMALOMX_PARAM_TRANSLATION_TYPE_DIRECT) |
158 | { |
159 | OMX_U32 size; |
160 | mmal_header = (MMAL_PARAMETER_HEADER_T *)(((uint8_t *)pParam) + (xlat->portless ? 0 : 4)); |
161 | mmal_generic.header = *mmal_header; |
162 | mmal_header->size = omx_header->nSize - (xlat->portless ? 0 : 4); |
163 | mmal_header->id = xlat->mmal_id; |
164 | status = mmal_port_parameter_get(mmal_port, mmal_header); |
165 | *mmal_header = mmal_generic.header; |
166 | size = mmal_header->size + (xlat->portless ? 0 : 4); |
167 | omx_header->nSize = size; |
168 | return mmalil_error_to_omx(status); |
169 | } |
170 | |
171 | if (xlat->fn.custom) |
172 | { |
173 | return mmalil_error_to_omx(xlat->fn.custom(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, mmal_header, |
174 | pParam, mmal_port)); |
175 | } |
176 | |
177 | if (xlat->fn.list) |
178 | { |
179 | OMX_U32 index, elements; |
180 | mmal_header = mmal_port_parameter_alloc_get(mmal_port, xlat->mmal_id, |
181 | 10*xlat->mmal_size, &status); |
182 | if (!mmal_header) |
183 | return OMX_ErrorInsufficientResources; |
184 | |
185 | /* Check we're not requesting too much */ |
186 | index = *(OMX_U32 *)(((uint8_t *)pParam) + xlat->xlat_enum_num); |
187 | elements = (mmal_header->size - sizeof(MMAL_PARAMETER_HEADER_T)) / |
188 | (xlat->mmal_size - sizeof(MMAL_PARAMETER_HEADER_T)); |
189 | if (index >= elements) |
190 | { |
191 | vcos_free(mmal_header); |
192 | return OMX_ErrorNoMore; |
193 | } |
194 | status = xlat->fn.list(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, index, mmal_header, pParam, mmal_port); |
195 | vcos_free(mmal_header); |
196 | return mmalil_error_to_omx(status); |
197 | } |
198 | |
199 | if (!xlat->fn.generic && !xlat->fn.simple) |
200 | { |
201 | // FIXME |
202 | return OMX_ErrorNotImplemented; |
203 | } |
204 | |
205 | // FIXME: check size of mmal_generic is sufficient |
206 | if (sizeof(mmal_generic) < xlat->mmal_size) |
207 | return OMX_ErrorBadParameter; |
208 | |
209 | mmal_header->size = xlat->mmal_size; |
210 | mmal_header->id = xlat->mmal_id; |
211 | |
212 | if (xlat->double_translation) |
213 | { |
214 | if (xlat->fn.generic) |
215 | status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_MMAL, xlat, mmal_header, pParam, mmal_port); |
216 | else |
217 | status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_MMAL, mmal_header, pParam); |
218 | } |
219 | if (status != MMAL_SUCCESS) |
220 | goto error; |
221 | |
222 | status = mmal_port_parameter_get(mmal_port, mmal_header); |
223 | if (status != MMAL_SUCCESS) |
224 | goto error; |
225 | |
226 | if (xlat->fn.generic) |
227 | status = xlat->fn.generic(MMALOMX_PARAM_MAPPING_TO_OMX, xlat, mmal_header, pParam, mmal_port); |
228 | else |
229 | status = xlat->fn.simple(MMALOMX_PARAM_MAPPING_TO_OMX, mmal_header, pParam); |
230 | |
231 | error: |
232 | return mmalil_error_to_omx(status); |
233 | } |
234 | |
235 | OMX_ERRORTYPE mmalomx_parameter_extension_index_get(OMX_STRING cParameterName, |
236 | OMX_INDEXTYPE *pIndex) |
237 | { |
238 | const MMALOMX_PARAM_TRANSLATION_T *xlat; |
239 | MMAL_BOOL_T config = MMAL_FALSE; |
240 | unsigned int i = 0; |
241 | |
242 | /* Check we're dealing with our extensions */ |
243 | if (!vcos_strncasecmp(cParameterName, MMALOMX_COMPONENT_PREFIX, sizeof(MMALOMX_COMPONENT_PREFIX)-1)) |
244 | return OMX_ErrorNotImplemented; |
245 | cParameterName += sizeof(MMALOMX_COMPONENT_PREFIX)-1; |
246 | |
247 | /* Check if we're dealing with a config or param */ |
248 | if (!vcos_strncasecmp(cParameterName, "index.config." , sizeof("index.config." )-1)) |
249 | config = MMAL_TRUE; |
250 | if (!config && vcos_strncasecmp(cParameterName, "index.param." , sizeof("index.param." )-1)) |
251 | return OMX_ErrorNotImplemented; |
252 | if (config) |
253 | cParameterName += sizeof("index.config." )-1; |
254 | else |
255 | cParameterName += sizeof("index.param." )-1; |
256 | |
257 | /* Loop through all the */ |
258 | while ((xlat = mmalomx_find_parameter_enum(i++)) != NULL) |
259 | { |
260 | const char *name = xlat->omx_name; |
261 | |
262 | /* We only report vendor extensions */ |
263 | if (xlat->omx_id < OMX_IndexVendorStartUnused) |
264 | continue; |
265 | |
266 | /* Strip out the standard prefix */ |
267 | if (config) |
268 | { |
269 | if (!strncmp(name, "OMX_IndexConfigBrcm" , sizeof("OMX_IndexConfigBrcm" )-1)) |
270 | name += sizeof("OMX_IndexConfigBrcm" )-1; |
271 | else if (!strncmp(name, "OMX_IndexConfig" , sizeof("OMX_IndexConfig" )-1)) |
272 | name += sizeof("OMX_IndexConfig" )-1; |
273 | else continue; |
274 | } |
275 | else |
276 | { |
277 | if (!strncmp(name, "OMX_IndexParamBrcm" , sizeof("OMX_IndexParamBrcm" )-1)) |
278 | name += sizeof("OMX_IndexParamBrcm" )-1; |
279 | else if (!strncmp(name, "OMX_IndexParam" , sizeof("OMX_IndexParam" )-1)) |
280 | name += sizeof("OMX_IndexParam" )-1; |
281 | else continue; |
282 | } |
283 | |
284 | /* Compare the last part of the name */ |
285 | if (!vcos_strcasecmp(name, cParameterName)) |
286 | { |
287 | *pIndex = xlat->omx_id; |
288 | return OMX_ErrorNone; |
289 | } |
290 | } |
291 | |
292 | return OMX_ErrorNotImplemented; |
293 | } |
294 | |
295 | /*****************************************************************************/ |
296 | static OMX_ERRORTYPE mmalomx_get_video_param(MMALOMX_PORT_T *port, |
297 | uint32_t *profile, uint32_t *level, uint32_t *intraperiod) |
298 | { |
299 | MMAL_PARAMETER_VIDEO_PROFILE_T mmal_param = {{MMAL_PARAMETER_PROFILE, sizeof(mmal_param)}, |
300 | {{(MMAL_VIDEO_PROFILE_T)0, (MMAL_VIDEO_LEVEL_T)0}}}; |
301 | |
302 | *profile = *level = *intraperiod = 0; |
303 | |
304 | mmal_port_parameter_get_uint32(port->mmal, MMAL_PARAMETER_INTRAPERIOD, intraperiod); |
305 | |
306 | if (mmal_port_parameter_get(port->mmal, &mmal_param.hdr) == MMAL_SUCCESS) |
307 | { |
308 | *profile = mmalil_video_profile_to_omx(mmal_param.profile[0].profile); |
309 | *level = mmalil_video_level_to_omx(mmal_param.profile[0].level); |
310 | } |
311 | |
312 | return OMX_ErrorNone; |
313 | } |
314 | |
315 | /*****************************************************************************/ |
316 | OMX_ERRORTYPE mmalomx_parameter_get(MMALOMX_COMPONENT_T *component, |
317 | OMX_INDEXTYPE nParamIndex, OMX_PTR pParam) |
318 | { |
319 | MMALOMX_PORT_T *port = NULL; |
320 | |
321 | switch(nParamIndex) |
322 | { |
323 | /* All OMX_IndexParamVideo parameters are only partially implemented |
324 | * and we try and use sensible hard-coded values for the rest. */ |
325 | case OMX_IndexParamVideoAvc: |
326 | { |
327 | OMX_VIDEO_PARAM_AVCTYPE *param = (OMX_VIDEO_PARAM_AVCTYPE *)pParam; |
328 | uint32_t profile, level, intraperiod; |
329 | PARAM_GET_PORT(port, component, param->nPortIndex); |
330 | if (param->nSize < sizeof(*param)) |
331 | return OMX_ErrorBadParameter; |
332 | memset(¶m->nSliceHeaderSpacing, 0, |
333 | param->nSize - offsetof(OMX_VIDEO_PARAM_AVCTYPE, nSliceHeaderSpacing)); |
334 | |
335 | mmalomx_get_video_param(port, &profile, &level, &intraperiod); |
336 | param->eProfile = (OMX_VIDEO_AVCPROFILETYPE)profile; |
337 | param->eLevel = (OMX_VIDEO_AVCLEVELTYPE)level; |
338 | param->nPFrames = intraperiod - 1; |
339 | param->bUseHadamard = OMX_TRUE; |
340 | param->nRefFrames = 1; |
341 | param->nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; |
342 | param->bFrameMBsOnly = OMX_TRUE; |
343 | if (param->eProfile != OMX_VIDEO_AVCProfileBaseline) |
344 | param->bEntropyCodingCABAC = OMX_TRUE; |
345 | param->eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; |
346 | } |
347 | return OMX_ErrorNone; |
348 | case OMX_IndexParamVideoMpeg4: |
349 | { |
350 | OMX_VIDEO_PARAM_MPEG4TYPE *param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pParam; |
351 | uint32_t profile, level, intraperiod; |
352 | PARAM_GET_PORT(port, component, param->nPortIndex); |
353 | if (param->nSize < sizeof(*param)) |
354 | return OMX_ErrorBadParameter; |
355 | memset(¶m->nSliceHeaderSpacing, 0, |
356 | param->nSize - offsetof(OMX_VIDEO_PARAM_MPEG4TYPE, nSliceHeaderSpacing)); |
357 | |
358 | mmalomx_get_video_param(port, &profile, &level, &intraperiod); |
359 | param->eProfile = (OMX_VIDEO_MPEG4PROFILETYPE)profile; |
360 | param->eLevel = (OMX_VIDEO_MPEG4LEVELTYPE)level; |
361 | param->nPFrames = intraperiod - 1; |
362 | param->bACPred = OMX_TRUE; |
363 | param->nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; |
364 | } |
365 | return OMX_ErrorNone; |
366 | case OMX_IndexParamVideoH263: |
367 | { |
368 | OMX_VIDEO_PARAM_H263TYPE *param = (OMX_VIDEO_PARAM_H263TYPE *)pParam; |
369 | uint32_t profile, level, intraperiod; |
370 | PARAM_GET_PORT(port, component, param->nPortIndex); |
371 | if (param->nSize < sizeof(*param)) |
372 | return OMX_ErrorBadParameter; |
373 | memset(¶m->nPFrames, 0, |
374 | param->nSize - offsetof(OMX_VIDEO_PARAM_H263TYPE, nPFrames)); |
375 | |
376 | mmalomx_get_video_param(port, &profile, &level, &intraperiod); |
377 | param->eProfile = (OMX_VIDEO_H263PROFILETYPE)profile; |
378 | param->eLevel = (OMX_VIDEO_H263LEVELTYPE)level; |
379 | param->nPFrames = intraperiod - 1; |
380 | param->nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; |
381 | } |
382 | return OMX_ErrorNone; |
383 | case OMX_IndexParamVideoMpeg2: |
384 | case OMX_IndexParamVideoWmv: |
385 | case OMX_IndexParamVideoRv: |
386 | { |
387 | OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam; |
388 | PARAM_GET_PORT(port, component, param->common.nPortIndex); |
389 | OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32); |
390 | if (param->common.nSize > sizeof(port->format_param) || |
391 | param->common.nSize < offset) |
392 | return OMX_ErrorBadParameter; |
393 | memcpy(¶m->common.nU32, &port->format_param.common.nU32, |
394 | param->common.nSize - offset); |
395 | return OMX_ErrorNone; |
396 | } |
397 | case OMX_IndexParamAudioPcm: |
398 | case OMX_IndexParamAudioAac: |
399 | case OMX_IndexParamAudioMp3: |
400 | case OMX_IndexParamAudioDdp: |
401 | { |
402 | OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam; |
403 | PARAM_GET_PORT(port, component, param->common.nPortIndex); |
404 | OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32); |
405 | if (param->common.nSize > sizeof(port->format_param) || |
406 | param->common.nSize < offset) |
407 | return OMX_ErrorBadParameter; |
408 | memcpy(¶m->common.nU32, &port->format_param.common.nU32, |
409 | param->common.nSize - offset); |
410 | mmalil_format_to_omx_audio_param(param, NULL, port->mmal->format); |
411 | return OMX_ErrorNone; |
412 | } |
413 | case OMX_IndexParamBrcmPixelAspectRatio: |
414 | { |
415 | OMX_CONFIG_POINTTYPE *param = (OMX_CONFIG_POINTTYPE *)pParam; |
416 | PARAM_GET_PORT(port, component, param->nPortIndex); |
417 | param->nX = port->mmal->format->es->video.par.num; |
418 | param->nY = port->mmal->format->es->video.par.den; |
419 | return OMX_ErrorNone; |
420 | } |
421 | case OMX_IndexParamColorSpace: |
422 | { |
423 | OMX_PARAM_COLORSPACETYPE *param = (OMX_PARAM_COLORSPACETYPE *)pParam; |
424 | PARAM_GET_PORT(port, component, param->nPortIndex); |
425 | param->eColorSpace = mmalil_color_space_to_omx(port->mmal->format->es->video.color_space); |
426 | return OMX_ErrorNone; |
427 | } |
428 | case OMX_IndexConfigCommonOutputCrop: |
429 | { |
430 | OMX_CONFIG_RECTTYPE *param = (OMX_CONFIG_RECTTYPE *)pParam; |
431 | PARAM_GET_PORT(port, component, param->nPortIndex); |
432 | param->nLeft = port->mmal->format->es->video.crop.x; |
433 | param->nTop = port->mmal->format->es->video.crop.y; |
434 | param->nWidth = port->mmal->format->es->video.width; |
435 | if (port->mmal->format->es->video.crop.width) |
436 | param->nWidth = port->mmal->format->es->video.crop.width; |
437 | param->nHeight = port->mmal->format->es->video.height; |
438 | if (port->mmal->format->es->video.crop.height) |
439 | param->nHeight = port->mmal->format->es->video.crop.height; |
440 | return OMX_ErrorNone; |
441 | } |
442 | case OMX_IndexConfigCommonScale: |
443 | { |
444 | OMX_CONFIG_SCALEFACTORTYPE *param = (OMX_CONFIG_SCALEFACTORTYPE *)pParam; |
445 | PARAM_GET_PORT(port, component, param->nPortIndex); |
446 | param->xWidth = param->xHeight = 1<<16; |
447 | if (port->mmal->format->es->video.par.num && |
448 | port->mmal->format->es->video.par.den) |
449 | param->xWidth = mmal_rational_to_fixed_16_16(port->mmal->format->es->video.par); |
450 | return OMX_ErrorNone; |
451 | } |
452 | default: |
453 | return mmalomx_parameter_get_xlat(component, nParamIndex, pParam); |
454 | } |
455 | |
456 | return OMX_ErrorNotImplemented; |
457 | } |
458 | |
459 | /*****************************************************************************/ |
460 | static OMX_ERRORTYPE mmalomx_set_video_param(MMALOMX_PORT_T *port, |
461 | uint32_t profile, uint32_t level, uint32_t intraperiod) |
462 | { |
463 | MMAL_PARAMETER_VIDEO_PROFILE_T mmal_param = {{MMAL_PARAMETER_PROFILE, sizeof(mmal_param)}, |
464 | {{(MMAL_VIDEO_PROFILE_T)0, (MMAL_VIDEO_LEVEL_T)0}}}; |
465 | OMX_VIDEO_CODINGTYPE coding = |
466 | mmalil_encoding_to_omx_video_coding(port->mmal->format->encoding); |
467 | |
468 | if (mmal_port_parameter_set_uint32(port->mmal, MMAL_PARAMETER_INTRAPERIOD, |
469 | intraperiod) != MMAL_SUCCESS) |
470 | return OMX_ErrorBadParameter; |
471 | |
472 | mmal_param.profile[0].profile = (MMAL_VIDEO_PROFILE_T) |
473 | mmalil_omx_video_profile_to_mmal(profile, coding); |
474 | mmal_param.profile[0].level = (MMAL_VIDEO_LEVEL_T) |
475 | mmalil_omx_video_level_to_mmal(level, coding); |
476 | if (mmal_port_parameter_set(port->mmal, &mmal_param.hdr) != MMAL_SUCCESS) |
477 | return OMX_ErrorBadParameter; |
478 | |
479 | return OMX_ErrorNone; |
480 | } |
481 | |
482 | /*****************************************************************************/ |
483 | OMX_ERRORTYPE mmalomx_parameter_set(MMALOMX_COMPONENT_T *component, |
484 | OMX_INDEXTYPE nParamIndex, OMX_PTR pParam) |
485 | { |
486 | MMALOMX_PORT_T *port = NULL; |
487 | |
488 | switch(nParamIndex) |
489 | { |
490 | /* All OMX_IndexParamVideo parameters are only partially implemented */ |
491 | case OMX_IndexParamVideoAvc: |
492 | { |
493 | OMX_VIDEO_PARAM_AVCTYPE *param = (OMX_VIDEO_PARAM_AVCTYPE *)pParam; |
494 | PARAM_GET_PORT(port, component, param->nPortIndex); |
495 | if (param->nSize < sizeof(*param)) |
496 | return OMX_ErrorBadParameter; |
497 | return mmalomx_set_video_param(port, param->eProfile, param->eLevel, |
498 | param->nPFrames + 1); |
499 | } |
500 | case OMX_IndexParamVideoMpeg4: |
501 | { |
502 | OMX_VIDEO_PARAM_MPEG4TYPE *param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pParam; |
503 | PARAM_GET_PORT(port, component, param->nPortIndex); |
504 | if (param->nSize < sizeof(*param)) |
505 | return OMX_ErrorBadParameter; |
506 | return mmalomx_set_video_param(port, param->eProfile, param->eLevel, |
507 | param->nPFrames + 1); |
508 | } |
509 | case OMX_IndexParamVideoH263: |
510 | { |
511 | OMX_VIDEO_PARAM_H263TYPE *param = (OMX_VIDEO_PARAM_H263TYPE *)pParam; |
512 | PARAM_GET_PORT(port, component, param->nPortIndex); |
513 | if (param->nSize < sizeof(*param)) |
514 | return OMX_ErrorBadParameter; |
515 | return mmalomx_set_video_param(port, param->eProfile, param->eLevel, |
516 | param->nPFrames + 1); |
517 | } |
518 | case OMX_IndexParamVideoMpeg2: |
519 | case OMX_IndexParamVideoWmv: |
520 | case OMX_IndexParamVideoRv: |
521 | { |
522 | OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam; |
523 | OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32); |
524 | PARAM_GET_PORT(port, component, param->common.nPortIndex); |
525 | if (param->common.nSize > sizeof(port->format_param) || |
526 | param->common.nSize < offset) |
527 | return OMX_ErrorBadParameter; |
528 | memcpy(&port->format_param.common.nU32, ¶m->common.nU32, |
529 | param->common.nSize - offset); |
530 | return OMX_ErrorNone; |
531 | } |
532 | case OMX_IndexParamAudioPcm: |
533 | case OMX_IndexParamAudioAac: |
534 | case OMX_IndexParamAudioMp3: |
535 | case OMX_IndexParamAudioDdp: |
536 | { |
537 | OMX_FORMAT_PARAM_TYPE *param = (OMX_FORMAT_PARAM_TYPE *)pParam; |
538 | OMX_U32 offset = offsetof(OMX_PARAM_U32TYPE, nU32); |
539 | PARAM_GET_PORT(port, component, param->common.nPortIndex); |
540 | if (param->common.nSize > sizeof(port->format_param) || |
541 | param->common.nSize < offset) |
542 | return OMX_ErrorBadParameter; |
543 | memcpy(&port->format_param.common.nU32, ¶m->common.nU32, |
544 | param->common.nSize - offset); |
545 | mmalil_omx_audio_param_to_format(port->mmal->format, |
546 | mmalil_omx_audio_param_index_to_coding(nParamIndex), param); |
547 | mmal_port_format_commit(port->mmal); |
548 | return OMX_ErrorNone; |
549 | } |
550 | case OMX_IndexParamBrcmPixelAspectRatio: |
551 | { |
552 | OMX_CONFIG_POINTTYPE *param = (OMX_CONFIG_POINTTYPE *)pParam; |
553 | PARAM_GET_PORT(port, component, param->nPortIndex); |
554 | port->mmal->format->es->video.par.num = param->nX; |
555 | port->mmal->format->es->video.par.den = param->nY; |
556 | mmal_rational_simplify(&port->mmal->format->es->video.par); |
557 | return mmalil_error_to_omx(mmal_port_format_commit(port->mmal)); |
558 | } |
559 | case OMX_IndexParamColorSpace: |
560 | { |
561 | OMX_PARAM_COLORSPACETYPE *param = (OMX_PARAM_COLORSPACETYPE *)pParam; |
562 | PARAM_GET_PORT(port, component, param->nPortIndex); |
563 | port->mmal->format->es->video.color_space = mmalil_omx_color_space_to_mmal(param->eColorSpace); |
564 | return mmalil_error_to_omx(mmal_port_format_commit(port->mmal)); |
565 | } |
566 | case OMX_IndexParamBrcmVideoCroppingDisable: |
567 | { |
568 | OMX_CONFIG_PORTBOOLEANTYPE *param = (OMX_CONFIG_PORTBOOLEANTYPE *)pParam; |
569 | PARAM_GET_PORT(port, component, param->nPortIndex); |
570 | port->no_cropping = param->bEnabled; |
571 | return OMX_ErrorNone; |
572 | } |
573 | default: |
574 | return mmalomx_parameter_set_xlat(component, nParamIndex, pParam); |
575 | } |
576 | |
577 | return OMX_ErrorNotImplemented; |
578 | } |
579 | |