]> git.sesse.net Git - vlc/blob - modules/codec/omxil/utils.c
mediacodec: fix comparison between signed and unsigned warning
[vlc] / modules / codec / omxil / utils.c
1 /*****************************************************************************
2  * utils.c: helper functions
3  *****************************************************************************
4  * Copyright (C) 2010 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <vlc_block_helper.h>
35 #include <vlc_cpu.h>
36
37 #include "omxil.h"
38 #include "qcom.h"
39 #include "../../video_chroma/copy.h"
40
41 /*****************************************************************************
42  * Events utility functions
43  *****************************************************************************/
44 void InitOmxEventQueue(OmxEventQueue *queue)
45 {
46     queue->pp_last_event = &queue->p_events;
47     vlc_mutex_init(&queue->mutex);
48     vlc_cond_init(&queue->cond);
49 }
50
51 void DeinitOmxEventQueue(OmxEventQueue *queue)
52 {
53     vlc_mutex_destroy(&queue->mutex);
54     vlc_cond_destroy(&queue->cond);
55 }
56
57 OMX_ERRORTYPE PostOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE event,
58     OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
59 {
60     OmxEvent *p_event;
61
62     p_event = malloc(sizeof(OmxEvent));
63     if(!p_event) return OMX_ErrorInsufficientResources;
64
65     p_event->event = event;
66     p_event->data_1 = data_1;
67     p_event->data_2 = data_2;
68     p_event->event_data = event_data;
69     p_event->next = 0;
70
71     vlc_mutex_lock(&queue->mutex);
72     *queue->pp_last_event = p_event;
73     queue->pp_last_event = &p_event->next;
74     vlc_cond_signal(&queue->cond);
75     vlc_mutex_unlock(&queue->mutex);
76     return OMX_ErrorNone;
77 }
78
79 OMX_ERRORTYPE WaitForOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE *event,
80     OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
81 {
82     OmxEvent *p_event;
83
84     vlc_mutex_lock(&queue->mutex);
85
86     if(!queue->p_events)
87         vlc_cond_timedwait(&queue->cond, &queue->mutex, mdate()+CLOCK_FREQ);
88
89     p_event = queue->p_events;
90     if(p_event)
91     {
92         queue->p_events = p_event->next;
93         if(!queue->p_events) queue->pp_last_event = &queue->p_events;
94     }
95
96     vlc_mutex_unlock(&queue->mutex);
97
98     if(p_event)
99     {
100         if(event) *event = p_event->event;
101         if(data_1) *data_1 = p_event->data_1;
102         if(data_2) *data_2 = p_event->data_2;
103         if(event_data) *event_data = p_event->event_data;
104         free(p_event);
105         return OMX_ErrorNone;
106     }
107
108     return OMX_ErrorTimeout;
109 }
110
111 OMX_ERRORTYPE WaitForSpecificOmxEvent(OmxEventQueue *queue,
112     OMX_EVENTTYPE specific_event, OMX_U32 *data_1, OMX_U32 *data_2,
113     OMX_PTR *event_data)
114 {
115     OMX_ERRORTYPE status;
116     OMX_EVENTTYPE event;
117     mtime_t before =  mdate();
118
119     while(1)
120     {
121         status = WaitForOmxEvent(queue, &event, data_1, data_2, event_data);
122         if(status != OMX_ErrorNone) return status;
123
124         if(event == specific_event) break;
125         if(mdate() - before > CLOCK_FREQ) return OMX_ErrorTimeout;
126     }
127
128     return OMX_ErrorNone;
129 }
130
131 void PrintOmxEvent(vlc_object_t *p_this, OMX_EVENTTYPE event, OMX_U32 data_1,
132     OMX_U32 data_2, OMX_PTR event_data)
133 {
134     switch (event)
135     {
136     case OMX_EventCmdComplete:
137         switch ((OMX_STATETYPE)data_1)
138         {
139         case OMX_CommandStateSet:
140             msg_Dbg( p_this, "OmxEventHandler (%s, %s, %s)", EventToString(event),
141                      CommandToString(data_1), StateToString(data_2) );
142             break;
143
144         default:
145             msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u)", EventToString(event),
146                      CommandToString(data_1), (unsigned int)data_2 );
147             break;
148         }
149         break;
150
151     case OMX_EventError:
152         msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
153                  ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
154                  (const char *)event_data);
155         break;
156
157     default:
158         msg_Dbg( p_this, "OmxEventHandler (%s, %u, %u)", EventToString(event),
159                  (unsigned int)data_1, (unsigned int)data_2 );
160         break;
161     }
162 }
163
164 /*****************************************************************************
165  * Picture utility functions
166  *****************************************************************************/
167 void ArchitectureSpecificCopyHooks( decoder_t *p_dec, int i_color_format,
168                                     int i_slice_height, int i_src_stride,
169                                     ArchitectureSpecificCopyData *p_architecture_specific )
170 {
171     (void)i_slice_height;
172
173 #ifdef CAN_COMPILE_SSE2
174     if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
175     {
176         copy_cache_t *p_surface_cache = malloc( sizeof(copy_cache_t) );
177         if( !p_surface_cache || CopyInitCache( p_surface_cache, i_src_stride ) )
178         {
179             free( p_surface_cache );
180             return;
181         }
182         p_architecture_specific->data = p_surface_cache;
183         p_dec->fmt_out.i_codec = VLC_CODEC_YV12;
184     }
185 #endif
186 }
187
188 void ArchitectureSpecificCopyHooksDestroy( int i_color_format,
189                                            ArchitectureSpecificCopyData *p_architecture_specific )
190 {
191     if (!p_architecture_specific->data)
192         return;
193 #ifdef CAN_COMPILE_SSE2
194     if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
195     {
196         copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
197         CopyCleanCache(p_surface_cache);
198     }
199 #endif
200     free(p_architecture_specific->data);
201     p_architecture_specific->data = NULL;
202 }
203
204 void CopyOmxPicture( int i_color_format, picture_t *p_pic,
205                      int i_slice_height,
206                      int i_src_stride, uint8_t *p_src, int i_chroma_div,
207                      ArchitectureSpecificCopyData *p_architecture_specific )
208 {
209     uint8_t *p_dst;
210     int i_dst_stride;
211     int i_plane, i_width, i_line;
212     if( i_color_format == QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka )
213     {
214         qcom_convert(p_src, p_pic);
215         return;
216     }
217 #ifdef CAN_COMPILE_SSE2
218     if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar
219         && vlc_CPU_SSE2() && p_architecture_specific->data )
220     {
221         copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
222         uint8_t *ppi_src_pointers[2] = { p_src, p_src + i_src_stride * i_slice_height };
223         size_t pi_src_strides[2] = { i_src_stride, i_src_stride };
224         CopyFromNv12( p_pic, ppi_src_pointers, pi_src_strides, i_src_stride, i_slice_height, p_surface_cache );
225         return;
226     }
227 #endif
228
229     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
230     {
231         if(i_plane == 1) i_src_stride /= i_chroma_div;
232         p_dst = p_pic->p[i_plane].p_pixels;
233         i_dst_stride = p_pic->p[i_plane].i_pitch;
234         i_width = p_pic->p[i_plane].i_visible_pitch;
235
236         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
237         {
238             memcpy( p_dst, p_src, i_width );
239             p_src += i_src_stride;
240             p_dst += i_dst_stride;
241         }
242         /* Handle plane height, which may be indicated via nSliceHeight in OMX.
243          * The handling for chroma planes currently assumes vertically
244          * subsampled chroma, e.g. 422 planar wouldn't work right. */
245         if( i_plane == 0 && i_slice_height > p_pic->p[i_plane].i_visible_lines )
246             p_src += i_src_stride * (i_slice_height - p_pic->p[i_plane].i_visible_lines);
247         else if ( i_plane > 0 && i_slice_height/2 > p_pic->p[i_plane].i_visible_lines )
248             p_src += i_src_stride * (i_slice_height/2 - p_pic->p[i_plane].i_visible_lines);
249     }
250 }
251
252 void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
253                      picture_t *p_pic)
254 {
255     decoder_sys_t *p_sys = p_dec->p_sys;
256     int i_src_stride, i_dst_stride;
257     int i_plane, i_width, i_line;
258     uint8_t *p_dst, *p_src;
259
260     i_dst_stride  = p_sys->out.i_frame_stride;
261     p_dst = p_header->pBuffer + p_header->nOffset;
262
263     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
264     {
265         if(i_plane == 1) i_dst_stride /= p_sys->in.i_frame_stride_chroma_div;
266         p_src = p_pic->p[i_plane].p_pixels;
267         i_src_stride = p_pic->p[i_plane].i_pitch;
268         i_width = p_pic->p[i_plane].i_visible_pitch;
269
270         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
271         {
272             memcpy( p_dst, p_src, i_width );
273             p_src += i_src_stride;
274             p_dst += i_dst_stride;
275         }
276     }
277 }
278
279 int IgnoreOmxDecoderPadding(const char *name)
280 {
281     // The list of decoders that signal padding properly is not necessary,
282     // since that is the default, but keep it here for reference. (This is
283     // only relevant for manufacturers that are known to have decoders with
284     // this kind of bug.)
285 /*
286     static const char *padding_decoders[] = {
287         "OMX.SEC.AVC.Decoder",
288         "OMX.SEC.wmv7.dec",
289         "OMX.SEC.wmv8.dec",
290         NULL
291     };
292 */
293     static const char *nopadding_decoders[] = {
294         "OMX.SEC.avc.dec",
295         "OMX.SEC.avcdec",
296         "OMX.SEC.MPEG4.Decoder",
297         "OMX.SEC.mpeg4.dec",
298         "OMX.SEC.vc1.dec",
299         NULL
300     };
301     for (const char **ptr = nopadding_decoders; *ptr; ptr++) {
302         if (!strcmp(*ptr, name))
303             return 1;
304     }
305     return 0;
306 }
307
308 /*****************************************************************************
309  * Logging utility functions
310  *****************************************************************************/
311 const char *StateToString(OMX_STATETYPE state)
312 {
313     static const char *psz_names[] = {
314         "OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
315         "OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
316         "OMX_State unknown"
317     };
318
319     if((unsigned int)state > sizeof(psz_names)/sizeof(char*)-1)
320         state = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
321     return psz_names[state];
322 }
323
324 const char *CommandToString(OMX_COMMANDTYPE command)
325 {
326     static const char *psz_names[] = {
327         "OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
328         "OMX_CommandPortEnable", "OMX_CommandMarkBuffer",
329         "OMX_Command unknown"
330     };
331
332     if((unsigned int)command > sizeof(psz_names)/sizeof(char*)-1)
333         command = (OMX_COMMANDTYPE)(sizeof(psz_names)/sizeof(char*)-1);
334     return psz_names[command];
335 }
336
337 const char *EventToString(OMX_EVENTTYPE event)
338 {
339     static const char *psz_names[] = {
340         "OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
341         "OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
342         "OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
343         "OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
344         "OMX_Event unknown"
345     };
346
347     if((unsigned int)event > sizeof(psz_names)/sizeof(char*)-1)
348         event = (OMX_EVENTTYPE)(sizeof(psz_names)/sizeof(char*)-1);
349     return psz_names[event];
350 }
351
352 const char *ErrorToString(OMX_ERRORTYPE error)
353 {
354     static const char *psz_names[] = {
355         "OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
356         "OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
357         "OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
358         "OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
359         "OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
360         "OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
361         "OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
362         "OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
363         "OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
364         "OMX_ErrorPortUnresponsiveDuringDeallocation",
365         "OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
366         "OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
367         "OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
368         "OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
369         "OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
370         "OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
371         "OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
372         "OMX_ErrorTunnelingUnsupported",
373         "OMX_Error unknown"
374     };
375
376     if(error == OMX_ErrorNone) return "OMX_ErrorNone";
377
378     error -= OMX_ErrorInsufficientResources;
379
380     if((unsigned int)error > sizeof(psz_names)/sizeof(char*)-1)
381         error = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
382     return psz_names[error];
383 }
384
385 /*****************************************************************************
386  * fourcc -> omx id mapping
387  *****************************************************************************/
388 static const struct
389 {
390     vlc_fourcc_t i_fourcc;
391     OMX_VIDEO_CODINGTYPE i_codec;
392     const char *psz_role;
393
394 } video_format_table[] =
395 {
396     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_decoder.mpeg2" },
397     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_decoder.mpeg4" },
398     { VLC_CODEC_HEVC, OMX_VIDEO_CodingAutoDetect, "video_decoder.hevc" },
399     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_decoder.avc"   },
400     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_decoder.h263"  },
401     { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_decoder.wmv1"  },
402     { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_decoder.wmv2"  },
403     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
404     { VLC_CODEC_VC1,  OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
405     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.jpeg"  },
406     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.mjpeg" },
407     { VLC_CODEC_RV10, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
408     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
409     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
410     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
411     { VLC_CODEC_VP8,  OMX_VIDEO_CodingAutoDetect, "video_decoder.vp8" },
412     { VLC_CODEC_VP9,  OMX_VIDEO_CodingAutoDetect, "video_decoder.vp9" },
413     { 0, 0, 0 }
414 };
415
416 static const struct
417 {
418     vlc_fourcc_t i_fourcc;
419     OMX_AUDIO_CODINGTYPE i_codec;
420     const char *psz_role;
421
422 } audio_format_table[] =
423 {
424     { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amrnb" },
425     { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amrwb" },
426     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_decoder.aac" },
427     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_decoder.pcm" },
428     { VLC_CODEC_MP3,    OMX_AUDIO_CodingMP3, "audio_decoder.mp3" },
429     { 0, 0, 0 }
430 };
431
432 static const struct
433 {
434     vlc_fourcc_t i_fourcc;
435     OMX_VIDEO_CODINGTYPE i_codec;
436     const char *psz_role;
437
438 } video_enc_format_table[] =
439 {
440     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_encoder.mpeg2" },
441     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_encoder.mpeg4" },
442     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_encoder.avc"   },
443     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_encoder.h263"  },
444     { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
445     { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
446     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
447     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_encoder.jpeg"  },
448     { VLC_CODEC_RV10, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
449     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
450     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
451     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
452     { 0, 0, 0 }
453 };
454
455 static const struct
456 {
457     vlc_fourcc_t i_fourcc;
458     OMX_AUDIO_CODINGTYPE i_codec;
459     const char *psz_role;
460
461 } audio_enc_format_table[] =
462 {
463     { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amrnb" },
464     { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amrwb" },
465     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_encoder.aac" },
466     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_encoder.pcm" },
467     { 0, 0, 0 }
468 };
469
470 static const struct
471 {
472     vlc_fourcc_t i_fourcc;
473     OMX_COLOR_FORMATTYPE i_codec;
474     unsigned int i_size_mul;
475     unsigned int i_line_mul;
476     unsigned int i_line_chroma_div;
477
478 } chroma_format_table[] =
479 {
480     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420Planar, 3, 1, 2 },
481     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420PackedPlanar, 3, 1, 2 },
482     { VLC_CODEC_NV12, OMX_COLOR_FormatYUV420SemiPlanar, 3, 1, 1 },
483     { VLC_CODEC_NV21, OMX_QCOM_COLOR_FormatYVU420SemiPlanar, 3, 1, 1 },
484     { VLC_CODEC_NV12, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar, 3, 1, 1 },
485     { VLC_CODEC_NV12, QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, 3, 1, 1 },
486     { VLC_CODEC_NV12, OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m, 3, 1, 1 },
487     { VLC_CODEC_YUYV, OMX_COLOR_FormatYCbYCr, 4, 2, 0 },
488     { VLC_CODEC_YVYU, OMX_COLOR_FormatYCrYCb, 4, 2, 0 },
489     { VLC_CODEC_UYVY, OMX_COLOR_FormatCbYCrY, 4, 2, 0 },
490     { VLC_CODEC_VYUY, OMX_COLOR_FormatCrYCbY, 4, 2, 0 },
491     { 0, 0, 0, 0, 0 }
492 };
493
494 int GetOmxVideoFormat( vlc_fourcc_t i_fourcc,
495                        OMX_VIDEO_CODINGTYPE *pi_omx_codec,
496                        const char **ppsz_name )
497 {
498     unsigned int i;
499
500     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
501
502     for( i = 0; video_format_table[i].i_codec != 0; i++ )
503         if( video_format_table[i].i_fourcc == i_fourcc ) break;
504
505     if( pi_omx_codec ) *pi_omx_codec = video_format_table[i].i_codec;
506     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
507     return !!video_format_table[i].i_codec;
508 }
509
510 int GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec,
511                        vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
512 {
513     unsigned int i;
514
515     for( i = 0; video_format_table[i].i_codec != 0; i++ )
516         if( video_format_table[i].i_codec == i_omx_codec ) break;
517
518     if( pi_fourcc ) *pi_fourcc = video_format_table[i].i_fourcc;
519     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
520                                      video_format_table[i].i_fourcc );
521     return !!video_format_table[i].i_fourcc;
522 }
523
524 static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc )
525 {
526     unsigned int i;
527
528     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
529
530     for( i = 0; video_format_table[i].i_codec != 0; i++ )
531         if( video_format_table[i].i_fourcc == i_fourcc ) break;
532
533     return video_format_table[i].psz_role;
534 }
535
536 static const char *GetOmxVideoEncRole( vlc_fourcc_t i_fourcc )
537 {
538     unsigned int i;
539
540     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
541
542     for( i = 0; video_enc_format_table[i].i_codec != 0; i++ )
543         if( video_enc_format_table[i].i_fourcc == i_fourcc ) break;
544
545     return video_enc_format_table[i].psz_role;
546 }
547
548 int GetOmxAudioFormat( vlc_fourcc_t i_fourcc,
549                        OMX_AUDIO_CODINGTYPE *pi_omx_codec,
550                        const char **ppsz_name )
551 {
552     unsigned int i;
553
554     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
555
556     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
557         if( audio_format_table[i].i_fourcc == i_fourcc ) break;
558
559     if( pi_omx_codec ) *pi_omx_codec = audio_format_table[i].i_codec;
560     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES, i_fourcc );
561     return !!audio_format_table[i].i_codec;
562 }
563
564 int OmxToVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec,
565                        vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
566 {
567     unsigned int i;
568
569     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
570         if( audio_format_table[i].i_codec == i_omx_codec ) break;
571
572     if( pi_fourcc ) *pi_fourcc = audio_format_table[i].i_fourcc;
573     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES,
574                                      audio_format_table[i].i_fourcc );
575     return !!audio_format_table[i].i_fourcc;
576 }
577
578 static const char *GetOmxAudioRole( vlc_fourcc_t i_fourcc )
579 {
580     unsigned int i;
581
582     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
583
584     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
585         if( audio_format_table[i].i_fourcc == i_fourcc ) break;
586
587     return audio_format_table[i].psz_role;
588 }
589
590 static const char *GetOmxAudioEncRole( vlc_fourcc_t i_fourcc )
591 {
592     unsigned int i;
593
594     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
595
596     for( i = 0; audio_enc_format_table[i].i_codec != 0; i++ )
597         if( audio_enc_format_table[i].i_fourcc == i_fourcc ) break;
598
599     return audio_enc_format_table[i].psz_role;
600 }
601
602 const char *GetOmxRole( vlc_fourcc_t i_fourcc, int i_cat, bool b_enc )
603 {
604     if(b_enc)
605         return i_cat == VIDEO_ES ?
606             GetOmxVideoEncRole( i_fourcc ) : GetOmxAudioEncRole( i_fourcc );
607     else
608         return i_cat == VIDEO_ES ?
609             GetOmxVideoRole( i_fourcc ) : GetOmxAudioRole( i_fourcc );
610 }
611
612 int GetOmxChromaFormat( vlc_fourcc_t i_fourcc,
613                         OMX_COLOR_FORMATTYPE *pi_omx_codec,
614                         const char **ppsz_name )
615 {
616     unsigned int i;
617
618     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
619
620     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
621         if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
622
623     if( pi_omx_codec ) *pi_omx_codec = chroma_format_table[i].i_codec;
624     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
625     return !!chroma_format_table[i].i_codec;
626 }
627
628 int GetVlcChromaFormat( OMX_COLOR_FORMATTYPE i_omx_codec,
629                         vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
630 {
631     unsigned int i;
632
633     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
634         if( chroma_format_table[i].i_codec == i_omx_codec ) break;
635
636     if( pi_fourcc ) *pi_fourcc = chroma_format_table[i].i_fourcc;
637     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
638                                      chroma_format_table[i].i_fourcc );
639     return !!chroma_format_table[i].i_fourcc;
640 }
641
642 int GetVlcChromaSizes( vlc_fourcc_t i_fourcc,
643                        unsigned int width, unsigned int height,
644                        unsigned int *size, unsigned int *pitch,
645                        unsigned int *chroma_pitch_div )
646 {
647     unsigned int i;
648
649     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
650
651     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
652         if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
653
654     /* Align on macroblock boundary */
655     width = (width + 15) & ~0xF;
656     height = (height + 15) & ~0xF;
657
658     if( size ) *size = width * height * chroma_format_table[i].i_size_mul / 2;
659     if( pitch ) *pitch = width * chroma_format_table[i].i_line_mul;
660     if( chroma_pitch_div )
661         *chroma_pitch_div = chroma_format_table[i].i_line_chroma_div;
662     return !!chroma_format_table[i].i_codec;
663 }
664
665 /*****************************************************************************
666  * Functions to deal with audio format parameters
667  *****************************************************************************/
668 static const struct {
669     OMX_AUDIO_CODINGTYPE encoding;
670     OMX_INDEXTYPE index;
671     int size;
672 } audio_encoding_param[] =
673 {   { OMX_AUDIO_CodingPCM, OMX_IndexParamAudioPcm,
674       sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
675     { OMX_AUDIO_CodingADPCM, OMX_IndexParamAudioAdpcm,
676       sizeof(OMX_AUDIO_PARAM_ADPCMTYPE) },
677     { OMX_AUDIO_CodingAMR, OMX_IndexParamAudioAmr,
678       sizeof(OMX_AUDIO_PARAM_AMRTYPE) },
679     { OMX_AUDIO_CodingG711, OMX_IndexParamAudioPcm,
680       sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
681     { OMX_AUDIO_CodingG723, OMX_IndexParamAudioG723,
682       sizeof(OMX_AUDIO_PARAM_G723TYPE) },
683     { OMX_AUDIO_CodingG726, OMX_IndexParamAudioG726,
684       sizeof(OMX_AUDIO_PARAM_G726TYPE) },
685     { OMX_AUDIO_CodingG729, OMX_IndexParamAudioG729,
686       sizeof(OMX_AUDIO_PARAM_G729TYPE) },
687     { OMX_AUDIO_CodingAAC, OMX_IndexParamAudioAac,
688       sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE) },
689     { OMX_AUDIO_CodingMP3, OMX_IndexParamAudioMp3,
690       sizeof(OMX_AUDIO_PARAM_MP3TYPE) },
691     { OMX_AUDIO_CodingSBC, OMX_IndexParamAudioSbc,
692       sizeof(OMX_AUDIO_PARAM_SBCTYPE) },
693     { OMX_AUDIO_CodingVORBIS, OMX_IndexParamAudioVorbis,
694       sizeof(OMX_AUDIO_PARAM_VORBISTYPE) },
695     { OMX_AUDIO_CodingWMA, OMX_IndexParamAudioWma,
696       sizeof(OMX_AUDIO_PARAM_WMATYPE) },
697     { OMX_AUDIO_CodingRA, OMX_IndexParamAudioRa,
698       sizeof(OMX_AUDIO_PARAM_RATYPE) },
699     { OMX_AUDIO_CodingUnused, 0, 0 }
700 };
701
702 static OMX_INDEXTYPE GetAudioParamFormatIndex(OMX_AUDIO_CODINGTYPE encoding)
703 {
704   int i;
705
706   for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
707       audio_encoding_param[i].encoding != encoding; i++);
708
709   return audio_encoding_param[i].index;
710 }
711
712 unsigned int GetAudioParamSize(OMX_INDEXTYPE index)
713 {
714   int i;
715
716   for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
717       audio_encoding_param[i].index != index; i++);
718
719   return audio_encoding_param[i].size;
720 }
721
722 OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
723     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
724     vlc_fourcc_t i_codec, uint8_t i_channels, unsigned int i_samplerate,
725     unsigned int i_bitrate, unsigned int i_bps, unsigned int i_blocksize)
726 {
727     OMX_INDEXTYPE index;
728
729     switch(encoding)
730     {
731     case OMX_AUDIO_CodingPCM:
732     case OMX_AUDIO_CodingG711:
733         OMX_INIT_STRUCTURE(param->pcm);
734         param->pcm.nChannels = i_channels;
735         param->pcm.nSamplingRate = i_samplerate;
736         param->pcm.eNumData = OMX_NumericalDataSigned;
737         param->pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
738         param->pcm.eEndian = OMX_EndianLittle;
739         param->pcm.bInterleaved = OMX_TRUE;
740         param->pcm.nBitPerSample = i_bps;
741         param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
742         if(i_channels == 2)
743         {
744             param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
745             param->pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
746         }
747         break;
748     case OMX_AUDIO_CodingADPCM:
749         OMX_INIT_STRUCTURE(param->adpcm);
750         param->adpcm.nChannels = i_channels;
751         param->adpcm.nSampleRate = i_samplerate;
752         param->adpcm.nBitsPerSample = i_bps;
753         break;
754     case OMX_AUDIO_CodingAMR:
755         OMX_INIT_STRUCTURE(param->amr);
756         param->amr.nChannels = i_channels;
757         param->amr.nBitRate = i_bitrate;
758         if (i_codec == VLC_CODEC_AMR_WB)
759             param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
760         else
761             param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
762         param->amr.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
763         param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
764         break;
765     case OMX_AUDIO_CodingG723:
766         OMX_INIT_STRUCTURE(param->g723);
767         param->g723.nChannels = i_channels;
768         param->g723.bDTX = OMX_FALSE;
769         param->g723.eBitRate = OMX_AUDIO_G723ModeUnused;
770         param->g723.bHiPassFilter = OMX_TRUE;
771         param->g723.bPostFilter = OMX_TRUE;
772         break;
773     case OMX_AUDIO_CodingG726:
774         OMX_INIT_STRUCTURE(param->g726);
775         param->g726.nChannels = i_channels;
776         param->g726.eG726Mode = OMX_AUDIO_G726ModeUnused;
777         break;
778     case OMX_AUDIO_CodingG729:
779         OMX_INIT_STRUCTURE(param->g729);
780         param->g729.nChannels = i_channels;
781         param->g729.bDTX = OMX_FALSE;
782         param->g729.eBitType = OMX_AUDIO_G729;
783         break;
784     case OMX_AUDIO_CodingAAC:
785         OMX_INIT_STRUCTURE(param->aac);
786         param->aac.nChannels = i_channels;
787         param->aac.nSampleRate = i_samplerate;
788         param->aac.nBitRate = i_bitrate;
789         param->aac.nAudioBandWidth = 0;
790         param->aac.nFrameLength = 1024;
791         param->aac.nAACtools = OMX_AUDIO_AACToolAll;
792         param->aac.nAACERtools = OMX_AUDIO_AACERAll;
793         param->aac.eAACProfile = OMX_AUDIO_AACObjectLC;
794         param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
795         param->aac.eChannelMode = i_channels > 1 ?
796             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
797         break;
798     case OMX_AUDIO_CodingMP3:
799         OMX_INIT_STRUCTURE(param->mp3);
800         param->mp3.nChannels = i_channels;
801         param->mp3.nSampleRate = i_samplerate;
802         param->mp3.nBitRate = i_bitrate;
803         param->mp3.eChannelMode = i_channels > 1 ?
804             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
805         param->mp3.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
806         break;
807     case OMX_AUDIO_CodingWMA:
808         OMX_INIT_STRUCTURE(param->wma);
809         param->wma.nChannels = i_channels;
810         param->wma.nBitRate = i_bitrate;
811         param->wma.eFormat = OMX_AUDIO_WMAFormatUnused;
812         param->wma.eProfile = OMX_AUDIO_WMAProfileUnused;
813         param->wma.nSamplingRate = i_samplerate;
814         param->wma.nBlockAlign = i_blocksize;
815         param->wma.nEncodeOptions = 0;
816         param->wma.nSuperBlockAlign = 0;
817         break;
818     case OMX_AUDIO_CodingRA:
819         OMX_INIT_STRUCTURE(param->ra);
820         param->ra.nChannels = i_channels;
821         param->ra.nSamplingRate = i_samplerate;
822         param->ra.nBitsPerFrame = i_bps;
823         param->ra.nSamplePerFrame = 0;
824         param->ra.nCouplingQuantBits = 0;
825         param->ra.nCouplingStartRegion = 0;
826         param->ra.nNumRegions = 0;
827         param->ra.eFormat = OMX_AUDIO_RAFormatUnused;
828         break;
829     case OMX_AUDIO_CodingVORBIS:
830         OMX_INIT_STRUCTURE(param->vorbis);
831         param->vorbis.nChannels = i_channels;
832         param->vorbis.nBitRate = i_bitrate;
833         param->vorbis.nMinBitRate = 0;
834         param->vorbis.nMaxBitRate = i_bitrate;
835         param->vorbis.nSampleRate = i_samplerate;
836         param->vorbis.nAudioBandWidth = 0;
837         param->vorbis.nQuality = 3;
838         param->vorbis.bManaged = OMX_FALSE;
839         param->vorbis.bDownmix = OMX_FALSE;
840         break;
841     default:
842         return OMX_ErrorBadParameter;
843     }
844
845     param->common.nPortIndex = i_port;
846
847     index = GetAudioParamFormatIndex(encoding);
848     return OMX_SetParameter(handle, index, param);
849 }
850
851 OMX_ERRORTYPE GetAudioParameters(OMX_HANDLETYPE handle,
852     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
853     uint8_t *pi_channels, unsigned int *pi_samplerate,
854     unsigned int *pi_bitrate, unsigned int *pi_bps, unsigned int *pi_blocksize)
855 {
856     int i_channels = 0, i_samplerate = 0, i_bitrate = 0;
857     int i_bps = 0, i_blocksize = 0;
858     OMX_ERRORTYPE omx_error;
859     OMX_INDEXTYPE index;
860
861     OMX_INIT_COMMON(param->common);
862     param->common.nPortIndex = i_port;
863     index = GetAudioParamFormatIndex(encoding);
864     if(!index) return OMX_ErrorNotImplemented;
865
866     param->common.nSize = GetAudioParamSize(index);
867     omx_error = OMX_GetParameter(handle, index, param);
868     if(omx_error != OMX_ErrorNone) return omx_error;
869
870     switch(encoding)
871     {
872     case OMX_AUDIO_CodingPCM:
873     case OMX_AUDIO_CodingG711:
874         i_channels = param->pcm.nChannels;
875         i_samplerate = param->pcm.nSamplingRate;
876         i_bps = param->pcm.nBitPerSample;
877         break;
878     case OMX_AUDIO_CodingADPCM:
879         i_channels = param->adpcm.nChannels;
880         i_samplerate = param->adpcm.nSampleRate;
881         i_bps = param->adpcm.nBitsPerSample;
882         break;
883     case OMX_AUDIO_CodingAMR:
884         i_channels = param->amr.nChannels;
885         i_bitrate = param->amr.nBitRate;
886         i_samplerate = 8000;
887         break;
888     case OMX_AUDIO_CodingG723:
889         i_channels = param->g723.nChannels;
890         break;
891     case OMX_AUDIO_CodingG726:
892         i_channels = param->g726.nChannels;
893         break;
894     case OMX_AUDIO_CodingG729:
895         i_channels = param->g729.nChannels;
896         break;
897     case OMX_AUDIO_CodingAAC:
898         i_channels = param->aac.nChannels;
899         i_samplerate = param->aac.nSampleRate;
900         i_bitrate = param->aac.nBitRate;
901         i_channels = param->aac.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
902         break;
903     case OMX_AUDIO_CodingMP3:
904         i_channels = param->mp3.nChannels;
905         i_samplerate = param->mp3.nSampleRate;
906         i_bitrate = param->mp3.nBitRate;
907         i_channels = param->mp3.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
908         break;
909     case OMX_AUDIO_CodingVORBIS:
910         i_channels = param->vorbis.nChannels;
911         i_bitrate = param->vorbis.nBitRate;
912         i_samplerate = param->vorbis.nSampleRate;
913         break;
914     case OMX_AUDIO_CodingWMA:
915         i_channels = param->wma.nChannels;
916         i_bitrate = param->wma.nBitRate;
917         i_samplerate = param->wma.nSamplingRate;
918         i_blocksize = param->wma.nBlockAlign;
919         break;
920     case OMX_AUDIO_CodingRA:
921         i_channels = param->ra.nChannels;
922         i_samplerate = param->ra.nSamplingRate;
923         i_bps = param->ra.nBitsPerFrame;
924         break;
925     default:
926         return OMX_ErrorBadParameter;
927     }
928
929     if(pi_channels) *pi_channels = i_channels;
930     if(pi_samplerate) *pi_samplerate = i_samplerate;
931     if(pi_bitrate) *pi_bitrate = i_bitrate;
932     if(pi_bps) *pi_bps = i_bps;
933     if(pi_blocksize) *pi_blocksize = i_blocksize;
934     return OMX_ErrorNone;
935 }
936
937 /*****************************************************************************
938  * PrintOmx: print component summary
939  *****************************************************************************/
940 void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
941 {
942     OMX_PARAM_PORTDEFINITIONTYPE definition;
943     OMX_PORT_PARAM_TYPE param;
944     OMX_ERRORTYPE omx_error;
945     unsigned int i, j;
946
947     /* Find the input / output ports */
948     OMX_INIT_STRUCTURE(param);
949     OMX_INIT_STRUCTURE(definition);
950
951     for(i = 0; i < 3; i++)
952     {
953         omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamAudioInit + i, &param);
954         if(omx_error != OMX_ErrorNone) continue;
955
956         if(i_port == OMX_ALL)
957             msg_Dbg( p_dec, "found %i %s ports", (int)param.nPorts,
958                      i == 0 ? "audio" : i == 1 ? "image" : "video" );
959
960         for(j = 0; j < param.nPorts; j++)
961         {
962             unsigned int i_samplerate, i_bitrate;
963             unsigned int i_bitspersample, i_blockalign;
964             uint8_t i_channels;
965             OmxFormatParam format_param;
966             vlc_fourcc_t i_fourcc;
967             const char *psz_name;
968             OMX_CONFIG_RECTTYPE crop_rect;
969
970             if(i_port != OMX_ALL && i_port != param.nStartPortNumber + j)
971                 continue;
972
973             /* Get port definition */
974             definition.nPortIndex = param.nStartPortNumber + j;
975             omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
976                                       &definition);
977             if(omx_error != OMX_ErrorNone) continue;
978
979             OMX_PARAM_U32TYPE u32param;
980             OMX_INIT_STRUCTURE(u32param);
981             u32param.nPortIndex = param.nStartPortNumber + j;
982             omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamNumAvailableStreams,
983                                          (OMX_PTR)&u32param);
984
985             msg_Dbg( p_dec, "-> %s %i (%i streams) (%i:%i:%i buffers) (%i,%i) %s",
986                      definition.eDir == OMX_DirOutput ? "output" : "input",
987                      (int)definition.nPortIndex, (int)u32param.nU32,
988                      (int)definition.nBufferCountActual,
989                      (int)definition.nBufferCountMin, (int)definition.nBufferSize,
990                      (int)definition.bBuffersContiguous,
991                      (int)definition.nBufferAlignment,
992                      definition.bEnabled ? "enabled" : "disabled" );
993
994             switch(definition.eDomain)
995             {
996             case OMX_PortDomainVideo:
997
998                 if(definition.format.video.eCompressionFormat)
999                     GetVlcVideoFormat( definition.format.video.eCompressionFormat,
1000                                        &i_fourcc, &psz_name );
1001                 else
1002                     GetVlcChromaFormat( definition.format.video.eColorFormat,
1003                                         &i_fourcc, &psz_name );
1004
1005                 OMX_INIT_STRUCTURE(crop_rect);
1006                 crop_rect.nPortIndex = definition.nPortIndex;
1007                 omx_error = OMX_GetConfig(omx_handle, OMX_IndexConfigCommonOutputCrop, &crop_rect);
1008                 if (omx_error != OMX_ErrorNone)
1009                 {
1010                     crop_rect.nLeft = crop_rect.nTop = 0;
1011                     crop_rect.nWidth  = definition.format.video.nFrameWidth;
1012                     crop_rect.nHeight = definition.format.video.nFrameHeight;
1013                 }
1014
1015                 msg_Dbg( p_dec, "  -> video %s %ix%i@%.2f (%i,%i) (%i,%i) (%i,%i,%i,%i)", psz_name,
1016                          (int)definition.format.video.nFrameWidth,
1017                          (int)definition.format.video.nFrameHeight,
1018                          (float)definition.format.video.xFramerate/(float)(1<<16),
1019                          (int)definition.format.video.eCompressionFormat,
1020                          (int)definition.format.video.eColorFormat,
1021                          (int)definition.format.video.nStride,
1022                          (int)definition.format.video.nSliceHeight,
1023                          (int)crop_rect.nLeft, (int)crop_rect.nTop,
1024                          (int)crop_rect.nWidth, (int)crop_rect.nHeight);
1025                 break;
1026
1027             case OMX_PortDomainAudio:
1028
1029                 OmxToVlcAudioFormat( definition.format.audio.eEncoding,
1030                                    &i_fourcc, &psz_name );
1031
1032                 GetAudioParameters(omx_handle, &format_param,
1033                                    definition.nPortIndex,
1034                                    definition.format.audio.eEncoding,
1035                                    &i_channels, &i_samplerate, &i_bitrate,
1036                                    &i_bitspersample, &i_blockalign);
1037
1038                 msg_Dbg( p_dec, "  -> audio %s (%i) %i,%i,%i,%i,%i", psz_name,
1039                          (int)definition.format.audio.eEncoding,
1040                          i_channels, i_samplerate, i_bitrate, i_bitspersample,
1041                          i_blockalign);
1042                 break;
1043
1044             default: break;
1045             }
1046         }
1047     }
1048 }
1049
1050 static const struct
1051 {
1052     OMX_VIDEO_AVCPROFILETYPE omx_profile;
1053     size_t                   profile_idc;
1054 } omx_to_profile_idc[] =
1055 {
1056     { OMX_VIDEO_AVCProfileBaseline,  66 },
1057     { OMX_VIDEO_AVCProfileMain,      77 },
1058     { OMX_VIDEO_AVCProfileExtended,  88 },
1059     { OMX_VIDEO_AVCProfileHigh,     100 },
1060     { OMX_VIDEO_AVCProfileHigh10,   110 },
1061     { OMX_VIDEO_AVCProfileHigh422,  122 },
1062     { OMX_VIDEO_AVCProfileHigh444,  244 },
1063 };
1064
1065 size_t convert_omx_to_profile_idc(OMX_VIDEO_AVCPROFILETYPE profile_type)
1066 {
1067     size_t array_length = sizeof(omx_to_profile_idc)/sizeof(omx_to_profile_idc[0]);
1068     for (size_t i = 0; i < array_length; ++i) {
1069         if (omx_to_profile_idc[i].omx_profile == profile_type)
1070             return omx_to_profile_idc[i].profile_idc;
1071     }
1072     return 0;
1073 }
1074
1075 static const struct
1076 {
1077     OMX_VIDEO_AVCLEVELTYPE omx_level;
1078     size_t                 level_idc;
1079 } omx_to_level_idc[] =
1080 {
1081     { OMX_VIDEO_AVCLevel1,  10 },
1082     { OMX_VIDEO_AVCLevel1b,  9 },
1083     { OMX_VIDEO_AVCLevel11, 11 },
1084     { OMX_VIDEO_AVCLevel12, 12 },
1085     { OMX_VIDEO_AVCLevel13, 13 },
1086     { OMX_VIDEO_AVCLevel2,  20 },
1087     { OMX_VIDEO_AVCLevel21, 21 },
1088     { OMX_VIDEO_AVCLevel22, 22 },
1089     { OMX_VIDEO_AVCLevel3,  30 },
1090     { OMX_VIDEO_AVCLevel31, 31 },
1091     { OMX_VIDEO_AVCLevel32, 32 },
1092     { OMX_VIDEO_AVCLevel4,  40 },
1093     { OMX_VIDEO_AVCLevel41, 41 },
1094     { OMX_VIDEO_AVCLevel42, 42 },
1095     { OMX_VIDEO_AVCLevel5,  50 },
1096     { OMX_VIDEO_AVCLevel51, 51 },
1097 };
1098
1099 size_t convert_omx_to_level_idc(OMX_VIDEO_AVCLEVELTYPE level_type)
1100 {
1101     size_t array_length = sizeof(omx_to_level_idc)/sizeof(omx_to_level_idc[0]);
1102     for (size_t i = 0; i < array_length; ++i) {
1103         if (omx_to_level_idc[i].omx_level == level_type)
1104             return omx_to_level_idc[i].level_idc;
1105     }
1106     return 0;
1107 }