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