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