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