]> git.sesse.net Git - vlc/blob - modules/codec/omxil/utils.c
a114f09006a498d73cca3ad0cf07c3af40e9273b
[vlc] / modules / codec / omxil / utils.c
1 /*****************************************************************************
2  * utils.c: helper functions
3  *****************************************************************************
4  * Copyright (C) 2010 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 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 General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, 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
39 #define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00
40
41 /*****************************************************************************
42  * Events utility functions
43  *****************************************************************************/
44 OMX_ERRORTYPE PostOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE event,
45     OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
46 {
47     decoder_sys_t *p_sys = p_dec->p_sys;
48     OmxEvent *p_event;
49
50     p_event = malloc(sizeof(OmxEvent));
51     if(!p_event) return OMX_ErrorInsufficientResources;
52
53     p_event->event = event;
54     p_event->data_1 = data_1;
55     p_event->data_2 = data_2;
56     p_event->event_data = event_data;
57     p_event->next = 0;
58
59     vlc_mutex_lock(&p_sys->mutex);
60     *p_sys->pp_last_event = p_event;
61     p_sys->pp_last_event = &p_event->next;
62     vlc_cond_signal(&p_sys->cond);
63     vlc_mutex_unlock(&p_sys->mutex);
64     return OMX_ErrorNone;
65 }
66
67 OMX_ERRORTYPE WaitForOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE *event,
68     OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
69 {
70     decoder_sys_t *p_sys = p_dec->p_sys;
71     OmxEvent *p_event;
72
73     vlc_mutex_lock(&p_sys->mutex);
74
75     if(!p_sys->p_events)
76         vlc_cond_timedwait(&p_sys->cond, &p_sys->mutex, mdate()+CLOCK_FREQ);
77
78     p_event = p_sys->p_events;
79     if(p_event)
80     {
81         p_sys->p_events = p_event->next;
82         if(!p_sys->p_events) p_sys->pp_last_event = &p_sys->p_events;
83     }
84
85     vlc_mutex_unlock(&p_sys->mutex);
86
87     if(p_event)
88     {
89         if(event) *event = p_event->event;
90         if(data_1) *data_1 = p_event->data_1;
91         if(data_2) *data_2 = p_event->data_2;
92         if(event_data) *event_data = p_event->event_data;
93         free(p_event);
94         return OMX_ErrorNone;
95     }
96
97     return OMX_ErrorTimeout;
98 }
99
100 OMX_ERRORTYPE WaitForSpecificOmxEvent(decoder_t *p_dec,
101     OMX_EVENTTYPE specific_event, OMX_U32 *data_1, OMX_U32 *data_2,
102     OMX_PTR *event_data)
103 {
104     OMX_ERRORTYPE status;
105     OMX_EVENTTYPE event;
106     mtime_t before =  mdate();
107
108     while(1)
109     {
110         status = WaitForOmxEvent(p_dec, &event, data_1, data_2, event_data);
111         if(status != OMX_ErrorNone) return status;
112
113         if(event == specific_event) break;
114         if(mdate() - before > CLOCK_FREQ) return OMX_ErrorTimeout;
115     }
116
117     return OMX_ErrorNone;
118 }
119
120 /*****************************************************************************
121  * Picture utility functions
122  *****************************************************************************/
123 void CopyOmxPicture( decoder_t *p_dec, picture_t *p_pic,
124                      OMX_BUFFERHEADERTYPE *p_header, int i_slice_height )
125 {
126     decoder_sys_t *p_sys = p_dec->p_sys;
127     int i_src_stride, i_dst_stride;
128     int i_plane, i_width, i_line;
129     uint8_t *p_dst, *p_src;
130
131     i_src_stride  = p_sys->out.i_frame_stride;
132     p_src = p_header->pBuffer + p_header->nOffset;
133
134     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
135     {
136         if(i_plane == 1) i_src_stride /= p_sys->out.i_frame_stride_chroma_div;
137         p_dst = p_pic->p[i_plane].p_pixels;
138         i_dst_stride = p_pic->p[i_plane].i_pitch;
139         i_width = p_pic->p[i_plane].i_visible_pitch;
140
141         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
142         {
143             vlc_memcpy( p_dst, p_src, i_width );
144             p_src += i_src_stride;
145             p_dst += i_dst_stride;
146         }
147         /* Handle plane height, which may be indicated via nSliceHeight in OMX.
148          * The handling for chroma planes currently assumes vertically
149          * subsampled chroma, e.g. 422 planar wouldn't work right. */
150         if( i_plane == 0 && i_slice_height > p_pic->p[i_plane].i_visible_lines )
151             p_src += i_src_stride * (i_slice_height - p_pic->p[i_plane].i_visible_lines);
152         else if ( i_plane > 0 && i_slice_height/2 > p_pic->p[i_plane].i_visible_lines )
153             p_src += i_src_stride * (i_slice_height/2 - p_pic->p[i_plane].i_visible_lines);
154     }
155 }
156
157 void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
158                      picture_t *p_pic)
159 {
160     decoder_sys_t *p_sys = p_dec->p_sys;
161     int i_src_stride, i_dst_stride;
162     int i_plane, i_width, i_line;
163     uint8_t *p_dst, *p_src;
164
165     i_dst_stride  = p_sys->out.i_frame_stride;
166     p_dst = p_header->pBuffer + p_header->nOffset;
167
168     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
169     {
170         if(i_plane == 1) i_dst_stride /= p_sys->in.i_frame_stride_chroma_div;
171         p_src = p_pic->p[i_plane].p_pixels;
172         i_src_stride = p_pic->p[i_plane].i_pitch;
173         i_width = p_pic->p[i_plane].i_visible_pitch;
174
175         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
176         {
177             vlc_memcpy( p_dst, p_src, i_width );
178             p_src += i_src_stride;
179             p_dst += i_dst_stride;
180         }
181     }
182 }
183
184 /*****************************************************************************
185  * Logging utility functions
186  *****************************************************************************/
187 const char *StateToString(OMX_STATETYPE state)
188 {
189     static const char *psz_names[] = {
190         "OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
191         "OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
192         "OMX_State unknown"
193     };
194
195     if((unsigned int)state > sizeof(psz_names)/sizeof(char*)-1)
196         state = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
197     return psz_names[state];
198 }
199
200 const char *CommandToString(OMX_COMMANDTYPE command)
201 {
202     static const char *psz_names[] = {
203         "OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
204         "OMX_CommandPortEnable", "OMX_CommandMarkBuffer",
205         "OMX_Command unknown"
206     };
207
208     if((unsigned int)command > sizeof(psz_names)/sizeof(char*)-1)
209         command = (OMX_COMMANDTYPE)(sizeof(psz_names)/sizeof(char*)-1);
210     return psz_names[command];
211 }
212
213 const char *EventToString(OMX_EVENTTYPE event)
214 {
215     static const char *psz_names[] = {
216         "OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
217         "OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
218         "OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
219         "OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
220         "OMX_Event unknown"
221     };
222
223     if((unsigned int)event > sizeof(psz_names)/sizeof(char*)-1)
224         event = (OMX_EVENTTYPE)(sizeof(psz_names)/sizeof(char*)-1);
225     return psz_names[event];
226 }
227
228 const char *ErrorToString(OMX_ERRORTYPE error)
229 {
230     static const char *psz_names[] = {
231         "OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
232         "OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
233         "OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
234         "OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
235         "OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
236         "OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
237         "OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
238         "OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
239         "OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
240         "OMX_ErrorPortUnresponsiveDuringDeallocation",
241         "OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
242         "OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
243         "OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
244         "OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
245         "OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
246         "OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
247         "OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
248         "OMX_ErrorTunnelingUnsupported",
249         "OMX_Error unkown"
250     };
251
252     if(error == OMX_ErrorNone) return "OMX_ErrorNone";
253
254     error -= OMX_ErrorInsufficientResources;
255
256     if((unsigned int)error > sizeof(psz_names)/sizeof(char*)-1)
257         error = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
258     return psz_names[error];
259 }
260
261 /*****************************************************************************
262  * fourcc -> omx id mapping
263  *****************************************************************************/
264 static const struct
265 {
266     vlc_fourcc_t i_fourcc;
267     OMX_VIDEO_CODINGTYPE i_codec;
268     const char *psz_role;
269
270 } video_format_table[] =
271 {
272     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_decoder.mpeg2" },
273     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_decoder.mpeg4" },
274     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_decoder.avc"   },
275     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_decoder.h263"  },
276     { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
277     { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
278     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
279     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.jpeg"  },
280     { VLC_CODEC_RV10, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
281     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
282     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
283     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
284     { 0, 0, 0 }
285 };
286
287 static const struct
288 {
289     vlc_fourcc_t i_fourcc;
290     OMX_AUDIO_CODINGTYPE i_codec;
291     const char *psz_role;
292
293 } audio_format_table[] =
294 {
295     { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amr" },
296     { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amr" },
297     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_decoder.aac" },
298     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_decoder.pcm" },
299     { 0, 0, 0 }
300 };
301
302 static const struct
303 {
304     vlc_fourcc_t i_fourcc;
305     OMX_VIDEO_CODINGTYPE i_codec;
306     const char *psz_role;
307
308 } video_enc_format_table[] =
309 {
310     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_encoder.mpeg2" },
311     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_encoder.mpeg4" },
312     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_encoder.avc"   },
313     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_encoder.h263"  },
314     { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
315     { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
316     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
317     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_encoder.jpeg"  },
318     { VLC_CODEC_RV10, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
319     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
320     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
321     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
322     { 0, 0, 0 }
323 };
324
325 static const struct
326 {
327     vlc_fourcc_t i_fourcc;
328     OMX_AUDIO_CODINGTYPE i_codec;
329     const char *psz_role;
330
331 } audio_enc_format_table[] =
332 {
333     { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amr" },
334     { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amr" },
335     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_encoder.aac" },
336     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_encoder.pcm" },
337     { 0, 0, 0 }
338 };
339
340 static const struct
341 {
342     vlc_fourcc_t i_fourcc;
343     OMX_COLOR_FORMATTYPE i_codec;
344     unsigned int i_size_mul;
345     unsigned int i_line_mul;
346     unsigned int i_line_chroma_div;
347
348 } chroma_format_table[] =
349 {
350     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420Planar, 3, 1, 2 },
351     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420PackedPlanar, 3, 1, 2 },
352     { VLC_CODEC_NV12, OMX_COLOR_FormatYUV420SemiPlanar, 3, 1, 1 },
353     { VLC_CODEC_NV21, OMX_QCOM_COLOR_FormatYVU420SemiPlanar, 3, 1, 1 },
354     { VLC_CODEC_YUYV, OMX_COLOR_FormatYCbYCr, 4, 2, 0 },
355     { VLC_CODEC_YVYU, OMX_COLOR_FormatYCrYCb, 4, 2, 0 },
356     { VLC_CODEC_UYVY, OMX_COLOR_FormatCbYCrY, 4, 2, 0 },
357     { VLC_CODEC_VYUY, OMX_COLOR_FormatCrYCbY, 4, 2, 0 },
358     { 0, 0, 0, 0, 0 }
359 };
360
361 int GetOmxVideoFormat( vlc_fourcc_t i_fourcc,
362                        OMX_VIDEO_CODINGTYPE *pi_omx_codec,
363                        const char **ppsz_name )
364 {
365     unsigned int i;
366
367     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
368
369     for( i = 0; video_format_table[i].i_codec != 0; i++ )
370         if( video_format_table[i].i_fourcc == i_fourcc ) break;
371
372     if( pi_omx_codec ) *pi_omx_codec = video_format_table[i].i_codec;
373     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
374     return !!video_format_table[i].i_codec;
375 }
376
377 int GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec,
378                        vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
379 {
380     unsigned int i;
381
382     for( i = 0; video_format_table[i].i_codec != 0; i++ )
383         if( video_format_table[i].i_codec == i_omx_codec ) break;
384
385     if( pi_fourcc ) *pi_fourcc = video_format_table[i].i_fourcc;
386     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
387                                      video_format_table[i].i_fourcc );
388     return !!video_format_table[i].i_fourcc;
389 }
390
391 static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc )
392 {
393     unsigned int i;
394
395     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
396
397     for( i = 0; video_format_table[i].i_codec != 0; i++ )
398         if( video_format_table[i].i_fourcc == i_fourcc ) break;
399
400     return video_format_table[i].psz_role;
401 }
402
403 static const char *GetOmxVideoEncRole( vlc_fourcc_t i_fourcc )
404 {
405     unsigned int i;
406
407     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
408
409     for( i = 0; video_enc_format_table[i].i_codec != 0; i++ )
410         if( video_enc_format_table[i].i_fourcc == i_fourcc ) break;
411
412     return video_enc_format_table[i].psz_role;
413 }
414
415 int GetOmxAudioFormat( vlc_fourcc_t i_fourcc,
416                        OMX_AUDIO_CODINGTYPE *pi_omx_codec,
417                        const char **ppsz_name )
418 {
419     unsigned int i;
420
421     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
422
423     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
424         if( audio_format_table[i].i_fourcc == i_fourcc ) break;
425
426     if( pi_omx_codec ) *pi_omx_codec = audio_format_table[i].i_codec;
427     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES, i_fourcc );
428     return !!audio_format_table[i].i_codec;
429 }
430
431 int GetVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec,
432                        vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
433 {
434     unsigned int i;
435
436     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
437         if( audio_format_table[i].i_codec == i_omx_codec ) break;
438
439     if( pi_fourcc ) *pi_fourcc = audio_format_table[i].i_fourcc;
440     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES,
441                                      audio_format_table[i].i_fourcc );
442     return !!audio_format_table[i].i_fourcc;
443 }
444
445 static const char *GetOmxAudioRole( vlc_fourcc_t i_fourcc )
446 {
447     unsigned int i;
448
449     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
450
451     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
452         if( audio_format_table[i].i_fourcc == i_fourcc ) break;
453
454     return audio_format_table[i].psz_role;
455 }
456
457 static const char *GetOmxAudioEncRole( vlc_fourcc_t i_fourcc )
458 {
459     unsigned int i;
460
461     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
462
463     for( i = 0; audio_enc_format_table[i].i_codec != 0; i++ )
464         if( audio_enc_format_table[i].i_fourcc == i_fourcc ) break;
465
466     return audio_enc_format_table[i].psz_role;
467 }
468
469 const char *GetOmxRole( vlc_fourcc_t i_fourcc, int i_cat, bool b_enc )
470 {
471     if(b_enc)
472         return i_cat == VIDEO_ES ?
473             GetOmxVideoEncRole( i_fourcc ) : GetOmxAudioEncRole( i_fourcc );
474     else
475         return i_cat == VIDEO_ES ?
476             GetOmxVideoRole( i_fourcc ) : GetOmxAudioRole( i_fourcc );
477 }
478
479 int GetOmxChromaFormat( vlc_fourcc_t i_fourcc,
480                         OMX_COLOR_FORMATTYPE *pi_omx_codec,
481                         const char **ppsz_name )
482 {
483     unsigned int i;
484
485     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
486
487     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
488         if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
489
490     if( pi_omx_codec ) *pi_omx_codec = chroma_format_table[i].i_codec;
491     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
492     return !!chroma_format_table[i].i_codec;
493 }
494
495 int GetVlcChromaFormat( OMX_COLOR_FORMATTYPE i_omx_codec,
496                         vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
497 {
498     unsigned int i;
499
500     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
501         if( chroma_format_table[i].i_codec == i_omx_codec ) break;
502
503     if( pi_fourcc ) *pi_fourcc = chroma_format_table[i].i_fourcc;
504     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
505                                      chroma_format_table[i].i_fourcc );
506     return !!chroma_format_table[i].i_fourcc;
507 }
508
509 int GetVlcChromaSizes( vlc_fourcc_t i_fourcc,
510                        unsigned int width, unsigned int height,
511                        unsigned int *size, unsigned int *pitch,
512                        unsigned int *chroma_pitch_div )
513 {
514     unsigned int i;
515
516     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
517
518     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
519         if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
520
521     /* Align on macroblock boundary */
522     width = (width + 15) & ~0xF;
523     height = (height + 15) & ~0xF;
524
525     if( size ) *size = width * height * chroma_format_table[i].i_size_mul / 2;
526     if( pitch ) *pitch = width * chroma_format_table[i].i_line_mul;
527     if( chroma_pitch_div )
528         *chroma_pitch_div = chroma_format_table[i].i_line_chroma_div;
529     return !!chroma_format_table[i].i_codec;
530 }
531
532 /*****************************************************************************
533  * Functions to deal with audio format parameters
534  *****************************************************************************/
535 static const struct {
536     OMX_AUDIO_CODINGTYPE encoding;
537     OMX_INDEXTYPE index;
538     int size;
539 } audio_encoding_param[] =
540 {   { OMX_AUDIO_CodingPCM, OMX_IndexParamAudioPcm,
541       sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
542     { OMX_AUDIO_CodingADPCM, OMX_IndexParamAudioAdpcm,
543       sizeof(OMX_AUDIO_PARAM_ADPCMTYPE) },
544     { OMX_AUDIO_CodingAMR, OMX_IndexParamAudioAmr,
545       sizeof(OMX_AUDIO_PARAM_AMRTYPE) },
546     { OMX_AUDIO_CodingG711, OMX_IndexParamAudioPcm,
547       sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
548     { OMX_AUDIO_CodingG723, OMX_IndexParamAudioG723,
549       sizeof(OMX_AUDIO_PARAM_G723TYPE) },
550     { OMX_AUDIO_CodingG726, OMX_IndexParamAudioG726,
551       sizeof(OMX_AUDIO_PARAM_G726TYPE) },
552     { OMX_AUDIO_CodingG729, OMX_IndexParamAudioG729,
553       sizeof(OMX_AUDIO_PARAM_G729TYPE) },
554     { OMX_AUDIO_CodingAAC, OMX_IndexParamAudioAac,
555       sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE) },
556     { OMX_AUDIO_CodingMP3, OMX_IndexParamAudioMp3,
557       sizeof(OMX_AUDIO_PARAM_MP3TYPE) },
558     { OMX_AUDIO_CodingSBC, OMX_IndexParamAudioSbc,
559       sizeof(OMX_AUDIO_PARAM_SBCTYPE) },
560     { OMX_AUDIO_CodingVORBIS, OMX_IndexParamAudioVorbis,
561       sizeof(OMX_AUDIO_PARAM_VORBISTYPE) },
562     { OMX_AUDIO_CodingWMA, OMX_IndexParamAudioWma,
563       sizeof(OMX_AUDIO_PARAM_WMATYPE) },
564     { OMX_AUDIO_CodingRA, OMX_IndexParamAudioRa,
565       sizeof(OMX_AUDIO_PARAM_RATYPE) },
566     { OMX_AUDIO_CodingUnused, 0, 0 }
567 };
568
569 static OMX_INDEXTYPE GetAudioParamFormatIndex(OMX_AUDIO_CODINGTYPE encoding)
570 {
571   int i;
572
573   for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
574       audio_encoding_param[i].encoding != encoding; i++);
575
576   return audio_encoding_param[i].index;
577 }
578
579 unsigned int GetAudioParamSize(OMX_INDEXTYPE index)
580 {
581   int i;
582
583   for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
584       audio_encoding_param[i].index != index; i++);
585
586   return audio_encoding_param[i].size;
587 }
588
589 OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
590     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
591     uint8_t i_channels, unsigned int i_samplerate, unsigned int i_bitrate,
592     unsigned int i_bps, unsigned int i_blocksize)
593 {
594     OMX_INDEXTYPE index;
595
596     switch(encoding)
597     {
598     case OMX_AUDIO_CodingPCM:
599     case OMX_AUDIO_CodingG711:
600         OMX_INIT_STRUCTURE(param->pcm);
601         param->pcm.nChannels = i_channels;
602         param->pcm.nSamplingRate = i_samplerate;
603         param->pcm.eNumData = OMX_NumericalDataSigned;
604         param->pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
605         param->pcm.eEndian = OMX_EndianLittle;
606         param->pcm.bInterleaved = OMX_TRUE;
607         param->pcm.nBitPerSample = i_bps;
608         param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
609         if(i_channels == 2)
610         {
611             param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
612             param->pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
613         }
614         break;
615     case OMX_AUDIO_CodingADPCM:
616         OMX_INIT_STRUCTURE(param->adpcm);
617         param->adpcm.nChannels = i_channels;
618         param->adpcm.nSampleRate = i_samplerate;
619         param->adpcm.nBitsPerSample = i_bps;
620         break;
621     case OMX_AUDIO_CodingAMR:
622         OMX_INIT_STRUCTURE(param->amr);
623         param->amr.nChannels = i_channels;
624         param->amr.nBitRate = i_bitrate;
625         param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeUnused;
626         param->amr.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
627         param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatConformance;
628         break;
629     case OMX_AUDIO_CodingG723:
630         OMX_INIT_STRUCTURE(param->g723);
631         param->g723.nChannels = i_channels;
632         param->g723.bDTX = OMX_FALSE;
633         param->g723.eBitRate = OMX_AUDIO_G723ModeUnused;
634         param->g723.bHiPassFilter = OMX_TRUE;
635         param->g723.bPostFilter = OMX_TRUE;
636         break;
637     case OMX_AUDIO_CodingG726:
638         OMX_INIT_STRUCTURE(param->g726);
639         param->g726.nChannels = i_channels;
640         param->g726.eG726Mode = OMX_AUDIO_G726ModeUnused;
641         break;
642     case OMX_AUDIO_CodingG729:
643         OMX_INIT_STRUCTURE(param->g729);
644         param->g729.nChannels = i_channels;
645         param->g729.bDTX = OMX_FALSE;
646         param->g729.eBitType = OMX_AUDIO_G729;
647         break;
648     case OMX_AUDIO_CodingAAC:
649         OMX_INIT_STRUCTURE(param->aac);
650         param->aac.nChannels = i_channels;
651         param->aac.nSampleRate = i_samplerate;
652         param->aac.nBitRate = i_bitrate;
653         param->aac.nAudioBandWidth = 0;
654         param->aac.nFrameLength = 1024;
655         param->aac.nAACtools = OMX_AUDIO_AACToolAll;
656         param->aac.nAACERtools = OMX_AUDIO_AACERAll;
657         param->aac.eAACProfile = OMX_AUDIO_AACObjectLC;
658         param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
659         param->aac.eChannelMode = i_channels ?
660             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
661         break;
662     case OMX_AUDIO_CodingMP3:
663         OMX_INIT_STRUCTURE(param->mp3);
664         param->mp3.nChannels = i_channels;
665         param->mp3.nSampleRate = i_samplerate;
666         param->mp3.nBitRate = i_bitrate;
667         param->mp3.eChannelMode = i_channels ?
668             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
669         param->mp3.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
670         break;
671     case OMX_AUDIO_CodingWMA:
672         OMX_INIT_STRUCTURE(param->wma);
673         param->wma.nChannels = i_channels;
674         param->wma.nBitRate = i_bitrate;
675         param->wma.eFormat = OMX_AUDIO_WMAFormatUnused;
676         param->wma.eProfile = OMX_AUDIO_WMAProfileUnused;
677         param->wma.nSamplingRate = i_samplerate;
678         param->wma.nBlockAlign = i_blocksize;
679         param->wma.nEncodeOptions = 0;
680         param->wma.nSuperBlockAlign = 0;
681         break;
682     case OMX_AUDIO_CodingRA:
683         OMX_INIT_STRUCTURE(param->ra);
684         param->ra.nChannels = i_channels;
685         param->ra.nSamplingRate = i_samplerate;
686         param->ra.nBitsPerFrame = i_bps;
687         param->ra.nSamplePerFrame = 0;
688         param->ra.nCouplingQuantBits = 0;
689         param->ra.nCouplingStartRegion = 0;
690         param->ra.nNumRegions = 0;
691         param->ra.eFormat = OMX_AUDIO_RAFormatUnused;
692         break;
693     case OMX_AUDIO_CodingVORBIS:
694         OMX_INIT_STRUCTURE(param->vorbis);
695         param->vorbis.nChannels = i_channels;
696         param->vorbis.nBitRate = i_bitrate;
697         param->vorbis.nMinBitRate = 0;
698         param->vorbis.nMaxBitRate = i_bitrate;
699         param->vorbis.nSampleRate = i_samplerate;
700         param->vorbis.nAudioBandWidth = 0;
701         param->vorbis.nQuality = 3;
702         param->vorbis.bManaged = OMX_FALSE;
703         param->vorbis.bDownmix = OMX_FALSE;
704         break;
705     default:
706         return OMX_ErrorBadParameter;
707     }
708
709     param->common.nPortIndex = i_port;
710
711     index = GetAudioParamFormatIndex(encoding);
712     return OMX_SetParameter(handle, index, param);
713 }
714
715 OMX_ERRORTYPE GetAudioParameters(OMX_HANDLETYPE handle,
716     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
717     uint8_t *pi_channels, unsigned int *pi_samplerate,
718     unsigned int *pi_bitrate, unsigned int *pi_bps, unsigned int *pi_blocksize)
719 {
720     int i_channels = 0, i_samplerate = 0, i_bitrate = 0;
721     int i_bps = 0, i_blocksize = 0;
722     OMX_ERRORTYPE omx_error;
723     OMX_INDEXTYPE index;
724
725     OMX_INIT_COMMON(param->common);
726     param->common.nPortIndex = i_port;
727     index = GetAudioParamFormatIndex(encoding);
728     if(!index) return OMX_ErrorNotImplemented;
729
730     param->common.nSize = GetAudioParamSize(index);
731     omx_error = OMX_GetParameter(handle, index, param);
732     if(omx_error != OMX_ErrorNone) return omx_error;
733
734     switch(encoding)
735     {
736     case OMX_AUDIO_CodingPCM:
737     case OMX_AUDIO_CodingG711:
738         i_channels = param->pcm.nChannels;
739         i_samplerate = param->pcm.nSamplingRate;
740         i_bps = param->pcm.nBitPerSample;
741         break;
742     case OMX_AUDIO_CodingADPCM:
743         i_channels = param->adpcm.nChannels;
744         i_samplerate = param->adpcm.nSampleRate;
745         i_bps = param->adpcm.nBitsPerSample;
746         break;
747     case OMX_AUDIO_CodingAMR:
748         i_channels = param->amr.nChannels;
749         i_bitrate = param->amr.nBitRate;
750         i_samplerate = 8000;
751         break;
752     case OMX_AUDIO_CodingG723:
753         i_channels = param->g723.nChannels;
754         break;
755     case OMX_AUDIO_CodingG726:
756         i_channels = param->g726.nChannels;
757         break;
758     case OMX_AUDIO_CodingG729:
759         i_channels = param->g729.nChannels;
760         break;
761     case OMX_AUDIO_CodingAAC:
762         i_channels = param->aac.nChannels;
763         i_samplerate = param->aac.nSampleRate;
764         i_bitrate = param->aac.nBitRate;
765         i_channels = param->aac.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
766         break;
767     case OMX_AUDIO_CodingMP3:
768         i_channels = param->mp3.nChannels;
769         i_samplerate = param->mp3.nSampleRate;
770         i_bitrate = param->mp3.nBitRate;
771         i_channels = param->mp3.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
772         break;
773     case OMX_AUDIO_CodingVORBIS:
774         i_channels = param->vorbis.nChannels;
775         i_bitrate = param->vorbis.nBitRate;
776         i_samplerate = param->vorbis.nSampleRate;
777         break;
778     case OMX_AUDIO_CodingWMA:
779         i_channels = param->wma.nChannels;
780         i_bitrate = param->wma.nBitRate;
781         i_samplerate = param->wma.nSamplingRate;
782         i_blocksize = param->wma.nBlockAlign;
783         break;
784     case OMX_AUDIO_CodingRA:
785         i_channels = param->ra.nChannels;
786         i_samplerate = param->ra.nSamplingRate;
787         i_bps = param->ra.nBitsPerFrame;
788         break;
789     default:
790         return OMX_ErrorBadParameter;
791     }
792
793     if(pi_channels) *pi_channels = i_channels;
794     if(pi_samplerate) *pi_samplerate = i_samplerate;
795     if(pi_bitrate) *pi_bitrate = i_bitrate;
796     if(pi_bps) *pi_bps = i_bps;
797     if(pi_blocksize) *pi_blocksize = i_blocksize;
798     return OMX_ErrorNone;
799 }
800
801 /*****************************************************************************
802  * PrintOmx: print component summary 
803  *****************************************************************************/
804 void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
805 {
806     OMX_PARAM_PORTDEFINITIONTYPE definition;
807     OMX_PORT_PARAM_TYPE param;
808     OMX_ERRORTYPE omx_error;
809     unsigned int i, j;
810
811     /* Find the input / output ports */
812     OMX_INIT_STRUCTURE(param);
813     OMX_INIT_STRUCTURE(definition);
814
815     for(i = 0; i < 3; i++)
816     {
817         omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamAudioInit + i, &param);
818         if(omx_error != OMX_ErrorNone) continue;
819
820         if(i_port == OMX_ALL)
821             msg_Dbg( p_dec, "found %i %s ports", (int)param.nPorts,
822                      i == 0 ? "audio" : i == 1 ? "image" : "video" );
823
824         for(j = 0; j < param.nPorts; j++)
825         {
826             unsigned int i_samplerate, i_bitrate;
827             unsigned int i_bitspersample, i_blockalign;
828             uint8_t i_channels;
829             OmxFormatParam format_param;
830             vlc_fourcc_t i_fourcc;
831             const char *psz_name;
832
833             if(i_port != OMX_ALL && i_port != param.nStartPortNumber + j)
834                 continue;
835
836             /* Get port definition */
837             definition.nPortIndex = param.nStartPortNumber + j;
838             omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
839                                       &definition);
840             if(omx_error != OMX_ErrorNone) continue;
841
842             OMX_PARAM_U32TYPE u32param;
843             OMX_INIT_STRUCTURE(u32param);
844             u32param.nPortIndex = param.nStartPortNumber + j;
845             omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamNumAvailableStreams,
846                                          (OMX_PTR)&u32param);
847
848             msg_Dbg( p_dec, "-> %s %i (%i streams) (%i:%i:%i buffers) (%i,%i) %s",
849                      definition.eDir == OMX_DirOutput ? "output" : "input",
850                      (int)definition.nPortIndex, (int)u32param.nU32,
851                      (int)definition.nBufferCountActual,
852                      (int)definition.nBufferCountMin, (int)definition.nBufferSize,
853                      (int)definition.bBuffersContiguous,
854                      (int)definition.nBufferAlignment,
855                      definition.bEnabled ? "enabled" : "disabled" );
856
857             switch(definition.eDomain)
858             {
859             case OMX_PortDomainVideo:
860
861                 if(definition.format.video.eCompressionFormat)
862                     GetVlcVideoFormat( definition.format.video.eCompressionFormat,
863                                        &i_fourcc, &psz_name );
864                 else
865                     GetVlcChromaFormat( definition.format.video.eColorFormat,
866                                         &i_fourcc, &psz_name );
867
868                 msg_Dbg( p_dec, "  -> video %s %ix%i@%.2f (%i,%i) (%i,%i)", psz_name,
869                          (int)definition.format.video.nFrameWidth,
870                          (int)definition.format.video.nFrameHeight,
871                          (float)definition.format.video.xFramerate/(float)(1<<16),
872                          (int)definition.format.video.eCompressionFormat,
873                          (int)definition.format.video.eColorFormat,
874                          (int)definition.format.video.nStride,
875                          (int)definition.format.video.nSliceHeight);
876                 break;
877
878             case OMX_PortDomainAudio:
879
880                 GetVlcAudioFormat( definition.format.audio.eEncoding,
881                                    &i_fourcc, &psz_name );
882
883                 GetAudioParameters(omx_handle, &format_param,
884                                    definition.nPortIndex,
885                                    definition.format.audio.eEncoding,
886                                    &i_channels, &i_samplerate, &i_bitrate,
887                                    &i_bitspersample, &i_blockalign);
888
889                 msg_Dbg( p_dec, "  -> audio %s (%i) %i,%i,%i,%i,%i", psz_name,
890                          (int)definition.format.audio.eEncoding,
891                          i_channels, i_samplerate, i_bitrate, i_bitspersample,
892                          i_blockalign);
893                 break;
894
895             default: break;
896             }
897         }
898     }
899 }