1 /*****************************************************************************
2 * utils.c: helper functions
3 *****************************************************************************
4 * Copyright (C) 2010 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <vlc_block_helper.h>
39 #include "../../video_chroma/copy.h"
41 /*****************************************************************************
42 * Events utility functions
43 *****************************************************************************/
44 void InitOmxEventQueue(OmxEventQueue *queue)
46 queue->pp_last_event = &queue->p_events;
47 vlc_mutex_init(&queue->mutex);
48 vlc_cond_init(&queue->cond);
51 void DeinitOmxEventQueue(OmxEventQueue *queue)
53 vlc_mutex_destroy(&queue->mutex);
54 vlc_cond_destroy(&queue->cond);
57 OMX_ERRORTYPE PostOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE event,
58 OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
62 p_event = malloc(sizeof(OmxEvent));
63 if(!p_event) return OMX_ErrorInsufficientResources;
65 p_event->event = event;
66 p_event->data_1 = data_1;
67 p_event->data_2 = data_2;
68 p_event->event_data = event_data;
71 vlc_mutex_lock(&queue->mutex);
72 *queue->pp_last_event = p_event;
73 queue->pp_last_event = &p_event->next;
74 vlc_cond_signal(&queue->cond);
75 vlc_mutex_unlock(&queue->mutex);
79 OMX_ERRORTYPE WaitForOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE *event,
80 OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
84 vlc_mutex_lock(&queue->mutex);
87 vlc_cond_timedwait(&queue->cond, &queue->mutex, mdate()+CLOCK_FREQ);
89 p_event = queue->p_events;
92 queue->p_events = p_event->next;
93 if(!queue->p_events) queue->pp_last_event = &queue->p_events;
96 vlc_mutex_unlock(&queue->mutex);
100 if(event) *event = p_event->event;
101 if(data_1) *data_1 = p_event->data_1;
102 if(data_2) *data_2 = p_event->data_2;
103 if(event_data) *event_data = p_event->event_data;
105 return OMX_ErrorNone;
108 return OMX_ErrorTimeout;
111 OMX_ERRORTYPE WaitForSpecificOmxEvent(OmxEventQueue *queue,
112 OMX_EVENTTYPE specific_event, OMX_U32 *data_1, OMX_U32 *data_2,
115 OMX_ERRORTYPE status;
117 mtime_t before = mdate();
121 status = WaitForOmxEvent(queue, &event, data_1, data_2, event_data);
122 if(status != OMX_ErrorNone) return status;
124 if(event == specific_event) break;
125 if(mdate() - before > CLOCK_FREQ) return OMX_ErrorTimeout;
128 return OMX_ErrorNone;
131 void PrintOmxEvent(vlc_object_t *p_this, OMX_EVENTTYPE event, OMX_U32 data_1,
132 OMX_U32 data_2, OMX_PTR event_data)
136 case OMX_EventCmdComplete:
137 switch ((OMX_STATETYPE)data_1)
139 case OMX_CommandStateSet:
140 msg_Dbg( p_this, "OmxEventHandler (%s, %s, %s)", EventToString(event),
141 CommandToString(data_1), StateToString(data_2) );
145 msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u)", EventToString(event),
146 CommandToString(data_1), (unsigned int)data_2 );
152 msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
153 ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
154 (const char *)event_data);
158 msg_Dbg( p_this, "OmxEventHandler (%s, %u, %u)", EventToString(event),
159 (unsigned int)data_1, (unsigned int)data_2 );
164 /*****************************************************************************
165 * Picture utility functions
166 *****************************************************************************/
167 void ArchitectureSpecificCopyHooks( decoder_t *p_dec, int i_color_format,
168 int i_slice_height, int i_src_stride,
169 ArchitectureSpecificCopyData *p_architecture_specific )
171 (void)i_slice_height;
173 #ifdef CAN_COMPILE_SSE2
174 if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
176 copy_cache_t *p_surface_cache = malloc( sizeof(copy_cache_t) );
177 if( !p_surface_cache || CopyInitCache( p_surface_cache, i_src_stride ) )
179 free( p_surface_cache );
182 p_architecture_specific->data = p_surface_cache;
183 p_dec->fmt_out.i_codec = VLC_CODEC_YV12;
188 void ArchitectureSpecificCopyHooksDestroy( int i_color_format,
189 ArchitectureSpecificCopyData *p_architecture_specific )
191 if (!p_architecture_specific->data)
193 #ifdef CAN_COMPILE_SSE2
194 if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
196 copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
197 CopyCleanCache(p_surface_cache);
200 free(p_architecture_specific->data);
201 p_architecture_specific->data = NULL;
204 void CopyOmxPicture( int i_color_format, picture_t *p_pic,
206 int i_src_stride, uint8_t *p_src, int i_chroma_div,
207 ArchitectureSpecificCopyData *p_architecture_specific )
211 int i_plane, i_width, i_line;
212 if( i_color_format == QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka )
214 qcom_convert(p_src, p_pic);
217 #ifdef CAN_COMPILE_SSE2
218 if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar
219 && vlc_CPU_SSE2() && p_architecture_specific->data )
221 copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
222 uint8_t *ppi_src_pointers[2] = { p_src, p_src + i_src_stride * i_slice_height };
223 size_t pi_src_strides[2] = { i_src_stride, i_src_stride };
224 CopyFromNv12( p_pic, ppi_src_pointers, pi_src_strides, i_src_stride, i_slice_height, p_surface_cache );
229 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
231 if(i_plane == 1) i_src_stride /= i_chroma_div;
232 p_dst = p_pic->p[i_plane].p_pixels;
233 i_dst_stride = p_pic->p[i_plane].i_pitch;
234 i_width = p_pic->p[i_plane].i_visible_pitch;
236 for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
238 memcpy( p_dst, p_src, i_width );
239 p_src += i_src_stride;
240 p_dst += i_dst_stride;
242 /* Handle plane height, which may be indicated via nSliceHeight in OMX.
243 * The handling for chroma planes currently assumes vertically
244 * subsampled chroma, e.g. 422 planar wouldn't work right. */
245 if( i_plane == 0 && i_slice_height > p_pic->p[i_plane].i_visible_lines )
246 p_src += i_src_stride * (i_slice_height - p_pic->p[i_plane].i_visible_lines);
247 else if ( i_plane > 0 && i_slice_height/2 > p_pic->p[i_plane].i_visible_lines )
248 p_src += i_src_stride * (i_slice_height/2 - p_pic->p[i_plane].i_visible_lines);
252 void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
255 decoder_sys_t *p_sys = p_dec->p_sys;
256 int i_src_stride, i_dst_stride;
257 int i_plane, i_width, i_line;
258 uint8_t *p_dst, *p_src;
260 i_dst_stride = p_sys->out.i_frame_stride;
261 p_dst = p_header->pBuffer + p_header->nOffset;
263 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
265 if(i_plane == 1) i_dst_stride /= p_sys->in.i_frame_stride_chroma_div;
266 p_src = p_pic->p[i_plane].p_pixels;
267 i_src_stride = p_pic->p[i_plane].i_pitch;
268 i_width = p_pic->p[i_plane].i_visible_pitch;
270 for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
272 memcpy( p_dst, p_src, i_width );
273 p_src += i_src_stride;
274 p_dst += i_dst_stride;
279 int IgnoreOmxDecoderPadding(const char *name)
281 // The list of decoders that signal padding properly is not necessary,
282 // since that is the default, but keep it here for reference. (This is
283 // only relevant for manufacturers that are known to have decoders with
284 // this kind of bug.)
286 static const char *padding_decoders[] = {
287 "OMX.SEC.AVC.Decoder",
293 static const char *nopadding_decoders[] = {
296 "OMX.SEC.MPEG4.Decoder",
301 for (const char **ptr = nopadding_decoders; *ptr; ptr++) {
302 if (!strcmp(*ptr, name))
308 /*****************************************************************************
309 * Logging utility functions
310 *****************************************************************************/
311 const char *StateToString(OMX_STATETYPE state)
313 static const char *psz_names[] = {
314 "OMX_StateInvalid", "OMX_StateLoaded", "OMX_StateIdle",
315 "OMX_StateExecuting", "OMX_StatePause", "OMX_StateWaitForResources",
319 if((unsigned int)state > sizeof(psz_names)/sizeof(char*)-1)
320 state = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
321 return psz_names[state];
324 const char *CommandToString(OMX_COMMANDTYPE command)
326 static const char *psz_names[] = {
327 "OMX_CommandStateSet", "OMX_CommandFlush", "OMX_CommandPortDisable",
328 "OMX_CommandPortEnable", "OMX_CommandMarkBuffer",
329 "OMX_Command unknown"
332 if((unsigned int)command > sizeof(psz_names)/sizeof(char*)-1)
333 command = (OMX_COMMANDTYPE)(sizeof(psz_names)/sizeof(char*)-1);
334 return psz_names[command];
337 const char *EventToString(OMX_EVENTTYPE event)
339 static const char *psz_names[] = {
340 "OMX_EventCmdComplete", "OMX_EventError", "OMX_EventMark",
341 "OMX_EventPortSettingsChanged", "OMX_EventBufferFlag",
342 "OMX_EventResourcesAcquired", "OMX_EventComponentResumed",
343 "OMX_EventDynamicResourcesAvailable", "OMX_EventPortFormatDetected",
347 if((unsigned int)event > sizeof(psz_names)/sizeof(char*)-1)
348 event = (OMX_EVENTTYPE)(sizeof(psz_names)/sizeof(char*)-1);
349 return psz_names[event];
352 const char *ErrorToString(OMX_ERRORTYPE error)
354 static const char *psz_names[] = {
355 "OMX_ErrorInsufficientResources", "OMX_ErrorUndefined",
356 "OMX_ErrorInvalidComponentName", "OMX_ErrorComponentNotFound",
357 "OMX_ErrorInvalidComponent", "OMX_ErrorBadParameter",
358 "OMX_ErrorNotImplemented", "OMX_ErrorUnderflow",
359 "OMX_ErrorOverflow", "OMX_ErrorHardware", "OMX_ErrorInvalidState",
360 "OMX_ErrorStreamCorrupt", "OMX_ErrorPortsNotCompatible",
361 "OMX_ErrorResourcesLost", "OMX_ErrorNoMore", "OMX_ErrorVersionMismatch",
362 "OMX_ErrorNotReady", "OMX_ErrorTimeout", "OMX_ErrorSameState",
363 "OMX_ErrorResourcesPreempted", "OMX_ErrorPortUnresponsiveDuringAllocation",
364 "OMX_ErrorPortUnresponsiveDuringDeallocation",
365 "OMX_ErrorPortUnresponsiveDuringStop", "OMX_ErrorIncorrectStateTransition",
366 "OMX_ErrorIncorrectStateOperation", "OMX_ErrorUnsupportedSetting",
367 "OMX_ErrorUnsupportedIndex", "OMX_ErrorBadPortIndex",
368 "OMX_ErrorPortUnpopulated", "OMX_ErrorComponentSuspended",
369 "OMX_ErrorDynamicResourcesUnavailable", "OMX_ErrorMbErrorsInFrame",
370 "OMX_ErrorFormatNotDetected", "OMX_ErrorContentPipeOpenFailed",
371 "OMX_ErrorContentPipeCreationFailed", "OMX_ErrorSeperateTablesUsed",
372 "OMX_ErrorTunnelingUnsupported",
376 if(error == OMX_ErrorNone) return "OMX_ErrorNone";
378 error -= OMX_ErrorInsufficientResources;
380 if((unsigned int)error > sizeof(psz_names)/sizeof(char*)-1)
381 error = (OMX_STATETYPE)(sizeof(psz_names)/sizeof(char*)-1);
382 return psz_names[error];
385 /*****************************************************************************
386 * fourcc -> omx id mapping
387 *****************************************************************************/
390 vlc_fourcc_t i_fourcc;
391 OMX_VIDEO_CODINGTYPE i_codec;
392 const char *psz_role;
394 } video_format_table[] =
396 { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_decoder.mpeg2" },
397 { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_decoder.mpeg4" },
398 { VLC_CODEC_HEVC, OMX_VIDEO_CodingAutoDetect, "video_decoder.hevc" },
399 { VLC_CODEC_H264, OMX_VIDEO_CodingAVC, "video_decoder.avc" },
400 { VLC_CODEC_H263, OMX_VIDEO_CodingH263, "video_decoder.h263" },
401 { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV, "video_decoder.wmv1" },
402 { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV, "video_decoder.wmv2" },
403 { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV, "video_decoder.wmv" },
404 { VLC_CODEC_VC1, OMX_VIDEO_CodingWMV, "video_decoder.wmv" },
405 { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.jpeg" },
406 { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.mjpeg" },
407 { VLC_CODEC_RV10, OMX_VIDEO_CodingRV, "video_decoder.rv" },
408 { VLC_CODEC_RV20, OMX_VIDEO_CodingRV, "video_decoder.rv" },
409 { VLC_CODEC_RV30, OMX_VIDEO_CodingRV, "video_decoder.rv" },
410 { VLC_CODEC_RV40, OMX_VIDEO_CodingRV, "video_decoder.rv" },
411 { VLC_CODEC_VP8, OMX_VIDEO_CodingAutoDetect, "video_decoder.vp8" },
412 { VLC_CODEC_VP9, OMX_VIDEO_CodingAutoDetect, "video_decoder.vp9" },
418 vlc_fourcc_t i_fourcc;
419 OMX_AUDIO_CODINGTYPE i_codec;
420 const char *psz_role;
422 } audio_format_table[] =
424 { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amrnb" },
425 { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amrwb" },
426 { VLC_CODEC_MP4A, OMX_AUDIO_CodingAAC, "audio_decoder.aac" },
427 { VLC_CODEC_S16N, OMX_AUDIO_CodingPCM, "audio_decoder.pcm" },
428 { VLC_CODEC_MP3, OMX_AUDIO_CodingMP3, "audio_decoder.mp3" },
434 vlc_fourcc_t i_fourcc;
435 OMX_VIDEO_CODINGTYPE i_codec;
436 const char *psz_role;
438 } video_enc_format_table[] =
440 { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_encoder.mpeg2" },
441 { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_encoder.mpeg4" },
442 { VLC_CODEC_H264, OMX_VIDEO_CodingAVC, "video_encoder.avc" },
443 { VLC_CODEC_H263, OMX_VIDEO_CodingH263, "video_encoder.h263" },
444 { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV, "video_encoder.wmv" },
445 { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV, "video_encoder.wmv" },
446 { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV, "video_encoder.wmv" },
447 { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_encoder.jpeg" },
448 { VLC_CODEC_RV10, OMX_VIDEO_CodingRV, "video_encoder.rv" },
449 { VLC_CODEC_RV20, OMX_VIDEO_CodingRV, "video_encoder.rv" },
450 { VLC_CODEC_RV30, OMX_VIDEO_CodingRV, "video_encoder.rv" },
451 { VLC_CODEC_RV40, OMX_VIDEO_CodingRV, "video_encoder.rv" },
457 vlc_fourcc_t i_fourcc;
458 OMX_AUDIO_CODINGTYPE i_codec;
459 const char *psz_role;
461 } audio_enc_format_table[] =
463 { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amrnb" },
464 { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amrwb" },
465 { VLC_CODEC_MP4A, OMX_AUDIO_CodingAAC, "audio_encoder.aac" },
466 { VLC_CODEC_S16N, OMX_AUDIO_CodingPCM, "audio_encoder.pcm" },
472 vlc_fourcc_t i_fourcc;
473 OMX_COLOR_FORMATTYPE i_codec;
474 unsigned int i_size_mul;
475 unsigned int i_line_mul;
476 unsigned int i_line_chroma_div;
478 } chroma_format_table[] =
480 { VLC_CODEC_I420, OMX_COLOR_FormatYUV420Planar, 3, 1, 2 },
481 { VLC_CODEC_I420, OMX_COLOR_FormatYUV420PackedPlanar, 3, 1, 2 },
482 { VLC_CODEC_NV12, OMX_COLOR_FormatYUV420SemiPlanar, 3, 1, 1 },
483 { VLC_CODEC_NV21, OMX_QCOM_COLOR_FormatYVU420SemiPlanar, 3, 1, 1 },
484 { VLC_CODEC_NV12, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar, 3, 1, 1 },
485 { VLC_CODEC_NV12, QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, 3, 1, 1 },
486 { VLC_CODEC_NV12, OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m, 3, 1, 1 },
487 { VLC_CODEC_YUYV, OMX_COLOR_FormatYCbYCr, 4, 2, 0 },
488 { VLC_CODEC_YVYU, OMX_COLOR_FormatYCrYCb, 4, 2, 0 },
489 { VLC_CODEC_UYVY, OMX_COLOR_FormatCbYCrY, 4, 2, 0 },
490 { VLC_CODEC_VYUY, OMX_COLOR_FormatCrYCbY, 4, 2, 0 },
494 int GetOmxVideoFormat( vlc_fourcc_t i_fourcc,
495 OMX_VIDEO_CODINGTYPE *pi_omx_codec,
496 const char **ppsz_name )
500 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
502 for( i = 0; video_format_table[i].i_codec != 0; i++ )
503 if( video_format_table[i].i_fourcc == i_fourcc ) break;
505 if( pi_omx_codec ) *pi_omx_codec = video_format_table[i].i_codec;
506 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
507 return !!video_format_table[i].i_codec;
510 int GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec,
511 vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
515 for( i = 0; video_format_table[i].i_codec != 0; i++ )
516 if( video_format_table[i].i_codec == i_omx_codec ) break;
518 if( pi_fourcc ) *pi_fourcc = video_format_table[i].i_fourcc;
519 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
520 video_format_table[i].i_fourcc );
521 return !!video_format_table[i].i_fourcc;
524 static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc )
528 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
530 for( i = 0; video_format_table[i].i_codec != 0; i++ )
531 if( video_format_table[i].i_fourcc == i_fourcc ) break;
533 return video_format_table[i].psz_role;
536 static const char *GetOmxVideoEncRole( vlc_fourcc_t i_fourcc )
540 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
542 for( i = 0; video_enc_format_table[i].i_codec != 0; i++ )
543 if( video_enc_format_table[i].i_fourcc == i_fourcc ) break;
545 return video_enc_format_table[i].psz_role;
548 int GetOmxAudioFormat( vlc_fourcc_t i_fourcc,
549 OMX_AUDIO_CODINGTYPE *pi_omx_codec,
550 const char **ppsz_name )
554 i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
556 for( i = 0; audio_format_table[i].i_codec != 0; i++ )
557 if( audio_format_table[i].i_fourcc == i_fourcc ) break;
559 if( pi_omx_codec ) *pi_omx_codec = audio_format_table[i].i_codec;
560 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES, i_fourcc );
561 return !!audio_format_table[i].i_codec;
564 int OmxToVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec,
565 vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
569 for( i = 0; audio_format_table[i].i_codec != 0; i++ )
570 if( audio_format_table[i].i_codec == i_omx_codec ) break;
572 if( pi_fourcc ) *pi_fourcc = audio_format_table[i].i_fourcc;
573 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( AUDIO_ES,
574 audio_format_table[i].i_fourcc );
575 return !!audio_format_table[i].i_fourcc;
578 static const char *GetOmxAudioRole( vlc_fourcc_t i_fourcc )
582 i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
584 for( i = 0; audio_format_table[i].i_codec != 0; i++ )
585 if( audio_format_table[i].i_fourcc == i_fourcc ) break;
587 return audio_format_table[i].psz_role;
590 static const char *GetOmxAudioEncRole( vlc_fourcc_t i_fourcc )
594 i_fourcc = vlc_fourcc_GetCodec( AUDIO_ES, i_fourcc );
596 for( i = 0; audio_enc_format_table[i].i_codec != 0; i++ )
597 if( audio_enc_format_table[i].i_fourcc == i_fourcc ) break;
599 return audio_enc_format_table[i].psz_role;
602 const char *GetOmxRole( vlc_fourcc_t i_fourcc, int i_cat, bool b_enc )
605 return i_cat == VIDEO_ES ?
606 GetOmxVideoEncRole( i_fourcc ) : GetOmxAudioEncRole( i_fourcc );
608 return i_cat == VIDEO_ES ?
609 GetOmxVideoRole( i_fourcc ) : GetOmxAudioRole( i_fourcc );
612 int GetOmxChromaFormat( vlc_fourcc_t i_fourcc,
613 OMX_COLOR_FORMATTYPE *pi_omx_codec,
614 const char **ppsz_name )
618 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
620 for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
621 if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
623 if( pi_omx_codec ) *pi_omx_codec = chroma_format_table[i].i_codec;
624 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES, i_fourcc );
625 return !!chroma_format_table[i].i_codec;
628 int GetVlcChromaFormat( OMX_COLOR_FORMATTYPE i_omx_codec,
629 vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
633 for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
634 if( chroma_format_table[i].i_codec == i_omx_codec ) break;
636 if( pi_fourcc ) *pi_fourcc = chroma_format_table[i].i_fourcc;
637 if( ppsz_name ) *ppsz_name = vlc_fourcc_GetDescription( VIDEO_ES,
638 chroma_format_table[i].i_fourcc );
639 return !!chroma_format_table[i].i_fourcc;
642 int GetVlcChromaSizes( vlc_fourcc_t i_fourcc,
643 unsigned int width, unsigned int height,
644 unsigned int *size, unsigned int *pitch,
645 unsigned int *chroma_pitch_div )
649 i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
651 for( i = 0; chroma_format_table[i].i_codec != 0; i++ )
652 if( chroma_format_table[i].i_fourcc == i_fourcc ) break;
654 /* Align on macroblock boundary */
655 width = (width + 15) & ~0xF;
656 height = (height + 15) & ~0xF;
658 if( size ) *size = width * height * chroma_format_table[i].i_size_mul / 2;
659 if( pitch ) *pitch = width * chroma_format_table[i].i_line_mul;
660 if( chroma_pitch_div )
661 *chroma_pitch_div = chroma_format_table[i].i_line_chroma_div;
662 return !!chroma_format_table[i].i_codec;
665 /*****************************************************************************
666 * Functions to deal with audio format parameters
667 *****************************************************************************/
668 static const struct {
669 OMX_AUDIO_CODINGTYPE encoding;
672 } audio_encoding_param[] =
673 { { OMX_AUDIO_CodingPCM, OMX_IndexParamAudioPcm,
674 sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
675 { OMX_AUDIO_CodingADPCM, OMX_IndexParamAudioAdpcm,
676 sizeof(OMX_AUDIO_PARAM_ADPCMTYPE) },
677 { OMX_AUDIO_CodingAMR, OMX_IndexParamAudioAmr,
678 sizeof(OMX_AUDIO_PARAM_AMRTYPE) },
679 { OMX_AUDIO_CodingG711, OMX_IndexParamAudioPcm,
680 sizeof(OMX_AUDIO_PARAM_PCMMODETYPE) },
681 { OMX_AUDIO_CodingG723, OMX_IndexParamAudioG723,
682 sizeof(OMX_AUDIO_PARAM_G723TYPE) },
683 { OMX_AUDIO_CodingG726, OMX_IndexParamAudioG726,
684 sizeof(OMX_AUDIO_PARAM_G726TYPE) },
685 { OMX_AUDIO_CodingG729, OMX_IndexParamAudioG729,
686 sizeof(OMX_AUDIO_PARAM_G729TYPE) },
687 { OMX_AUDIO_CodingAAC, OMX_IndexParamAudioAac,
688 sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE) },
689 { OMX_AUDIO_CodingMP3, OMX_IndexParamAudioMp3,
690 sizeof(OMX_AUDIO_PARAM_MP3TYPE) },
691 { OMX_AUDIO_CodingSBC, OMX_IndexParamAudioSbc,
692 sizeof(OMX_AUDIO_PARAM_SBCTYPE) },
693 { OMX_AUDIO_CodingVORBIS, OMX_IndexParamAudioVorbis,
694 sizeof(OMX_AUDIO_PARAM_VORBISTYPE) },
695 { OMX_AUDIO_CodingWMA, OMX_IndexParamAudioWma,
696 sizeof(OMX_AUDIO_PARAM_WMATYPE) },
697 { OMX_AUDIO_CodingRA, OMX_IndexParamAudioRa,
698 sizeof(OMX_AUDIO_PARAM_RATYPE) },
699 { OMX_AUDIO_CodingUnused, 0, 0 }
702 static OMX_INDEXTYPE GetAudioParamFormatIndex(OMX_AUDIO_CODINGTYPE encoding)
706 for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
707 audio_encoding_param[i].encoding != encoding; i++);
709 return audio_encoding_param[i].index;
712 unsigned int GetAudioParamSize(OMX_INDEXTYPE index)
716 for(i = 0; audio_encoding_param[i].encoding != OMX_AUDIO_CodingUnused &&
717 audio_encoding_param[i].index != index; i++);
719 return audio_encoding_param[i].size;
722 OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
723 OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
724 vlc_fourcc_t i_codec, uint8_t i_channels, unsigned int i_samplerate,
725 unsigned int i_bitrate, unsigned int i_bps, unsigned int i_blocksize)
731 case OMX_AUDIO_CodingPCM:
732 case OMX_AUDIO_CodingG711:
733 OMX_INIT_STRUCTURE(param->pcm);
734 param->pcm.nChannels = i_channels;
735 param->pcm.nSamplingRate = i_samplerate;
736 param->pcm.eNumData = OMX_NumericalDataSigned;
737 param->pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
738 param->pcm.eEndian = OMX_EndianLittle;
739 param->pcm.bInterleaved = OMX_TRUE;
740 param->pcm.nBitPerSample = i_bps;
741 param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
744 param->pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
745 param->pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
748 case OMX_AUDIO_CodingADPCM:
749 OMX_INIT_STRUCTURE(param->adpcm);
750 param->adpcm.nChannels = i_channels;
751 param->adpcm.nSampleRate = i_samplerate;
752 param->adpcm.nBitsPerSample = i_bps;
754 case OMX_AUDIO_CodingAMR:
755 OMX_INIT_STRUCTURE(param->amr);
756 param->amr.nChannels = i_channels;
757 param->amr.nBitRate = i_bitrate;
758 if (i_codec == VLC_CODEC_AMR_WB)
759 param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
761 param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
762 param->amr.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
763 param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
765 case OMX_AUDIO_CodingG723:
766 OMX_INIT_STRUCTURE(param->g723);
767 param->g723.nChannels = i_channels;
768 param->g723.bDTX = OMX_FALSE;
769 param->g723.eBitRate = OMX_AUDIO_G723ModeUnused;
770 param->g723.bHiPassFilter = OMX_TRUE;
771 param->g723.bPostFilter = OMX_TRUE;
773 case OMX_AUDIO_CodingG726:
774 OMX_INIT_STRUCTURE(param->g726);
775 param->g726.nChannels = i_channels;
776 param->g726.eG726Mode = OMX_AUDIO_G726ModeUnused;
778 case OMX_AUDIO_CodingG729:
779 OMX_INIT_STRUCTURE(param->g729);
780 param->g729.nChannels = i_channels;
781 param->g729.bDTX = OMX_FALSE;
782 param->g729.eBitType = OMX_AUDIO_G729;
784 case OMX_AUDIO_CodingAAC:
785 OMX_INIT_STRUCTURE(param->aac);
786 param->aac.nChannels = i_channels;
787 param->aac.nSampleRate = i_samplerate;
788 param->aac.nBitRate = i_bitrate;
789 param->aac.nAudioBandWidth = 0;
790 param->aac.nFrameLength = 1024;
791 param->aac.nAACtools = OMX_AUDIO_AACToolAll;
792 param->aac.nAACERtools = OMX_AUDIO_AACERAll;
793 param->aac.eAACProfile = OMX_AUDIO_AACObjectLC;
794 param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
795 param->aac.eChannelMode = i_channels > 1 ?
796 OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
798 case OMX_AUDIO_CodingMP3:
799 OMX_INIT_STRUCTURE(param->mp3);
800 param->mp3.nChannels = i_channels;
801 param->mp3.nSampleRate = i_samplerate;
802 param->mp3.nBitRate = i_bitrate;
803 param->mp3.eChannelMode = i_channels > 1 ?
804 OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
805 param->mp3.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
807 case OMX_AUDIO_CodingWMA:
808 OMX_INIT_STRUCTURE(param->wma);
809 param->wma.nChannels = i_channels;
810 param->wma.nBitRate = i_bitrate;
811 param->wma.eFormat = OMX_AUDIO_WMAFormatUnused;
812 param->wma.eProfile = OMX_AUDIO_WMAProfileUnused;
813 param->wma.nSamplingRate = i_samplerate;
814 param->wma.nBlockAlign = i_blocksize;
815 param->wma.nEncodeOptions = 0;
816 param->wma.nSuperBlockAlign = 0;
818 case OMX_AUDIO_CodingRA:
819 OMX_INIT_STRUCTURE(param->ra);
820 param->ra.nChannels = i_channels;
821 param->ra.nSamplingRate = i_samplerate;
822 param->ra.nBitsPerFrame = i_bps;
823 param->ra.nSamplePerFrame = 0;
824 param->ra.nCouplingQuantBits = 0;
825 param->ra.nCouplingStartRegion = 0;
826 param->ra.nNumRegions = 0;
827 param->ra.eFormat = OMX_AUDIO_RAFormatUnused;
829 case OMX_AUDIO_CodingVORBIS:
830 OMX_INIT_STRUCTURE(param->vorbis);
831 param->vorbis.nChannels = i_channels;
832 param->vorbis.nBitRate = i_bitrate;
833 param->vorbis.nMinBitRate = 0;
834 param->vorbis.nMaxBitRate = i_bitrate;
835 param->vorbis.nSampleRate = i_samplerate;
836 param->vorbis.nAudioBandWidth = 0;
837 param->vorbis.nQuality = 3;
838 param->vorbis.bManaged = OMX_FALSE;
839 param->vorbis.bDownmix = OMX_FALSE;
842 return OMX_ErrorBadParameter;
845 param->common.nPortIndex = i_port;
847 index = GetAudioParamFormatIndex(encoding);
848 return OMX_SetParameter(handle, index, param);
851 OMX_ERRORTYPE GetAudioParameters(OMX_HANDLETYPE handle,
852 OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
853 uint8_t *pi_channels, unsigned int *pi_samplerate,
854 unsigned int *pi_bitrate, unsigned int *pi_bps, unsigned int *pi_blocksize)
856 int i_channels = 0, i_samplerate = 0, i_bitrate = 0;
857 int i_bps = 0, i_blocksize = 0;
858 OMX_ERRORTYPE omx_error;
861 OMX_INIT_COMMON(param->common);
862 param->common.nPortIndex = i_port;
863 index = GetAudioParamFormatIndex(encoding);
864 if(!index) return OMX_ErrorNotImplemented;
866 param->common.nSize = GetAudioParamSize(index);
867 omx_error = OMX_GetParameter(handle, index, param);
868 if(omx_error != OMX_ErrorNone) return omx_error;
872 case OMX_AUDIO_CodingPCM:
873 case OMX_AUDIO_CodingG711:
874 i_channels = param->pcm.nChannels;
875 i_samplerate = param->pcm.nSamplingRate;
876 i_bps = param->pcm.nBitPerSample;
878 case OMX_AUDIO_CodingADPCM:
879 i_channels = param->adpcm.nChannels;
880 i_samplerate = param->adpcm.nSampleRate;
881 i_bps = param->adpcm.nBitsPerSample;
883 case OMX_AUDIO_CodingAMR:
884 i_channels = param->amr.nChannels;
885 i_bitrate = param->amr.nBitRate;
888 case OMX_AUDIO_CodingG723:
889 i_channels = param->g723.nChannels;
891 case OMX_AUDIO_CodingG726:
892 i_channels = param->g726.nChannels;
894 case OMX_AUDIO_CodingG729:
895 i_channels = param->g729.nChannels;
897 case OMX_AUDIO_CodingAAC:
898 i_channels = param->aac.nChannels;
899 i_samplerate = param->aac.nSampleRate;
900 i_bitrate = param->aac.nBitRate;
901 i_channels = param->aac.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
903 case OMX_AUDIO_CodingMP3:
904 i_channels = param->mp3.nChannels;
905 i_samplerate = param->mp3.nSampleRate;
906 i_bitrate = param->mp3.nBitRate;
907 i_channels = param->mp3.eChannelMode == OMX_AUDIO_ChannelModeStereo ? 2 : 1;
909 case OMX_AUDIO_CodingVORBIS:
910 i_channels = param->vorbis.nChannels;
911 i_bitrate = param->vorbis.nBitRate;
912 i_samplerate = param->vorbis.nSampleRate;
914 case OMX_AUDIO_CodingWMA:
915 i_channels = param->wma.nChannels;
916 i_bitrate = param->wma.nBitRate;
917 i_samplerate = param->wma.nSamplingRate;
918 i_blocksize = param->wma.nBlockAlign;
920 case OMX_AUDIO_CodingRA:
921 i_channels = param->ra.nChannels;
922 i_samplerate = param->ra.nSamplingRate;
923 i_bps = param->ra.nBitsPerFrame;
926 return OMX_ErrorBadParameter;
929 if(pi_channels) *pi_channels = i_channels;
930 if(pi_samplerate) *pi_samplerate = i_samplerate;
931 if(pi_bitrate) *pi_bitrate = i_bitrate;
932 if(pi_bps) *pi_bps = i_bps;
933 if(pi_blocksize) *pi_blocksize = i_blocksize;
934 return OMX_ErrorNone;
937 /*****************************************************************************
938 * PrintOmx: print component summary
939 *****************************************************************************/
940 void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
942 OMX_PARAM_PORTDEFINITIONTYPE definition;
943 OMX_PORT_PARAM_TYPE param;
944 OMX_ERRORTYPE omx_error;
947 /* Find the input / output ports */
948 OMX_INIT_STRUCTURE(param);
949 OMX_INIT_STRUCTURE(definition);
951 for(i = 0; i < 3; i++)
953 omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamAudioInit + i, ¶m);
954 if(omx_error != OMX_ErrorNone) continue;
956 if(i_port == OMX_ALL)
957 msg_Dbg( p_dec, "found %i %s ports", (int)param.nPorts,
958 i == 0 ? "audio" : i == 1 ? "image" : "video" );
960 for(j = 0; j < param.nPorts; j++)
962 unsigned int i_samplerate, i_bitrate;
963 unsigned int i_bitspersample, i_blockalign;
965 OmxFormatParam format_param;
966 vlc_fourcc_t i_fourcc;
967 const char *psz_name;
968 OMX_CONFIG_RECTTYPE crop_rect;
970 if(i_port != OMX_ALL && i_port != param.nStartPortNumber + j)
973 /* Get port definition */
974 definition.nPortIndex = param.nStartPortNumber + j;
975 omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
977 if(omx_error != OMX_ErrorNone) continue;
979 OMX_PARAM_U32TYPE u32param;
980 OMX_INIT_STRUCTURE(u32param);
981 u32param.nPortIndex = param.nStartPortNumber + j;
982 omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamNumAvailableStreams,
985 msg_Dbg( p_dec, "-> %s %i (%i streams) (%i:%i:%i buffers) (%i,%i) %s",
986 definition.eDir == OMX_DirOutput ? "output" : "input",
987 (int)definition.nPortIndex, (int)u32param.nU32,
988 (int)definition.nBufferCountActual,
989 (int)definition.nBufferCountMin, (int)definition.nBufferSize,
990 (int)definition.bBuffersContiguous,
991 (int)definition.nBufferAlignment,
992 definition.bEnabled ? "enabled" : "disabled" );
994 switch(definition.eDomain)
996 case OMX_PortDomainVideo:
998 if(definition.format.video.eCompressionFormat)
999 GetVlcVideoFormat( definition.format.video.eCompressionFormat,
1000 &i_fourcc, &psz_name );
1002 GetVlcChromaFormat( definition.format.video.eColorFormat,
1003 &i_fourcc, &psz_name );
1005 OMX_INIT_STRUCTURE(crop_rect);
1006 crop_rect.nPortIndex = definition.nPortIndex;
1007 omx_error = OMX_GetConfig(omx_handle, OMX_IndexConfigCommonOutputCrop, &crop_rect);
1008 if (omx_error != OMX_ErrorNone)
1010 crop_rect.nLeft = crop_rect.nTop = 0;
1011 crop_rect.nWidth = definition.format.video.nFrameWidth;
1012 crop_rect.nHeight = definition.format.video.nFrameHeight;
1015 msg_Dbg( p_dec, " -> video %s %ix%i@%.2f (%i,%i) (%i,%i) (%i,%i,%i,%i)", psz_name,
1016 (int)definition.format.video.nFrameWidth,
1017 (int)definition.format.video.nFrameHeight,
1018 (float)definition.format.video.xFramerate/(float)(1<<16),
1019 (int)definition.format.video.eCompressionFormat,
1020 (int)definition.format.video.eColorFormat,
1021 (int)definition.format.video.nStride,
1022 (int)definition.format.video.nSliceHeight,
1023 (int)crop_rect.nLeft, (int)crop_rect.nTop,
1024 (int)crop_rect.nWidth, (int)crop_rect.nHeight);
1027 case OMX_PortDomainAudio:
1029 OmxToVlcAudioFormat( definition.format.audio.eEncoding,
1030 &i_fourcc, &psz_name );
1032 GetAudioParameters(omx_handle, &format_param,
1033 definition.nPortIndex,
1034 definition.format.audio.eEncoding,
1035 &i_channels, &i_samplerate, &i_bitrate,
1036 &i_bitspersample, &i_blockalign);
1038 msg_Dbg( p_dec, " -> audio %s (%i) %i,%i,%i,%i,%i", psz_name,
1039 (int)definition.format.audio.eEncoding,
1040 i_channels, i_samplerate, i_bitrate, i_bitspersample,
1052 OMX_VIDEO_AVCPROFILETYPE omx_profile;
1054 } omx_to_profile_idc[] =
1056 { OMX_VIDEO_AVCProfileBaseline, 66 },
1057 { OMX_VIDEO_AVCProfileMain, 77 },
1058 { OMX_VIDEO_AVCProfileExtended, 88 },
1059 { OMX_VIDEO_AVCProfileHigh, 100 },
1060 { OMX_VIDEO_AVCProfileHigh10, 110 },
1061 { OMX_VIDEO_AVCProfileHigh422, 122 },
1062 { OMX_VIDEO_AVCProfileHigh444, 244 },
1065 size_t convert_omx_to_profile_idc(OMX_VIDEO_AVCPROFILETYPE profile_type)
1067 size_t array_length = sizeof(omx_to_profile_idc)/sizeof(omx_to_profile_idc[0]);
1068 for (size_t i = 0; i < array_length; ++i) {
1069 if (omx_to_profile_idc[i].omx_profile == profile_type)
1070 return omx_to_profile_idc[i].profile_idc;
1077 OMX_VIDEO_AVCLEVELTYPE omx_level;
1079 } omx_to_level_idc[] =
1081 { OMX_VIDEO_AVCLevel1, 10 },
1082 { OMX_VIDEO_AVCLevel1b, 9 },
1083 { OMX_VIDEO_AVCLevel11, 11 },
1084 { OMX_VIDEO_AVCLevel12, 12 },
1085 { OMX_VIDEO_AVCLevel13, 13 },
1086 { OMX_VIDEO_AVCLevel2, 20 },
1087 { OMX_VIDEO_AVCLevel21, 21 },
1088 { OMX_VIDEO_AVCLevel22, 22 },
1089 { OMX_VIDEO_AVCLevel3, 30 },
1090 { OMX_VIDEO_AVCLevel31, 31 },
1091 { OMX_VIDEO_AVCLevel32, 32 },
1092 { OMX_VIDEO_AVCLevel4, 40 },
1093 { OMX_VIDEO_AVCLevel41, 41 },
1094 { OMX_VIDEO_AVCLevel42, 42 },
1095 { OMX_VIDEO_AVCLevel5, 50 },
1096 { OMX_VIDEO_AVCLevel51, 51 },
1099 size_t convert_omx_to_level_idc(OMX_VIDEO_AVCLEVELTYPE level_type)
1101 size_t array_length = sizeof(omx_to_level_idc)/sizeof(omx_to_level_idc[0]);
1102 for (size_t i = 0; i < array_length; ++i) {
1103 if (omx_to_level_idc[i].omx_level == level_type)
1104 return omx_to_level_idc[i].level_idc;