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