1 /*****************************************************************************
2 * utils.c: helper functions
3 *****************************************************************************
4 * Copyright (C) 2010 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <vlc_block_helper.h>
40 /*****************************************************************************
41 * Events utility functions
42 *****************************************************************************/
43 void InitOmxEventQueue(OmxEventQueue *queue)
45 queue->pp_last_event = &queue->p_events;
46 vlc_mutex_init(&queue->mutex);
47 vlc_cond_init(&queue->cond);
50 void DeinitOmxEventQueue(OmxEventQueue *queue)
52 vlc_mutex_destroy(&queue->mutex);
53 vlc_cond_destroy(&queue->cond);
56 OMX_ERRORTYPE PostOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE event,
57 OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
61 p_event = malloc(sizeof(OmxEvent));
62 if(!p_event) return OMX_ErrorInsufficientResources;
64 p_event->event = event;
65 p_event->data_1 = data_1;
66 p_event->data_2 = data_2;
67 p_event->event_data = event_data;
70 vlc_mutex_lock(&queue->mutex);
71 *queue->pp_last_event = p_event;
72 queue->pp_last_event = &p_event->next;
73 vlc_cond_signal(&queue->cond);
74 vlc_mutex_unlock(&queue->mutex);
78 OMX_ERRORTYPE WaitForOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE *event,
79 OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
83 vlc_mutex_lock(&queue->mutex);
86 vlc_cond_timedwait(&queue->cond, &queue->mutex, mdate()+CLOCK_FREQ);
88 p_event = queue->p_events;
91 queue->p_events = p_event->next;
92 if(!queue->p_events) queue->pp_last_event = &queue->p_events;
95 vlc_mutex_unlock(&queue->mutex);
99 if(event) *event = p_event->event;
100 if(data_1) *data_1 = p_event->data_1;
101 if(data_2) *data_2 = p_event->data_2;
102 if(event_data) *event_data = p_event->event_data;
104 return OMX_ErrorNone;
107 return OMX_ErrorTimeout;
110 OMX_ERRORTYPE WaitForSpecificOmxEvent(OmxEventQueue *queue,
111 OMX_EVENTTYPE specific_event, OMX_U32 *data_1, OMX_U32 *data_2,
114 OMX_ERRORTYPE status;
116 mtime_t before = mdate();
120 status = WaitForOmxEvent(queue, &event, data_1, data_2, event_data);
121 if(status != OMX_ErrorNone) return status;
123 if(event == specific_event) break;
124 if(mdate() - before > CLOCK_FREQ) return OMX_ErrorTimeout;
127 return OMX_ErrorNone;
130 void PrintOmxEvent(vlc_object_t *p_this, OMX_EVENTTYPE event, OMX_U32 data_1,
131 OMX_U32 data_2, OMX_PTR event_data)
135 case OMX_EventCmdComplete:
136 switch ((OMX_STATETYPE)data_1)
138 case OMX_CommandStateSet:
139 msg_Dbg( p_this, "OmxEventHandler (%s, %s, %s)", EventToString(event),
140 CommandToString(data_1), StateToString(data_2) );
144 msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u)", EventToString(event),
145 CommandToString(data_1), (unsigned int)data_2 );
151 msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
152 ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
153 (const char *)event_data);
157 msg_Dbg( p_this, "OmxEventHandler (%s, %u, %u)", EventToString(event),
158 (unsigned int)data_1, (unsigned int)data_2 );
163 /*****************************************************************************
164 * Picture utility functions
165 *****************************************************************************/
166 void CopyOmxPicture( int i_color_format, picture_t *p_pic,
168 int i_src_stride, uint8_t *p_src, int i_chroma_div )
172 int i_plane, i_width, i_line;
173 if( i_color_format == QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka )
175 qcom_convert(p_src, p_pic);
179 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
181 if(i_plane == 1) i_src_stride /= i_chroma_div;
182 p_dst = p_pic->p[i_plane].p_pixels;
183 i_dst_stride = p_pic->p[i_plane].i_pitch;
184 i_width = p_pic->p[i_plane].i_visible_pitch;
186 for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
188 memcpy( p_dst, p_src, i_width );
189 p_src += i_src_stride;
190 p_dst += i_dst_stride;
192 /* Handle plane height, which may be indicated via nSliceHeight in OMX.
193 * The handling for chroma planes currently assumes vertically
194 * subsampled chroma, e.g. 422 planar wouldn't work right. */
195 if( i_plane == 0 && i_slice_height > p_pic->p[i_plane].i_visible_lines )
196 p_src += i_src_stride * (i_slice_height - p_pic->p[i_plane].i_visible_lines);
197 else if ( i_plane > 0 && i_slice_height/2 > p_pic->p[i_plane].i_visible_lines )
198 p_src += i_src_stride * (i_slice_height/2 - p_pic->p[i_plane].i_visible_lines);
202 void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
205 decoder_sys_t *p_sys = p_dec->p_sys;
206 int i_src_stride, i_dst_stride;
207 int i_plane, i_width, i_line;
208 uint8_t *p_dst, *p_src;
210 i_dst_stride = p_sys->out.i_frame_stride;
211 p_dst = p_header->pBuffer + p_header->nOffset;
213 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
215 if(i_plane == 1) i_dst_stride /= p_sys->in.i_frame_stride_chroma_div;
216 p_src = p_pic->p[i_plane].p_pixels;
217 i_src_stride = p_pic->p[i_plane].i_pitch;
218 i_width = p_pic->p[i_plane].i_visible_pitch;
220 for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
222 memcpy( p_dst, p_src, i_width );
223 p_src += i_src_stride;
224 p_dst += i_dst_stride;
229 int IgnoreOmxDecoderPadding(const char *name)
231 // The list of decoders that signal padding properly is not necessary,
232 // since that is the default, but keep it here for reference. (This is
233 // only relevant for manufacturers that are known to have decoders with
234 // this kind of bug.)
236 static const char *padding_decoders[] = {
237 "OMX.SEC.AVC.Decoder",
243 static const char *nopadding_decoders[] = {
246 "OMX.SEC.MPEG4.Decoder",
251 for (const char **ptr = nopadding_decoders; *ptr; ptr++) {
252 if (!strcmp(*ptr, name))
258 /*****************************************************************************
259 * Logging utility functions
260 *****************************************************************************/
261 const char *StateToString(OMX_STATETYPE state)
263 static const char *psz_names[] = {
264 "OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
265 "OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
269 if((unsigned int)state > sizeof(psz_names)/sizeof(char*)-1)
270 state = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
271 return psz_names[state];
274 const char *CommandToString(OMX_COMMANDTYPE command)
276 static const char *psz_names[] = {
277 "OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
278 "OMX_CommandPortEnable", "OMX_CommandMarkBuffer",
279 "OMX_Command unknown"
282 if((unsigned int)command > sizeof(psz_names)/sizeof(char*)-1)
283 command = (OMX_COMMANDTYPE)(sizeof(psz_names)/sizeof(char*)-1);
284 return psz_names[command];
287 const char *EventToString(OMX_EVENTTYPE event)
289 static const char *psz_names[] = {
290 "OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
291 "OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
292 "OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
293 "OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
297 if((unsigned int)event > sizeof(psz_names)/sizeof(char*)-1)
298 event = (OMX_EVENTTYPE)(sizeof(psz_names)/sizeof(char*)-1);
299 return psz_names[event];
302 const char *ErrorToString(OMX_ERRORTYPE error)
304 static const char *psz_names[] = {
305 "OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
306 "OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
307 "OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
308 "OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
309 "OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
310 "OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
311 "OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
312 "OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
313 "OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
314 "OMX_ErrorPortUnresponsiveDuringDeallocation",
315 "OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
316 "OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
317 "OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
318 "OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
319 "OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
320 "OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
321 "OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
322 "OMX_ErrorTunnelingUnsupported",
326 if(error == OMX_ErrorNone) return "OMX_ErrorNone";
328 error -= OMX_ErrorInsufficientResources;
330 if((unsigned int)error > sizeof(psz_names)/sizeof(char*)-1)
331 error = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
332 return psz_names[error];
335 /*****************************************************************************
336 * fourcc -> omx id mapping
337 *****************************************************************************/
340 vlc_fourcc_t i_fourcc;
341 OMX_VIDEO_CODINGTYPE i_codec;
342 const char *psz_role;
344 } video_format_table[] =
346 { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_decoder.mpeg2" },
347 { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_decoder.mpeg4" },
348 { VLC_CODEC_H264, OMX_VIDEO_CodingAVC, "video_decoder.avc" },
349 { VLC_CODEC_H263, OMX_VIDEO_CodingH263, "video_decoder.h263" },
350 { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV, "video_decoder.wmv1" },
351 { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV, "video_decoder.wmv2" },
352 { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV, "video_decoder.wmv" },
353 { VLC_CODEC_VC1, OMX_VIDEO_CodingWMV, "video_decoder.wmv" },
354 { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.jpeg" },
355 { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.mjpeg" },
356 { VLC_CODEC_RV10, OMX_VIDEO_CodingRV, "video_decoder.rv" },
357 { VLC_CODEC_RV20, OMX_VIDEO_CodingRV, "video_decoder.rv" },
358 { VLC_CODEC_RV30, OMX_VIDEO_CodingRV, "video_decoder.rv" },
359 { VLC_CODEC_RV40, OMX_VIDEO_CodingRV, "video_decoder.rv" },
365 vlc_fourcc_t i_fourcc;
366 OMX_AUDIO_CODINGTYPE i_codec;
367 const char *psz_role;
369 } audio_format_table[] =
371 { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amrnb" },
372 { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amrwb" },
373 { VLC_CODEC_MP4A, OMX_AUDIO_CodingAAC, "audio_decoder.aac" },
374 { VLC_CODEC_S16N, OMX_AUDIO_CodingPCM, "audio_decoder.pcm" },
375 { VLC_CODEC_MP3, OMX_AUDIO_CodingMP3, "audio_decoder.mp3" },
381 vlc_fourcc_t i_fourcc;
382 OMX_VIDEO_CODINGTYPE i_codec;
383 const char *psz_role;
385 } video_enc_format_table[] =
387 { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_encoder.mpeg2" },
388 { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_encoder.mpeg4" },
389 { VLC_CODEC_H264, OMX_VIDEO_CodingAVC, "video_encoder.avc" },
390 { VLC_CODEC_H263, OMX_VIDEO_CodingH263, "video_encoder.h263" },
391 { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV, "video_encoder.wmv" },
392 { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV, "video_encoder.wmv" },
393 { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV, "video_encoder.wmv" },
394 { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_encoder.jpeg" },
395 { VLC_CODEC_RV10, OMX_VIDEO_CodingRV, "video_encoder.rv" },
396 { VLC_CODEC_RV20, OMX_VIDEO_CodingRV, "video_encoder.rv" },
397 { VLC_CODEC_RV30, OMX_VIDEO_CodingRV, "video_encoder.rv" },
398 { VLC_CODEC_RV40, OMX_VIDEO_CodingRV, "video_encoder.rv" },
404 vlc_fourcc_t i_fourcc;
405 OMX_AUDIO_CODINGTYPE i_codec;
406 const char *psz_role;
408 } audio_enc_format_table[] =
410 { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amrnb" },
411 { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amrwb" },
412 { VLC_CODEC_MP4A, OMX_AUDIO_CodingAAC, "audio_encoder.aac" },
413 { VLC_CODEC_S16N, OMX_AUDIO_CodingPCM, "audio_encoder.pcm" },
419 vlc_fourcc_t i_fourcc;
420 OMX_COLOR_FORMATTYPE i_codec;
421 unsigned int i_size_mul;
422 unsigned int i_line_mul;
423 unsigned int i_line_chroma_div;
425 } chroma_format_table[] =
427 { VLC_CODEC_I420, OMX_COLOR_FormatYUV420Planar, 3, 1, 2 },
428 { VLC_CODEC_I420, OMX_COLOR_FormatYUV420PackedPlanar, 3, 1, 2 },
429 { VLC_CODEC_NV12, OMX_COLOR_FormatYUV420SemiPlanar, 3, 1, 1 },
430 { VLC_CODEC_NV21, OMX_QCOM_COLOR_FormatYVU420SemiPlanar, 3, 1, 1 },
431 { VLC_CODEC_NV12, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar, 3, 1, 2 },
432 { VLC_CODEC_NV12, QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, 3, 1, 1 },
433 { VLC_CODEC_YUYV, OMX_COLOR_FormatYCbYCr, 4, 2, 0 },
434 { VLC_CODEC_YVYU, OMX_COLOR_FormatYCrYCb, 4, 2, 0 },
435 { VLC_CODEC_UYVY, OMX_COLOR_FormatCbYCrY, 4, 2, 0 },
436 { VLC_CODEC_VYUY, OMX_COLOR_FormatCrYCbY, 4, 2, 0 },
440 int GetOmxVideoFormat( vlc_fourcc_t i_fourcc,
441 OMX_VIDEO_CODINGTYPE *pi_omx_codec,
442 const char **ppsz_name )
446 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
448 for( i = 0; video_format_table[i].i_codec != 0; i++ )
449 if( video_format_table[i].i_fourcc == i_fourcc ) break;
451 if( pi_omx_codec ) *pi_omx_codec = video_format_table[i].i_codec;
452 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
453 return !!video_format_table[i].i_codec;
456 int GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec,
457 vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
461 for( i = 0; video_format_table[i].i_codec != 0; i++ )
462 if( video_format_table[i].i_codec == i_omx_codec ) break;
464 if( pi_fourcc ) *pi_fourcc = video_format_table[i].i_fourcc;
465 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
466 video_format_table[i].i_fourcc );
467 return !!video_format_table[i].i_fourcc;
470 static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc )
474 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
476 for( i = 0; video_format_table[i].i_codec != 0; i++ )
477 if( video_format_table[i].i_fourcc == i_fourcc ) break;
479 return video_format_table[i].psz_role;
482 static const char *GetOmxVideoEncRole( vlc_fourcc_t i_fourcc )
486 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
488 for( i = 0; video_enc_format_table[i].i_codec != 0; i++ )
489 if( video_enc_format_table[i].i_fourcc == i_fourcc ) break;
491 return video_enc_format_table[i].psz_role;
494 int GetOmxAudioFormat( vlc_fourcc_t i_fourcc,
495 OMX_AUDIO_CODINGTYPE *pi_omx_codec,
496 const char **ppsz_name )
500 i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
502 for( i = 0; audio_format_table[i].i_codec != 0; i++ )
503 if( audio_format_table[i].i_fourcc == i_fourcc ) break;
505 if( pi_omx_codec ) *pi_omx_codec = audio_format_table[i].i_codec;
506 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES, i_fourcc );
507 return !!audio_format_table[i].i_codec;
510 int OmxToVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec,
511 vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
515 for( i = 0; audio_format_table[i].i_codec != 0; i++ )
516 if( audio_format_table[i].i_codec == i_omx_codec ) break;
518 if( pi_fourcc ) *pi_fourcc = audio_format_table[i].i_fourcc;
519 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES,
520 audio_format_table[i].i_fourcc );
521 return !!audio_format_table[i].i_fourcc;
524 static const char *GetOmxAudioRole( vlc_fourcc_t i_fourcc )
528 i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
530 for( i = 0; audio_format_table[i].i_codec != 0; i++ )
531 if( audio_format_table[i].i_fourcc == i_fourcc ) break;
533 return audio_format_table[i].psz_role;
536 static const char *GetOmxAudioEncRole( vlc_fourcc_t i_fourcc )
540 i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
542 for( i = 0; audio_enc_format_table[i].i_codec != 0; i++ )
543 if( audio_enc_format_table[i].i_fourcc == i_fourcc ) break;
545 return audio_enc_format_table[i].psz_role;
548 const char *GetOmxRole( vlc_fourcc_t i_fourcc, int i_cat, bool b_enc )
551 return i_cat == VIDEO_ES ?
552 GetOmxVideoEncRole( i_fourcc ) : GetOmxAudioEncRole( i_fourcc );
554 return i_cat == VIDEO_ES ?
555 GetOmxVideoRole( i_fourcc ) : GetOmxAudioRole( i_fourcc );
558 int GetOmxChromaFormat( vlc_fourcc_t i_fourcc,
559 OMX_COLOR_FORMATTYPE *pi_omx_codec,
560 const char **ppsz_name )
564 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
566 for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
567 if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
569 if( pi_omx_codec ) *pi_omx_codec = chroma_format_table[i].i_codec;
570 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
571 return !!chroma_format_table[i].i_codec;
574 int GetVlcChromaFormat( OMX_COLOR_FORMATTYPE i_omx_codec,
575 vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
579 for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
580 if( chroma_format_table[i].i_codec == i_omx_codec ) break;
582 if( pi_fourcc ) *pi_fourcc = chroma_format_table[i].i_fourcc;
583 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
584 chroma_format_table[i].i_fourcc );
585 return !!chroma_format_table[i].i_fourcc;
588 int GetVlcChromaSizes( vlc_fourcc_t i_fourcc,
589 unsigned int width, unsigned int height,
590 unsigned int *size, unsigned int *pitch,
591 unsigned int *chroma_pitch_div )
595 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
597 for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
598 if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
600 /* Align on macroblock boundary */
601 width = (width + 15) & ~0xF;
602 height = (height + 15) & ~0xF;
604 if( size ) *size = width * height * chroma_format_table[i].i_size_mul / 2;
605 if( pitch ) *pitch = width * chroma_format_table[i].i_line_mul;
606 if( chroma_pitch_div )
607 *chroma_pitch_div = chroma_format_table[i].i_line_chroma_div;
608 return !!chroma_format_table[i].i_codec;
611 /*****************************************************************************
612 * Functions to deal with audio format parameters
613 *****************************************************************************/
614 static const struct {
615 OMX_AUDIO_CODINGTYPE encoding;
618 } audio_encoding_param[] =
619 { { OMX_AUDIO_CodingPCM, OMX_IndexParamAudioPcm,
620 sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
621 { OMX_AUDIO_CodingADPCM, OMX_IndexParamAudioAdpcm,
622 sizeof(OMX_AUDIO_PARAM_ADPCMTYPE) },
623 { OMX_AUDIO_CodingAMR, OMX_IndexParamAudioAmr,
624 sizeof(OMX_AUDIO_PARAM_AMRTYPE) },
625 { OMX_AUDIO_CodingG711, OMX_IndexParamAudioPcm,
626 sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
627 { OMX_AUDIO_CodingG723, OMX_IndexParamAudioG723,
628 sizeof(OMX_AUDIO_PARAM_G723TYPE) },
629 { OMX_AUDIO_CodingG726, OMX_IndexParamAudioG726,
630 sizeof(OMX_AUDIO_PARAM_G726TYPE) },
631 { OMX_AUDIO_CodingG729, OMX_IndexParamAudioG729,
632 sizeof(OMX_AUDIO_PARAM_G729TYPE) },
633 { OMX_AUDIO_CodingAAC, OMX_IndexParamAudioAac,
634 sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE) },
635 { OMX_AUDIO_CodingMP3, OMX_IndexParamAudioMp3,
636 sizeof(OMX_AUDIO_PARAM_MP3TYPE) },
637 { OMX_AUDIO_CodingSBC, OMX_IndexParamAudioSbc,
638 sizeof(OMX_AUDIO_PARAM_SBCTYPE) },
639 { OMX_AUDIO_CodingVORBIS, OMX_IndexParamAudioVorbis,
640 sizeof(OMX_AUDIO_PARAM_VORBISTYPE) },
641 { OMX_AUDIO_CodingWMA, OMX_IndexParamAudioWma,
642 sizeof(OMX_AUDIO_PARAM_WMATYPE) },
643 { OMX_AUDIO_CodingRA, OMX_IndexParamAudioRa,
644 sizeof(OMX_AUDIO_PARAM_RATYPE) },
645 { OMX_AUDIO_CodingUnused, 0, 0 }
648 static OMX_INDEXTYPE GetAudioParamFormatIndex(OMX_AUDIO_CODINGTYPE encoding)
652 for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
653 audio_encoding_param[i].encoding != encoding; i++);
655 return audio_encoding_param[i].index;
658 unsigned int GetAudioParamSize(OMX_INDEXTYPE index)
662 for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
663 audio_encoding_param[i].index != index; i++);
665 return audio_encoding_param[i].size;
668 OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
669 OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
670 vlc_fourcc_t i_codec, uint8_t i_channels, unsigned int i_samplerate,
671 unsigned int i_bitrate, unsigned int i_bps, unsigned int i_blocksize)
677 case OMX_AUDIO_CodingPCM:
678 case OMX_AUDIO_CodingG711:
679 OMX_INIT_STRUCTURE(param->pcm);
680 param->pcm.nChannels = i_channels;
681 param->pcm.nSamplingRate = i_samplerate;
682 param->pcm.eNumData = OMX_NumericalDataSigned;
683 param->pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
684 param->pcm.eEndian = OMX_EndianLittle;
685 param->pcm.bInterleaved = OMX_TRUE;
686 param->pcm.nBitPerSample = i_bps;
687 param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
690 param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
691 param->pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
694 case OMX_AUDIO_CodingADPCM:
695 OMX_INIT_STRUCTURE(param->adpcm);
696 param->adpcm.nChannels = i_channels;
697 param->adpcm.nSampleRate = i_samplerate;
698 param->adpcm.nBitsPerSample = i_bps;
700 case OMX_AUDIO_CodingAMR:
701 OMX_INIT_STRUCTURE(param->amr);
702 param->amr.nChannels = i_channels;
703 param->amr.nBitRate = i_bitrate;
704 if (i_codec == VLC_CODEC_AMR_WB)
705 param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
707 param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
708 param->amr.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
709 param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
711 case OMX_AUDIO_CodingG723:
712 OMX_INIT_STRUCTURE(param->g723);
713 param->g723.nChannels = i_channels;
714 param->g723.bDTX = OMX_FALSE;
715 param->g723.eBitRate = OMX_AUDIO_G723ModeUnused;
716 param->g723.bHiPassFilter = OMX_TRUE;
717 param->g723.bPostFilter = OMX_TRUE;
719 case OMX_AUDIO_CodingG726:
720 OMX_INIT_STRUCTURE(param->g726);
721 param->g726.nChannels = i_channels;
722 param->g726.eG726Mode = OMX_AUDIO_G726ModeUnused;
724 case OMX_AUDIO_CodingG729:
725 OMX_INIT_STRUCTURE(param->g729);
726 param->g729.nChannels = i_channels;
727 param->g729.bDTX = OMX_FALSE;
728 param->g729.eBitType = OMX_AUDIO_G729;
730 case OMX_AUDIO_CodingAAC:
731 OMX_INIT_STRUCTURE(param->aac);
732 param->aac.nChannels = i_channels;
733 param->aac.nSampleRate = i_samplerate;
734 param->aac.nBitRate = i_bitrate;
735 param->aac.nAudioBandWidth = 0;
736 param->aac.nFrameLength = 1024;
737 param->aac.nAACtools = OMX_AUDIO_AACToolAll;
738 param->aac.nAACERtools = OMX_AUDIO_AACERAll;
739 param->aac.eAACProfile = OMX_AUDIO_AACObjectLC;
740 param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
741 param->aac.eChannelMode = i_channels > 1 ?
742 OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
744 case OMX_AUDIO_CodingMP3:
745 OMX_INIT_STRUCTURE(param->mp3);
746 param->mp3.nChannels = i_channels;
747 param->mp3.nSampleRate = i_samplerate;
748 param->mp3.nBitRate = i_bitrate;
749 param->mp3.eChannelMode = i_channels > 1 ?
750 OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
751 param->mp3.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
753 case OMX_AUDIO_CodingWMA:
754 OMX_INIT_STRUCTURE(param->wma);
755 param->wma.nChannels = i_channels;
756 param->wma.nBitRate = i_bitrate;
757 param->wma.eFormat = OMX_AUDIO_WMAFormatUnused;
758 param->wma.eProfile = OMX_AUDIO_WMAProfileUnused;
759 param->wma.nSamplingRate = i_samplerate;
760 param->wma.nBlockAlign = i_blocksize;
761 param->wma.nEncodeOptions = 0;
762 param->wma.nSuperBlockAlign = 0;
764 case OMX_AUDIO_CodingRA:
765 OMX_INIT_STRUCTURE(param->ra);
766 param->ra.nChannels = i_channels;
767 param->ra.nSamplingRate = i_samplerate;
768 param->ra.nBitsPerFrame = i_bps;
769 param->ra.nSamplePerFrame = 0;
770 param->ra.nCouplingQuantBits = 0;
771 param->ra.nCouplingStartRegion = 0;
772 param->ra.nNumRegions = 0;
773 param->ra.eFormat = OMX_AUDIO_RAFormatUnused;
775 case OMX_AUDIO_CodingVORBIS:
776 OMX_INIT_STRUCTURE(param->vorbis);
777 param->vorbis.nChannels = i_channels;
778 param->vorbis.nBitRate = i_bitrate;
779 param->vorbis.nMinBitRate = 0;
780 param->vorbis.nMaxBitRate = i_bitrate;
781 param->vorbis.nSampleRate = i_samplerate;
782 param->vorbis.nAudioBandWidth = 0;
783 param->vorbis.nQuality = 3;
784 param->vorbis.bManaged = OMX_FALSE;
785 param->vorbis.bDownmix = OMX_FALSE;
788 return OMX_ErrorBadParameter;
791 param->common.nPortIndex = i_port;
793 index = GetAudioParamFormatIndex(encoding);
794 return OMX_SetParameter(handle, index, param);
797 OMX_ERRORTYPE GetAudioParameters(OMX_HANDLETYPE handle,
798 OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
799 uint8_t *pi_channels, unsigned int *pi_samplerate,
800 unsigned int *pi_bitrate, unsigned int *pi_bps, unsigned int *pi_blocksize)
802 int i_channels = 0, i_samplerate = 0, i_bitrate = 0;
803 int i_bps = 0, i_blocksize = 0;
804 OMX_ERRORTYPE omx_error;
807 OMX_INIT_COMMON(param->common);
808 param->common.nPortIndex = i_port;
809 index = GetAudioParamFormatIndex(encoding);
810 if(!index) return OMX_ErrorNotImplemented;
812 param->common.nSize = GetAudioParamSize(index);
813 omx_error = OMX_GetParameter(handle, index, param);
814 if(omx_error != OMX_ErrorNone) return omx_error;
818 case OMX_AUDIO_CodingPCM:
819 case OMX_AUDIO_CodingG711:
820 i_channels = param->pcm.nChannels;
821 i_samplerate = param->pcm.nSamplingRate;
822 i_bps = param->pcm.nBitPerSample;
824 case OMX_AUDIO_CodingADPCM:
825 i_channels = param->adpcm.nChannels;
826 i_samplerate = param->adpcm.nSampleRate;
827 i_bps = param->adpcm.nBitsPerSample;
829 case OMX_AUDIO_CodingAMR:
830 i_channels = param->amr.nChannels;
831 i_bitrate = param->amr.nBitRate;
834 case OMX_AUDIO_CodingG723:
835 i_channels = param->g723.nChannels;
837 case OMX_AUDIO_CodingG726:
838 i_channels = param->g726.nChannels;
840 case OMX_AUDIO_CodingG729:
841 i_channels = param->g729.nChannels;
843 case OMX_AUDIO_CodingAAC:
844 i_channels = param->aac.nChannels;
845 i_samplerate = param->aac.nSampleRate;
846 i_bitrate = param->aac.nBitRate;
847 i_channels = param->aac.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
849 case OMX_AUDIO_CodingMP3:
850 i_channels = param->mp3.nChannels;
851 i_samplerate = param->mp3.nSampleRate;
852 i_bitrate = param->mp3.nBitRate;
853 i_channels = param->mp3.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
855 case OMX_AUDIO_CodingVORBIS:
856 i_channels = param->vorbis.nChannels;
857 i_bitrate = param->vorbis.nBitRate;
858 i_samplerate = param->vorbis.nSampleRate;
860 case OMX_AUDIO_CodingWMA:
861 i_channels = param->wma.nChannels;
862 i_bitrate = param->wma.nBitRate;
863 i_samplerate = param->wma.nSamplingRate;
864 i_blocksize = param->wma.nBlockAlign;
866 case OMX_AUDIO_CodingRA:
867 i_channels = param->ra.nChannels;
868 i_samplerate = param->ra.nSamplingRate;
869 i_bps = param->ra.nBitsPerFrame;
872 return OMX_ErrorBadParameter;
875 if(pi_channels) *pi_channels = i_channels;
876 if(pi_samplerate) *pi_samplerate = i_samplerate;
877 if(pi_bitrate) *pi_bitrate = i_bitrate;
878 if(pi_bps) *pi_bps = i_bps;
879 if(pi_blocksize) *pi_blocksize = i_blocksize;
880 return OMX_ErrorNone;
883 /*****************************************************************************
884 * PrintOmx: print component summary
885 *****************************************************************************/
886 void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
888 OMX_PARAM_PORTDEFINITIONTYPE definition;
889 OMX_PORT_PARAM_TYPE param;
890 OMX_ERRORTYPE omx_error;
893 /* Find the input / output ports */
894 OMX_INIT_STRUCTURE(param);
895 OMX_INIT_STRUCTURE(definition);
897 for(i = 0; i < 3; i++)
899 omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamAudioInit + i, ¶m);
900 if(omx_error != OMX_ErrorNone) continue;
902 if(i_port == OMX_ALL)
903 msg_Dbg( p_dec, "found %i %s ports", (int)param.nPorts,
904 i == 0 ? "audio" : i == 1 ? "image" : "video" );
906 for(j = 0; j < param.nPorts; j++)
908 unsigned int i_samplerate, i_bitrate;
909 unsigned int i_bitspersample, i_blockalign;
911 OmxFormatParam format_param;
912 vlc_fourcc_t i_fourcc;
913 const char *psz_name;
914 OMX_CONFIG_RECTTYPE crop_rect;
916 if(i_port != OMX_ALL && i_port != param.nStartPortNumber + j)
919 /* Get port definition */
920 definition.nPortIndex = param.nStartPortNumber + j;
921 omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
923 if(omx_error != OMX_ErrorNone) continue;
925 OMX_PARAM_U32TYPE u32param;
926 OMX_INIT_STRUCTURE(u32param);
927 u32param.nPortIndex = param.nStartPortNumber + j;
928 omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamNumAvailableStreams,
931 msg_Dbg( p_dec, "-> %s %i (%i streams) (%i:%i:%i buffers) (%i,%i) %s",
932 definition.eDir == OMX_DirOutput ? "output" : "input",
933 (int)definition.nPortIndex, (int)u32param.nU32,
934 (int)definition.nBufferCountActual,
935 (int)definition.nBufferCountMin, (int)definition.nBufferSize,
936 (int)definition.bBuffersContiguous,
937 (int)definition.nBufferAlignment,
938 definition.bEnabled ? "enabled" : "disabled" );
940 switch(definition.eDomain)
942 case OMX_PortDomainVideo:
944 if(definition.format.video.eCompressionFormat)
945 GetVlcVideoFormat( definition.format.video.eCompressionFormat,
946 &i_fourcc, &psz_name );
948 GetVlcChromaFormat( definition.format.video.eColorFormat,
949 &i_fourcc, &psz_name );
951 OMX_INIT_STRUCTURE(crop_rect);
952 crop_rect.nPortIndex = definition.nPortIndex;
953 omx_error = OMX_GetConfig(omx_handle, OMX_IndexConfigCommonOutputCrop, &crop_rect);
954 if (omx_error != OMX_ErrorNone)
956 crop_rect.nLeft = crop_rect.nTop = 0;
957 crop_rect.nWidth = definition.format.video.nFrameWidth;
958 crop_rect.nHeight = definition.format.video.nFrameHeight;
961 msg_Dbg( p_dec, " -> video %s %ix%i@%.2f (%i,%i) (%i,%i) (%i,%i,%i,%i)", psz_name,
962 (int)definition.format.video.nFrameWidth,
963 (int)definition.format.video.nFrameHeight,
964 (float)definition.format.video.xFramerate/(float)(1<<16),
965 (int)definition.format.video.eCompressionFormat,
966 (int)definition.format.video.eColorFormat,
967 (int)definition.format.video.nStride,
968 (int)definition.format.video.nSliceHeight,
969 (int)crop_rect.nLeft, (int)crop_rect.nTop,
970 (int)crop_rect.nWidth, (int)crop_rect.nHeight);
973 case OMX_PortDomainAudio:
975 OmxToVlcAudioFormat( definition.format.audio.eEncoding,
976 &i_fourcc, &psz_name );
978 GetAudioParameters(omx_handle, &format_param,
979 definition.nPortIndex,
980 definition.format.audio.eEncoding,
981 &i_channels, &i_samplerate, &i_bitrate,
982 &i_bitspersample, &i_blockalign);
984 msg_Dbg( p_dec, " -> audio %s (%i) %i,%i,%i,%i,%i", psz_name,
985 (int)definition.format.audio.eEncoding,
986 i_channels, i_samplerate, i_bitrate, i_bitspersample,