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