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 OMX_ERRORTYPE
PostOmxEvent(decoder_t
*p_dec
, OMX_EVENTTYPE event
,
44 OMX_U32 data_1
, OMX_U32 data_2
, OMX_PTR event_data
)
46 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
49 p_event
= malloc(sizeof(OmxEvent
));
50 if(!p_event
) return OMX_ErrorInsufficientResources
;
52 p_event
->event
= event
;
53 p_event
->data_1
= data_1
;
54 p_event
->data_2
= data_2
;
55 p_event
->event_data
= event_data
;
58 vlc_mutex_lock(&p_sys
->mutex
);
59 *p_sys
->pp_last_event
= p_event
;
60 p_sys
->pp_last_event
= &p_event
->next
;
61 vlc_cond_signal(&p_sys
->cond
);
62 vlc_mutex_unlock(&p_sys
->mutex
);
66 OMX_ERRORTYPE
WaitForOmxEvent(decoder_t
*p_dec
, OMX_EVENTTYPE
*event
,
67 OMX_U32
*data_1
, OMX_U32
*data_2
, OMX_PTR
*event_data
)
69 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
72 vlc_mutex_lock(&p_sys
->mutex
);
75 vlc_cond_timedwait(&p_sys
->cond
, &p_sys
->mutex
, mdate()+CLOCK_FREQ
);
77 p_event
= p_sys
->p_events
;
80 p_sys
->p_events
= p_event
->next
;
81 if(!p_sys
->p_events
) p_sys
->pp_last_event
= &p_sys
->p_events
;
84 vlc_mutex_unlock(&p_sys
->mutex
);
88 if(event
) *event
= p_event
->event
;
89 if(data_1
) *data_1
= p_event
->data_1
;
90 if(data_2
) *data_2
= p_event
->data_2
;
91 if(event_data
) *event_data
= p_event
->event_data
;
96 return OMX_ErrorTimeout
;
99 OMX_ERRORTYPE
WaitForSpecificOmxEvent(decoder_t
*p_dec
,
100 OMX_EVENTTYPE specific_event
, OMX_U32
*data_1
, OMX_U32
*data_2
,
103 OMX_ERRORTYPE status
;
105 mtime_t before
= mdate();
109 status
= WaitForOmxEvent(p_dec
, &event
, data_1
, data_2
, event_data
);
110 if(status
!= OMX_ErrorNone
) return status
;
112 if(event
== specific_event
) break;
113 if(mdate() - before
> CLOCK_FREQ
) return OMX_ErrorTimeout
;
116 return OMX_ErrorNone
;
119 void PrintOmxEvent(vlc_object_t
*p_this
, OMX_EVENTTYPE event
, OMX_U32 data_1
,
120 OMX_U32 data_2
, OMX_PTR event_data
)
124 case OMX_EventCmdComplete
:
125 switch ((OMX_STATETYPE
)data_1
)
127 case OMX_CommandStateSet
:
128 msg_Dbg( p_this
, "OmxEventHandler (%s, %s, %s)", EventToString(event
),
129 CommandToString(data_1
), StateToString(data_2
) );
133 msg_Dbg( p_this
, "OmxEventHandler (%s, %s, %u)", EventToString(event
),
134 CommandToString(data_1
), (unsigned int)data_2
);
140 msg_Dbg( p_this
, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event
),
141 ErrorToString((OMX_ERRORTYPE
)data_1
), (unsigned int)data_2
,
142 (const char *)event_data
);
146 msg_Dbg( p_this
, "OmxEventHandler (%s, %u, %u)", EventToString(event
),
147 (unsigned int)data_1
, (unsigned int)data_2
);
152 /*****************************************************************************
153 * Picture utility functions
154 *****************************************************************************/
155 void CopyOmxPicture( int i_color_format
, picture_t
*p_pic
,
157 int i_src_stride
, uint8_t *p_src
, int i_chroma_div
)
161 int i_plane
, i_width
, i_line
;
162 if( i_color_format
== QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
)
164 qcom_convert(p_src
, p_pic
);
168 for( i_plane
= 0; i_plane
< p_pic
->i_planes
; i_plane
++ )
170 if(i_plane
== 1) i_src_stride
/= i_chroma_div
;
171 p_dst
= p_pic
->p
[i_plane
].p_pixels
;
172 i_dst_stride
= p_pic
->p
[i_plane
].i_pitch
;
173 i_width
= p_pic
->p
[i_plane
].i_visible_pitch
;
175 for( i_line
= 0; i_line
< p_pic
->p
[i_plane
].i_visible_lines
; i_line
++ )
177 memcpy( p_dst
, p_src
, i_width
);
178 p_src
+= i_src_stride
;
179 p_dst
+= i_dst_stride
;
181 /* Handle plane height, which may be indicated via nSliceHeight in OMX.
182 * The handling for chroma planes currently assumes vertically
183 * subsampled chroma, e.g. 422 planar wouldn't work right. */
184 if( i_plane
== 0 && i_slice_height
> p_pic
->p
[i_plane
].i_visible_lines
)
185 p_src
+= i_src_stride
* (i_slice_height
- p_pic
->p
[i_plane
].i_visible_lines
);
186 else if ( i_plane
> 0 && i_slice_height
/2 > p_pic
->p
[i_plane
].i_visible_lines
)
187 p_src
+= i_src_stride
* (i_slice_height
/2 - p_pic
->p
[i_plane
].i_visible_lines
);
191 void CopyVlcPicture( decoder_t
*p_dec
, OMX_BUFFERHEADERTYPE
*p_header
,
194 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
195 int i_src_stride
, i_dst_stride
;
196 int i_plane
, i_width
, i_line
;
197 uint8_t *p_dst
, *p_src
;
199 i_dst_stride
= p_sys
->out
.i_frame_stride
;
200 p_dst
= p_header
->pBuffer
+ p_header
->nOffset
;
202 for( i_plane
= 0; i_plane
< p_pic
->i_planes
; i_plane
++ )
204 if(i_plane
== 1) i_dst_stride
/= p_sys
->in
.i_frame_stride_chroma_div
;
205 p_src
= p_pic
->p
[i_plane
].p_pixels
;
206 i_src_stride
= p_pic
->p
[i_plane
].i_pitch
;
207 i_width
= p_pic
->p
[i_plane
].i_visible_pitch
;
209 for( i_line
= 0; i_line
< p_pic
->p
[i_plane
].i_visible_lines
; i_line
++ )
211 memcpy( p_dst
, p_src
, i_width
);
212 p_src
+= i_src_stride
;
213 p_dst
+= i_dst_stride
;
218 int IgnoreOmxDecoderPadding(const char *name
)
220 // The list of decoders that signal padding properly is not necessary,
221 // since that is the default, but keep it here for reference. (This is
222 // only relevant for manufacturers that are known to have decoders with
223 // this kind of bug.)
225 static const char *padding_decoders[] = {
226 "OMX.SEC.AVC.Decoder",
232 static const char *nopadding_decoders
[] = {
235 "OMX.SEC.MPEG4.Decoder",
240 for (const char **ptr
= nopadding_decoders
; *ptr
; ptr
++) {
241 if (!strcmp(*ptr
, name
))
247 /*****************************************************************************
248 * Logging utility functions
249 *****************************************************************************/
250 const char *StateToString(OMX_STATETYPE state
)
252 static const char *psz_names
[] = {
253 "OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
254 "OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
258 if((unsigned int)state
> sizeof(psz_names
)/sizeof(char*)-1)
259 state
= (OMX_STATETYPE
)(sizeof(psz_names
)/sizeof(char*)-1);
260 return psz_names
[state
];
263 const char *CommandToString(OMX_COMMANDTYPE command
)
265 static const char *psz_names
[] = {
266 "OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
267 "OMX_CommandPortEnable", "OMX_CommandMarkBuffer",
268 "OMX_Command unknown"
271 if((unsigned int)command
> sizeof(psz_names
)/sizeof(char*)-1)
272 command
= (OMX_COMMANDTYPE
)(sizeof(psz_names
)/sizeof(char*)-1);
273 return psz_names
[command
];
276 const char *EventToString(OMX_EVENTTYPE event
)
278 static const char *psz_names
[] = {
279 "OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
280 "OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
281 "OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
282 "OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
286 if((unsigned int)event
> sizeof(psz_names
)/sizeof(char*)-1)
287 event
= (OMX_EVENTTYPE
)(sizeof(psz_names
)/sizeof(char*)-1);
288 return psz_names
[event
];
291 const char *ErrorToString(OMX_ERRORTYPE error
)
293 static const char *psz_names
[] = {
294 "OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
295 "OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
296 "OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
297 "OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
298 "OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
299 "OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
300 "OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
301 "OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
302 "OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
303 "OMX_ErrorPortUnresponsiveDuringDeallocation",
304 "OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
305 "OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
306 "OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
307 "OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
308 "OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
309 "OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
310 "OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
311 "OMX_ErrorTunnelingUnsupported",
315 if(error
== OMX_ErrorNone
) return "OMX_ErrorNone";
317 error
-= OMX_ErrorInsufficientResources
;
319 if((unsigned int)error
> sizeof(psz_names
)/sizeof(char*)-1)
320 error
= (OMX_STATETYPE
)(sizeof(psz_names
)/sizeof(char*)-1);
321 return psz_names
[error
];
324 /*****************************************************************************
325 * fourcc -> omx id mapping
326 *****************************************************************************/
329 vlc_fourcc_t i_fourcc
;
330 OMX_VIDEO_CODINGTYPE i_codec
;
331 const char *psz_role
;
333 } video_format_table
[] =
335 { VLC_CODEC_MPGV
, OMX_VIDEO_CodingMPEG2
, "video_decoder.mpeg2" },
336 { VLC_CODEC_MP4V
, OMX_VIDEO_CodingMPEG4
, "video_decoder.mpeg4" },
337 { VLC_CODEC_H264
, OMX_VIDEO_CodingAVC
, "video_decoder.avc" },
338 { VLC_CODEC_H263
, OMX_VIDEO_CodingH263
, "video_decoder.h263" },
339 { VLC_CODEC_WMV1
, OMX_VIDEO_CodingWMV
, "video_decoder.wmv1" },
340 { VLC_CODEC_WMV2
, OMX_VIDEO_CodingWMV
, "video_decoder.wmv2" },
341 { VLC_CODEC_WMV3
, OMX_VIDEO_CodingWMV
, "video_decoder.wmv" },
342 { VLC_CODEC_VC1
, OMX_VIDEO_CodingWMV
, "video_decoder.wmv" },
343 { VLC_CODEC_MJPG
, OMX_VIDEO_CodingMJPEG
, "video_decoder.jpeg" },
344 { VLC_CODEC_MJPG
, OMX_VIDEO_CodingMJPEG
, "video_decoder.mjpeg" },
345 { VLC_CODEC_RV10
, OMX_VIDEO_CodingRV
, "video_decoder.rv" },
346 { VLC_CODEC_RV20
, OMX_VIDEO_CodingRV
, "video_decoder.rv" },
347 { VLC_CODEC_RV30
, OMX_VIDEO_CodingRV
, "video_decoder.rv" },
348 { VLC_CODEC_RV40
, OMX_VIDEO_CodingRV
, "video_decoder.rv" },
354 vlc_fourcc_t i_fourcc
;
355 OMX_AUDIO_CODINGTYPE i_codec
;
356 const char *psz_role
;
358 } audio_format_table
[] =
360 { VLC_CODEC_AMR_NB
, OMX_AUDIO_CodingAMR
, "audio_decoder.amrnb" },
361 { VLC_CODEC_AMR_WB
, OMX_AUDIO_CodingAMR
, "audio_decoder.amrwb" },
362 { VLC_CODEC_MP4A
, OMX_AUDIO_CodingAAC
, "audio_decoder.aac" },
363 { VLC_CODEC_S16N
, OMX_AUDIO_CodingPCM
, "audio_decoder.pcm" },
364 { VLC_CODEC_MP3
, OMX_AUDIO_CodingMP3
, "audio_decoder.mp3" },
370 vlc_fourcc_t i_fourcc
;
371 OMX_VIDEO_CODINGTYPE i_codec
;
372 const char *psz_role
;
374 } video_enc_format_table
[] =
376 { VLC_CODEC_MPGV
, OMX_VIDEO_CodingMPEG2
, "video_encoder.mpeg2" },
377 { VLC_CODEC_MP4V
, OMX_VIDEO_CodingMPEG4
, "video_encoder.mpeg4" },
378 { VLC_CODEC_H264
, OMX_VIDEO_CodingAVC
, "video_encoder.avc" },
379 { VLC_CODEC_H263
, OMX_VIDEO_CodingH263
, "video_encoder.h263" },
380 { VLC_CODEC_WMV1
, OMX_VIDEO_CodingWMV
, "video_encoder.wmv" },
381 { VLC_CODEC_WMV2
, OMX_VIDEO_CodingWMV
, "video_encoder.wmv" },
382 { VLC_CODEC_WMV3
, OMX_VIDEO_CodingWMV
, "video_encoder.wmv" },
383 { VLC_CODEC_MJPG
, OMX_VIDEO_CodingMJPEG
, "video_encoder.jpeg" },
384 { VLC_CODEC_RV10
, OMX_VIDEO_CodingRV
, "video_encoder.rv" },
385 { VLC_CODEC_RV20
, OMX_VIDEO_CodingRV
, "video_encoder.rv" },
386 { VLC_CODEC_RV30
, OMX_VIDEO_CodingRV
, "video_encoder.rv" },
387 { VLC_CODEC_RV40
, OMX_VIDEO_CodingRV
, "video_encoder.rv" },
393 vlc_fourcc_t i_fourcc
;
394 OMX_AUDIO_CODINGTYPE i_codec
;
395 const char *psz_role
;
397 } audio_enc_format_table
[] =
399 { VLC_CODEC_AMR_NB
, OMX_AUDIO_CodingAMR
, "audio_encoder.amrnb" },
400 { VLC_CODEC_AMR_WB
, OMX_AUDIO_CodingAMR
, "audio_encoder.amrwb" },
401 { VLC_CODEC_MP4A
, OMX_AUDIO_CodingAAC
, "audio_encoder.aac" },
402 { VLC_CODEC_S16N
, OMX_AUDIO_CodingPCM
, "audio_encoder.pcm" },
408 vlc_fourcc_t i_fourcc
;
409 OMX_COLOR_FORMATTYPE i_codec
;
410 unsigned int i_size_mul
;
411 unsigned int i_line_mul
;
412 unsigned int i_line_chroma_div
;
414 } chroma_format_table
[] =
416 { VLC_CODEC_I420
, OMX_COLOR_FormatYUV420Planar
, 3, 1, 2 },
417 { VLC_CODEC_I420
, OMX_COLOR_FormatYUV420PackedPlanar
, 3, 1, 2 },
418 { VLC_CODEC_NV12
, OMX_COLOR_FormatYUV420SemiPlanar
, 3, 1, 1 },
419 { VLC_CODEC_NV21
, OMX_QCOM_COLOR_FormatYVU420SemiPlanar
, 3, 1, 1 },
420 { VLC_CODEC_NV12
, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
, 3, 1, 2 },
421 { VLC_CODEC_NV12
, QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
, 3, 1, 1 },
422 { VLC_CODEC_YUYV
, OMX_COLOR_FormatYCbYCr
, 4, 2, 0 },
423 { VLC_CODEC_YVYU
, OMX_COLOR_FormatYCrYCb
, 4, 2, 0 },
424 { VLC_CODEC_UYVY
, OMX_COLOR_FormatCbYCrY
, 4, 2, 0 },
425 { VLC_CODEC_VYUY
, OMX_COLOR_FormatCrYCbY
, 4, 2, 0 },
429 int GetOmxVideoFormat( vlc_fourcc_t i_fourcc
,
430 OMX_VIDEO_CODINGTYPE
*pi_omx_codec
,
431 const char **ppsz_name
)
435 i_fourcc
= vlc_fourcc_GetCodec( VIDEO_ES
, i_fourcc
);
437 for( i
= 0; video_format_table
[i
].i_codec
!= 0; i
++ )
438 if( video_format_table
[i
].i_fourcc
== i_fourcc
) break;
440 if( pi_omx_codec
) *pi_omx_codec
= video_format_table
[i
].i_codec
;
441 if( ppsz_name
) *ppsz_name
= vlc_fourcc_GetDescription( VIDEO_ES
, i_fourcc
);
442 return !!video_format_table
[i
].i_codec
;
445 int GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec
,
446 vlc_fourcc_t
*pi_fourcc
, const char **ppsz_name
)
450 for( i
= 0; video_format_table
[i
].i_codec
!= 0; i
++ )
451 if( video_format_table
[i
].i_codec
== i_omx_codec
) break;
453 if( pi_fourcc
) *pi_fourcc
= video_format_table
[i
].i_fourcc
;
454 if( ppsz_name
) *ppsz_name
= vlc_fourcc_GetDescription( VIDEO_ES
,
455 video_format_table
[i
].i_fourcc
);
456 return !!video_format_table
[i
].i_fourcc
;
459 static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc
)
463 i_fourcc
= vlc_fourcc_GetCodec( VIDEO_ES
, i_fourcc
);
465 for( i
= 0; video_format_table
[i
].i_codec
!= 0; i
++ )
466 if( video_format_table
[i
].i_fourcc
== i_fourcc
) break;
468 return video_format_table
[i
].psz_role
;
471 static const char *GetOmxVideoEncRole( vlc_fourcc_t i_fourcc
)
475 i_fourcc
= vlc_fourcc_GetCodec( VIDEO_ES
, i_fourcc
);
477 for( i
= 0; video_enc_format_table
[i
].i_codec
!= 0; i
++ )
478 if( video_enc_format_table
[i
].i_fourcc
== i_fourcc
) break;
480 return video_enc_format_table
[i
].psz_role
;
483 int GetOmxAudioFormat( vlc_fourcc_t i_fourcc
,
484 OMX_AUDIO_CODINGTYPE
*pi_omx_codec
,
485 const char **ppsz_name
)
489 i_fourcc
= vlc_fourcc_GetCodec( AUDIO_ES
, i_fourcc
);
491 for( i
= 0; audio_format_table
[i
].i_codec
!= 0; i
++ )
492 if( audio_format_table
[i
].i_fourcc
== i_fourcc
) break;
494 if( pi_omx_codec
) *pi_omx_codec
= audio_format_table
[i
].i_codec
;
495 if( ppsz_name
) *ppsz_name
= vlc_fourcc_GetDescription( AUDIO_ES
, i_fourcc
);
496 return !!audio_format_table
[i
].i_codec
;
499 int OmxToVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec
,
500 vlc_fourcc_t
*pi_fourcc
, const char **ppsz_name
)
504 for( i
= 0; audio_format_table
[i
].i_codec
!= 0; i
++ )
505 if( audio_format_table
[i
].i_codec
== i_omx_codec
) break;
507 if( pi_fourcc
) *pi_fourcc
= audio_format_table
[i
].i_fourcc
;
508 if( ppsz_name
) *ppsz_name
= vlc_fourcc_GetDescription( AUDIO_ES
,
509 audio_format_table
[i
].i_fourcc
);
510 return !!audio_format_table
[i
].i_fourcc
;
513 static const char *GetOmxAudioRole( vlc_fourcc_t i_fourcc
)
517 i_fourcc
= vlc_fourcc_GetCodec( AUDIO_ES
, i_fourcc
);
519 for( i
= 0; audio_format_table
[i
].i_codec
!= 0; i
++ )
520 if( audio_format_table
[i
].i_fourcc
== i_fourcc
) break;
522 return audio_format_table
[i
].psz_role
;
525 static const char *GetOmxAudioEncRole( vlc_fourcc_t i_fourcc
)
529 i_fourcc
= vlc_fourcc_GetCodec( AUDIO_ES
, i_fourcc
);
531 for( i
= 0; audio_enc_format_table
[i
].i_codec
!= 0; i
++ )
532 if( audio_enc_format_table
[i
].i_fourcc
== i_fourcc
) break;
534 return audio_enc_format_table
[i
].psz_role
;
537 const char *GetOmxRole( vlc_fourcc_t i_fourcc
, int i_cat
, bool b_enc
)
540 return i_cat
== VIDEO_ES
?
541 GetOmxVideoEncRole( i_fourcc
) : GetOmxAudioEncRole( i_fourcc
);
543 return i_cat
== VIDEO_ES
?
544 GetOmxVideoRole( i_fourcc
) : GetOmxAudioRole( i_fourcc
);
547 int GetOmxChromaFormat( vlc_fourcc_t i_fourcc
,
548 OMX_COLOR_FORMATTYPE
*pi_omx_codec
,
549 const char **ppsz_name
)
553 i_fourcc
= vlc_fourcc_GetCodec( VIDEO_ES
, i_fourcc
);
555 for( i
= 0; chroma_format_table
[i
].i_codec
!= 0; i
++ )
556 if( chroma_format_table
[i
].i_fourcc
== i_fourcc
) break;
558 if( pi_omx_codec
) *pi_omx_codec
= chroma_format_table
[i
].i_codec
;
559 if( ppsz_name
) *ppsz_name
= vlc_fourcc_GetDescription( VIDEO_ES
, i_fourcc
);
560 return !!chroma_format_table
[i
].i_codec
;
563 int GetVlcChromaFormat( OMX_COLOR_FORMATTYPE i_omx_codec
,
564 vlc_fourcc_t
*pi_fourcc
, const char **ppsz_name
)
568 for( i
= 0; chroma_format_table
[i
].i_codec
!= 0; i
++ )
569 if( chroma_format_table
[i
].i_codec
== i_omx_codec
) break;
571 if( pi_fourcc
) *pi_fourcc
= chroma_format_table
[i
].i_fourcc
;
572 if( ppsz_name
) *ppsz_name
= vlc_fourcc_GetDescription( VIDEO_ES
,
573 chroma_format_table
[i
].i_fourcc
);
574 return !!chroma_format_table
[i
].i_fourcc
;
577 int GetVlcChromaSizes( vlc_fourcc_t i_fourcc
,
578 unsigned int width
, unsigned int height
,
579 unsigned int *size
, unsigned int *pitch
,
580 unsigned int *chroma_pitch_div
)
584 i_fourcc
= vlc_fourcc_GetCodec( VIDEO_ES
, i_fourcc
);
586 for( i
= 0; chroma_format_table
[i
].i_codec
!= 0; i
++ )
587 if( chroma_format_table
[i
].i_fourcc
== i_fourcc
) break;
589 /* Align on macroblock boundary */
590 width
= (width
+ 15) & ~0xF;
591 height
= (height
+ 15) & ~0xF;
593 if( size
) *size
= width
* height
* chroma_format_table
[i
].i_size_mul
/ 2;
594 if( pitch
) *pitch
= width
* chroma_format_table
[i
].i_line_mul
;
595 if( chroma_pitch_div
)
596 *chroma_pitch_div
= chroma_format_table
[i
].i_line_chroma_div
;
597 return !!chroma_format_table
[i
].i_codec
;
600 /*****************************************************************************
601 * Functions to deal with audio format parameters
602 *****************************************************************************/
603 static const struct {
604 OMX_AUDIO_CODINGTYPE encoding
;
607 } audio_encoding_param
[] =
608 { { OMX_AUDIO_CodingPCM
, OMX_IndexParamAudioPcm
,
609 sizeof(OMX_AUDIO_PARAM_PCMMODETYPE
) },
610 { OMX_AUDIO_CodingADPCM
, OMX_IndexParamAudioAdpcm
,
611 sizeof(OMX_AUDIO_PARAM_ADPCMTYPE
) },
612 { OMX_AUDIO_CodingAMR
, OMX_IndexParamAudioAmr
,
613 sizeof(OMX_AUDIO_PARAM_AMRTYPE
) },
614 { OMX_AUDIO_CodingG711
, OMX_IndexParamAudioPcm
,
615 sizeof(OMX_AUDIO_PARAM_PCMMODETYPE
) },
616 { OMX_AUDIO_CodingG723
, OMX_IndexParamAudioG723
,
617 sizeof(OMX_AUDIO_PARAM_G723TYPE
) },
618 { OMX_AUDIO_CodingG726
, OMX_IndexParamAudioG726
,
619 sizeof(OMX_AUDIO_PARAM_G726TYPE
) },
620 { OMX_AUDIO_CodingG729
, OMX_IndexParamAudioG729
,
621 sizeof(OMX_AUDIO_PARAM_G729TYPE
) },
622 { OMX_AUDIO_CodingAAC
, OMX_IndexParamAudioAac
,
623 sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE
) },
624 { OMX_AUDIO_CodingMP3
, OMX_IndexParamAudioMp3
,
625 sizeof(OMX_AUDIO_PARAM_MP3TYPE
) },
626 { OMX_AUDIO_CodingSBC
, OMX_IndexParamAudioSbc
,
627 sizeof(OMX_AUDIO_PARAM_SBCTYPE
) },
628 { OMX_AUDIO_CodingVORBIS
, OMX_IndexParamAudioVorbis
,
629 sizeof(OMX_AUDIO_PARAM_VORBISTYPE
) },
630 { OMX_AUDIO_CodingWMA
, OMX_IndexParamAudioWma
,
631 sizeof(OMX_AUDIO_PARAM_WMATYPE
) },
632 { OMX_AUDIO_CodingRA
, OMX_IndexParamAudioRa
,
633 sizeof(OMX_AUDIO_PARAM_RATYPE
) },
634 { OMX_AUDIO_CodingUnused
, 0, 0 }
637 static OMX_INDEXTYPE
GetAudioParamFormatIndex(OMX_AUDIO_CODINGTYPE encoding
)
641 for(i
= 0; audio_encoding_param
[i
].encoding
!= OMX_AUDIO_CodingUnused
&&
642 audio_encoding_param
[i
].encoding
!= encoding
; i
++);
644 return audio_encoding_param
[i
].index
;
647 unsigned int GetAudioParamSize(OMX_INDEXTYPE index
)
651 for(i
= 0; audio_encoding_param
[i
].encoding
!= OMX_AUDIO_CodingUnused
&&
652 audio_encoding_param
[i
].index
!= index
; i
++);
654 return audio_encoding_param
[i
].size
;
657 OMX_ERRORTYPE
SetAudioParameters(OMX_HANDLETYPE handle
,
658 OmxFormatParam
*param
, OMX_U32 i_port
, OMX_AUDIO_CODINGTYPE encoding
,
659 vlc_fourcc_t i_codec
, uint8_t i_channels
, unsigned int i_samplerate
,
660 unsigned int i_bitrate
, unsigned int i_bps
, unsigned int i_blocksize
)
666 case OMX_AUDIO_CodingPCM
:
667 case OMX_AUDIO_CodingG711
:
668 OMX_INIT_STRUCTURE(param
->pcm
);
669 param
->pcm
.nChannels
= i_channels
;
670 param
->pcm
.nSamplingRate
= i_samplerate
;
671 param
->pcm
.eNumData
= OMX_NumericalDataSigned
;
672 param
->pcm
.ePCMMode
= OMX_AUDIO_PCMModeLinear
;
673 param
->pcm
.eEndian
= OMX_EndianLittle
;
674 param
->pcm
.bInterleaved
= OMX_TRUE
;
675 param
->pcm
.nBitPerSample
= i_bps
;
676 param
->pcm
.eChannelMapping
[0] = OMX_AUDIO_ChannelCF
;
679 param
->pcm
.eChannelMapping
[0] = OMX_AUDIO_ChannelLF
;
680 param
->pcm
.eChannelMapping
[1] = OMX_AUDIO_ChannelRF
;
683 case OMX_AUDIO_CodingADPCM
:
684 OMX_INIT_STRUCTURE(param
->adpcm
);
685 param
->adpcm
.nChannels
= i_channels
;
686 param
->adpcm
.nSampleRate
= i_samplerate
;
687 param
->adpcm
.nBitsPerSample
= i_bps
;
689 case OMX_AUDIO_CodingAMR
:
690 OMX_INIT_STRUCTURE(param
->amr
);
691 param
->amr
.nChannels
= i_channels
;
692 param
->amr
.nBitRate
= i_bitrate
;
693 if (i_codec
== VLC_CODEC_AMR_WB
)
694 param
->amr
.eAMRBandMode
= OMX_AUDIO_AMRBandModeWB0
;
696 param
->amr
.eAMRBandMode
= OMX_AUDIO_AMRBandModeNB0
;
697 param
->amr
.eAMRDTXMode
= OMX_AUDIO_AMRDTXModeOff
;
698 param
->amr
.eAMRFrameFormat
= OMX_AUDIO_AMRFrameFormatFSF
;
700 case OMX_AUDIO_CodingG723
:
701 OMX_INIT_STRUCTURE(param
->g723
);
702 param
->g723
.nChannels
= i_channels
;
703 param
->g723
.bDTX
= OMX_FALSE
;
704 param
->g723
.eBitRate
= OMX_AUDIO_G723ModeUnused
;
705 param
->g723
.bHiPassFilter
= OMX_TRUE
;
706 param
->g723
.bPostFilter
= OMX_TRUE
;
708 case OMX_AUDIO_CodingG726
:
709 OMX_INIT_STRUCTURE(param
->g726
);
710 param
->g726
.nChannels
= i_channels
;
711 param
->g726
.eG726Mode
= OMX_AUDIO_G726ModeUnused
;
713 case OMX_AUDIO_CodingG729
:
714 OMX_INIT_STRUCTURE(param
->g729
);
715 param
->g729
.nChannels
= i_channels
;
716 param
->g729
.bDTX
= OMX_FALSE
;
717 param
->g729
.eBitType
= OMX_AUDIO_G729
;
719 case OMX_AUDIO_CodingAAC
:
720 OMX_INIT_STRUCTURE(param
->aac
);
721 param
->aac
.nChannels
= i_channels
;
722 param
->aac
.nSampleRate
= i_samplerate
;
723 param
->aac
.nBitRate
= i_bitrate
;
724 param
->aac
.nAudioBandWidth
= 0;
725 param
->aac
.nFrameLength
= 1024;
726 param
->aac
.nAACtools
= OMX_AUDIO_AACToolAll
;
727 param
->aac
.nAACERtools
= OMX_AUDIO_AACERAll
;
728 param
->aac
.eAACProfile
= OMX_AUDIO_AACObjectLC
;
729 param
->aac
.eAACStreamFormat
= OMX_AUDIO_AACStreamFormatMP4FF
;
730 param
->aac
.eChannelMode
= i_channels
> 1 ?
731 OMX_AUDIO_ChannelModeStereo
: OMX_AUDIO_ChannelModeMono
;
733 case OMX_AUDIO_CodingMP3
:
734 OMX_INIT_STRUCTURE(param
->mp3
);
735 param
->mp3
.nChannels
= i_channels
;
736 param
->mp3
.nSampleRate
= i_samplerate
;
737 param
->mp3
.nBitRate
= i_bitrate
;
738 param
->mp3
.eChannelMode
= i_channels
> 1 ?
739 OMX_AUDIO_ChannelModeStereo
: OMX_AUDIO_ChannelModeMono
;
740 param
->mp3
.eFormat
= OMX_AUDIO_MP3StreamFormatMP1Layer3
;
742 case OMX_AUDIO_CodingWMA
:
743 OMX_INIT_STRUCTURE(param
->wma
);
744 param
->wma
.nChannels
= i_channels
;
745 param
->wma
.nBitRate
= i_bitrate
;
746 param
->wma
.eFormat
= OMX_AUDIO_WMAFormatUnused
;
747 param
->wma
.eProfile
= OMX_AUDIO_WMAProfileUnused
;
748 param
->wma
.nSamplingRate
= i_samplerate
;
749 param
->wma
.nBlockAlign
= i_blocksize
;
750 param
->wma
.nEncodeOptions
= 0;
751 param
->wma
.nSuperBlockAlign
= 0;
753 case OMX_AUDIO_CodingRA
:
754 OMX_INIT_STRUCTURE(param
->ra
);
755 param
->ra
.nChannels
= i_channels
;
756 param
->ra
.nSamplingRate
= i_samplerate
;
757 param
->ra
.nBitsPerFrame
= i_bps
;
758 param
->ra
.nSamplePerFrame
= 0;
759 param
->ra
.nCouplingQuantBits
= 0;
760 param
->ra
.nCouplingStartRegion
= 0;
761 param
->ra
.nNumRegions
= 0;
762 param
->ra
.eFormat
= OMX_AUDIO_RAFormatUnused
;
764 case OMX_AUDIO_CodingVORBIS
:
765 OMX_INIT_STRUCTURE(param
->vorbis
);
766 param
->vorbis
.nChannels
= i_channels
;
767 param
->vorbis
.nBitRate
= i_bitrate
;
768 param
->vorbis
.nMinBitRate
= 0;
769 param
->vorbis
.nMaxBitRate
= i_bitrate
;
770 param
->vorbis
.nSampleRate
= i_samplerate
;
771 param
->vorbis
.nAudioBandWidth
= 0;
772 param
->vorbis
.nQuality
= 3;
773 param
->vorbis
.bManaged
= OMX_FALSE
;
774 param
->vorbis
.bDownmix
= OMX_FALSE
;
777 return OMX_ErrorBadParameter
;
780 param
->common
.nPortIndex
= i_port
;
782 index
= GetAudioParamFormatIndex(encoding
);
783 return OMX_SetParameter(handle
, index
, param
);
786 OMX_ERRORTYPE
GetAudioParameters(OMX_HANDLETYPE handle
,
787 OmxFormatParam
*param
, OMX_U32 i_port
, OMX_AUDIO_CODINGTYPE encoding
,
788 uint8_t *pi_channels
, unsigned int *pi_samplerate
,
789 unsigned int *pi_bitrate
, unsigned int *pi_bps
, unsigned int *pi_blocksize
)
791 int i_channels
= 0, i_samplerate
= 0, i_bitrate
= 0;
792 int i_bps
= 0, i_blocksize
= 0;
793 OMX_ERRORTYPE omx_error
;
796 OMX_INIT_COMMON(param
->common
);
797 param
->common
.nPortIndex
= i_port
;
798 index
= GetAudioParamFormatIndex(encoding
);
799 if(!index
) return OMX_ErrorNotImplemented
;
801 param
->common
.nSize
= GetAudioParamSize(index
);
802 omx_error
= OMX_GetParameter(handle
, index
, param
);
803 if(omx_error
!= OMX_ErrorNone
) return omx_error
;
807 case OMX_AUDIO_CodingPCM
:
808 case OMX_AUDIO_CodingG711
:
809 i_channels
= param
->pcm
.nChannels
;
810 i_samplerate
= param
->pcm
.nSamplingRate
;
811 i_bps
= param
->pcm
.nBitPerSample
;
813 case OMX_AUDIO_CodingADPCM
:
814 i_channels
= param
->adpcm
.nChannels
;
815 i_samplerate
= param
->adpcm
.nSampleRate
;
816 i_bps
= param
->adpcm
.nBitsPerSample
;
818 case OMX_AUDIO_CodingAMR
:
819 i_channels
= param
->amr
.nChannels
;
820 i_bitrate
= param
->amr
.nBitRate
;
823 case OMX_AUDIO_CodingG723
:
824 i_channels
= param
->g723
.nChannels
;
826 case OMX_AUDIO_CodingG726
:
827 i_channels
= param
->g726
.nChannels
;
829 case OMX_AUDIO_CodingG729
:
830 i_channels
= param
->g729
.nChannels
;
832 case OMX_AUDIO_CodingAAC
:
833 i_channels
= param
->aac
.nChannels
;
834 i_samplerate
= param
->aac
.nSampleRate
;
835 i_bitrate
= param
->aac
.nBitRate
;
836 i_channels
= param
->aac
.eChannelMode
== OMX_AUDIO_ChannelModeStereo
? 2 : 1;
838 case OMX_AUDIO_CodingMP3
:
839 i_channels
= param
->mp3
.nChannels
;
840 i_samplerate
= param
->mp3
.nSampleRate
;
841 i_bitrate
= param
->mp3
.nBitRate
;
842 i_channels
= param
->mp3
.eChannelMode
== OMX_AUDIO_ChannelModeStereo
? 2 : 1;
844 case OMX_AUDIO_CodingVORBIS
:
845 i_channels
= param
->vorbis
.nChannels
;
846 i_bitrate
= param
->vorbis
.nBitRate
;
847 i_samplerate
= param
->vorbis
.nSampleRate
;
849 case OMX_AUDIO_CodingWMA
:
850 i_channels
= param
->wma
.nChannels
;
851 i_bitrate
= param
->wma
.nBitRate
;
852 i_samplerate
= param
->wma
.nSamplingRate
;
853 i_blocksize
= param
->wma
.nBlockAlign
;
855 case OMX_AUDIO_CodingRA
:
856 i_channels
= param
->ra
.nChannels
;
857 i_samplerate
= param
->ra
.nSamplingRate
;
858 i_bps
= param
->ra
.nBitsPerFrame
;
861 return OMX_ErrorBadParameter
;
864 if(pi_channels
) *pi_channels
= i_channels
;
865 if(pi_samplerate
) *pi_samplerate
= i_samplerate
;
866 if(pi_bitrate
) *pi_bitrate
= i_bitrate
;
867 if(pi_bps
) *pi_bps
= i_bps
;
868 if(pi_blocksize
) *pi_blocksize
= i_blocksize
;
869 return OMX_ErrorNone
;
872 /*****************************************************************************
873 * PrintOmx: print component summary
874 *****************************************************************************/
875 void PrintOmx(decoder_t
*p_dec
, OMX_HANDLETYPE omx_handle
, OMX_U32 i_port
)
877 OMX_PARAM_PORTDEFINITIONTYPE definition
;
878 OMX_PORT_PARAM_TYPE param
;
879 OMX_ERRORTYPE omx_error
;
882 /* Find the input / output ports */
883 OMX_INIT_STRUCTURE(param
);
884 OMX_INIT_STRUCTURE(definition
);
886 for(i
= 0; i
< 3; i
++)
888 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamAudioInit
+ i
, ¶m
);
889 if(omx_error
!= OMX_ErrorNone
) continue;
891 if(i_port
== OMX_ALL
)
892 msg_Dbg( p_dec
, "found %i %s ports", (int)param
.nPorts
,
893 i
== 0 ? "audio" : i
== 1 ? "image" : "video" );
895 for(j
= 0; j
< param
.nPorts
; j
++)
897 unsigned int i_samplerate
, i_bitrate
;
898 unsigned int i_bitspersample
, i_blockalign
;
900 OmxFormatParam format_param
;
901 vlc_fourcc_t i_fourcc
;
902 const char *psz_name
;
903 OMX_CONFIG_RECTTYPE crop_rect
;
905 if(i_port
!= OMX_ALL
&& i_port
!= param
.nStartPortNumber
+ j
)
908 /* Get port definition */
909 definition
.nPortIndex
= param
.nStartPortNumber
+ j
;
910 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamPortDefinition
,
912 if(omx_error
!= OMX_ErrorNone
) continue;
914 OMX_PARAM_U32TYPE u32param
;
915 OMX_INIT_STRUCTURE(u32param
);
916 u32param
.nPortIndex
= param
.nStartPortNumber
+ j
;
917 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamNumAvailableStreams
,
920 msg_Dbg( p_dec
, "-> %s %i (%i streams) (%i:%i:%i buffers) (%i,%i) %s",
921 definition
.eDir
== OMX_DirOutput
? "output" : "input",
922 (int)definition
.nPortIndex
, (int)u32param
.nU32
,
923 (int)definition
.nBufferCountActual
,
924 (int)definition
.nBufferCountMin
, (int)definition
.nBufferSize
,
925 (int)definition
.bBuffersContiguous
,
926 (int)definition
.nBufferAlignment
,
927 definition
.bEnabled
? "enabled" : "disabled" );
929 switch(definition
.eDomain
)
931 case OMX_PortDomainVideo
:
933 if(definition
.format
.video
.eCompressionFormat
)
934 GetVlcVideoFormat( definition
.format
.video
.eCompressionFormat
,
935 &i_fourcc
, &psz_name
);
937 GetVlcChromaFormat( definition
.format
.video
.eColorFormat
,
938 &i_fourcc
, &psz_name
);
940 OMX_INIT_STRUCTURE(crop_rect
);
941 crop_rect
.nPortIndex
= definition
.nPortIndex
;
942 omx_error
= OMX_GetConfig(omx_handle
, OMX_IndexConfigCommonOutputCrop
, &crop_rect
);
943 if (omx_error
!= OMX_ErrorNone
)
945 crop_rect
.nLeft
= crop_rect
.nTop
= 0;
946 crop_rect
.nWidth
= definition
.format
.video
.nFrameWidth
;
947 crop_rect
.nHeight
= definition
.format
.video
.nFrameHeight
;
950 msg_Dbg( p_dec
, " -> video %s %ix%i@%.2f (%i,%i) (%i,%i) (%i,%i,%i,%i)", psz_name
,
951 (int)definition
.format
.video
.nFrameWidth
,
952 (int)definition
.format
.video
.nFrameHeight
,
953 (float)definition
.format
.video
.xFramerate
/(float)(1<<16),
954 (int)definition
.format
.video
.eCompressionFormat
,
955 (int)definition
.format
.video
.eColorFormat
,
956 (int)definition
.format
.video
.nStride
,
957 (int)definition
.format
.video
.nSliceHeight
,
958 (int)crop_rect
.nLeft
, (int)crop_rect
.nTop
,
959 (int)crop_rect
.nWidth
, (int)crop_rect
.nHeight
);
962 case OMX_PortDomainAudio
:
964 OmxToVlcAudioFormat( definition
.format
.audio
.eEncoding
,
965 &i_fourcc
, &psz_name
);
967 GetAudioParameters(omx_handle
, &format_param
,
968 definition
.nPortIndex
,
969 definition
.format
.audio
.eEncoding
,
970 &i_channels
, &i_samplerate
, &i_bitrate
,
971 &i_bitspersample
, &i_blockalign
);
973 msg_Dbg( p_dec
, " -> audio %s (%i) %i,%i,%i,%i,%i", psz_name
,
974 (int)definition
.format
.audio
.eEncoding
,
975 i_channels
, i_samplerate
, i_bitrate
, i_bitspersample
,