5de339844089c170544d4f57ce3c4be137773f0c
[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 #include "../../video_chroma/copy.h"
40 #include "../../packetizer/h264_nal.h"
41
42 /*****************************************************************************
43  * Events utility functions
44  *****************************************************************************/
45 void InitOmxEventQueue(OmxEventQueue *queue)
46 {
47     queue->pp_last_event = &queue->p_events;
48     vlc_mutex_init(&queue->mutex);
49     vlc_cond_init(&queue->cond);
50 }
51
52 void DeinitOmxEventQueue(OmxEventQueue *queue)
53 {
54     vlc_mutex_destroy(&queue->mutex);
55     vlc_cond_destroy(&queue->cond);
56 }
57
58 OMX_ERRORTYPE PostOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE event,
59     OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
60 {
61     OmxEvent *p_event;
62
63     p_event = malloc(sizeof(OmxEvent));
64     if(!p_event) return OMX_ErrorInsufficientResources;
65
66     p_event->event = event;
67     p_event->data_1 = data_1;
68     p_event->data_2 = data_2;
69     p_event->event_data = event_data;
70     p_event->next = 0;
71
72     vlc_mutex_lock(&queue->mutex);
73     *queue->pp_last_event = p_event;
74     queue->pp_last_event = &p_event->next;
75     vlc_cond_signal(&queue->cond);
76     vlc_mutex_unlock(&queue->mutex);
77     return OMX_ErrorNone;
78 }
79
80 OMX_ERRORTYPE WaitForOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE *event,
81     OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
82 {
83     OmxEvent *p_event;
84     mtime_t deadline = mdate() + CLOCK_FREQ;
85
86     vlc_mutex_lock(&queue->mutex);
87
88     while ((p_event = queue->p_events) == NULL)
89         if (vlc_cond_timedwait(&queue->cond, &queue->mutex, deadline))
90             break;
91
92     if(p_event)
93     {
94         queue->p_events = p_event->next;
95         if(!queue->p_events) queue->pp_last_event = &queue->p_events;
96     }
97
98     vlc_mutex_unlock(&queue->mutex);
99
100     if(p_event)
101     {
102         if(event) *event = p_event->event;
103         if(data_1) *data_1 = p_event->data_1;
104         if(data_2) *data_2 = p_event->data_2;
105         if(event_data) *event_data = p_event->event_data;
106         free(p_event);
107         return OMX_ErrorNone;
108     }
109
110     return OMX_ErrorTimeout;
111 }
112
113 OMX_ERRORTYPE WaitForSpecificOmxEvent(OmxEventQueue *queue,
114     OMX_EVENTTYPE specific_event, OMX_U32 *data_1, OMX_U32 *data_2,
115     OMX_PTR *event_data)
116 {
117     OMX_ERRORTYPE status;
118     OMX_EVENTTYPE event;
119     mtime_t before =  mdate();
120
121     while(1)
122     {
123         status = WaitForOmxEvent(queue, &event, data_1, data_2, event_data);
124         if(status != OMX_ErrorNone) return status;
125
126         if(event == specific_event) break;
127         if(mdate() - before > CLOCK_FREQ) return OMX_ErrorTimeout;
128     }
129
130     return OMX_ErrorNone;
131 }
132
133 void PrintOmxEvent(vlc_object_t *p_this, OMX_EVENTTYPE event, OMX_U32 data_1,
134     OMX_U32 data_2, OMX_PTR event_data)
135 {
136     switch (event)
137     {
138     case OMX_EventCmdComplete:
139         switch ((OMX_STATETYPE)data_1)
140         {
141         case OMX_CommandStateSet:
142             msg_Dbg( p_this, "OmxEventHandler (%s, %s, %s)", EventToString(event),
143                      CommandToString(data_1), StateToString(data_2) );
144             break;
145
146         default:
147             msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u)", EventToString(event),
148                      CommandToString(data_1), (unsigned int)data_2 );
149             break;
150         }
151         break;
152
153     case OMX_EventError:
154         msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
155                  ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
156                  (const char *)event_data);
157         break;
158
159     default:
160         msg_Dbg( p_this, "OmxEventHandler (%s, %u, %u)", EventToString(event),
161                  (unsigned int)data_1, (unsigned int)data_2 );
162         break;
163     }
164 }
165
166 /*****************************************************************************
167  * Picture utility functions
168  *****************************************************************************/
169 void ArchitectureSpecificCopyHooks( decoder_t *p_dec, int i_color_format,
170                                     int i_slice_height, int i_src_stride,
171                                     ArchitectureSpecificCopyData *p_architecture_specific )
172 {
173     (void)i_slice_height;
174
175 #ifdef CAN_COMPILE_SSE2
176     if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
177     {
178         copy_cache_t *p_surface_cache = malloc( sizeof(copy_cache_t) );
179         if( !p_surface_cache || CopyInitCache( p_surface_cache, i_src_stride ) )
180         {
181             free( p_surface_cache );
182             return;
183         }
184         p_architecture_specific->data = p_surface_cache;
185         p_dec->fmt_out.i_codec = VLC_CODEC_YV12;
186     }
187 #endif
188 }
189
190 void ArchitectureSpecificCopyHooksDestroy( int i_color_format,
191                                            ArchitectureSpecificCopyData *p_architecture_specific )
192 {
193     if (!p_architecture_specific->data)
194         return;
195 #ifdef CAN_COMPILE_SSE2
196     if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
197     {
198         copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
199         CopyCleanCache(p_surface_cache);
200     }
201 #endif
202     free(p_architecture_specific->data);
203     p_architecture_specific->data = NULL;
204 }
205
206 void CopyOmxPicture( int i_color_format, picture_t *p_pic,
207                      int i_slice_height,
208                      int i_src_stride, uint8_t *p_src, int i_chroma_div,
209                      ArchitectureSpecificCopyData *p_architecture_specific )
210 {
211     uint8_t *p_dst;
212     int i_dst_stride;
213     int i_plane, i_width, i_line;
214     if( i_color_format == QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka )
215     {
216         qcom_convert(p_src, p_pic);
217         return;
218     }
219 #ifdef CAN_COMPILE_SSE2
220     if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar
221         && vlc_CPU_SSE2() && p_architecture_specific->data )
222     {
223         copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
224         uint8_t *ppi_src_pointers[2] = { p_src, p_src + i_src_stride * i_slice_height };
225         size_t pi_src_strides[2] = { i_src_stride, i_src_stride };
226         CopyFromNv12( p_pic, ppi_src_pointers, pi_src_strides, i_src_stride, i_slice_height, p_surface_cache );
227         return;
228     }
229 #endif
230
231     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
232     {
233         if(i_plane == 1) i_src_stride /= i_chroma_div;
234         p_dst = p_pic->p[i_plane].p_pixels;
235         i_dst_stride = p_pic->p[i_plane].i_pitch;
236         i_width = p_pic->p[i_plane].i_visible_pitch;
237
238         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
239         {
240             memcpy( p_dst, p_src, i_width );
241             p_src += i_src_stride;
242             p_dst += i_dst_stride;
243         }
244         /* Handle plane height, which may be indicated via nSliceHeight in OMX.
245          * The handling for chroma planes currently assumes vertically
246          * subsampled chroma, e.g. 422 planar wouldn't work right. */
247         if( i_plane == 0 && i_slice_height > p_pic->p[i_plane].i_visible_lines )
248             p_src += i_src_stride * (i_slice_height - p_pic->p[i_plane].i_visible_lines);
249         else if ( i_plane > 0 && i_slice_height/2 > p_pic->p[i_plane].i_visible_lines )
250             p_src += i_src_stride * (i_slice_height/2 - p_pic->p[i_plane].i_visible_lines);
251     }
252 }
253
254 void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
255                      picture_t *p_pic)
256 {
257     decoder_sys_t *p_sys = p_dec->p_sys;
258     int i_src_stride, i_dst_stride;
259     int i_plane, i_width, i_line;
260     uint8_t *p_dst, *p_src;
261
262     i_dst_stride  = p_sys->out.i_frame_stride;
263     p_dst = p_header->pBuffer + p_header->nOffset;
264
265     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
266     {
267         if(i_plane == 1) i_dst_stride /= p_sys->in.i_frame_stride_chroma_div;
268         p_src = p_pic->p[i_plane].p_pixels;
269         i_src_stride = p_pic->p[i_plane].i_pitch;
270         i_width = p_pic->p[i_plane].i_visible_pitch;
271
272         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
273         {
274             memcpy( p_dst, p_src, i_width );
275             p_src += i_src_stride;
276             p_dst += i_dst_stride;
277         }
278     }
279 }
280
281 /*****************************************************************************
282  * Utility functions
283  *****************************************************************************/
284 bool OMXCodec_IsBlacklisted( const char *p_name, unsigned int i_name_len )
285 {
286     static const char *blacklisted_prefix[] = {
287         /* ignore OpenCore software codecs */
288         "OMX.PV.",
289         /* The same sw codecs, renamed in ICS (perhaps also in honeycomb) */
290         "OMX.google.",
291         /* This one has been seen on HTC One V - it behaves like it works,
292          * but FillBufferDone returns buffers filled with 0 bytes. The One V
293          * has got a working OMX.qcom.video.decoder.avc instead though. */
294         "OMX.ARICENT.",
295         /* Use VC1 decoder for WMV3 for now */
296         "OMX.SEC.WMV.Decoder",
297         /* This decoder does work, but has an insane latency (leading to errors
298          * about "main audio output playback way too late" and dropped frames).
299          * At least Samsung Galaxy S III (where this decoder is present) has
300          * got another one, OMX.SEC.mp3.dec, that works well and has a
301          * sensible latency. (Also, even if that one isn't found, in general,
302          * using SW codecs is usually more than fast enough for MP3.) */
303         "OMX.SEC.MP3.Decoder",
304         /* This codec should be able to handle both VC1 and WMV3, but
305          * for VC1 it doesn't output any buffers at all (in the way we use
306          * it) and for WMV3 it outputs plain black buffers. Thus ignore
307          * it until we can make it work properly. */
308         "OMX.Nvidia.vc1.decode",
309         /* black screen */
310         "OMX.MTK.VIDEO.DECODER.VC1",
311         /* Not working or crashing (Samsung) */
312         "OMX.SEC.vp8.dec",
313         NULL
314     };
315
316     static const char *blacklisted_suffix[] = {
317         /* Codecs with DRM, that don't output plain YUV data but only
318          * support direct rendering where the output can't be intercepted. */
319         ".secure",
320         /* Samsung sw decoders */
321         ".sw.dec",
322         NULL
323     };
324
325     /* p_name is not '\0' terminated */
326
327     for( const char **pp_bl_prefix = blacklisted_prefix; *pp_bl_prefix != NULL;
328           pp_bl_prefix++ )
329     {
330         if( !strncmp( p_name, *pp_bl_prefix,
331            __MIN( strlen(*pp_bl_prefix), i_name_len ) ) )
332            return true;
333     }
334
335     for( const char **pp_bl_suffix = blacklisted_suffix; *pp_bl_suffix != NULL;
336          pp_bl_suffix++ )
337     {
338        size_t i_suffix_len = strlen( *pp_bl_suffix );
339
340        if( i_name_len > i_suffix_len
341         && !strncmp( p_name + i_name_len - i_suffix_len, *pp_bl_suffix,
342                      i_suffix_len ) )
343            return true;
344     }
345
346     return false;
347 }
348
349 struct str2quirks {
350     const char *psz_name;
351     int i_quirks;
352 };
353
354 int OMXCodec_GetQuirks( int i_cat, vlc_fourcc_t i_codec,
355                         const char *p_name, unsigned int i_name_len )
356 {
357     static const struct str2quirks quirks_prefix[] = {
358         { "OMX.MTK.VIDEO.DECODER.MPEG4", OMXCODEC_QUIRKS_NEED_CSD },
359         { "OMX.Marvell", OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS },
360
361         /* The list of decoders that signal padding properly is not necessary,
362          * since that is the default, but keep it here for reference. (This is
363          * only relevant for manufacturers that are known to have decoders with
364          * this kind of bug.)
365          * static const char *padding_decoders[] = {
366          *    "OMX.SEC.AVC.Decoder",
367          *    "OMX.SEC.wmv7.dec",
368          *    "OMX.SEC.wmv8.dec",
369          *     NULL
370          * };
371          */
372         { "OMX.SEC.avc.dec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
373         { "OMX.SEC.avcdec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
374         { "OMX.SEC.MPEG4.Decoder", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
375         { "OMX.SEC.mpeg4.dec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
376         { "OMX.SEC.vc1.dec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
377         { NULL, 0 }
378     };
379
380     static struct str2quirks quirks_suffix[] = {
381         { NULL, 0 }
382     };
383
384     int i_quirks = OMXCODEC_NO_QUIRKS;
385
386     if( i_cat == VIDEO_ES )
387     {
388         i_quirks |= OMXCODEC_VIDEO_QUIRKS_NEED_SIZE;
389         switch( i_codec )
390         {
391         case VLC_CODEC_H264:
392         case VLC_CODEC_VC1:
393             i_quirks |= OMXCODEC_QUIRKS_NEED_CSD;
394             break;
395         }
396     } else if( i_cat == AUDIO_ES )
397     {
398         switch( i_codec )
399         {
400         case VLC_CODEC_VORBIS:
401         case VLC_CODEC_MP4A:
402             i_quirks |= OMXCODEC_QUIRKS_NEED_CSD;
403             break;
404         }
405     }
406
407     /* p_name is not '\0' terminated */
408
409     for( const struct str2quirks *p_q_prefix = quirks_prefix; p_q_prefix->psz_name;
410          p_q_prefix++ )
411     {
412         const char *psz_prefix = p_q_prefix->psz_name;
413         if( !strncmp( p_name, psz_prefix,
414            __MIN( strlen(psz_prefix), i_name_len ) ) )
415            i_quirks |= p_q_prefix->i_quirks;
416     }
417
418     for( const struct str2quirks *p_q_suffix = quirks_suffix; p_q_suffix->psz_name;
419          p_q_suffix++ )
420     {
421         const char *psz_suffix = p_q_suffix->psz_name;
422         size_t i_suffix_len = strlen( psz_suffix );
423
424         if( i_name_len > i_suffix_len
425          && !strncmp( p_name + i_name_len - i_suffix_len, psz_suffix,
426                       i_suffix_len ) )
427            i_quirks |= p_q_suffix->i_quirks;
428     }
429
430     return i_quirks;
431 }
432
433 /*****************************************************************************
434  * Logging utility functions
435  *****************************************************************************/
436 const char *StateToString(OMX_STATETYPE state)
437 {
438     static const char *psz_names[] = {
439         "OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
440         "OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
441         "OMX_State unknown"
442     };
443
444     if((unsigned int)state > sizeof(psz_names)/sizeof(char*)-1)
445         state = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
446     return psz_names[state];
447 }
448
449 const char *CommandToString(OMX_COMMANDTYPE command)
450 {
451     static const char *psz_names[] = {
452         "OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
453         "OMX_CommandPortEnable", "OMX_CommandMarkBuffer",
454         "OMX_Command unknown"
455     };
456
457     if((unsigned int)command > sizeof(psz_names)/sizeof(char*)-1)
458         command = (OMX_COMMANDTYPE)(sizeof(psz_names)/sizeof(char*)-1);
459     return psz_names[command];
460 }
461
462 const char *EventToString(OMX_EVENTTYPE event)
463 {
464     static const char *psz_names[] = {
465         "OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
466         "OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
467         "OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
468         "OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
469         "OMX_Event unknown"
470     };
471
472     if((unsigned int)event > sizeof(psz_names)/sizeof(char*)-1)
473         event = (OMX_EVENTTYPE)(sizeof(psz_names)/sizeof(char*)-1);
474     return psz_names[event];
475 }
476
477 const char *ErrorToString(OMX_ERRORTYPE error)
478 {
479     static const char *psz_names[] = {
480         "OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
481         "OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
482         "OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
483         "OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
484         "OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
485         "OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
486         "OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
487         "OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
488         "OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
489         "OMX_ErrorPortUnresponsiveDuringDeallocation",
490         "OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
491         "OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
492         "OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
493         "OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
494         "OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
495         "OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
496         "OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
497         "OMX_ErrorTunnelingUnsupported",
498         "OMX_Error unknown"
499     };
500
501     if(error == OMX_ErrorNone) return "OMX_ErrorNone";
502
503     error -= OMX_ErrorInsufficientResources;
504
505     if((unsigned int)error > sizeof(psz_names)/sizeof(char*)-1)
506         error = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
507     return psz_names[error];
508 }
509
510 /*****************************************************************************
511  * fourcc -> omx id mapping
512  *****************************************************************************/
513 static const struct
514 {
515     vlc_fourcc_t i_fourcc;
516     OMX_VIDEO_CODINGTYPE i_codec;
517     const char *psz_role;
518
519 } video_format_table[] =
520 {
521     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_decoder.mpeg2" },
522     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_decoder.mpeg4" },
523     { VLC_CODEC_HEVC, OMX_VIDEO_CodingAutoDetect, "video_decoder.hevc" },
524     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_decoder.avc"   },
525     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_decoder.h263"  },
526     { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_decoder.wmv1"  },
527     { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_decoder.wmv2"  },
528     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
529     { VLC_CODEC_VC1,  OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
530     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.jpeg"  },
531     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.mjpeg" },
532     { VLC_CODEC_RV10, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
533     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
534     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
535     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
536     { VLC_CODEC_VP8,  OMX_VIDEO_CodingAutoDetect, "video_decoder.vp8" },
537     { VLC_CODEC_VP9,  OMX_VIDEO_CodingAutoDetect, "video_decoder.vp9" },
538     { 0, 0, 0 }
539 };
540
541 static const struct
542 {
543     vlc_fourcc_t i_fourcc;
544     OMX_AUDIO_CODINGTYPE i_codec;
545     const char *psz_role;
546
547 } audio_format_table[] =
548 {
549     { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amrnb" },
550     { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amrwb" },
551     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_decoder.aac" },
552     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_decoder.pcm" },
553     { VLC_CODEC_MP3,    OMX_AUDIO_CodingMP3, "audio_decoder.mp3" },
554     { 0, 0, 0 }
555 };
556
557 static const struct
558 {
559     vlc_fourcc_t i_fourcc;
560     OMX_VIDEO_CODINGTYPE i_codec;
561     const char *psz_role;
562
563 } video_enc_format_table[] =
564 {
565     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_encoder.mpeg2" },
566     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_encoder.mpeg4" },
567     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_encoder.avc"   },
568     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_encoder.h263"  },
569     { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
570     { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
571     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_encoder.wmv"   },
572     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_encoder.jpeg"  },
573     { VLC_CODEC_RV10, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
574     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
575     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
576     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_encoder.rv"    },
577     { 0, 0, 0 }
578 };
579
580 static const struct
581 {
582     vlc_fourcc_t i_fourcc;
583     OMX_AUDIO_CODINGTYPE i_codec;
584     const char *psz_role;
585
586 } audio_enc_format_table[] =
587 {
588     { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amrnb" },
589     { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amrwb" },
590     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_encoder.aac" },
591     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_encoder.pcm" },
592     { 0, 0, 0 }
593 };
594
595 static const struct
596 {
597     vlc_fourcc_t i_fourcc;
598     OMX_COLOR_FORMATTYPE i_codec;
599     unsigned int i_size_mul;
600     unsigned int i_line_mul;
601     unsigned int i_line_chroma_div;
602
603 } chroma_format_table[] =
604 {
605     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420Planar, 3, 1, 2 },
606     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420PackedPlanar, 3, 1, 2 },
607     { VLC_CODEC_NV12, OMX_COLOR_FormatYUV420SemiPlanar, 3, 1, 1 },
608     { VLC_CODEC_NV21, OMX_QCOM_COLOR_FormatYVU420SemiPlanar, 3, 1, 1 },
609     { VLC_CODEC_NV12, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar, 3, 1, 1 },
610     { VLC_CODEC_NV12, QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, 3, 1, 1 },
611     { VLC_CODEC_NV12, OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m, 3, 1, 1 },
612     { VLC_CODEC_YUYV, OMX_COLOR_FormatYCbYCr, 4, 2, 0 },
613     { VLC_CODEC_YVYU, OMX_COLOR_FormatYCrYCb, 4, 2, 0 },
614     { VLC_CODEC_UYVY, OMX_COLOR_FormatCbYCrY, 4, 2, 0 },
615     { VLC_CODEC_VYUY, OMX_COLOR_FormatCrYCbY, 4, 2, 0 },
616     { 0, 0, 0, 0, 0 }
617 };
618
619 int GetOmxVideoFormat( vlc_fourcc_t i_fourcc,
620                        OMX_VIDEO_CODINGTYPE *pi_omx_codec,
621                        const char **ppsz_name )
622 {
623     unsigned int i;
624
625     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
626
627     for( i = 0; video_format_table[i].i_codec != 0; i++ )
628         if( video_format_table[i].i_fourcc == i_fourcc ) break;
629
630     if( pi_omx_codec ) *pi_omx_codec = video_format_table[i].i_codec;
631     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
632     return !!video_format_table[i].i_codec;
633 }
634
635 int GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec,
636                        vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
637 {
638     unsigned int i;
639
640     for( i = 0; video_format_table[i].i_codec != 0; i++ )
641         if( video_format_table[i].i_codec == i_omx_codec ) break;
642
643     if( pi_fourcc ) *pi_fourcc = video_format_table[i].i_fourcc;
644     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
645                                      video_format_table[i].i_fourcc );
646     return !!video_format_table[i].i_fourcc;
647 }
648
649 static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc )
650 {
651     unsigned int i;
652
653     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
654
655     for( i = 0; video_format_table[i].i_codec != 0; i++ )
656         if( video_format_table[i].i_fourcc == i_fourcc ) break;
657
658     return video_format_table[i].psz_role;
659 }
660
661 static const char *GetOmxVideoEncRole( vlc_fourcc_t i_fourcc )
662 {
663     unsigned int i;
664
665     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
666
667     for( i = 0; video_enc_format_table[i].i_codec != 0; i++ )
668         if( video_enc_format_table[i].i_fourcc == i_fourcc ) break;
669
670     return video_enc_format_table[i].psz_role;
671 }
672
673 int GetOmxAudioFormat( vlc_fourcc_t i_fourcc,
674                        OMX_AUDIO_CODINGTYPE *pi_omx_codec,
675                        const char **ppsz_name )
676 {
677     unsigned int i;
678
679     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
680
681     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
682         if( audio_format_table[i].i_fourcc == i_fourcc ) break;
683
684     if( pi_omx_codec ) *pi_omx_codec = audio_format_table[i].i_codec;
685     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES, i_fourcc );
686     return !!audio_format_table[i].i_codec;
687 }
688
689 int OmxToVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec,
690                        vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
691 {
692     unsigned int i;
693
694     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
695         if( audio_format_table[i].i_codec == i_omx_codec ) break;
696
697     if( pi_fourcc ) *pi_fourcc = audio_format_table[i].i_fourcc;
698     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES,
699                                      audio_format_table[i].i_fourcc );
700     return !!audio_format_table[i].i_fourcc;
701 }
702
703 static const char *GetOmxAudioRole( vlc_fourcc_t i_fourcc )
704 {
705     unsigned int i;
706
707     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
708
709     for( i = 0; audio_format_table[i].i_codec != 0; i++ )
710         if( audio_format_table[i].i_fourcc == i_fourcc ) break;
711
712     return audio_format_table[i].psz_role;
713 }
714
715 static const char *GetOmxAudioEncRole( vlc_fourcc_t i_fourcc )
716 {
717     unsigned int i;
718
719     i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
720
721     for( i = 0; audio_enc_format_table[i].i_codec != 0; i++ )
722         if( audio_enc_format_table[i].i_fourcc == i_fourcc ) break;
723
724     return audio_enc_format_table[i].psz_role;
725 }
726
727 const char *GetOmxRole( vlc_fourcc_t i_fourcc, int i_cat, bool b_enc )
728 {
729     if(b_enc)
730         return i_cat == VIDEO_ES ?
731             GetOmxVideoEncRole( i_fourcc ) : GetOmxAudioEncRole( i_fourcc );
732     else
733         return i_cat == VIDEO_ES ?
734             GetOmxVideoRole( i_fourcc ) : GetOmxAudioRole( i_fourcc );
735 }
736
737 int GetOmxChromaFormat( vlc_fourcc_t i_fourcc,
738                         OMX_COLOR_FORMATTYPE *pi_omx_codec,
739                         const char **ppsz_name )
740 {
741     unsigned int i;
742
743     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
744
745     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
746         if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
747
748     if( pi_omx_codec ) *pi_omx_codec = chroma_format_table[i].i_codec;
749     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
750     return !!chroma_format_table[i].i_codec;
751 }
752
753 int GetVlcChromaFormat( OMX_COLOR_FORMATTYPE i_omx_codec,
754                         vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
755 {
756     unsigned int i;
757
758     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
759         if( chroma_format_table[i].i_codec == i_omx_codec ) break;
760
761     if( pi_fourcc ) *pi_fourcc = chroma_format_table[i].i_fourcc;
762     if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
763                                      chroma_format_table[i].i_fourcc );
764     return !!chroma_format_table[i].i_fourcc;
765 }
766
767 int GetVlcChromaSizes( vlc_fourcc_t i_fourcc,
768                        unsigned int width, unsigned int height,
769                        unsigned int *size, unsigned int *pitch,
770                        unsigned int *chroma_pitch_div )
771 {
772     unsigned int i;
773
774     i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
775
776     for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
777         if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
778
779     /* Align on macroblock boundary */
780     width = (width + 15) & ~0xF;
781     height = (height + 15) & ~0xF;
782
783     if( size ) *size = width * height * chroma_format_table[i].i_size_mul / 2;
784     if( pitch ) *pitch = width * chroma_format_table[i].i_line_mul;
785     if( chroma_pitch_div )
786         *chroma_pitch_div = chroma_format_table[i].i_line_chroma_div;
787     return !!chroma_format_table[i].i_codec;
788 }
789
790 /*****************************************************************************
791  * Functions to deal with audio format parameters
792  *****************************************************************************/
793 static const struct {
794     OMX_AUDIO_CODINGTYPE encoding;
795     OMX_INDEXTYPE index;
796     int size;
797 } audio_encoding_param[] =
798 {   { OMX_AUDIO_CodingPCM, OMX_IndexParamAudioPcm,
799       sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
800     { OMX_AUDIO_CodingADPCM, OMX_IndexParamAudioAdpcm,
801       sizeof(OMX_AUDIO_PARAM_ADPCMTYPE) },
802     { OMX_AUDIO_CodingAMR, OMX_IndexParamAudioAmr,
803       sizeof(OMX_AUDIO_PARAM_AMRTYPE) },
804     { OMX_AUDIO_CodingG711, OMX_IndexParamAudioPcm,
805       sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
806     { OMX_AUDIO_CodingG723, OMX_IndexParamAudioG723,
807       sizeof(OMX_AUDIO_PARAM_G723TYPE) },
808     { OMX_AUDIO_CodingG726, OMX_IndexParamAudioG726,
809       sizeof(OMX_AUDIO_PARAM_G726TYPE) },
810     { OMX_AUDIO_CodingG729, OMX_IndexParamAudioG729,
811       sizeof(OMX_AUDIO_PARAM_G729TYPE) },
812     { OMX_AUDIO_CodingAAC, OMX_IndexParamAudioAac,
813       sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE) },
814     { OMX_AUDIO_CodingMP3, OMX_IndexParamAudioMp3,
815       sizeof(OMX_AUDIO_PARAM_MP3TYPE) },
816     { OMX_AUDIO_CodingSBC, OMX_IndexParamAudioSbc,
817       sizeof(OMX_AUDIO_PARAM_SBCTYPE) },
818     { OMX_AUDIO_CodingVORBIS, OMX_IndexParamAudioVorbis,
819       sizeof(OMX_AUDIO_PARAM_VORBISTYPE) },
820     { OMX_AUDIO_CodingWMA, OMX_IndexParamAudioWma,
821       sizeof(OMX_AUDIO_PARAM_WMATYPE) },
822     { OMX_AUDIO_CodingRA, OMX_IndexParamAudioRa,
823       sizeof(OMX_AUDIO_PARAM_RATYPE) },
824     { OMX_AUDIO_CodingUnused, 0, 0 }
825 };
826
827 static OMX_INDEXTYPE GetAudioParamFormatIndex(OMX_AUDIO_CODINGTYPE encoding)
828 {
829   int i;
830
831   for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
832       audio_encoding_param[i].encoding != encoding; i++);
833
834   return audio_encoding_param[i].index;
835 }
836
837 unsigned int GetAudioParamSize(OMX_INDEXTYPE index)
838 {
839   int i;
840
841   for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
842       audio_encoding_param[i].index != index; i++);
843
844   return audio_encoding_param[i].size;
845 }
846
847 OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
848     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
849     vlc_fourcc_t i_codec, uint8_t i_channels, unsigned int i_samplerate,
850     unsigned int i_bitrate, unsigned int i_bps, unsigned int i_blocksize)
851 {
852     OMX_INDEXTYPE index;
853
854     switch(encoding)
855     {
856     case OMX_AUDIO_CodingPCM:
857     case OMX_AUDIO_CodingG711:
858         OMX_INIT_STRUCTURE(param->pcm);
859         param->pcm.nChannels = i_channels;
860         param->pcm.nSamplingRate = i_samplerate;
861         param->pcm.eNumData = OMX_NumericalDataSigned;
862         param->pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
863         param->pcm.eEndian = OMX_EndianLittle;
864         param->pcm.bInterleaved = OMX_TRUE;
865         param->pcm.nBitPerSample = i_bps;
866         param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
867         if(i_channels == 2)
868         {
869             param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
870             param->pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
871         }
872         break;
873     case OMX_AUDIO_CodingADPCM:
874         OMX_INIT_STRUCTURE(param->adpcm);
875         param->adpcm.nChannels = i_channels;
876         param->adpcm.nSampleRate = i_samplerate;
877         param->adpcm.nBitsPerSample = i_bps;
878         break;
879     case OMX_AUDIO_CodingAMR:
880         OMX_INIT_STRUCTURE(param->amr);
881         param->amr.nChannels = i_channels;
882         param->amr.nBitRate = i_bitrate;
883         if (i_codec == VLC_CODEC_AMR_WB)
884             param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
885         else
886             param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
887         param->amr.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
888         param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
889         break;
890     case OMX_AUDIO_CodingG723:
891         OMX_INIT_STRUCTURE(param->g723);
892         param->g723.nChannels = i_channels;
893         param->g723.bDTX = OMX_FALSE;
894         param->g723.eBitRate = OMX_AUDIO_G723ModeUnused;
895         param->g723.bHiPassFilter = OMX_TRUE;
896         param->g723.bPostFilter = OMX_TRUE;
897         break;
898     case OMX_AUDIO_CodingG726:
899         OMX_INIT_STRUCTURE(param->g726);
900         param->g726.nChannels = i_channels;
901         param->g726.eG726Mode = OMX_AUDIO_G726ModeUnused;
902         break;
903     case OMX_AUDIO_CodingG729:
904         OMX_INIT_STRUCTURE(param->g729);
905         param->g729.nChannels = i_channels;
906         param->g729.bDTX = OMX_FALSE;
907         param->g729.eBitType = OMX_AUDIO_G729;
908         break;
909     case OMX_AUDIO_CodingAAC:
910         OMX_INIT_STRUCTURE(param->aac);
911         param->aac.nChannels = i_channels;
912         param->aac.nSampleRate = i_samplerate;
913         param->aac.nBitRate = i_bitrate;
914         param->aac.nAudioBandWidth = 0;
915         param->aac.nFrameLength = 1024;
916         param->aac.nAACtools = OMX_AUDIO_AACToolAll;
917         param->aac.nAACERtools = OMX_AUDIO_AACERAll;
918         param->aac.eAACProfile = OMX_AUDIO_AACObjectLC;
919         param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
920         param->aac.eChannelMode = i_channels > 1 ?
921             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
922         break;
923     case OMX_AUDIO_CodingMP3:
924         OMX_INIT_STRUCTURE(param->mp3);
925         param->mp3.nChannels = i_channels;
926         param->mp3.nSampleRate = i_samplerate;
927         param->mp3.nBitRate = i_bitrate;
928         param->mp3.eChannelMode = i_channels > 1 ?
929             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
930         param->mp3.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
931         break;
932     case OMX_AUDIO_CodingWMA:
933         OMX_INIT_STRUCTURE(param->wma);
934         param->wma.nChannels = i_channels;
935         param->wma.nBitRate = i_bitrate;
936         param->wma.eFormat = OMX_AUDIO_WMAFormatUnused;
937         param->wma.eProfile = OMX_AUDIO_WMAProfileUnused;
938         param->wma.nSamplingRate = i_samplerate;
939         param->wma.nBlockAlign = i_blocksize;
940         param->wma.nEncodeOptions = 0;
941         param->wma.nSuperBlockAlign = 0;
942         break;
943     case OMX_AUDIO_CodingRA:
944         OMX_INIT_STRUCTURE(param->ra);
945         param->ra.nChannels = i_channels;
946         param->ra.nSamplingRate = i_samplerate;
947         param->ra.nBitsPerFrame = i_bps;
948         param->ra.nSamplePerFrame = 0;
949         param->ra.nCouplingQuantBits = 0;
950         param->ra.nCouplingStartRegion = 0;
951         param->ra.nNumRegions = 0;
952         param->ra.eFormat = OMX_AUDIO_RAFormatUnused;
953         break;
954     case OMX_AUDIO_CodingVORBIS:
955         OMX_INIT_STRUCTURE(param->vorbis);
956         param->vorbis.nChannels = i_channels;
957         param->vorbis.nBitRate = i_bitrate;
958         param->vorbis.nMinBitRate = 0;
959         param->vorbis.nMaxBitRate = i_bitrate;
960         param->vorbis.nSampleRate = i_samplerate;
961         param->vorbis.nAudioBandWidth = 0;
962         param->vorbis.nQuality = 3;
963         param->vorbis.bManaged = OMX_FALSE;
964         param->vorbis.bDownmix = OMX_FALSE;
965         break;
966     default:
967         return OMX_ErrorBadParameter;
968     }
969
970     param->common.nPortIndex = i_port;
971
972     index = GetAudioParamFormatIndex(encoding);
973     return OMX_SetParameter(handle, index, param);
974 }
975
976 OMX_ERRORTYPE GetAudioParameters(OMX_HANDLETYPE handle,
977     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
978     uint8_t *pi_channels, unsigned int *pi_samplerate,
979     unsigned int *pi_bitrate, unsigned int *pi_bps, unsigned int *pi_blocksize)
980 {
981     int i_channels = 0, i_samplerate = 0, i_bitrate = 0;
982     int i_bps = 0, i_blocksize = 0;
983     OMX_ERRORTYPE omx_error;
984     OMX_INDEXTYPE index;
985
986     OMX_INIT_COMMON(param->common);
987     param->common.nPortIndex = i_port;
988     index = GetAudioParamFormatIndex(encoding);
989     if(!index) return OMX_ErrorNotImplemented;
990
991     param->common.nSize = GetAudioParamSize(index);
992     omx_error = OMX_GetParameter(handle, index, param);
993     if(omx_error != OMX_ErrorNone) return omx_error;
994
995     switch(encoding)
996     {
997     case OMX_AUDIO_CodingPCM:
998     case OMX_AUDIO_CodingG711:
999         i_channels = param->pcm.nChannels;
1000         i_samplerate = param->pcm.nSamplingRate;
1001         i_bps = param->pcm.nBitPerSample;
1002         break;
1003     case OMX_AUDIO_CodingADPCM:
1004         i_channels = param->adpcm.nChannels;
1005         i_samplerate = param->adpcm.nSampleRate;
1006         i_bps = param->adpcm.nBitsPerSample;
1007         break;
1008     case OMX_AUDIO_CodingAMR:
1009         i_channels = param->amr.nChannels;
1010         i_bitrate = param->amr.nBitRate;
1011         i_samplerate = 8000;
1012         break;
1013     case OMX_AUDIO_CodingG723:
1014         i_channels = param->g723.nChannels;
1015         break;
1016     case OMX_AUDIO_CodingG726:
1017         i_channels = param->g726.nChannels;
1018         break;
1019     case OMX_AUDIO_CodingG729:
1020         i_channels = param->g729.nChannels;
1021         break;
1022     case OMX_AUDIO_CodingAAC:
1023         i_channels = param->aac.nChannels;
1024         i_samplerate = param->aac.nSampleRate;
1025         i_bitrate = param->aac.nBitRate;
1026         i_channels = param->aac.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
1027         break;
1028     case OMX_AUDIO_CodingMP3:
1029         i_channels = param->mp3.nChannels;
1030         i_samplerate = param->mp3.nSampleRate;
1031         i_bitrate = param->mp3.nBitRate;
1032         i_channels = param->mp3.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
1033         break;
1034     case OMX_AUDIO_CodingVORBIS:
1035         i_channels = param->vorbis.nChannels;
1036         i_bitrate = param->vorbis.nBitRate;
1037         i_samplerate = param->vorbis.nSampleRate;
1038         break;
1039     case OMX_AUDIO_CodingWMA:
1040         i_channels = param->wma.nChannels;
1041         i_bitrate = param->wma.nBitRate;
1042         i_samplerate = param->wma.nSamplingRate;
1043         i_blocksize = param->wma.nBlockAlign;
1044         break;
1045     case OMX_AUDIO_CodingRA:
1046         i_channels = param->ra.nChannels;
1047         i_samplerate = param->ra.nSamplingRate;
1048         i_bps = param->ra.nBitsPerFrame;
1049         break;
1050     default:
1051         return OMX_ErrorBadParameter;
1052     }
1053
1054     if(pi_channels) *pi_channels = i_channels;
1055     if(pi_samplerate) *pi_samplerate = i_samplerate;
1056     if(pi_bitrate) *pi_bitrate = i_bitrate;
1057     if(pi_bps) *pi_bps = i_bps;
1058     if(pi_blocksize) *pi_blocksize = i_blocksize;
1059     return OMX_ErrorNone;
1060 }
1061
1062 /*****************************************************************************
1063  * PrintOmx: print component summary
1064  *****************************************************************************/
1065 void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
1066 {
1067     OMX_PARAM_PORTDEFINITIONTYPE definition;
1068     OMX_PORT_PARAM_TYPE param;
1069     OMX_ERRORTYPE omx_error;
1070     unsigned int i, j;
1071
1072     /* Find the input / output ports */
1073     OMX_INIT_STRUCTURE(param);
1074     OMX_INIT_STRUCTURE(definition);
1075
1076     for(i = 0; i < 3; i++)
1077     {
1078         omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamAudioInit + i, &param);
1079         if(omx_error != OMX_ErrorNone) continue;
1080
1081         if(i_port == OMX_ALL)
1082             msg_Dbg( p_dec, "found %i %s ports", (int)param.nPorts,
1083                      i == 0 ? "audio" : i == 1 ? "image" : "video" );
1084
1085         for(j = 0; j < param.nPorts; j++)
1086         {
1087             unsigned int i_samplerate, i_bitrate;
1088             unsigned int i_bitspersample, i_blockalign;
1089             uint8_t i_channels;
1090             OmxFormatParam format_param;
1091             vlc_fourcc_t i_fourcc;
1092             const char *psz_name;
1093             OMX_CONFIG_RECTTYPE crop_rect;
1094
1095             if(i_port != OMX_ALL && i_port != param.nStartPortNumber + j)
1096                 continue;
1097
1098             /* Get port definition */
1099             definition.nPortIndex = param.nStartPortNumber + j;
1100             omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
1101                                       &definition);
1102             if(omx_error != OMX_ErrorNone) continue;
1103
1104             OMX_PARAM_U32TYPE u32param;
1105             OMX_INIT_STRUCTURE(u32param);
1106             u32param.nPortIndex = param.nStartPortNumber + j;
1107             omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamNumAvailableStreams,
1108                                          (OMX_PTR)&u32param);
1109
1110             msg_Dbg( p_dec, "-> %s %i (%i streams) (%i:%i:%i buffers) (%i,%i) %s",
1111                      definition.eDir == OMX_DirOutput ? "output" : "input",
1112                      (int)definition.nPortIndex, (int)u32param.nU32,
1113                      (int)definition.nBufferCountActual,
1114                      (int)definition.nBufferCountMin, (int)definition.nBufferSize,
1115                      (int)definition.bBuffersContiguous,
1116                      (int)definition.nBufferAlignment,
1117                      definition.bEnabled ? "enabled" : "disabled" );
1118
1119             switch(definition.eDomain)
1120             {
1121             case OMX_PortDomainVideo:
1122
1123                 if(definition.format.video.eCompressionFormat)
1124                     GetVlcVideoFormat( definition.format.video.eCompressionFormat,
1125                                        &i_fourcc, &psz_name );
1126                 else
1127                     GetVlcChromaFormat( definition.format.video.eColorFormat,
1128                                         &i_fourcc, &psz_name );
1129
1130                 OMX_INIT_STRUCTURE(crop_rect);
1131                 crop_rect.nPortIndex = definition.nPortIndex;
1132                 omx_error = OMX_GetConfig(omx_handle, OMX_IndexConfigCommonOutputCrop, &crop_rect);
1133                 if (omx_error != OMX_ErrorNone)
1134                 {
1135                     crop_rect.nLeft = crop_rect.nTop = 0;
1136                     crop_rect.nWidth  = definition.format.video.nFrameWidth;
1137                     crop_rect.nHeight = definition.format.video.nFrameHeight;
1138                 }
1139
1140                 msg_Dbg( p_dec, "  -> video %s %ix%i@%.2f (%i,%i) (%i,%i) (%i,%i,%i,%i)", psz_name,
1141                          (int)definition.format.video.nFrameWidth,
1142                          (int)definition.format.video.nFrameHeight,
1143                          (float)definition.format.video.xFramerate/(float)(1<<16),
1144                          (int)definition.format.video.eCompressionFormat,
1145                          (int)definition.format.video.eColorFormat,
1146                          (int)definition.format.video.nStride,
1147                          (int)definition.format.video.nSliceHeight,
1148                          (int)crop_rect.nLeft, (int)crop_rect.nTop,
1149                          (int)crop_rect.nWidth, (int)crop_rect.nHeight);
1150                 break;
1151
1152             case OMX_PortDomainAudio:
1153
1154                 OmxToVlcAudioFormat( definition.format.audio.eEncoding,
1155                                    &i_fourcc, &psz_name );
1156
1157                 GetAudioParameters(omx_handle, &format_param,
1158                                    definition.nPortIndex,
1159                                    definition.format.audio.eEncoding,
1160                                    &i_channels, &i_samplerate, &i_bitrate,
1161                                    &i_bitspersample, &i_blockalign);
1162
1163                 msg_Dbg( p_dec, "  -> audio %s (%i) %i,%i,%i,%i,%i", psz_name,
1164                          (int)definition.format.audio.eEncoding,
1165                          i_channels, i_samplerate, i_bitrate, i_bitspersample,
1166                          i_blockalign);
1167                 break;
1168
1169             default: break;
1170             }
1171         }
1172     }
1173 }
1174
1175 static const struct
1176 {
1177     OMX_VIDEO_AVCPROFILETYPE omx_profile;
1178     size_t                   profile_idc;
1179 } omx_to_profile_idc[] =
1180 {
1181     { OMX_VIDEO_AVCProfileBaseline,  PROFILE_H264_BASELINE },
1182     { OMX_VIDEO_AVCProfileMain,      PROFILE_H264_MAIN },
1183     { OMX_VIDEO_AVCProfileExtended,  PROFILE_H264_EXTENDED },
1184     { OMX_VIDEO_AVCProfileHigh,      PROFILE_H264_HIGH },
1185     { OMX_VIDEO_AVCProfileHigh10,    PROFILE_H264_HIGH_10 },
1186     { OMX_VIDEO_AVCProfileHigh422,   PROFILE_H264_HIGH_422 },
1187     { OMX_VIDEO_AVCProfileHigh444,   PROFILE_H264_HIGH_444 },
1188 };
1189
1190 size_t convert_omx_to_profile_idc(OMX_VIDEO_AVCPROFILETYPE profile_type)
1191 {
1192     size_t array_length = sizeof(omx_to_profile_idc)/sizeof(omx_to_profile_idc[0]);
1193     for (size_t i = 0; i < array_length; ++i) {
1194         if (omx_to_profile_idc[i].omx_profile == profile_type)
1195             return omx_to_profile_idc[i].profile_idc;
1196     }
1197     return 0;
1198 }
1199
1200 static const struct
1201 {
1202     OMX_VIDEO_AVCLEVELTYPE omx_level;
1203     size_t                 level_idc;
1204 } omx_to_level_idc[] =
1205 {
1206     { OMX_VIDEO_AVCLevel1,  10 },
1207     { OMX_VIDEO_AVCLevel1b,  9 },
1208     { OMX_VIDEO_AVCLevel11, 11 },
1209     { OMX_VIDEO_AVCLevel12, 12 },
1210     { OMX_VIDEO_AVCLevel13, 13 },
1211     { OMX_VIDEO_AVCLevel2,  20 },
1212     { OMX_VIDEO_AVCLevel21, 21 },
1213     { OMX_VIDEO_AVCLevel22, 22 },
1214     { OMX_VIDEO_AVCLevel3,  30 },
1215     { OMX_VIDEO_AVCLevel31, 31 },
1216     { OMX_VIDEO_AVCLevel32, 32 },
1217     { OMX_VIDEO_AVCLevel4,  40 },
1218     { OMX_VIDEO_AVCLevel41, 41 },
1219     { OMX_VIDEO_AVCLevel42, 42 },
1220     { OMX_VIDEO_AVCLevel5,  50 },
1221     { OMX_VIDEO_AVCLevel51, 51 },
1222 };
1223
1224 size_t convert_omx_to_level_idc(OMX_VIDEO_AVCLEVELTYPE level_type)
1225 {
1226     size_t array_length = sizeof(omx_to_level_idc)/sizeof(omx_to_level_idc[0]);
1227     for (size_t i = 0; i < array_length; ++i) {
1228         if (omx_to_level_idc[i].omx_level == level_type)
1229             return omx_to_level_idc[i].level_idc;
1230     }
1231     return 0;
1232 }