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