1 /*****************************************************************************
2 * omxil.c: Video decoder module making use of OpenMAX IL components.
3 *****************************************************************************
4 * Copyright (C) 2010 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
34 #define dll_open(name) iomx_dlopen(name)
35 #define dll_close(handle) iomx_dlclose(handle)
36 #define dlsym(handle, name) iomx_dlsym(handle, name)
38 #define dll_open(name) dlopen( name, RTLD_NOW )
39 #define dll_close(handle) dlclose(handle)
42 #include <vlc_common.h>
43 #include <vlc_plugin.h>
44 #include <vlc_codec.h>
46 #include <vlc_block_helper.h>
48 #include "../h264_nal.h"
52 //#define OMXIL_EXTRA_DEBUG
54 /*****************************************************************************
55 * List of OpenMAX IL core we will try in order
56 *****************************************************************************/
57 static const char *ppsz_dll_list
[] =
59 "libOMX_Core.so", /* TI OMAP IL core */
60 "libOmxCore.so", /* Qualcomm IL core */
61 "libomxil-bellagio.so", /* Bellagio IL core */
65 /*****************************************************************************
67 *****************************************************************************/
68 static int OpenDecoder( vlc_object_t
* );
69 static int OpenEncoder( vlc_object_t
* );
70 static int OpenGeneric( vlc_object_t
*, bool b_encode
);
71 static void CloseGeneric( vlc_object_t
* );
73 static picture_t
*DecodeVideo( decoder_t
*, block_t
** );
74 static aout_buffer_t
*DecodeAudio ( decoder_t
*, block_t
** );
75 static block_t
*EncodeVideo( encoder_t
*, picture_t
* );
77 static OMX_ERRORTYPE
OmxEventHandler( OMX_HANDLETYPE
, OMX_PTR
, OMX_EVENTTYPE
,
78 OMX_U32
, OMX_U32
, OMX_PTR
);
79 static OMX_ERRORTYPE
OmxEmptyBufferDone( OMX_HANDLETYPE
, OMX_PTR
,
80 OMX_BUFFERHEADERTYPE
* );
81 static OMX_ERRORTYPE
OmxFillBufferDone( OMX_HANDLETYPE
, OMX_PTR
,
82 OMX_BUFFERHEADERTYPE
* );
84 /*****************************************************************************
86 *****************************************************************************/
88 set_description( N_("Audio/Video decoder (using OpenMAX IL)") )
89 set_category( CAT_INPUT
)
90 set_subcategory( SUBCAT_INPUT_VCODEC
)
91 set_section( N_("Decoding") , NULL
)
93 set_capability( "decoder", 80 )
95 set_capability( "decoder", 0 )
97 set_callbacks( OpenDecoder
, CloseGeneric
)
100 set_section( N_("Encoding") , NULL
)
101 set_description( N_("Video encoder (using OpenMAX IL)") )
102 set_capability( "encoder", 0 )
103 set_callbacks( OpenEncoder
, CloseGeneric
)
106 /*****************************************************************************
107 * CreateComponentsList: creates a list of components matching the given role
108 *****************************************************************************/
109 static int CreateComponentsList(decoder_t
*p_dec
, const char *psz_role
)
111 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
112 char psz_name
[OMX_MAX_STRINGNAME_SIZE
];
113 OMX_ERRORTYPE omx_error
;
115 OMX_U8
**ppsz_roles
= 0;
116 unsigned int i
, j
, len
;
118 if(!psz_role
) goto end
;
119 len
= strlen(psz_role
);
123 bool b_found
= false;
125 omx_error
= p_sys
->pf_component_enum(psz_name
, OMX_MAX_STRINGNAME_SIZE
, i
);
126 if(omx_error
!= OMX_ErrorNone
) break;
128 msg_Dbg(p_dec
, "component %s", psz_name
);
130 omx_error
= p_sys
->pf_get_roles_of_component(psz_name
, &roles
, 0);
131 if(omx_error
!= OMX_ErrorNone
|| !roles
) continue;
133 ppsz_roles
= malloc(roles
* (sizeof(OMX_U8
*) + OMX_MAX_STRINGNAME_SIZE
));
134 if(!ppsz_roles
) continue;
136 for( j
= 0; j
< roles
; j
++ )
137 ppsz_roles
[j
] = ((OMX_U8
*)(&ppsz_roles
[roles
])) +
138 j
* OMX_MAX_STRINGNAME_SIZE
;
140 omx_error
= p_sys
->pf_get_roles_of_component(psz_name
, &roles
, ppsz_roles
);
141 if(omx_error
!= OMX_ErrorNone
) roles
= 0;
143 for(j
= 0; j
< roles
; j
++)
145 msg_Dbg(p_dec
, " - role: %s", ppsz_roles
[j
]);
146 if(!strncmp((char *)ppsz_roles
[j
], psz_role
, len
)) b_found
= true;
151 if(!b_found
) continue;
153 if(p_sys
->components
>= MAX_COMPONENTS_LIST_SIZE
)
155 msg_Dbg(p_dec
, "too many matching components");
159 strncpy(p_sys
->ppsz_components
[p_sys
->components
], psz_name
,
160 OMX_MAX_STRINGNAME_SIZE
-1);
165 msg_Dbg(p_dec
, "found %i matching components for role %s",
166 p_sys
->components
, psz_role
);
167 for( i
= 0; i
< p_sys
->components
; i
++ )
168 msg_Dbg(p_dec
, "- %s", p_sys
->ppsz_components
[i
]);
170 return p_sys
->components
;
173 /*****************************************************************************
174 * ImplementationSpecificWorkarounds: place-holder for implementation
175 * specific workarounds
176 *****************************************************************************/
177 static OMX_ERRORTYPE
ImplementationSpecificWorkarounds(decoder_t
*p_dec
,
178 OmxPort
*p_port
, es_format_t
*p_fmt
)
180 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
181 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
182 int i_profile
= 0xFFFF, i_level
= 0xFFFF;
184 /* Try to find out the profile of the video */
185 while(p_fmt
->i_cat
== VIDEO_ES
&& def
->eDir
== OMX_DirInput
&&
186 p_fmt
->i_codec
== VLC_CODEC_H264
)
188 uint8_t *p
= (uint8_t*)p_dec
->fmt_in
.p_extra
;
189 if(!p
|| !p_dec
->fmt_in
.p_extra
) break;
191 /* Check the profile / level */
192 if(p_dec
->fmt_in
.i_original_fourcc
== VLC_FOURCC('a','v','c','1') &&
195 if(p_dec
->fmt_in
.i_extra
< 12) break;
196 p_sys
->i_nal_size_length
= 1 + (p
[4]&0x03);
197 if( !(p
[5]&0x1f) ) break;
202 if(p_dec
->fmt_in
.i_extra
< 8) break;
203 if(!p
[0] && !p
[1] && !p
[2] && p
[3] == 1) p
+= 4;
204 else if(!p
[0] && !p
[1] && p
[2] == 1) p
+= 3;
208 if( ((*p
++)&0x1f) != 7) break;
210 /* Get profile/level out of first SPS */
216 if(!strcmp(p_sys
->psz_component
, "OMX.TI.Video.Decoder"))
218 if(p_fmt
->i_cat
== VIDEO_ES
&& def
->eDir
== OMX_DirInput
&&
219 p_fmt
->i_codec
== VLC_CODEC_H264
&&
220 (i_profile
!= 66 || i_level
> 30))
222 msg_Dbg(p_dec
, "h264 profile/level not supported (0x%x, 0x%x)",
224 return OMX_ErrorNotImplemented
;
227 if(p_fmt
->i_cat
== VIDEO_ES
&& def
->eDir
== OMX_DirOutput
&&
228 p_fmt
->i_codec
== VLC_CODEC_I420
)
230 /* I420 xvideo is slow on OMAP */
231 def
->format
.video
.eColorFormat
= OMX_COLOR_FormatCbYCrY
;
232 GetVlcChromaFormat( def
->format
.video
.eColorFormat
,
233 &p_fmt
->i_codec
, 0 );
234 GetVlcChromaSizes( p_fmt
->i_codec
,
235 def
->format
.video
.nFrameWidth
,
236 def
->format
.video
.nFrameHeight
,
237 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
238 &p_port
->i_frame_stride_chroma_div
);
239 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
240 def
->nBufferSize
= p_port
->i_frame_size
;
243 else if(!strcmp(p_sys
->psz_component
, "OMX.st.video_encoder"))
245 if(p_fmt
->i_cat
== VIDEO_ES
)
247 /* Bellagio's encoder doesn't encode the framerate in Q16 */
248 def
->format
.video
.xFramerate
>>= 16;
252 return OMX_ErrorNone
;
255 /*****************************************************************************
256 * SetPortDefinition: set definition of the omx port based on the vlc format
257 *****************************************************************************/
258 static OMX_ERRORTYPE
SetPortDefinition(decoder_t
*p_dec
, OmxPort
*p_port
,
261 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
262 OMX_ERRORTYPE omx_error
;
264 omx_error
= OMX_GetParameter(p_port
->omx_handle
,
265 OMX_IndexParamPortDefinition
, def
);
266 CHECK_ERROR(omx_error
, "OMX_GetParameter failed (%x : %s)",
267 omx_error
, ErrorToString(omx_error
));
272 def
->format
.video
.nFrameWidth
= p_fmt
->video
.i_width
;
273 def
->format
.video
.nFrameHeight
= p_fmt
->video
.i_height
;
274 if(def
->format
.video
.eCompressionFormat
== OMX_VIDEO_CodingUnused
)
275 def
->format
.video
.nStride
= def
->format
.video
.nFrameWidth
;
276 if( p_fmt
->video
.i_frame_rate
> 0 &&
277 p_fmt
->video
.i_frame_rate_base
> 0 )
278 def
->format
.video
.xFramerate
= (p_fmt
->video
.i_frame_rate
<< 16) /
279 p_fmt
->video
.i_frame_rate_base
;
281 if(def
->eDir
== OMX_DirInput
|| p_dec
->p_sys
->b_enc
)
283 def
->nBufferSize
= def
->format
.video
.nFrameWidth
*
284 def
->format
.video
.nFrameHeight
* 2;
285 p_port
->i_frame_size
= def
->nBufferSize
;
287 if(!GetOmxVideoFormat(p_fmt
->i_codec
,
288 &def
->format
.video
.eCompressionFormat
, 0) )
290 if(!GetOmxChromaFormat(p_fmt
->i_codec
,
291 &def
->format
.video
.eColorFormat
, 0) )
293 omx_error
= OMX_ErrorNotImplemented
;
294 CHECK_ERROR(omx_error
, "codec %4.4s doesn't match any OMX format",
295 (char *)&p_fmt
->i_codec
);
297 GetVlcChromaSizes( p_fmt
->i_codec
,
298 def
->format
.video
.nFrameWidth
,
299 def
->format
.video
.nFrameHeight
,
300 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
301 &p_port
->i_frame_stride_chroma_div
);
302 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
303 def
->nBufferSize
= p_port
->i_frame_size
;
308 if( !GetVlcChromaFormat( def
->format
.video
.eColorFormat
,
309 &p_fmt
->i_codec
, 0 ) )
311 omx_error
= OMX_ErrorNotImplemented
;
312 CHECK_ERROR(omx_error
, "OMX color format %i not supported",
313 (int)def
->format
.video
.eColorFormat
);
315 GetVlcChromaSizes( p_fmt
->i_codec
,
316 def
->format
.video
.nFrameWidth
,
317 def
->format
.video
.nFrameHeight
,
318 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
319 &p_port
->i_frame_stride_chroma_div
);
320 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
321 def
->nBufferSize
= p_port
->i_frame_size
;
326 p_port
->i_frame_size
= def
->nBufferSize
;
327 if(def
->eDir
== OMX_DirInput
)
329 if(!GetOmxAudioFormat(p_fmt
->i_codec
,
330 &def
->format
.audio
.eEncoding
, 0) )
332 omx_error
= OMX_ErrorNotImplemented
;
333 CHECK_ERROR(omx_error
, "codec %4.4s doesn't match any OMX format",
334 (char *)&p_fmt
->i_codec
);
339 if( !GetVlcAudioFormat(def
->format
.audio
.eEncoding
,
340 &p_fmt
->i_codec
, 0 ) )
342 omx_error
= OMX_ErrorNotImplemented
;
343 CHECK_ERROR(omx_error
, "OMX audio encoding %i not supported",
344 (int)def
->format
.audio
.eEncoding
);
349 default: return OMX_ErrorNotImplemented
;
352 omx_error
= ImplementationSpecificWorkarounds(p_dec
, p_port
, p_fmt
);
353 CHECK_ERROR(omx_error
, "ImplementationSpecificWorkarounds failed (%x : %s)",
354 omx_error
, ErrorToString(omx_error
));
356 omx_error
= OMX_SetParameter(p_port
->omx_handle
,
357 OMX_IndexParamPortDefinition
, def
);
358 CHECK_ERROR(omx_error
, "OMX_SetParameter failed (%x : %s)",
359 omx_error
, ErrorToString(omx_error
));
361 omx_error
= OMX_GetParameter(p_port
->omx_handle
,
362 OMX_IndexParamPortDefinition
, def
);
363 CHECK_ERROR(omx_error
, "OMX_GetParameter failed (%x : %s)",
364 omx_error
, ErrorToString(omx_error
));
366 if(p_port
->i_frame_size
> def
->nBufferSize
)
367 def
->nBufferSize
= p_port
->i_frame_size
;
368 p_port
->i_frame_size
= def
->nBufferSize
;
370 /* Deal with audio params */
371 if(p_fmt
->i_cat
== AUDIO_ES
)
373 omx_error
= SetAudioParameters(p_port
->omx_handle
,
374 &p_port
->format_param
, def
->nPortIndex
,
375 def
->format
.audio
.eEncoding
,
376 p_fmt
->audio
.i_channels
,
379 p_fmt
->audio
.i_bitspersample
,
380 p_fmt
->audio
.i_blockalign
);
381 CHECK_ERROR(omx_error
, "SetAudioParameters failed (%x : %s)",
382 omx_error
, ErrorToString(omx_error
));
389 /*****************************************************************************
390 * GetPortDefinition: set vlc format based on the definition of the omx port
391 *****************************************************************************/
392 static OMX_ERRORTYPE
GetPortDefinition(decoder_t
*p_dec
, OmxPort
*p_port
,
395 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
396 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
397 OMX_ERRORTYPE omx_error
;
399 omx_error
= OMX_GetParameter(p_port
->omx_handle
,
400 OMX_IndexParamPortDefinition
, def
);
401 CHECK_ERROR(omx_error
, "OMX_GetParameter failed (%x : %s)",
402 omx_error
, ErrorToString(omx_error
));
407 p_fmt
->video
.i_width
= def
->format
.video
.nFrameWidth
;
408 p_fmt
->video
.i_visible_width
= def
->format
.video
.nFrameWidth
;
409 p_fmt
->video
.i_height
= def
->format
.video
.nFrameHeight
;
410 p_fmt
->video
.i_visible_height
= def
->format
.video
.nFrameHeight
;
411 p_fmt
->video
.i_frame_rate
= p_dec
->fmt_in
.video
.i_frame_rate
;
412 p_fmt
->video
.i_frame_rate_base
= p_dec
->fmt_in
.video
.i_frame_rate_base
;
414 /* Hack: Nexus One (stock firmware with binary OMX driver blob)
415 * claims to output 420Planar even though it in in practice is
417 if(def
->format
.video
.eColorFormat
== OMX_COLOR_FormatYUV420Planar
&&
418 !strncmp(p_sys
->psz_component
, "OMX.qcom.video.decoder",
419 strlen("OMX.qcom.video.decoder")))
420 def
->format
.video
.eColorFormat
= OMX_QCOM_COLOR_FormatYVU420SemiPlanar
;
422 if(!GetVlcVideoFormat( def
->format
.video
.eCompressionFormat
,
423 &p_fmt
->i_codec
, 0 ) )
425 if( !GetVlcChromaFormat( def
->format
.video
.eColorFormat
,
426 &p_fmt
->i_codec
, 0 ) )
428 omx_error
= OMX_ErrorNotImplemented
;
429 CHECK_ERROR(omx_error
, "OMX color format %i not supported",
430 (int)def
->format
.video
.eColorFormat
);
432 GetVlcChromaSizes( p_fmt
->i_codec
,
433 def
->format
.video
.nFrameWidth
,
434 def
->format
.video
.nFrameHeight
,
435 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
436 &p_port
->i_frame_stride_chroma_div
);
438 if(p_port
->i_frame_size
> def
->nBufferSize
)
439 def
->nBufferSize
= p_port
->i_frame_size
;
440 p_port
->i_frame_size
= def
->nBufferSize
;
442 if((int)p_port
->i_frame_stride
> def
->format
.video
.nStride
)
443 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
445 p_port
->i_frame_stride
= def
->format
.video
.nStride
;
449 if( !GetVlcAudioFormat( def
->format
.audio
.eEncoding
,
450 &p_fmt
->i_codec
, 0 ) )
452 omx_error
= OMX_ErrorNotImplemented
;
453 CHECK_ERROR(omx_error
, "OMX audio format %i not supported",
454 (int)def
->format
.audio
.eEncoding
);
457 omx_error
= GetAudioParameters(p_port
->omx_handle
,
458 &p_port
->format_param
, def
->nPortIndex
,
459 def
->format
.audio
.eEncoding
,
460 &p_fmt
->audio
.i_channels
,
461 &p_fmt
->audio
.i_rate
,
463 &p_fmt
->audio
.i_bitspersample
,
464 &p_fmt
->audio
.i_blockalign
);
465 CHECK_ERROR(omx_error
, "GetAudioParameters failed (%x : %s)",
466 omx_error
, ErrorToString(omx_error
));
468 if(p_fmt
->audio
.i_channels
< 9)
470 static const int pi_channels_maps
[9] =
472 0, AOUT_CHAN_CENTER
, AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
473 AOUT_CHAN_CENTER
| AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
474 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT
475 | AOUT_CHAN_REARRIGHT
,
476 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
477 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
,
478 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
479 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE
,
480 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
481 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
482 | AOUT_CHAN_MIDDLERIGHT
,
483 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT
484 | AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT
487 p_fmt
->audio
.i_physical_channels
=
488 p_fmt
->audio
.i_original_channels
=
489 pi_channels_maps
[p_fmt
->audio
.i_channels
];
492 date_Init( &p_dec
->p_sys
->end_date
, p_fmt
->audio
.i_rate
, 1 );
496 default: return OMX_ErrorNotImplemented
;
503 /*****************************************************************************
504 * DeinitialiseComponent: Deinitialise and unload an OMX component
505 *****************************************************************************/
506 static OMX_ERRORTYPE
DeinitialiseComponent(decoder_t
*p_dec
,
507 OMX_HANDLETYPE omx_handle
)
509 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
510 OMX_ERRORTYPE omx_error
;
514 if(!omx_handle
) return OMX_ErrorNone
;
516 omx_error
= OMX_GetState(omx_handle
, &state
);
517 CHECK_ERROR(omx_error
, "OMX_GetState failed (%x)", omx_error
);
519 if(state
== OMX_StateExecuting
)
521 omx_error
= OMX_SendCommand( omx_handle
, OMX_CommandStateSet
,
523 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Idle failed (%x)", omx_error
);
524 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
525 CHECK_ERROR(omx_error
, "Wait for Idle failed (%x)", omx_error
);
528 omx_error
= OMX_GetState(omx_handle
, &state
);
529 CHECK_ERROR(omx_error
, "OMX_GetState failed (%x)", omx_error
);
531 if(state
== OMX_StateIdle
)
533 omx_error
= OMX_SendCommand( omx_handle
, OMX_CommandStateSet
,
534 OMX_StateLoaded
, 0 );
535 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Loaded failed (%x)", omx_error
);
537 for(i
= 0; i
< p_sys
->ports
; i
++)
539 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
540 OMX_BUFFERHEADERTYPE
*p_buffer
;
542 for(j
= 0; j
< p_port
->i_buffers
; j
++)
544 OMX_FIFO_GET(&p_port
->fifo
, p_buffer
);
545 omx_error
= OMX_FreeBuffer( omx_handle
,
546 p_port
->i_port_index
, p_buffer
);
548 if(omx_error
!= OMX_ErrorNone
) break;
550 CHECK_ERROR(omx_error
, "OMX_FreeBuffer failed (%x, %i, %i)",
551 omx_error
, (int)p_port
->i_port_index
, j
);
554 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
555 CHECK_ERROR(omx_error
, "Wait for Loaded failed (%x)", omx_error
);
559 for(i
= 0; i
< p_sys
->ports
; i
++)
561 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
562 free(p_port
->pp_buffers
);
563 p_port
->pp_buffers
= 0;
565 omx_error
= p_sys
->pf_free_handle( omx_handle
);
569 /*****************************************************************************
570 * InitialiseComponent: Load and initialise an OMX component
571 *****************************************************************************/
572 static OMX_ERRORTYPE
InitialiseComponent(decoder_t
*p_dec
,
573 OMX_STRING psz_component
, OMX_HANDLETYPE
*p_handle
)
575 static OMX_CALLBACKTYPE callbacks
=
576 { OmxEventHandler
, OmxEmptyBufferDone
, OmxFillBufferDone
};
577 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
578 OMX_HANDLETYPE omx_handle
;
579 OMX_ERRORTYPE omx_error
;
581 OMX_U8 psz_role
[OMX_MAX_STRINGNAME_SIZE
];
582 OMX_PARAM_COMPONENTROLETYPE role
;
583 OMX_PARAM_PORTDEFINITIONTYPE definition
;
584 OMX_PORT_PARAM_TYPE param
;
587 omx_error
= p_sys
->pf_get_handle( &omx_handle
, psz_component
,
589 if(omx_error
!= OMX_ErrorNone
)
591 msg_Warn( p_dec
, "OMX_GetHandle(%s) failed (%x: %s)", psz_component
,
592 omx_error
, ErrorToString(omx_error
) );
595 strncpy(p_sys
->psz_component
, psz_component
, OMX_MAX_STRINGNAME_SIZE
-1);
597 omx_error
= OMX_ComponentRoleEnum(omx_handle
, psz_role
, 0);
598 if(omx_error
== OMX_ErrorNone
)
599 msg_Dbg(p_dec
, "loaded component %s of role %s", psz_component
, psz_role
);
601 msg_Dbg(p_dec
, "loaded component %s", psz_component
);
602 PrintOmx(p_dec
, omx_handle
, OMX_ALL
);
604 /* Set component role */
605 OMX_INIT_STRUCTURE(role
);
606 strcpy((char*)role
.cRole
,
607 GetOmxRole(p_sys
->b_enc
? p_dec
->fmt_out
.i_codec
: p_dec
->fmt_in
.i_codec
,
608 p_dec
->fmt_in
.i_cat
, p_sys
->b_enc
));
610 omx_error
= OMX_SetParameter(omx_handle
, OMX_IndexParamStandardComponentRole
,
612 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamStandardComponentRole
,
614 if(omx_error
== OMX_ErrorNone
)
615 msg_Dbg(p_dec
, "component standard role set to %s", role
.cRole
);
617 /* Find the input / output ports */
618 OMX_INIT_STRUCTURE(param
);
619 OMX_INIT_STRUCTURE(definition
);
620 omx_error
= OMX_GetParameter(omx_handle
, p_dec
->fmt_in
.i_cat
== VIDEO_ES
?
621 OMX_IndexParamVideoInit
: OMX_IndexParamAudioInit
, ¶m
);
622 if(omx_error
!= OMX_ErrorNone
) param
.nPorts
= 0;
624 for(i
= 0; i
< param
.nPorts
; i
++)
628 /* Get port definition */
629 definition
.nPortIndex
= param
.nStartPortNumber
+ i
;
630 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamPortDefinition
,
632 if(omx_error
!= OMX_ErrorNone
) continue;
634 if(definition
.eDir
== OMX_DirInput
) p_port
= &p_sys
->in
;
635 else p_port
= &p_sys
->out
;
637 p_port
->b_valid
= true;
638 p_port
->i_port_index
= definition
.nPortIndex
;
639 p_port
->definition
= definition
;
640 p_port
->omx_handle
= omx_handle
;
643 if(!p_sys
->in
.b_valid
|| !p_sys
->out
.b_valid
)
645 omx_error
= OMX_ErrorInvalidComponent
;
646 CHECK_ERROR(omx_error
, "couldn't find an input and output port");
649 if(!strncmp(p_sys
->psz_component
, "OMX.SEC.", 8))
652 omx_error
= OMX_GetExtensionIndex(omx_handle
, "OMX.SEC.index.ThumbnailMode", &index
);
653 if(omx_error
== OMX_ErrorNone
)
655 OMX_BOOL enable
= OMX_TRUE
;
656 omx_error
= OMX_SetConfig(omx_handle
, index
, &enable
);
657 CHECK_ERROR(omx_error
, "Unable to set ThumbnailMode");
661 /* Set port definitions */
662 for(i
= 0; i
< p_sys
->ports
; i
++)
664 omx_error
= SetPortDefinition(p_dec
, &p_sys
->p_ports
[i
],
665 p_sys
->p_ports
[i
].p_fmt
);
666 if(omx_error
!= OMX_ErrorNone
) goto error
;
669 /* Allocate our array for the omx buffers and enable ports */
670 for(i
= 0; i
< p_sys
->ports
; i
++)
672 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
675 malloc(p_port
->definition
.nBufferCountActual
*
676 sizeof(OMX_BUFFERHEADERTYPE
*));
677 if(!p_port
->pp_buffers
)
679 omx_error
= OMX_ErrorInsufficientResources
;
680 CHECK_ERROR(omx_error
, "memory allocation failed");
682 p_port
->i_buffers
= p_port
->definition
.nBufferCountActual
;
685 if(!p_port
->definition
.bEnabled
)
687 omx_error
= OMX_SendCommand( omx_handle
, OMX_CommandPortEnable
,
688 p_port
->i_port_index
, NULL
);
689 CHECK_ERROR(omx_error
, "OMX_CommandPortEnable on %i failed (%x)",
690 (int)p_port
->i_port_index
, omx_error
);
691 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
692 CHECK_ERROR(omx_error
, "Wait for PortEnable on %i failed (%x)",
693 (int)p_port
->i_port_index
, omx_error
);
697 *p_handle
= omx_handle
;
698 return OMX_ErrorNone
;
701 DeinitialiseComponent(p_dec
, omx_handle
);
706 /*****************************************************************************
707 * OpenDecoder: Create the decoder instance
708 *****************************************************************************/
709 static int OpenDecoder( vlc_object_t
*p_this
)
711 decoder_t
*p_dec
= (decoder_t
*)p_this
;
714 if( 0 || !GetOmxRole(p_dec
->fmt_in
.i_codec
, p_dec
->fmt_in
.i_cat
, false) )
718 if( p_dec
->fmt_in
.i_cat
!= VIDEO_ES
&& !p_dec
->b_force
)
722 status
= OpenGeneric( p_this
, false );
723 if(status
!= VLC_SUCCESS
) return status
;
725 p_dec
->pf_decode_video
= DecodeVideo
;
726 p_dec
->pf_decode_audio
= DecodeAudio
;
731 /*****************************************************************************
732 * OpenEncoder: Create the encoder instance
733 *****************************************************************************/
734 static int OpenEncoder( vlc_object_t
*p_this
)
736 encoder_t
*p_enc
= (encoder_t
*)p_this
;
739 if( !GetOmxRole(p_enc
->fmt_out
.i_codec
, p_enc
->fmt_in
.i_cat
, true) )
742 status
= OpenGeneric( p_this
, true );
743 if(status
!= VLC_SUCCESS
) return status
;
745 p_enc
->pf_encode_video
= EncodeVideo
;
750 /*****************************************************************************
751 * OpenGeneric: Create the generic decoder/encoder instance
752 *****************************************************************************/
753 static int OpenGeneric( vlc_object_t
*p_this
, bool b_encode
)
755 void *dll_handle
= 0, *pf_init
= 0, *pf_deinit
= 0;
756 void *pf_get_handle
= 0, *pf_free_handle
= 0, *pf_component_enum
= 0;
757 void *pf_get_roles_of_component
= 0;
758 decoder_t
*p_dec
= (decoder_t
*)p_this
;
759 decoder_sys_t
*p_sys
;
760 OMX_ERRORTYPE omx_error
;
761 OMX_BUFFERHEADERTYPE
*p_header
;
764 /* Load the OMX core */
765 for( i
= 0; ppsz_dll_list
[i
]; i
++ )
767 dll_handle
= dll_open( ppsz_dll_list
[i
] );
768 if( dll_handle
) break;
770 if( !dll_handle
) return VLC_EGENERIC
;
772 pf_init
= dlsym( dll_handle
, "OMX_Init" );
773 pf_deinit
= dlsym( dll_handle
, "OMX_Deinit" );
774 pf_get_handle
= dlsym( dll_handle
, "OMX_GetHandle" );
775 pf_free_handle
= dlsym( dll_handle
, "OMX_FreeHandle" );
776 pf_component_enum
= dlsym( dll_handle
, "OMX_ComponentNameEnum" );
777 pf_get_roles_of_component
= dlsym( dll_handle
, "OMX_GetRolesOfComponent" );
778 if( !pf_init
|| !pf_deinit
|| !pf_get_handle
|| !pf_free_handle
||
779 !pf_component_enum
|| !pf_get_roles_of_component
)
781 msg_Warn( p_this
, "cannot find OMX_* symbols in `%s' (%s)",
782 ppsz_dll_list
[i
], dlerror() );
783 dll_close(dll_handle
);
786 if( !pf_init
|| !pf_deinit
|| !pf_get_handle
|| !pf_free_handle
|| !pf_component_enum
)
788 dll_close(dll_handle
);
792 /* Allocate the memory needed to store the decoder's structure */
793 if( ( p_dec
->p_sys
= p_sys
= calloc( 1, sizeof(*p_sys
)) ) == NULL
)
795 dll_close(dll_handle
);
799 /* Initialise the thread properties */
802 p_dec
->fmt_out
.i_cat
= p_dec
->fmt_in
.i_cat
;
803 p_dec
->fmt_out
.video
= p_dec
->fmt_in
.video
;
804 p_dec
->fmt_out
.audio
= p_dec
->fmt_in
.audio
;
805 p_dec
->fmt_out
.i_codec
= 0;
807 p_sys
->b_enc
= b_encode
;
808 p_sys
->dll_handle
= dll_handle
;
809 p_sys
->pf_init
= pf_init
;
810 p_sys
->pf_deinit
= pf_deinit
;
811 p_sys
->pf_get_handle
= pf_get_handle
;
812 p_sys
->pf_free_handle
= pf_free_handle
;
813 p_sys
->pf_component_enum
= pf_component_enum
;
814 p_sys
->pf_get_roles_of_component
= pf_get_roles_of_component
;
815 p_sys
->pp_last_event
= &p_sys
->p_events
;
816 vlc_mutex_init (&p_sys
->mutex
);
817 vlc_cond_init (&p_sys
->cond
);
818 vlc_mutex_init (&p_sys
->lock
);
819 vlc_mutex_init (&p_sys
->in
.fifo
.lock
);
820 vlc_cond_init (&p_sys
->in
.fifo
.wait
);
821 p_sys
->in
.fifo
.offset
= offsetof(OMX_BUFFERHEADERTYPE
, pOutputPortPrivate
) / sizeof(void *);
822 p_sys
->in
.fifo
.pp_last
= &p_sys
->in
.fifo
.p_first
;
823 p_sys
->in
.b_direct
= false;
824 p_sys
->in
.b_flushed
= true;
825 p_sys
->in
.p_fmt
= &p_dec
->fmt_in
;
826 vlc_mutex_init (&p_sys
->out
.fifo
.lock
);
827 vlc_cond_init (&p_sys
->out
.fifo
.wait
);
828 p_sys
->out
.fifo
.offset
= offsetof(OMX_BUFFERHEADERTYPE
, pInputPortPrivate
) / sizeof(void *);
829 p_sys
->out
.fifo
.pp_last
= &p_sys
->out
.fifo
.p_first
;
830 p_sys
->out
.b_direct
= true;
831 p_sys
->out
.b_flushed
= true;
832 p_sys
->out
.p_fmt
= &p_dec
->fmt_out
;
834 p_sys
->p_ports
= &p_sys
->in
;
836 msg_Dbg(p_dec
, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec
->fmt_in
.i_codec
,
837 (char *)&p_dec
->fmt_out
.i_codec
);
839 /* Initialise the OMX core */
840 omx_error
= p_sys
->pf_init();
841 if(omx_error
!= OMX_ErrorNone
)
843 msg_Warn( p_this
, "OMX_Init failed (%x: %s)", omx_error
,
844 ErrorToString(omx_error
) );
845 CloseGeneric(p_this
);
848 p_sys
->b_init
= true;
850 /* Enumerate components and build a list of the one we want to try */
851 if( !CreateComponentsList(p_dec
,
852 GetOmxRole(p_sys
->b_enc
? p_dec
->fmt_out
.i_codec
:
853 p_dec
->fmt_in
.i_codec
, p_dec
->fmt_in
.i_cat
,
856 msg_Warn( p_this
, "couldn't find an omx component for codec %4.4s",
857 (char *)&p_dec
->fmt_in
.i_codec
);
858 CloseGeneric(p_this
);
862 /* Try to load and initialise a component */
863 for(i
= 0; i
< p_sys
->components
; i
++)
865 omx_error
= InitialiseComponent(p_dec
, p_sys
->ppsz_components
[i
],
867 if(omx_error
== OMX_ErrorNone
) break;
869 CHECK_ERROR(omx_error
, "no component could be initialised" );
871 /* Move component to Idle then Executing state */
872 OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandStateSet
, OMX_StateIdle
, 0 );
873 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Idle failed (%x)", omx_error
);
875 /* Allocate omx buffers */
876 for(i
= 0; i
< p_sys
->ports
; i
++)
878 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
880 for(j
= 0; j
< p_port
->i_buffers
; j
++)
883 #define ALIGN(x,BLOCKLIGN) (((x) + BLOCKLIGN - 1) & ~(BLOCKLIGN - 1))
884 char *p_buf
= malloc(p_port
->definition
.nBufferSize
+
885 p_port
->definition
.nBufferAlignment
);
886 p_port
->pp_buffers
[i
] = (void *)ALIGN((uintptr_t)p_buf
, p_port
->definition
.nBufferAlignment
);
889 if(0 && p_port
->b_direct
)
891 OMX_UseBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[j
],
892 p_port
->i_port_index
, 0,
893 p_port
->definition
.nBufferSize
, (void*)1);
896 OMX_AllocateBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[j
],
897 p_port
->i_port_index
, 0,
898 p_port
->definition
.nBufferSize
);
900 if(omx_error
!= OMX_ErrorNone
) break;
901 OMX_FIFO_PUT(&p_port
->fifo
, p_port
->pp_buffers
[j
]);
903 p_port
->i_buffers
= j
;
904 CHECK_ERROR(omx_error
, "OMX_UseBuffer failed (%x, %i, %i)",
905 omx_error
, (int)p_port
->i_port_index
, j
);
908 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
909 CHECK_ERROR(omx_error
, "Wait for Idle failed (%x)", omx_error
);
911 omx_error
= OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandStateSet
,
912 OMX_StateExecuting
, 0);
913 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Executing failed (%x)", omx_error
);
914 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
915 CHECK_ERROR(omx_error
, "Wait for Executing failed (%x)", omx_error
);
917 /* Send codec configuration data */
918 if( p_dec
->fmt_in
.i_extra
)
920 OMX_FIFO_GET(&p_sys
->in
.fifo
, p_header
);
921 p_header
->nFilledLen
= p_dec
->fmt_in
.i_extra
;
923 /* Convert H.264 NAL format to annex b */
924 if( p_sys
->i_nal_size_length
&& !p_sys
->in
.b_direct
)
926 p_header
->nFilledLen
= 0;
927 convert_sps_pps( p_dec
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
,
928 p_header
->pBuffer
, p_header
->nAllocLen
,
929 (uint32_t*) &p_header
->nFilledLen
,
930 &p_sys
->i_nal_size_length
);
932 else if(p_sys
->in
.b_direct
)
934 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
935 p_header
->pBuffer
= p_dec
->fmt_in
.p_extra
;
939 if(p_header
->nFilledLen
> p_header
->nAllocLen
)
941 msg_Dbg(p_dec
, "buffer too small (%i,%i)", (int)p_header
->nFilledLen
,
942 (int)p_header
->nAllocLen
);
943 p_header
->nFilledLen
= p_header
->nAllocLen
;
945 memcpy(p_header
->pBuffer
, p_dec
->fmt_in
.p_extra
, p_header
->nFilledLen
);
948 p_header
->nOffset
= 0;
949 p_header
->nFlags
= OMX_BUFFERFLAG_CODECCONFIG
;
950 msg_Dbg(p_dec
, "sending codec config data %p, %p, %i", p_header
,
951 p_header
->pBuffer
, (int)p_header
->nFilledLen
);
952 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
955 /* Get back output port definition */
956 omx_error
= GetPortDefinition(p_dec
, &p_sys
->out
, p_sys
->out
.p_fmt
);
957 if(omx_error
!= OMX_ErrorNone
) goto error
;
959 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->in
.i_port_index
);
960 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->out
.i_port_index
);
962 if(p_sys
->b_error
) goto error
;
964 p_dec
->b_need_packetized
= true;
968 CloseGeneric(p_this
);
972 /*****************************************************************************
974 *****************************************************************************/
975 static OMX_ERRORTYPE
PortReconfigure(decoder_t
*p_dec
, OmxPort
*p_port
)
977 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
978 OMX_PARAM_PORTDEFINITIONTYPE definition
;
979 OMX_BUFFERHEADERTYPE
*p_buffer
;
980 OMX_ERRORTYPE omx_error
;
983 /* Sanity checking */
984 OMX_INIT_STRUCTURE(definition
);
985 definition
.nPortIndex
= p_port
->i_port_index
;
986 omx_error
= OMX_GetParameter(p_dec
->p_sys
->omx_handle
, OMX_IndexParamPortDefinition
,
988 if(omx_error
!= OMX_ErrorNone
||
989 !definition
.format
.video
.nFrameWidth
||
990 !definition
.format
.video
.nFrameHeight
)
991 return OMX_ErrorUndefined
;
993 omx_error
= OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandPortDisable
,
994 p_port
->i_port_index
, NULL
);
995 CHECK_ERROR(omx_error
, "OMX_CommandPortDisable on %i failed (%x)",
996 (int)p_port
->i_port_index
, omx_error
);
998 for(i
= 0; i
< p_port
->i_buffers
; i
++)
1000 OMX_FIFO_GET(&p_port
->fifo
, p_buffer
);
1001 omx_error
= OMX_FreeBuffer( p_sys
->omx_handle
,
1002 p_port
->i_port_index
, p_buffer
);
1004 if(omx_error
!= OMX_ErrorNone
) break;
1006 CHECK_ERROR(omx_error
, "OMX_FreeBuffer failed (%x, %i, %i)",
1007 omx_error
, (int)p_port
->i_port_index
, i
);
1009 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
1010 CHECK_ERROR(omx_error
, "Wait for PortDisable failed (%x)", omx_error
);
1012 /* Get the new port definition */
1013 omx_error
= GetPortDefinition(p_dec
, &p_sys
->out
, p_sys
->out
.p_fmt
);
1014 if(omx_error
!= OMX_ErrorNone
) goto error
;
1015 omx_error
= OMX_SetParameter(p_dec
->p_sys
->omx_handle
, OMX_IndexParamPortDefinition
,
1017 CHECK_ERROR(omx_error
, "OMX_SetParameter failed (%x : %s)",
1018 omx_error
, ErrorToString(omx_error
));
1020 omx_error
= OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandPortEnable
,
1021 p_port
->i_port_index
, NULL
);
1022 CHECK_ERROR(omx_error
, "OMX_CommandPortEnable on %i failed (%x)",
1023 (int)p_port
->i_port_index
, omx_error
);
1025 if (p_port
->definition
.nBufferCountActual
> p_port
->i_buffers
) {
1026 free(p_port
->pp_buffers
);
1027 p_port
->pp_buffers
= malloc(p_port
->definition
.nBufferCountActual
* sizeof(OMX_BUFFERHEADERTYPE
*));
1028 if(!p_port
->pp_buffers
)
1030 omx_error
= OMX_ErrorInsufficientResources
;
1031 CHECK_ERROR(omx_error
, "memory allocation failed");
1034 p_port
->i_buffers
= p_port
->definition
.nBufferCountActual
;
1035 for(i
= 0; i
< p_port
->i_buffers
; i
++)
1037 if(0 && p_port
->b_direct
)
1039 OMX_UseBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[i
],
1040 p_port
->i_port_index
, 0,
1041 p_port
->definition
.nBufferSize
, (void*)1);
1044 OMX_AllocateBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[i
],
1045 p_port
->i_port_index
, 0,
1046 p_port
->definition
.nBufferSize
);
1048 if(omx_error
!= OMX_ErrorNone
) break;
1049 OMX_FIFO_PUT(&p_port
->fifo
, p_port
->pp_buffers
[i
]);
1051 p_port
->i_buffers
= i
;
1052 CHECK_ERROR(omx_error
, "OMX_UseBuffer failed (%x, %i, %i)",
1053 omx_error
, (int)p_port
->i_port_index
, i
);
1055 omx_error
= WaitForSpecificOmxEvent(p_dec
, OMX_EventCmdComplete
, 0, 0, 0);
1056 CHECK_ERROR(omx_error
, "Wait for PortEnable failed (%x)", omx_error
);
1058 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->in
.i_port_index
);
1059 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->out
.i_port_index
);
1065 /*****************************************************************************
1066 * DecodeVideo: Called to decode one frame
1067 *****************************************************************************/
1068 static picture_t
*DecodeVideo( decoder_t
*p_dec
, block_t
**pp_block
)
1070 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1071 picture_t
*p_pic
= NULL
, *p_next_pic
;
1072 OMX_ERRORTYPE omx_error
;
1075 OMX_BUFFERHEADERTYPE
*p_header
;
1078 if( !pp_block
|| !*pp_block
)
1081 p_block
= *pp_block
;
1083 /* Check for errors from codec */
1086 msg_Dbg(p_dec
, "error during decoding");
1087 block_Release( p_block
);
1091 if( p_block
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
) )
1093 block_Release( p_block
);
1094 if(!p_sys
->in
.b_flushed
)
1096 msg_Dbg(p_dec
, "flushing");
1097 OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandFlush
,
1098 p_sys
->in
.definition
.nPortIndex
, 0 );
1100 p_sys
->in
.b_flushed
= true;
1104 /* Take care of decoded frames first */
1107 OMX_FIFO_PEEK(&p_sys
->out
.fifo
, p_header
);
1108 if(!p_header
) break; /* No frame available */
1110 if(p_header
->nFilledLen
)
1112 p_pic
= p_header
->pAppPrivate
;
1115 /* We're not in direct rendering mode.
1116 * Get a new picture and copy the content */
1117 p_pic
= decoder_NewPicture( p_dec
);
1118 if( !p_pic
) break; /* No picture available */
1120 CopyOmxPicture(p_dec
, p_pic
, p_header
, p_sys
->out
.definition
.format
.video
.nSliceHeight
);
1123 p_pic
->date
= p_header
->nTimeStamp
;
1124 p_header
->nFilledLen
= 0;
1125 p_header
->pAppPrivate
= 0;
1128 /* Get a new picture */
1129 if(p_sys
->in
.b_direct
&& !p_header
->pAppPrivate
)
1131 p_next_pic
= decoder_NewPicture( p_dec
);
1132 if(!p_next_pic
) break;
1134 OMX_FIFO_GET(&p_sys
->out
.fifo
, p_header
);
1135 p_header
->pAppPrivate
= p_next_pic
;
1136 p_header
->pInputPortPrivate
= p_header
->pBuffer
;
1137 p_header
->pBuffer
= p_next_pic
->p
[0].p_pixels
;
1141 OMX_FIFO_GET(&p_sys
->out
.fifo
, p_header
);
1144 #ifdef OMXIL_EXTRA_DEBUG
1145 msg_Dbg( p_dec
, "FillThisBuffer %p, %p", p_header
, p_header
->pBuffer
);
1147 OMX_FillThisBuffer(p_sys
->omx_handle
, p_header
);
1150 /* Send the input buffer to the component */
1151 OMX_FIFO_GET(&p_sys
->in
.fifo
, p_header
);
1153 if (p_header
&& p_header
->nFlags
& OMX_BUFFERFLAG_EOS
)
1158 p_header
->nFilledLen
= p_block
->i_buffer
;
1159 p_header
->nOffset
= 0;
1160 p_header
->nFlags
= OMX_BUFFERFLAG_ENDOFFRAME
;
1161 p_header
->nTimeStamp
= p_block
->i_dts
;
1163 /* In direct mode we pass the input pointer as is.
1164 * Otherwise we memcopy the data */
1165 if(p_sys
->in
.b_direct
)
1167 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1168 p_header
->pBuffer
= p_block
->p_buffer
;
1169 p_header
->pAppPrivate
= p_block
;
1173 if(p_header
->nFilledLen
> p_header
->nAllocLen
)
1175 msg_Dbg(p_dec
, "buffer too small (%i,%i)",
1176 (int)p_header
->nFilledLen
, (int)p_header
->nAllocLen
);
1177 p_header
->nFilledLen
= p_header
->nAllocLen
;
1179 memcpy(p_header
->pBuffer
, p_block
->p_buffer
, p_header
->nFilledLen
);
1180 block_Release(p_block
);
1183 /* Convert H.264 NAL format to annex b */
1184 if( p_sys
->i_nal_size_length
>= 3 && p_sys
->i_nal_size_length
<= 4 )
1186 /* This only works for NAL sizes 3-4 */
1187 int i_len
= p_header
->nFilledLen
, i
;
1188 uint8_t* ptr
= p_header
->pBuffer
;
1189 while( i_len
>= p_sys
->i_nal_size_length
)
1191 uint32_t nal_len
= 0;
1192 for( i
= 0; i
< p_sys
->i_nal_size_length
; i
++ ) {
1193 nal_len
= (nal_len
<< 8) | ptr
[i
];
1196 ptr
[p_sys
->i_nal_size_length
- 1] = 1;
1197 if( nal_len
> INT_MAX
|| nal_len
> (unsigned int) i_len
)
1200 i_len
-= nal_len
+ 4;
1203 #ifdef OMXIL_EXTRA_DEBUG
1204 msg_Dbg( p_dec
, "EmptyThisBuffer %p, %p, %i", p_header
, p_header
->pBuffer
,
1205 (int)p_header
->nFilledLen
);
1207 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
1208 p_sys
->in
.b_flushed
= false;
1209 *pp_block
= NULL
; /* Avoid being fed the same packet again */
1213 /* Handle the PortSettingsChanged events */
1214 for(i
= 0; i
< p_sys
->ports
; i
++)
1216 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1217 if(!p_port
->b_reconfigure
) continue;
1218 p_port
->b_reconfigure
= 0;
1219 omx_error
= PortReconfigure(p_dec
, p_port
);
1225 /*****************************************************************************
1226 * DecodeAudio: Called to decode one frame
1227 *****************************************************************************/
1228 aout_buffer_t
*DecodeAudio ( decoder_t
*p_dec
, block_t
**pp_block
)
1230 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1231 aout_buffer_t
*p_buffer
= 0;
1232 OMX_BUFFERHEADERTYPE
*p_header
;
1233 OMX_ERRORTYPE omx_error
;
1237 if( !pp_block
|| !*pp_block
) return NULL
;
1239 p_block
= *pp_block
;
1241 /* Check for errors from codec */
1244 msg_Dbg(p_dec
, "error during decoding");
1245 block_Release( p_block
);
1249 if( p_block
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
) )
1251 block_Release( p_block
);
1252 date_Set( &p_sys
->end_date
, 0 );
1253 if(!p_sys
->in
.b_flushed
)
1255 msg_Dbg(p_dec
, "flushing");
1256 OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandFlush
,
1257 p_sys
->in
.definition
.nPortIndex
, 0 );
1259 p_sys
->in
.b_flushed
= true;
1263 if( !date_Get( &p_sys
->end_date
) )
1265 if( !p_block
->i_pts
)
1267 /* We've just started the stream, wait for the first PTS. */
1268 block_Release( p_block
);
1271 date_Set( &p_sys
->end_date
, p_block
->i_pts
);
1274 /* Take care of decoded frames first */
1277 unsigned int i_samples
;
1279 OMX_FIFO_PEEK(&p_sys
->out
.fifo
, p_header
);
1280 if(!p_header
) break; /* No frame available */
1282 i_samples
= p_header
->nFilledLen
/ p_sys
->out
.p_fmt
->audio
.i_channels
/ 2;
1285 p_buffer
= decoder_NewAudioBuffer( p_dec
, i_samples
);
1286 if( !p_buffer
) break; /* No audio buffer available */
1288 memcpy( p_buffer
->p_buffer
, p_header
->pBuffer
, p_buffer
->i_buffer
);
1289 p_header
->nFilledLen
= 0;
1291 if( p_header
->nTimeStamp
!= 0 &&
1292 p_header
->nTimeStamp
!= date_Get( &p_sys
->end_date
) )
1293 date_Set( &p_sys
->end_date
, p_header
->nTimeStamp
);
1295 p_buffer
->i_pts
= date_Get( &p_sys
->end_date
);
1296 p_buffer
->i_length
= date_Increment( &p_sys
->end_date
, i_samples
) -
1300 #ifdef OMXIL_EXTRA_DEBUG
1301 msg_Dbg( p_dec
, "FillThisBuffer %p, %p", p_header
, p_header
->pBuffer
);
1303 OMX_FIFO_GET(&p_sys
->out
.fifo
, p_header
);
1304 OMX_FillThisBuffer(p_sys
->omx_handle
, p_header
);
1308 /* Send the input buffer to the component */
1309 OMX_FIFO_GET(&p_sys
->in
.fifo
, p_header
);
1312 p_header
->nFilledLen
= p_block
->i_buffer
;
1313 p_header
->nOffset
= 0;
1314 p_header
->nFlags
= OMX_BUFFERFLAG_ENDOFFRAME
;
1315 p_header
->nTimeStamp
= p_block
->i_dts
;
1317 /* In direct mode we pass the input pointer as is.
1318 * Otherwise we memcopy the data */
1319 if(p_sys
->in
.b_direct
)
1321 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1322 p_header
->pBuffer
= p_block
->p_buffer
;
1323 p_header
->pAppPrivate
= p_block
;
1327 if(p_header
->nFilledLen
> p_header
->nAllocLen
)
1329 msg_Dbg(p_dec
, "buffer too small (%i,%i)",
1330 (int)p_header
->nFilledLen
, (int)p_header
->nAllocLen
);
1331 p_header
->nFilledLen
= p_header
->nAllocLen
;
1333 memcpy(p_header
->pBuffer
, p_block
->p_buffer
, p_header
->nFilledLen
);
1334 block_Release(p_block
);
1337 #ifdef OMXIL_EXTRA_DEBUG
1338 msg_Dbg( p_dec
, "EmptyThisBuffer %p, %p, %i", p_header
, p_header
->pBuffer
,
1339 (int)p_header
->nFilledLen
);
1341 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
1342 p_sys
->in
.b_flushed
= false;
1343 *pp_block
= NULL
; /* Avoid being fed the same packet again */
1346 /* Handle the PortSettingsChanged events */
1347 for(i
= 0; i
< p_sys
->ports
; i
++)
1349 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1350 if(!p_port
->b_reconfigure
) continue;
1351 p_port
->b_reconfigure
= 0;
1352 omx_error
= PortReconfigure(p_dec
, p_port
);
1358 /*****************************************************************************
1359 * EncodeVideo: Called to encode one frame
1360 *****************************************************************************/
1361 static block_t
*EncodeVideo( encoder_t
*p_enc
, picture_t
*p_pic
)
1363 decoder_t
*p_dec
= ( decoder_t
*)p_enc
;
1364 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1365 OMX_ERRORTYPE omx_error
;
1368 OMX_BUFFERHEADERTYPE
*p_header
;
1369 block_t
*p_block
= 0;
1371 if( !p_pic
) return NULL
;
1373 /* Check for errors from codec */
1376 msg_Dbg(p_dec
, "error during encoding");
1380 /* Send the input buffer to the component */
1381 OMX_FIFO_GET(&p_sys
->in
.fifo
, p_header
);
1384 /* In direct mode we pass the input pointer as is.
1385 * Otherwise we memcopy the data */
1386 if(p_sys
->in
.b_direct
)
1388 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1389 p_header
->pBuffer
= p_pic
->p
[0].p_pixels
;
1393 CopyVlcPicture(p_dec
, p_header
, p_pic
);
1396 p_header
->nFilledLen
= p_sys
->in
.i_frame_size
;
1397 p_header
->nOffset
= 0;
1398 p_header
->nFlags
= OMX_BUFFERFLAG_ENDOFFRAME
;
1399 p_header
->nTimeStamp
= p_pic
->date
;
1400 #ifdef OMXIL_EXTRA_DEBUG
1401 msg_Dbg( p_dec
, "EmptyThisBuffer %p, %p, %i", p_header
, p_header
->pBuffer
,
1402 (int)p_header
->nFilledLen
);
1404 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
1405 p_sys
->in
.b_flushed
= false;
1408 /* Handle the PortSettingsChanged events */
1409 for(i
= 0; i
< p_sys
->ports
; i
++)
1411 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1412 if(!p_port
->b_reconfigure
) continue;
1413 p_port
->b_reconfigure
= 0;
1414 omx_error
= PortReconfigure(p_dec
, p_port
);
1417 /* Wait for the decoded frame */
1420 OMX_FIFO_GET(&p_sys
->out
.fifo
, p_header
);
1422 if(p_header
->nFilledLen
)
1424 if(p_header
->nFlags
& OMX_BUFFERFLAG_CODECCONFIG
)
1426 /* TODO: need to store codec config */
1427 msg_Dbg(p_dec
, "received codec config %i", (int)p_header
->nFilledLen
);
1430 p_block
= p_header
->pAppPrivate
;
1433 /* We're not in direct rendering mode.
1434 * Get a new block and copy the content */
1435 p_block
= block_New( p_dec
, p_header
->nFilledLen
);
1436 memcpy(p_block
->p_buffer
, p_header
->pBuffer
, p_header
->nFilledLen
);
1439 p_block
->i_buffer
= p_header
->nFilledLen
;
1440 p_block
->i_pts
= p_block
->i_dts
= p_header
->nTimeStamp
;
1441 p_header
->nFilledLen
= 0;
1442 p_header
->pAppPrivate
= 0;
1445 #ifdef OMXIL_EXTRA_DEBUG
1446 msg_Dbg( p_dec
, "FillThisBuffer %p, %p", p_header
, p_header
->pBuffer
);
1448 OMX_FillThisBuffer(p_sys
->omx_handle
, p_header
);
1451 msg_Dbg(p_dec
, "done");
1455 /*****************************************************************************
1456 * CloseGeneric: omxil decoder destruction
1457 *****************************************************************************/
1458 static void CloseGeneric( vlc_object_t
*p_this
)
1460 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1461 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1463 if(p_sys
->omx_handle
) DeinitialiseComponent(p_dec
, p_sys
->omx_handle
);
1464 if(p_sys
->b_init
) p_sys
->pf_deinit();
1465 dll_close( p_sys
->dll_handle
);
1467 vlc_mutex_destroy (&p_sys
->mutex
);
1468 vlc_cond_destroy (&p_sys
->cond
);
1469 vlc_mutex_destroy (&p_sys
->in
.fifo
.lock
);
1470 vlc_cond_destroy (&p_sys
->in
.fifo
.wait
);
1471 vlc_mutex_destroy (&p_sys
->out
.fifo
.lock
);
1472 vlc_cond_destroy (&p_sys
->out
.fifo
.wait
);
1477 /*****************************************************************************
1479 *****************************************************************************/
1480 static OMX_ERRORTYPE
OmxEventHandler( OMX_HANDLETYPE omx_handle
,
1481 OMX_PTR app_data
, OMX_EVENTTYPE event
, OMX_U32 data_1
,
1482 OMX_U32 data_2
, OMX_PTR event_data
)
1484 decoder_t
*p_dec
= (decoder_t
*)app_data
;
1485 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1491 case OMX_EventCmdComplete
:
1492 switch ((OMX_STATETYPE
)data_1
)
1494 case OMX_CommandStateSet
:
1495 msg_Dbg( p_dec
, "OmxEventHandler (%s, %s, %s)", EventToString(event
),
1496 CommandToString(data_1
), StateToString(data_2
) );
1500 msg_Dbg( p_dec
, "OmxEventHandler (%s, %s, %u)", EventToString(event
),
1501 CommandToString(data_1
), (unsigned int)data_2
);
1506 case OMX_EventError
:
1507 msg_Dbg( p_dec
, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event
),
1508 ErrorToString((OMX_ERRORTYPE
)data_1
), (unsigned int)data_2
,
1509 (const char *)event_data
);
1510 //p_sys->b_error = true;
1513 case OMX_EventPortSettingsChanged
:
1514 msg_Dbg( p_dec
, "OmxEventHandler (%s, %u, %u)", EventToString(event
),
1515 (unsigned int)data_1
, (unsigned int)data_2
);
1516 for(i
= 0; i
< p_sys
->ports
; i
++)
1517 if(p_sys
->p_ports
[i
].definition
.eDir
== OMX_DirOutput
)
1518 p_sys
->p_ports
[i
].b_reconfigure
= true;
1519 memset(&p_sys
->sentinel_buffer
, 0, sizeof(p_sys
->sentinel_buffer
));
1520 p_sys
->sentinel_buffer
.nFlags
= OMX_BUFFERFLAG_EOS
;
1521 OMX_FIFO_PUT(&p_sys
->in
.fifo
, &p_sys
->sentinel_buffer
);
1525 msg_Dbg( p_dec
, "OmxEventHandler (%s, %u, %u)", EventToString(event
),
1526 (unsigned int)data_1
, (unsigned int)data_2
);
1530 PostOmxEvent(p_dec
, event
, data_1
, data_2
, event_data
);
1531 return OMX_ErrorNone
;
1534 static OMX_ERRORTYPE
OmxEmptyBufferDone( OMX_HANDLETYPE omx_handle
,
1535 OMX_PTR app_data
, OMX_BUFFERHEADERTYPE
*omx_header
)
1537 decoder_t
*p_dec
= (decoder_t
*)app_data
;
1538 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1541 #ifdef OMXIL_EXTRA_DEBUG
1542 msg_Dbg( p_dec
, "OmxEmptyBufferDone %p, %p", omx_header
, omx_header
->pBuffer
);
1545 if(omx_header
->pAppPrivate
|| omx_header
->pOutputPortPrivate
)
1547 block_t
*p_block
= (block_t
*)omx_header
->pAppPrivate
;
1548 omx_header
->pBuffer
= omx_header
->pOutputPortPrivate
;
1549 if(p_block
) block_Release(p_block
);
1550 omx_header
->pAppPrivate
= 0;
1552 OMX_FIFO_PUT(&p_sys
->in
.fifo
, omx_header
);
1554 return OMX_ErrorNone
;
1557 static OMX_ERRORTYPE
OmxFillBufferDone( OMX_HANDLETYPE omx_handle
,
1558 OMX_PTR app_data
, OMX_BUFFERHEADERTYPE
*omx_header
)
1560 decoder_t
*p_dec
= (decoder_t
*)app_data
;
1561 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1564 #ifdef OMXIL_EXTRA_DEBUG
1565 msg_Dbg( p_dec
, "OmxFillBufferDone %p, %p, %i", omx_header
, omx_header
->pBuffer
,
1566 (int)omx_header
->nFilledLen
);
1569 if(omx_header
->pInputPortPrivate
)
1571 omx_header
->pBuffer
= omx_header
->pInputPortPrivate
;
1573 OMX_FIFO_PUT(&p_sys
->out
.fifo
, omx_header
);
1575 return OMX_ErrorNone
;