]> git.sesse.net Git - vlc/blob - modules/codec/omxil/omxil.c
OMX: rename GetVlcAudioFormat to OmxToVlcAudioFormat
[vlc] / modules / codec / omxil / omxil.c
1 /*****************************************************************************
2  * omxil.c: Video decoder module making use of OpenMAX IL components.
3  *****************************************************************************
4  * Copyright (C) 2010 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
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.
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 General Public License for more details.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <dlfcn.h>
32 #if defined(USE_IOMX)
33 # include "iomx.h"
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)
37 #else
38 # define dll_open(name) dlopen( name, RTLD_NOW )
39 # define dll_close(handle) dlclose(handle)
40 #endif
41
42 #include <limits.h>
43
44 #include <vlc_common.h>
45 #include <vlc_plugin.h>
46 #include <vlc_codec.h>
47 #include <vlc_aout.h>
48 #include <vlc_block_helper.h>
49 #include <vlc_cpu.h>
50 #include "../h264_nal.h"
51
52 #include "omxil.h"
53
54 //#define OMXIL_EXTRA_DEBUG
55
56 /*****************************************************************************
57  * List of OpenMAX IL core we will try in order
58  *****************************************************************************/
59 static const char *ppsz_dll_list[] =
60 {
61     "libOMX_Core.so", /* TI OMAP IL core */
62     "libOmxCore.so", /* Qualcomm IL core */
63     "libomxil-bellagio.so",  /* Bellagio IL core */
64     0
65 };
66
67 /*****************************************************************************
68  * Local prototypes
69  *****************************************************************************/
70 static int  OpenDecoder( vlc_object_t * );
71 static int  OpenEncoder( vlc_object_t * );
72 static int  OpenGeneric( vlc_object_t *, bool b_encode );
73 static void CloseGeneric( vlc_object_t * );
74
75 static picture_t *DecodeVideo( decoder_t *, block_t ** );
76 static aout_buffer_t *DecodeAudio ( decoder_t *, block_t ** );
77 static block_t *EncodeVideo( encoder_t *, picture_t * );
78
79 static OMX_ERRORTYPE OmxEventHandler( OMX_HANDLETYPE, OMX_PTR, OMX_EVENTTYPE,
80                                       OMX_U32, OMX_U32, OMX_PTR );
81 static OMX_ERRORTYPE OmxEmptyBufferDone( OMX_HANDLETYPE, OMX_PTR,
82                                          OMX_BUFFERHEADERTYPE * );
83 static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE, OMX_PTR,
84                                         OMX_BUFFERHEADERTYPE * );
85
86 /*****************************************************************************
87  * Module descriptor
88  *****************************************************************************/
89 vlc_module_begin ()
90     set_description( N_("Audio/Video decoder (using OpenMAX IL)") )
91     set_category( CAT_INPUT )
92     set_subcategory( SUBCAT_INPUT_VCODEC )
93     set_section( N_("Decoding") , NULL )
94 #ifdef HAVE_MAEMO
95     set_capability( "decoder", 80 )
96 #else
97     set_capability( "decoder", 0 )
98 #endif
99     set_callbacks( OpenDecoder, CloseGeneric )
100
101     add_submodule ()
102     set_section( N_("Encoding") , NULL )
103     set_description( N_("Video encoder (using OpenMAX IL)") )
104     set_capability( "encoder", 0 )
105     set_callbacks( OpenEncoder, CloseGeneric )
106 vlc_module_end ()
107
108 /*****************************************************************************
109  * CreateComponentsList: creates a list of components matching the given role
110  *****************************************************************************/
111 static int CreateComponentsList(decoder_t *p_dec, const char *psz_role)
112 {
113     decoder_sys_t *p_sys = p_dec->p_sys;
114     char psz_name[OMX_MAX_STRINGNAME_SIZE];
115     OMX_ERRORTYPE omx_error;
116     OMX_U32 roles = 0;
117     OMX_U8 **ppsz_roles = 0;
118     unsigned int i, j, len;
119
120     if(!psz_role) goto end;
121     len = strlen(psz_role);
122
123     for( i = 0; ; i++ )
124     {
125         bool b_found = false;
126
127         omx_error = p_sys->pf_component_enum(psz_name, OMX_MAX_STRINGNAME_SIZE, i);
128         if(omx_error != OMX_ErrorNone) break;
129
130         msg_Dbg(p_dec, "component %s", psz_name);
131
132         omx_error = p_sys->pf_get_roles_of_component(psz_name, &roles, 0);
133         if(omx_error != OMX_ErrorNone || !roles) continue;
134
135         ppsz_roles = malloc(roles * (sizeof(OMX_U8*) + OMX_MAX_STRINGNAME_SIZE));
136         if(!ppsz_roles) continue;
137
138         for( j = 0; j < roles; j++ )
139             ppsz_roles[j] = ((OMX_U8 *)(&ppsz_roles[roles])) +
140                 j * OMX_MAX_STRINGNAME_SIZE;
141
142         omx_error = p_sys->pf_get_roles_of_component(psz_name, &roles, ppsz_roles);
143         if(omx_error != OMX_ErrorNone) roles = 0;
144
145         for(j = 0; j < roles; j++)
146         {
147             msg_Dbg(p_dec, "  - role: %s", ppsz_roles[j]);
148             if(!strncmp((char *)ppsz_roles[j], psz_role, len)) b_found = true;
149         }
150
151         free(ppsz_roles);
152
153         if(!b_found) continue;
154
155         if(p_sys->components >= MAX_COMPONENTS_LIST_SIZE)
156         {
157             msg_Dbg(p_dec, "too many matching components");
158             continue;
159         }
160
161         strncpy(p_sys->ppsz_components[p_sys->components], psz_name,
162                 OMX_MAX_STRINGNAME_SIZE-1);
163         p_sys->components++;
164     }
165
166  end:
167     msg_Dbg(p_dec, "found %i matching components for role %s",
168             p_sys->components, psz_role);
169     for( i = 0; i < p_sys->components; i++ )
170         msg_Dbg(p_dec, "- %s", p_sys->ppsz_components[i]);
171
172     return p_sys->components;
173 }
174
175 /*****************************************************************************
176  * ImplementationSpecificWorkarounds: place-holder for implementation
177  * specific workarounds
178  *****************************************************************************/
179 static OMX_ERRORTYPE ImplementationSpecificWorkarounds(decoder_t *p_dec,
180     OmxPort *p_port, es_format_t *p_fmt)
181 {
182     decoder_sys_t *p_sys = p_dec->p_sys;
183     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
184     int i_profile = 0xFFFF, i_level = 0xFFFF;
185
186     /* Try to find out the profile of the video */
187     while(p_fmt->i_cat == VIDEO_ES && def->eDir == OMX_DirInput &&
188           p_fmt->i_codec == VLC_CODEC_H264)
189     {
190         uint8_t *p = (uint8_t*)p_dec->fmt_in.p_extra;
191         if(!p || !p_dec->fmt_in.p_extra) break;
192
193         /* Check the profile / level */
194         if(p_dec->fmt_in.i_original_fourcc == VLC_FOURCC('a','v','c','1') &&
195            p[0] == 1)
196         {
197             if(p_dec->fmt_in.i_extra < 12) break;
198             p_sys->i_nal_size_length = 1 + (p[4]&0x03);
199             if( !(p[5]&0x1f) ) break;
200             p += 8;
201         }
202         else
203         {
204             if(p_dec->fmt_in.i_extra < 8) break;
205             if(!p[0] && !p[1] && !p[2] && p[3] == 1) p += 4;
206             else if(!p[0] && !p[1] && p[2] == 1) p += 3;
207             else break;
208         }
209
210         if( ((*p++)&0x1f) != 7) break;
211
212         /* Get profile/level out of first SPS */
213         i_profile = p[0];
214         i_level = p[2];
215         break;
216     }
217
218     if(!strcmp(p_sys->psz_component, "OMX.TI.Video.Decoder"))
219     {
220         if(p_fmt->i_cat == VIDEO_ES && def->eDir == OMX_DirInput &&
221            p_fmt->i_codec == VLC_CODEC_H264 &&
222            (i_profile != 66 || i_level > 30))
223         {
224             msg_Dbg(p_dec, "h264 profile/level not supported (0x%x, 0x%x)",
225                     i_profile, i_level);
226             return OMX_ErrorNotImplemented;
227         }
228
229         if(p_fmt->i_cat == VIDEO_ES && def->eDir == OMX_DirOutput &&
230            p_fmt->i_codec == VLC_CODEC_I420)
231         {
232             /* I420 xvideo is slow on OMAP */
233             def->format.video.eColorFormat = OMX_COLOR_FormatCbYCrY;
234             GetVlcChromaFormat( def->format.video.eColorFormat,
235                                 &p_fmt->i_codec, 0 );
236             GetVlcChromaSizes( p_fmt->i_codec,
237                                def->format.video.nFrameWidth,
238                                def->format.video.nFrameHeight,
239                                &p_port->i_frame_size, &p_port->i_frame_stride,
240                                &p_port->i_frame_stride_chroma_div );
241             def->format.video.nStride = p_port->i_frame_stride;
242             def->nBufferSize = p_port->i_frame_size;
243         }
244     }
245     else if(!strcmp(p_sys->psz_component, "OMX.st.video_encoder"))
246     {
247         if(p_fmt->i_cat == VIDEO_ES)
248         {
249             /* Bellagio's encoder doesn't encode the framerate in Q16 */
250             def->format.video.xFramerate >>= 16;
251         }
252     }
253
254     return OMX_ErrorNone;
255 }
256
257 /*****************************************************************************
258  * SetPortDefinition: set definition of the omx port based on the vlc format
259  *****************************************************************************/
260 static OMX_ERRORTYPE SetPortDefinition(decoder_t *p_dec, OmxPort *p_port,
261                                        es_format_t *p_fmt)
262 {
263     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
264     OMX_ERRORTYPE omx_error;
265
266     omx_error = OMX_GetParameter(p_port->omx_handle,
267                                  OMX_IndexParamPortDefinition, def);
268     CHECK_ERROR(omx_error, "OMX_GetParameter failed (%x : %s)",
269                 omx_error, ErrorToString(omx_error));
270
271     switch(p_fmt->i_cat)
272     {
273     case VIDEO_ES:
274         def->format.video.nFrameWidth = p_fmt->video.i_width;
275         def->format.video.nFrameHeight = p_fmt->video.i_height;
276         if(def->format.video.eCompressionFormat == OMX_VIDEO_CodingUnused)
277             def->format.video.nStride = def->format.video.nFrameWidth;
278         if( p_fmt->video.i_frame_rate > 0 &&
279             p_fmt->video.i_frame_rate_base > 0 )
280             def->format.video.xFramerate = (p_fmt->video.i_frame_rate << 16) /
281                 p_fmt->video.i_frame_rate_base;
282
283         if(def->eDir == OMX_DirInput || p_dec->p_sys->b_enc)
284         {
285             def->nBufferSize = def->format.video.nFrameWidth *
286               def->format.video.nFrameHeight * 2;
287             p_port->i_frame_size = def->nBufferSize;
288
289             if(!GetOmxVideoFormat(p_fmt->i_codec,
290                                   &def->format.video.eCompressionFormat, 0) )
291             {
292                 if(!GetOmxChromaFormat(p_fmt->i_codec,
293                                        &def->format.video.eColorFormat, 0) )
294                 {
295                     omx_error = OMX_ErrorNotImplemented;
296                     CHECK_ERROR(omx_error, "codec %4.4s doesn't match any OMX format",
297                                 (char *)&p_fmt->i_codec );
298                 }
299                 GetVlcChromaSizes( p_fmt->i_codec,
300                                    def->format.video.nFrameWidth,
301                                    def->format.video.nFrameHeight,
302                                    &p_port->i_frame_size, &p_port->i_frame_stride,
303                                    &p_port->i_frame_stride_chroma_div );
304                 def->format.video.nStride = p_port->i_frame_stride;
305                 def->nBufferSize = p_port->i_frame_size;
306             }
307         }
308         else
309         {
310             if( !GetVlcChromaFormat( def->format.video.eColorFormat,
311                                      &p_fmt->i_codec, 0 ) )
312             {
313                 omx_error = OMX_ErrorNotImplemented;
314                 CHECK_ERROR(omx_error, "OMX color format %i not supported",
315                             (int)def->format.video.eColorFormat );
316             }
317             GetVlcChromaSizes( p_fmt->i_codec,
318                                def->format.video.nFrameWidth,
319                                def->format.video.nFrameHeight,
320                                &p_port->i_frame_size, &p_port->i_frame_stride,
321                                &p_port->i_frame_stride_chroma_div );
322             def->format.video.nStride = p_port->i_frame_stride;
323             def->nBufferSize = p_port->i_frame_size;
324         }
325         break;
326
327     case AUDIO_ES:
328         p_port->i_frame_size = def->nBufferSize;
329         if(def->eDir == OMX_DirInput)
330         {
331             if(!GetOmxAudioFormat(p_fmt->i_codec,
332                                   &def->format.audio.eEncoding, 0) )
333             {
334                 omx_error = OMX_ErrorNotImplemented;
335                 CHECK_ERROR(omx_error, "codec %4.4s doesn't match any OMX format",
336                             (char *)&p_fmt->i_codec );
337             }
338         }
339         else
340         {
341             if( !OmxToVlcAudioFormat(def->format.audio.eEncoding,
342                                    &p_fmt->i_codec, 0 ) )
343             {
344                 omx_error = OMX_ErrorNotImplemented;
345                 CHECK_ERROR(omx_error, "OMX audio encoding %i not supported",
346                             (int)def->format.audio.eEncoding );
347             }
348         }
349         break;
350
351     default: return OMX_ErrorNotImplemented;
352     }
353
354     omx_error = ImplementationSpecificWorkarounds(p_dec, p_port, p_fmt);
355     CHECK_ERROR(omx_error, "ImplementationSpecificWorkarounds failed (%x : %s)",
356                 omx_error, ErrorToString(omx_error));
357
358     omx_error = OMX_SetParameter(p_port->omx_handle,
359                                  OMX_IndexParamPortDefinition, def);
360     CHECK_ERROR(omx_error, "OMX_SetParameter failed (%x : %s)",
361                 omx_error, ErrorToString(omx_error));
362
363     omx_error = OMX_GetParameter(p_port->omx_handle,
364                                  OMX_IndexParamPortDefinition, def);
365     CHECK_ERROR(omx_error, "OMX_GetParameter failed (%x : %s)",
366                 omx_error, ErrorToString(omx_error));
367
368     if(p_port->i_frame_size > def->nBufferSize)
369         def->nBufferSize = p_port->i_frame_size;
370     p_port->i_frame_size = def->nBufferSize;
371
372     /* Deal with audio params */
373     if(p_fmt->i_cat == AUDIO_ES)
374     {
375         omx_error = SetAudioParameters(p_port->omx_handle,
376                                        &p_port->format_param, def->nPortIndex,
377                                        def->format.audio.eEncoding,
378                                        p_fmt->audio.i_channels,
379                                        p_fmt->audio.i_rate,
380                                        p_fmt->i_bitrate,
381                                        p_fmt->audio.i_bitspersample,
382                                        p_fmt->audio.i_blockalign);
383         CHECK_ERROR(omx_error, "SetAudioParameters failed (%x : %s)",
384                     omx_error, ErrorToString(omx_error));
385     }
386
387  error:
388     return omx_error;
389 }
390
391 /*****************************************************************************
392  * GetPortDefinition: set vlc format based on the definition of the omx port
393  *****************************************************************************/
394 static OMX_ERRORTYPE GetPortDefinition(decoder_t *p_dec, OmxPort *p_port,
395                                        es_format_t *p_fmt)
396 {
397     decoder_sys_t *p_sys = p_dec->p_sys;
398     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
399     OMX_ERRORTYPE omx_error;
400
401     omx_error = OMX_GetParameter(p_port->omx_handle,
402                                  OMX_IndexParamPortDefinition, def);
403     CHECK_ERROR(omx_error, "OMX_GetParameter failed (%x : %s)",
404                 omx_error, ErrorToString(omx_error));
405
406     switch(p_fmt->i_cat)
407     {
408     case VIDEO_ES:
409         p_fmt->video.i_width = def->format.video.nFrameWidth;
410         p_fmt->video.i_visible_width = def->format.video.nFrameWidth;
411         p_fmt->video.i_height = def->format.video.nFrameHeight;
412         p_fmt->video.i_visible_height = def->format.video.nFrameHeight;
413         p_fmt->video.i_frame_rate = p_dec->fmt_in.video.i_frame_rate;
414         p_fmt->video.i_frame_rate_base = p_dec->fmt_in.video.i_frame_rate_base;
415
416         /* Hack: Nexus One (stock firmware with binary OMX driver blob)
417          * claims to output 420Planar even though it in in practice is
418          * NV21. */
419         if(def->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar &&
420            !strncmp(p_sys->psz_component, "OMX.qcom.video.decoder",
421                     strlen("OMX.qcom.video.decoder")))
422             def->format.video.eColorFormat = OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
423
424         if(!GetVlcVideoFormat( def->format.video.eCompressionFormat,
425                                &p_fmt->i_codec, 0 ) )
426         {
427             if( !GetVlcChromaFormat( def->format.video.eColorFormat,
428                                      &p_fmt->i_codec, 0 ) )
429             {
430                 omx_error = OMX_ErrorNotImplemented;
431                 CHECK_ERROR(omx_error, "OMX color format %i not supported",
432                             (int)def->format.video.eColorFormat );
433             }
434             GetVlcChromaSizes( p_fmt->i_codec,
435                                def->format.video.nFrameWidth,
436                                def->format.video.nFrameHeight,
437                                &p_port->i_frame_size, &p_port->i_frame_stride,
438                                &p_port->i_frame_stride_chroma_div );
439         }
440         if(p_port->i_frame_size > def->nBufferSize)
441             def->nBufferSize = p_port->i_frame_size;
442         p_port->i_frame_size = def->nBufferSize;
443 #if 0
444         if((int)p_port->i_frame_stride > def->format.video.nStride)
445             def->format.video.nStride = p_port->i_frame_stride;
446 #endif
447         p_port->i_frame_stride = def->format.video.nStride;
448         break;
449
450     case AUDIO_ES:
451         if( !OmxToVlcAudioFormat( def->format.audio.eEncoding,
452                                 &p_fmt->i_codec, 0 ) )
453         {
454             omx_error = OMX_ErrorNotImplemented;
455             CHECK_ERROR(omx_error, "OMX audio format %i not supported",
456                         (int)def->format.audio.eEncoding );
457         }
458
459         omx_error = GetAudioParameters(p_port->omx_handle,
460                                        &p_port->format_param, def->nPortIndex,
461                                        def->format.audio.eEncoding,
462                                        &p_fmt->audio.i_channels,
463                                        &p_fmt->audio.i_rate,
464                                        &p_fmt->i_bitrate,
465                                        &p_fmt->audio.i_bitspersample,
466                                        &p_fmt->audio.i_blockalign);
467         CHECK_ERROR(omx_error, "GetAudioParameters failed (%x : %s)",
468                     omx_error, ErrorToString(omx_error));
469
470         if(p_fmt->audio.i_channels < 9)
471         {
472             static const int pi_channels_maps[9] =
473             {
474                 0, AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
475                 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
476                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
477                 | AOUT_CHAN_REARRIGHT,
478                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
479                 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
480                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
481                 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
482                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
483                 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
484                 | AOUT_CHAN_MIDDLERIGHT,
485                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
486                 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
487                 | AOUT_CHAN_LFE
488             };
489             p_fmt->audio.i_physical_channels =
490                 p_fmt->audio.i_original_channels =
491                     pi_channels_maps[p_fmt->audio.i_channels];
492         }
493
494         date_Init( &p_dec->p_sys->end_date, p_fmt->audio.i_rate, 1 );
495
496         break;
497
498     default: return OMX_ErrorNotImplemented;
499     }
500
501  error:
502     return omx_error;
503 }
504
505 /*****************************************************************************
506  * DeinitialiseComponent: Deinitialise and unload an OMX component
507  *****************************************************************************/
508 static OMX_ERRORTYPE DeinitialiseComponent(decoder_t *p_dec,
509                                            OMX_HANDLETYPE omx_handle)
510 {
511     decoder_sys_t *p_sys = p_dec->p_sys;
512     OMX_ERRORTYPE omx_error;
513     OMX_STATETYPE state;
514     unsigned int i, j;
515
516     if(!omx_handle) return OMX_ErrorNone;
517
518     omx_error = OMX_GetState(omx_handle, &state);
519     CHECK_ERROR(omx_error, "OMX_GetState failed (%x)", omx_error );
520
521     if(state == OMX_StateExecuting)
522     {
523         omx_error = OMX_SendCommand( omx_handle, OMX_CommandStateSet,
524                                      OMX_StateIdle, 0 );
525         CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x)", omx_error );
526         omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
527         CHECK_ERROR(omx_error, "Wait for Idle failed (%x)", omx_error );
528     }
529
530     omx_error = OMX_GetState(omx_handle, &state);
531     CHECK_ERROR(omx_error, "OMX_GetState failed (%x)", omx_error );
532
533     if(state == OMX_StateIdle)
534     {
535         omx_error = OMX_SendCommand( omx_handle, OMX_CommandStateSet,
536                                      OMX_StateLoaded, 0 );
537         CHECK_ERROR(omx_error, "OMX_CommandStateSet Loaded failed (%x)", omx_error );
538
539         for(i = 0; i < p_sys->ports; i++)
540         {
541             OmxPort *p_port = &p_sys->p_ports[i];
542             OMX_BUFFERHEADERTYPE *p_buffer;
543
544             for(j = 0; j < p_port->i_buffers; j++)
545             {
546                 OMX_FIFO_GET(&p_port->fifo, p_buffer);
547                 omx_error = OMX_FreeBuffer( omx_handle,
548                                             p_port->i_port_index, p_buffer );
549
550                 if(omx_error != OMX_ErrorNone) break;
551             }
552             CHECK_ERROR(omx_error, "OMX_FreeBuffer failed (%x, %i, %i)",
553                         omx_error, (int)p_port->i_port_index, j );
554         }
555
556         omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
557         CHECK_ERROR(omx_error, "Wait for Loaded failed (%x)", omx_error );
558     }
559
560  error:
561     for(i = 0; i < p_sys->ports; i++)
562     {
563         OmxPort *p_port = &p_sys->p_ports[i];
564         free(p_port->pp_buffers);
565         p_port->pp_buffers = 0;
566     }
567     omx_error = p_sys->pf_free_handle( omx_handle );
568     return omx_error;
569 }
570
571 /*****************************************************************************
572  * InitialiseComponent: Load and initialise an OMX component
573  *****************************************************************************/
574 static OMX_ERRORTYPE InitialiseComponent(decoder_t *p_dec,
575     OMX_STRING psz_component, OMX_HANDLETYPE *p_handle)
576 {
577     static OMX_CALLBACKTYPE callbacks =
578         { OmxEventHandler, OmxEmptyBufferDone, OmxFillBufferDone };
579     decoder_sys_t *p_sys = p_dec->p_sys;
580     OMX_HANDLETYPE omx_handle;
581     OMX_ERRORTYPE omx_error;
582     unsigned int i;
583     OMX_U8 psz_role[OMX_MAX_STRINGNAME_SIZE];
584     OMX_PARAM_COMPONENTROLETYPE role;
585     OMX_PARAM_PORTDEFINITIONTYPE definition;
586     OMX_PORT_PARAM_TYPE param;
587
588     /* Load component */
589     omx_error = p_sys->pf_get_handle( &omx_handle, psz_component,
590                                       p_dec, &callbacks );
591     if(omx_error != OMX_ErrorNone)
592     {
593         msg_Warn( p_dec, "OMX_GetHandle(%s) failed (%x: %s)", psz_component,
594                   omx_error, ErrorToString(omx_error) );
595         return omx_error;
596     }
597     strncpy(p_sys->psz_component, psz_component, OMX_MAX_STRINGNAME_SIZE-1);
598
599     omx_error = OMX_ComponentRoleEnum(omx_handle, psz_role, 0);
600     if(omx_error == OMX_ErrorNone)
601         msg_Dbg(p_dec, "loaded component %s of role %s", psz_component, psz_role);
602     else
603         msg_Dbg(p_dec, "loaded component %s", psz_component);
604     PrintOmx(p_dec, omx_handle, OMX_ALL);
605
606     /* Set component role */
607     OMX_INIT_STRUCTURE(role);
608     strcpy((char*)role.cRole,
609            GetOmxRole(p_sys->b_enc ? p_dec->fmt_out.i_codec : p_dec->fmt_in.i_codec,
610                       p_dec->fmt_in.i_cat, p_sys->b_enc));
611
612     omx_error = OMX_SetParameter(omx_handle, OMX_IndexParamStandardComponentRole,
613                                  &role);
614     omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamStandardComponentRole,
615                                  &role);
616     if(omx_error == OMX_ErrorNone)
617         msg_Dbg(p_dec, "component standard role set to %s", role.cRole);
618
619     /* Find the input / output ports */
620     OMX_INIT_STRUCTURE(param);
621     OMX_INIT_STRUCTURE(definition);
622     omx_error = OMX_GetParameter(omx_handle, p_dec->fmt_in.i_cat == VIDEO_ES ?
623                                  OMX_IndexParamVideoInit : OMX_IndexParamAudioInit, &param);
624     if(omx_error != OMX_ErrorNone) param.nPorts = 0;
625
626     for(i = 0; i < param.nPorts; i++)
627     {
628         OmxPort *p_port;
629
630         /* Get port definition */
631         definition.nPortIndex = param.nStartPortNumber + i;
632         omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
633                                      &definition);
634         if(omx_error != OMX_ErrorNone) continue;
635
636         if(definition.eDir == OMX_DirInput) p_port = &p_sys->in;
637         else  p_port = &p_sys->out;
638
639         p_port->b_valid = true;
640         p_port->i_port_index = definition.nPortIndex;
641         p_port->definition = definition;
642         p_port->omx_handle = omx_handle;
643     }
644
645     if(!p_sys->in.b_valid || !p_sys->out.b_valid)
646     {
647         omx_error = OMX_ErrorInvalidComponent;
648         CHECK_ERROR(omx_error, "couldn't find an input and output port");
649     }
650
651     if(!strncmp(p_sys->psz_component, "OMX.SEC.", 8))
652     {
653         OMX_INDEXTYPE index;
654         omx_error = OMX_GetExtensionIndex(omx_handle, (OMX_STRING) "OMX.SEC.index.ThumbnailMode", &index);
655         if(omx_error == OMX_ErrorNone)
656         {
657             OMX_BOOL enable = OMX_TRUE;
658             omx_error = OMX_SetConfig(omx_handle, index, &enable);
659             CHECK_ERROR(omx_error, "Unable to set ThumbnailMode");
660         }
661     }
662
663     /* Set port definitions */
664     for(i = 0; i < p_sys->ports; i++)
665     {
666         omx_error = SetPortDefinition(p_dec, &p_sys->p_ports[i],
667                                       p_sys->p_ports[i].p_fmt);
668         if(omx_error != OMX_ErrorNone) goto error;
669     }
670
671     /* Allocate our array for the omx buffers and enable ports */
672     for(i = 0; i < p_sys->ports; i++)
673     {
674         OmxPort *p_port = &p_sys->p_ports[i];
675
676         p_port->pp_buffers =
677             malloc(p_port->definition.nBufferCountActual *
678                    sizeof(OMX_BUFFERHEADERTYPE*));
679         if(!p_port->pp_buffers)
680         {
681           omx_error = OMX_ErrorInsufficientResources;
682           CHECK_ERROR(omx_error, "memory allocation failed");
683         }
684         p_port->i_buffers = p_port->definition.nBufferCountActual;
685
686         /* Enable port */
687         if(!p_port->definition.bEnabled)
688         {
689             omx_error = OMX_SendCommand( omx_handle, OMX_CommandPortEnable,
690                                          p_port->i_port_index, NULL);
691             CHECK_ERROR(omx_error, "OMX_CommandPortEnable on %i failed (%x)",
692                         (int)p_port->i_port_index, omx_error );
693             omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
694             CHECK_ERROR(omx_error, "Wait for PortEnable on %i failed (%x)",
695                         (int)p_port->i_port_index, omx_error );
696         }
697     }
698
699     *p_handle = omx_handle;
700     return OMX_ErrorNone;
701
702  error:
703     DeinitialiseComponent(p_dec, omx_handle);
704     *p_handle = 0;
705     return omx_error;
706 }
707
708 /*****************************************************************************
709  * OpenDecoder: Create the decoder instance
710  *****************************************************************************/
711 static int OpenDecoder( vlc_object_t *p_this )
712 {
713     decoder_t *p_dec = (decoder_t*)p_this;
714     int status;
715
716     if( 0 || !GetOmxRole(p_dec->fmt_in.i_codec, p_dec->fmt_in.i_cat, false) )
717         return VLC_EGENERIC;
718
719 #ifdef HAVE_MAEMO
720     if( p_dec->fmt_in.i_cat != VIDEO_ES && !p_dec->b_force)
721         return VLC_EGENERIC;
722 #endif
723
724     status = OpenGeneric( p_this, false );
725     if(status != VLC_SUCCESS) return status;
726
727     p_dec->pf_decode_video = DecodeVideo;
728     p_dec->pf_decode_audio = DecodeAudio;
729
730     return VLC_SUCCESS;
731 }
732
733 /*****************************************************************************
734  * OpenEncoder: Create the encoder instance
735  *****************************************************************************/
736 static int OpenEncoder( vlc_object_t *p_this )
737 {
738     encoder_t *p_enc = (encoder_t*)p_this;
739     int status;
740
741     if( !GetOmxRole(p_enc->fmt_out.i_codec, p_enc->fmt_in.i_cat, true) )
742         return VLC_EGENERIC;
743
744     status = OpenGeneric( p_this, true );
745     if(status != VLC_SUCCESS) return status;
746
747     p_enc->pf_encode_video = EncodeVideo;
748
749     return VLC_SUCCESS;
750 }
751
752 /*****************************************************************************
753  * OpenGeneric: Create the generic decoder/encoder instance
754  *****************************************************************************/
755 static int OpenGeneric( vlc_object_t *p_this, bool b_encode )
756 {
757     void *dll_handle = 0, *pf_init = 0, *pf_deinit = 0;
758     void *pf_get_handle = 0, *pf_free_handle = 0, *pf_component_enum = 0;
759     void *pf_get_roles_of_component = 0;
760     decoder_t *p_dec = (decoder_t*)p_this;
761     decoder_sys_t *p_sys;
762     OMX_ERRORTYPE omx_error;
763     OMX_BUFFERHEADERTYPE *p_header;
764     unsigned int i, j;
765
766     /* Load the OMX core */
767     for( i = 0; ppsz_dll_list[i]; i++ )
768     {
769         dll_handle = dll_open( ppsz_dll_list[i] );
770         if( dll_handle ) break;
771     }
772     if( !dll_handle ) return VLC_EGENERIC;
773
774     pf_init = dlsym( dll_handle, "OMX_Init" );
775     pf_deinit = dlsym( dll_handle, "OMX_Deinit" );
776     pf_get_handle = dlsym( dll_handle, "OMX_GetHandle" );
777     pf_free_handle = dlsym( dll_handle, "OMX_FreeHandle" );
778     pf_component_enum = dlsym( dll_handle, "OMX_ComponentNameEnum" );
779     pf_get_roles_of_component = dlsym( dll_handle, "OMX_GetRolesOfComponent" );
780     if( !pf_init || !pf_deinit || !pf_get_handle || !pf_free_handle ||
781         !pf_component_enum || !pf_get_roles_of_component )
782     {
783         msg_Warn( p_this, "cannot find OMX_* symbols in `%s' (%s)",
784                   ppsz_dll_list[i], dlerror() );
785         dll_close(dll_handle);
786     }
787
788     if( !pf_init || !pf_deinit || !pf_get_handle || !pf_free_handle || !pf_component_enum )
789     {
790         dll_close(dll_handle);
791         return VLC_EGENERIC;
792     }
793
794     /* Allocate the memory needed to store the decoder's structure */
795     if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL )
796     {
797         dll_close(dll_handle);
798         return VLC_ENOMEM;
799     }
800
801     /* Initialise the thread properties */
802     if(!b_encode)
803     {
804         p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
805         p_dec->fmt_out.video = p_dec->fmt_in.video;
806         p_dec->fmt_out.audio = p_dec->fmt_in.audio;
807         p_dec->fmt_out.i_codec = 0;
808     }
809     p_sys->b_enc = b_encode;
810     p_sys->dll_handle = dll_handle;
811     p_sys->pf_init = pf_init;
812     p_sys->pf_deinit = pf_deinit;
813     p_sys->pf_get_handle = pf_get_handle;
814     p_sys->pf_free_handle = pf_free_handle;
815     p_sys->pf_component_enum = pf_component_enum;
816     p_sys->pf_get_roles_of_component = pf_get_roles_of_component;
817     p_sys->pp_last_event = &p_sys->p_events;
818     vlc_mutex_init (&p_sys->mutex);
819     vlc_cond_init (&p_sys->cond);
820     vlc_mutex_init (&p_sys->lock);
821     vlc_mutex_init (&p_sys->in.fifo.lock);
822     vlc_cond_init (&p_sys->in.fifo.wait);
823     p_sys->in.fifo.offset = offsetof(OMX_BUFFERHEADERTYPE, pOutputPortPrivate) / sizeof(void *);
824     p_sys->in.fifo.pp_last = &p_sys->in.fifo.p_first;
825     p_sys->in.b_direct = false;
826     p_sys->in.b_flushed = true;
827     p_sys->in.p_fmt = &p_dec->fmt_in;
828     vlc_mutex_init (&p_sys->out.fifo.lock);
829     vlc_cond_init (&p_sys->out.fifo.wait);
830     p_sys->out.fifo.offset = offsetof(OMX_BUFFERHEADERTYPE, pInputPortPrivate) / sizeof(void *);
831     p_sys->out.fifo.pp_last = &p_sys->out.fifo.p_first;
832     p_sys->out.b_direct = true;
833     p_sys->out.b_flushed = true;
834     p_sys->out.p_fmt = &p_dec->fmt_out;
835     p_sys->ports = 2;
836     p_sys->p_ports = &p_sys->in;
837
838     msg_Dbg(p_dec, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec->fmt_in.i_codec,
839             (char *)&p_dec->fmt_out.i_codec);
840
841     /* Initialise the OMX core */
842     omx_error = p_sys->pf_init();
843     if(omx_error != OMX_ErrorNone)
844     {
845         msg_Warn( p_this, "OMX_Init failed (%x: %s)", omx_error,
846                   ErrorToString(omx_error) );
847         CloseGeneric(p_this);
848         return VLC_EGENERIC;
849     }
850     p_sys->b_init = true;
851
852     /* Enumerate components and build a list of the one we want to try */
853     if( !CreateComponentsList(p_dec,
854              GetOmxRole(p_sys->b_enc ? p_dec->fmt_out.i_codec :
855                         p_dec->fmt_in.i_codec, p_dec->fmt_in.i_cat,
856                         p_sys->b_enc)) )
857     {
858         msg_Warn( p_this, "couldn't find an omx component for codec %4.4s",
859                   (char *)&p_dec->fmt_in.i_codec );
860         CloseGeneric(p_this);
861         return VLC_EGENERIC;
862     }
863
864     /* Try to load and initialise a component */
865     omx_error = OMX_ErrorUndefined;
866     for(i = 0; i < p_sys->components; i++)
867     {
868 #ifdef __ANDROID__
869         /* ignore OpenCore software codecs */
870         if (!strncmp(p_sys->ppsz_components[i], "OMX.PV.", 7))
871             continue;
872 #endif
873         omx_error = InitialiseComponent(p_dec, p_sys->ppsz_components[i],
874                                         &p_sys->omx_handle);
875         if(omx_error == OMX_ErrorNone) break;
876     }
877     CHECK_ERROR(omx_error, "no component could be initialised" );
878
879     /* Move component to Idle then Executing state */
880     OMX_SendCommand( p_sys->omx_handle, OMX_CommandStateSet, OMX_StateIdle, 0 );
881     CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x)", omx_error );
882
883     /* Allocate omx buffers */
884     for(i = 0; i < p_sys->ports; i++)
885     {
886         OmxPort *p_port = &p_sys->p_ports[i];
887
888         for(j = 0; j < p_port->i_buffers; j++)
889         {
890 #if 0
891 #define ALIGN(x,BLOCKLIGN) (((x) + BLOCKLIGN - 1) & ~(BLOCKLIGN - 1))
892             char *p_buf = malloc(p_port->definition.nBufferSize +
893                                  p_port->definition.nBufferAlignment);
894             p_port->pp_buffers[i] = (void *)ALIGN((uintptr_t)p_buf, p_port->definition.nBufferAlignment);
895 #endif
896
897             if(0 && p_port->b_direct)
898                 omx_error =
899                     OMX_UseBuffer( p_sys->omx_handle, &p_port->pp_buffers[j],
900                                    p_port->i_port_index, 0,
901                                    p_port->definition.nBufferSize, (void*)1);
902             else
903                 omx_error =
904                     OMX_AllocateBuffer( p_sys->omx_handle, &p_port->pp_buffers[j],
905                                         p_port->i_port_index, 0,
906                                         p_port->definition.nBufferSize);
907
908             if(omx_error != OMX_ErrorNone) break;
909             OMX_FIFO_PUT(&p_port->fifo, p_port->pp_buffers[j]);
910         }
911         p_port->i_buffers = j;
912         CHECK_ERROR(omx_error, "OMX_UseBuffer failed (%x, %i, %i)",
913                     omx_error, (int)p_port->i_port_index, j );
914     }
915
916     omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
917     CHECK_ERROR(omx_error, "Wait for Idle failed (%x)", omx_error );
918
919     omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandStateSet,
920                                  OMX_StateExecuting, 0);
921     CHECK_ERROR(omx_error, "OMX_CommandStateSet Executing failed (%x)", omx_error );
922     omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
923     CHECK_ERROR(omx_error, "Wait for Executing failed (%x)", omx_error );
924
925     /* Send codec configuration data */
926     if( p_dec->fmt_in.i_extra )
927     {
928         OMX_FIFO_GET(&p_sys->in.fifo, p_header);
929         p_header->nFilledLen = p_dec->fmt_in.i_extra;
930
931         /* Convert H.264 NAL format to annex b */
932         if( p_sys->i_nal_size_length && !p_sys->in.b_direct )
933         {
934             p_header->nFilledLen = 0;
935             convert_sps_pps( p_dec, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra,
936                              p_header->pBuffer, p_header->nAllocLen,
937                              (uint32_t*) &p_header->nFilledLen, NULL );
938         }
939         else if(p_sys->in.b_direct)
940         {
941             p_header->pOutputPortPrivate = p_header->pBuffer;
942             p_header->pBuffer = p_dec->fmt_in.p_extra;
943         }
944         else
945         {
946             if(p_header->nFilledLen > p_header->nAllocLen)
947             {
948                 msg_Dbg(p_dec, "buffer too small (%i,%i)", (int)p_header->nFilledLen,
949                         (int)p_header->nAllocLen);
950                 p_header->nFilledLen = p_header->nAllocLen;
951             }
952             memcpy(p_header->pBuffer, p_dec->fmt_in.p_extra, p_header->nFilledLen);
953         }
954
955         p_header->nOffset = 0;
956         p_header->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
957         msg_Dbg(p_dec, "sending codec config data %p, %p, %i", p_header,
958                 p_header->pBuffer, (int)p_header->nFilledLen);
959         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
960     }
961
962     /* Get back output port definition */
963     omx_error = GetPortDefinition(p_dec, &p_sys->out, p_sys->out.p_fmt);
964     if(omx_error != OMX_ErrorNone) goto error;
965
966     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->in.i_port_index);
967     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->out.i_port_index);
968
969     if(p_sys->b_error) goto error;
970
971     p_dec->b_need_packetized = true;
972     return VLC_SUCCESS;
973
974  error:
975     CloseGeneric(p_this);
976     return VLC_EGENERIC;
977 }
978
979 /*****************************************************************************
980  * PortReconfigure
981  *****************************************************************************/
982 static OMX_ERRORTYPE PortReconfigure(decoder_t *p_dec, OmxPort *p_port)
983 {
984     decoder_sys_t *p_sys = p_dec->p_sys;
985     OMX_PARAM_PORTDEFINITIONTYPE definition;
986     OMX_BUFFERHEADERTYPE *p_buffer;
987     OMX_ERRORTYPE omx_error;
988     unsigned int i;
989
990     /* Sanity checking */
991     OMX_INIT_STRUCTURE(definition);
992     definition.nPortIndex = p_port->i_port_index;
993     omx_error = OMX_GetParameter(p_dec->p_sys->omx_handle, OMX_IndexParamPortDefinition,
994                                  &definition);
995     if(omx_error != OMX_ErrorNone ||
996        !definition.format.video.nFrameWidth ||
997        !definition.format.video.nFrameHeight )
998         return OMX_ErrorUndefined;
999
1000     omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandPortDisable,
1001                                  p_port->i_port_index, NULL);
1002     CHECK_ERROR(omx_error, "OMX_CommandPortDisable on %i failed (%x)",
1003                 (int)p_port->i_port_index, omx_error );
1004
1005     for(i = 0; i < p_port->i_buffers; i++)
1006     {
1007         OMX_FIFO_GET(&p_port->fifo, p_buffer);
1008         omx_error = OMX_FreeBuffer( p_sys->omx_handle,
1009                                     p_port->i_port_index, p_buffer );
1010
1011         if(omx_error != OMX_ErrorNone) break;
1012     }
1013     CHECK_ERROR(omx_error, "OMX_FreeBuffer failed (%x, %i, %i)",
1014                 omx_error, (int)p_port->i_port_index, i );
1015
1016     omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
1017     CHECK_ERROR(omx_error, "Wait for PortDisable failed (%x)", omx_error );
1018
1019     /* Get the new port definition */
1020     omx_error = GetPortDefinition(p_dec, &p_sys->out, p_sys->out.p_fmt);
1021     if(omx_error != OMX_ErrorNone) goto error;
1022     omx_error = OMX_SetParameter(p_dec->p_sys->omx_handle, OMX_IndexParamPortDefinition,
1023                                  &definition);
1024     CHECK_ERROR(omx_error, "OMX_SetParameter failed (%x : %s)",
1025                 omx_error, ErrorToString(omx_error));
1026
1027     omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandPortEnable,
1028                                  p_port->i_port_index, NULL);
1029     CHECK_ERROR(omx_error, "OMX_CommandPortEnable on %i failed (%x)",
1030                 (int)p_port->i_port_index, omx_error );
1031
1032     if (p_port->definition.nBufferCountActual > p_port->i_buffers) {
1033         free(p_port->pp_buffers);
1034         p_port->pp_buffers = malloc(p_port->definition.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE*));
1035         if(!p_port->pp_buffers)
1036         {
1037             omx_error = OMX_ErrorInsufficientResources;
1038             CHECK_ERROR(omx_error, "memory allocation failed");
1039         }
1040     }
1041     p_port->i_buffers = p_port->definition.nBufferCountActual;
1042     for(i = 0; i < p_port->i_buffers; i++)
1043     {
1044         if(0 && p_port->b_direct)
1045             omx_error =
1046                 OMX_UseBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
1047                                p_port->i_port_index, 0,
1048                                p_port->definition.nBufferSize, (void*)1);
1049         else
1050             omx_error =
1051                 OMX_AllocateBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
1052                                     p_port->i_port_index, 0,
1053                                     p_port->definition.nBufferSize);
1054
1055         if(omx_error != OMX_ErrorNone) break;
1056         OMX_FIFO_PUT(&p_port->fifo, p_port->pp_buffers[i]);
1057     }
1058     p_port->i_buffers = i;
1059     CHECK_ERROR(omx_error, "OMX_UseBuffer failed (%x, %i, %i)",
1060                 omx_error, (int)p_port->i_port_index, i );
1061
1062     omx_error = WaitForSpecificOmxEvent(p_dec, OMX_EventCmdComplete, 0, 0, 0);
1063     CHECK_ERROR(omx_error, "Wait for PortEnable failed (%x)", omx_error );
1064
1065     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->in.i_port_index);
1066     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->out.i_port_index);
1067
1068  error:
1069     return omx_error;
1070 }
1071
1072 /*****************************************************************************
1073  * DecodeVideo: Called to decode one frame
1074  *****************************************************************************/
1075 static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
1076 {
1077     decoder_sys_t *p_sys = p_dec->p_sys;
1078     picture_t *p_pic = NULL, *p_next_pic;
1079     OMX_ERRORTYPE omx_error;
1080     unsigned int i;
1081
1082     OMX_BUFFERHEADERTYPE *p_header;
1083     block_t *p_block;
1084
1085     if( !pp_block || !*pp_block )
1086         return NULL;
1087
1088     p_block = *pp_block;
1089
1090     /* Check for errors from codec */
1091     if(p_sys->b_error)
1092     {
1093         msg_Dbg(p_dec, "error during decoding");
1094         block_Release( p_block );
1095         return 0;
1096     }
1097
1098     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
1099     {
1100         block_Release( p_block );
1101         if(!p_sys->in.b_flushed)
1102         {
1103             msg_Dbg(p_dec, "flushing");
1104             OMX_SendCommand( p_sys->omx_handle, OMX_CommandFlush,
1105                              p_sys->in.definition.nPortIndex, 0 );
1106         }
1107         p_sys->in.b_flushed = true;
1108         return NULL;
1109     }
1110
1111     /* Take care of decoded frames first */
1112     while(!p_pic)
1113     {
1114         OMX_FIFO_PEEK(&p_sys->out.fifo, p_header);
1115         if(!p_header) break; /* No frame available */
1116
1117         if(p_header->nFilledLen)
1118         {
1119             p_pic = p_header->pAppPrivate;
1120             if(!p_pic)
1121             {
1122                 /* We're not in direct rendering mode.
1123                  * Get a new picture and copy the content */
1124                 p_pic = decoder_NewPicture( p_dec );
1125                 if( !p_pic ) break; /* No picture available */
1126
1127                 CopyOmxPicture(p_dec, p_pic, p_header, p_sys->out.definition.format.video.nSliceHeight);
1128             }
1129
1130             p_pic->date = p_header->nTimeStamp;
1131             p_header->nFilledLen = 0;
1132             p_header->pAppPrivate = 0;
1133         }
1134
1135         /* Get a new picture */
1136         if(p_sys->in.b_direct && !p_header->pAppPrivate)
1137         {
1138             p_next_pic = decoder_NewPicture( p_dec );
1139             if(!p_next_pic) break;
1140
1141             OMX_FIFO_GET(&p_sys->out.fifo, p_header);
1142             p_header->pAppPrivate = p_next_pic;
1143             p_header->pInputPortPrivate = p_header->pBuffer;
1144             p_header->pBuffer = p_next_pic->p[0].p_pixels;
1145         }
1146         else
1147         {
1148             OMX_FIFO_GET(&p_sys->out.fifo, p_header);
1149         }
1150
1151 #ifdef OMXIL_EXTRA_DEBUG
1152         msg_Dbg( p_dec, "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
1153 #endif
1154         OMX_FillThisBuffer(p_sys->omx_handle, p_header);
1155     }
1156
1157     /* Send the input buffer to the component */
1158     OMX_FIFO_GET(&p_sys->in.fifo, p_header);
1159
1160     if (p_header && p_header->nFlags & OMX_BUFFERFLAG_EOS)
1161         goto reconfig;
1162
1163     if(p_header)
1164     {
1165         p_header->nFilledLen = p_block->i_buffer;
1166         p_header->nOffset = 0;
1167         p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
1168         p_header->nTimeStamp = p_block->i_dts;
1169
1170         /* In direct mode we pass the input pointer as is.
1171          * Otherwise we memcopy the data */
1172         if(p_sys->in.b_direct)
1173         {
1174             p_header->pOutputPortPrivate = p_header->pBuffer;
1175             p_header->pBuffer = p_block->p_buffer;
1176             p_header->pAppPrivate = p_block;
1177         }
1178         else
1179         {
1180             if(p_header->nFilledLen > p_header->nAllocLen)
1181             {
1182                 msg_Dbg(p_dec, "buffer too small (%i,%i)",
1183                         (int)p_header->nFilledLen, (int)p_header->nAllocLen);
1184                 p_header->nFilledLen = p_header->nAllocLen;
1185             }
1186             memcpy(p_header->pBuffer, p_block->p_buffer, p_header->nFilledLen );
1187             block_Release(p_block);
1188         }
1189
1190         /* Convert H.264 NAL format to annex b */
1191         if( p_sys->i_nal_size_length >= 3 && p_sys->i_nal_size_length <= 4 )
1192         {
1193             /* This only works for NAL sizes 3-4 */
1194             int i_len = p_header->nFilledLen, i;
1195             uint8_t* ptr = p_header->pBuffer;
1196             while( i_len >= p_sys->i_nal_size_length )
1197             {
1198                 uint32_t nal_len = 0;
1199                 for( i = 0; i < p_sys->i_nal_size_length; i++ ) {
1200                     nal_len = (nal_len << 8) | ptr[i];
1201                     ptr[i] = 0;
1202                 }
1203                 ptr[p_sys->i_nal_size_length - 1] = 1;
1204                 if( nal_len > INT_MAX || nal_len > (unsigned int) i_len )
1205                     break;
1206                 ptr   += nal_len + 4;
1207                 i_len -= nal_len + 4;
1208             }
1209         }
1210 #ifdef OMXIL_EXTRA_DEBUG
1211         msg_Dbg( p_dec, "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
1212                  (int)p_header->nFilledLen );
1213 #endif
1214         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
1215         p_sys->in.b_flushed = false;
1216         *pp_block = NULL; /* Avoid being fed the same packet again */
1217     }
1218
1219 reconfig:
1220     /* Handle the PortSettingsChanged events */
1221     for(i = 0; i < p_sys->ports; i++)
1222     {
1223         OmxPort *p_port = &p_sys->p_ports[i];
1224         if(!p_port->b_reconfigure) continue;
1225         p_port->b_reconfigure = 0;
1226         omx_error = PortReconfigure(p_dec, p_port);
1227     }
1228
1229     return p_pic;
1230 }
1231
1232 /*****************************************************************************
1233  * DecodeAudio: Called to decode one frame
1234  *****************************************************************************/
1235 aout_buffer_t *DecodeAudio ( decoder_t *p_dec, block_t **pp_block )
1236 {
1237     decoder_sys_t *p_sys = p_dec->p_sys;
1238     aout_buffer_t *p_buffer = 0;
1239     OMX_BUFFERHEADERTYPE *p_header;
1240     OMX_ERRORTYPE omx_error;
1241     block_t *p_block;
1242     unsigned int i;
1243
1244     if( !pp_block || !*pp_block ) return NULL;
1245
1246     p_block = *pp_block;
1247
1248     /* Check for errors from codec */
1249     if(p_sys->b_error)
1250     {
1251         msg_Dbg(p_dec, "error during decoding");
1252         block_Release( p_block );
1253         return 0;
1254     }
1255
1256     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
1257     {
1258         block_Release( p_block );
1259         date_Set( &p_sys->end_date, 0 );
1260         if(!p_sys->in.b_flushed)
1261         {
1262             msg_Dbg(p_dec, "flushing");
1263             OMX_SendCommand( p_sys->omx_handle, OMX_CommandFlush,
1264                              p_sys->in.definition.nPortIndex, 0 );
1265         }
1266         p_sys->in.b_flushed = true;
1267         return NULL;
1268     }
1269
1270     if( !date_Get( &p_sys->end_date ) )
1271     {
1272         if( !p_block->i_pts )
1273         {
1274             /* We've just started the stream, wait for the first PTS. */
1275             block_Release( p_block );
1276             return NULL;
1277         }
1278         date_Set( &p_sys->end_date, p_block->i_pts );
1279     }
1280
1281     /* Take care of decoded frames first */
1282     while(!p_buffer)
1283     {
1284         unsigned int i_samples;
1285
1286         OMX_FIFO_PEEK(&p_sys->out.fifo, p_header);
1287         if(!p_header) break; /* No frame available */
1288
1289         i_samples = p_header->nFilledLen / p_sys->out.p_fmt->audio.i_channels / 2;
1290         if(i_samples)
1291         {
1292             p_buffer = decoder_NewAudioBuffer( p_dec, i_samples );
1293             if( !p_buffer ) break; /* No audio buffer available */
1294
1295             memcpy( p_buffer->p_buffer, p_header->pBuffer, p_buffer->i_buffer );
1296             p_header->nFilledLen = 0;
1297
1298             if( p_header->nTimeStamp != 0 &&
1299                 p_header->nTimeStamp != date_Get( &p_sys->end_date ) )
1300                 date_Set( &p_sys->end_date, p_header->nTimeStamp );
1301
1302             p_buffer->i_pts = date_Get( &p_sys->end_date );
1303             p_buffer->i_length = date_Increment( &p_sys->end_date, i_samples ) -
1304                 p_buffer->i_pts;
1305         }
1306
1307 #ifdef OMXIL_EXTRA_DEBUG
1308         msg_Dbg( p_dec, "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
1309 #endif
1310         OMX_FIFO_GET(&p_sys->out.fifo, p_header);
1311         OMX_FillThisBuffer(p_sys->omx_handle, p_header);
1312     }
1313
1314
1315     /* Send the input buffer to the component */
1316     OMX_FIFO_GET(&p_sys->in.fifo, p_header);
1317     if(p_header)
1318     {
1319         p_header->nFilledLen = p_block->i_buffer;
1320         p_header->nOffset = 0;
1321         p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
1322         p_header->nTimeStamp = p_block->i_dts;
1323
1324         /* In direct mode we pass the input pointer as is.
1325          * Otherwise we memcopy the data */
1326         if(p_sys->in.b_direct)
1327         {
1328             p_header->pOutputPortPrivate = p_header->pBuffer;
1329             p_header->pBuffer = p_block->p_buffer;
1330             p_header->pAppPrivate = p_block;
1331         }
1332         else
1333         {
1334             if(p_header->nFilledLen > p_header->nAllocLen)
1335             {
1336                 msg_Dbg(p_dec, "buffer too small (%i,%i)",
1337                         (int)p_header->nFilledLen, (int)p_header->nAllocLen);
1338                 p_header->nFilledLen = p_header->nAllocLen;
1339             }
1340             memcpy(p_header->pBuffer, p_block->p_buffer, p_header->nFilledLen );
1341             block_Release(p_block);
1342         }
1343
1344 #ifdef OMXIL_EXTRA_DEBUG
1345         msg_Dbg( p_dec, "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
1346                  (int)p_header->nFilledLen );
1347 #endif
1348         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
1349         p_sys->in.b_flushed = false;
1350         *pp_block = NULL; /* Avoid being fed the same packet again */
1351     }
1352
1353     /* Handle the PortSettingsChanged events */
1354     for(i = 0; i < p_sys->ports; i++)
1355     {
1356         OmxPort *p_port = &p_sys->p_ports[i];
1357         if(!p_port->b_reconfigure) continue;
1358         p_port->b_reconfigure = 0;
1359         omx_error = PortReconfigure(p_dec, p_port);
1360     }
1361
1362     return p_buffer;
1363 }
1364
1365 /*****************************************************************************
1366  * EncodeVideo: Called to encode one frame
1367  *****************************************************************************/
1368 static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
1369 {
1370     decoder_t *p_dec = ( decoder_t *)p_enc;
1371     decoder_sys_t *p_sys = p_dec->p_sys;
1372     OMX_ERRORTYPE omx_error;
1373     unsigned int i;
1374
1375     OMX_BUFFERHEADERTYPE *p_header;
1376     block_t *p_block = 0;
1377
1378     if( !p_pic ) return NULL;
1379
1380     /* Check for errors from codec */
1381     if(p_sys->b_error)
1382     {
1383         msg_Dbg(p_dec, "error during encoding");
1384         return NULL;
1385     }
1386
1387     /* Send the input buffer to the component */
1388     OMX_FIFO_GET(&p_sys->in.fifo, p_header);
1389     if(p_header)
1390     {
1391         /* In direct mode we pass the input pointer as is.
1392          * Otherwise we memcopy the data */
1393         if(p_sys->in.b_direct)
1394         {
1395             p_header->pOutputPortPrivate = p_header->pBuffer;
1396             p_header->pBuffer = p_pic->p[0].p_pixels;
1397         }
1398         else
1399         {
1400             CopyVlcPicture(p_dec, p_header, p_pic);
1401         }
1402
1403         p_header->nFilledLen = p_sys->in.i_frame_size;
1404         p_header->nOffset = 0;
1405         p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
1406         p_header->nTimeStamp = p_pic->date;
1407 #ifdef OMXIL_EXTRA_DEBUG
1408         msg_Dbg( p_dec, "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
1409                  (int)p_header->nFilledLen );
1410 #endif
1411         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
1412         p_sys->in.b_flushed = false;
1413     }
1414
1415     /* Handle the PortSettingsChanged events */
1416     for(i = 0; i < p_sys->ports; i++)
1417     {
1418         OmxPort *p_port = &p_sys->p_ports[i];
1419         if(!p_port->b_reconfigure) continue;
1420         p_port->b_reconfigure = 0;
1421         omx_error = PortReconfigure(p_dec, p_port);
1422     }
1423
1424     /* Wait for the decoded frame */
1425     while(!p_block)
1426     {
1427         OMX_FIFO_GET(&p_sys->out.fifo, p_header);
1428
1429         if(p_header->nFilledLen)
1430         {
1431             if(p_header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
1432             {
1433                 /* TODO: need to store codec config */
1434                 msg_Dbg(p_dec, "received codec config %i", (int)p_header->nFilledLen);
1435             }
1436
1437             p_block = p_header->pAppPrivate;
1438             if(!p_block)
1439             {
1440                 /* We're not in direct rendering mode.
1441                  * Get a new block and copy the content */
1442                 p_block = block_New( p_dec, p_header->nFilledLen );
1443                 memcpy(p_block->p_buffer, p_header->pBuffer, p_header->nFilledLen );
1444             }
1445
1446             p_block->i_buffer = p_header->nFilledLen;
1447             p_block->i_pts = p_block->i_dts = p_header->nTimeStamp;
1448             p_header->nFilledLen = 0;
1449             p_header->pAppPrivate = 0;
1450         }
1451
1452 #ifdef OMXIL_EXTRA_DEBUG
1453         msg_Dbg( p_dec, "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
1454 #endif
1455         OMX_FillThisBuffer(p_sys->omx_handle, p_header);
1456     }
1457
1458     msg_Dbg(p_dec, "done");
1459     return p_block;
1460 }
1461
1462 /*****************************************************************************
1463  * CloseGeneric: omxil decoder destruction
1464  *****************************************************************************/
1465 static void CloseGeneric( vlc_object_t *p_this )
1466 {
1467     decoder_t *p_dec = (decoder_t *)p_this;
1468     decoder_sys_t *p_sys = p_dec->p_sys;
1469
1470     if(p_sys->omx_handle) DeinitialiseComponent(p_dec, p_sys->omx_handle);
1471     if(p_sys->b_init) p_sys->pf_deinit();
1472     dll_close( p_sys->dll_handle );
1473
1474     vlc_mutex_destroy (&p_sys->mutex);
1475     vlc_cond_destroy (&p_sys->cond);
1476     vlc_mutex_destroy (&p_sys->in.fifo.lock);
1477     vlc_cond_destroy (&p_sys->in.fifo.wait);
1478     vlc_mutex_destroy (&p_sys->out.fifo.lock);
1479     vlc_cond_destroy (&p_sys->out.fifo.wait);
1480
1481     free( p_sys );
1482 }
1483
1484 /*****************************************************************************
1485  * OmxEventHandler: 
1486  *****************************************************************************/
1487 static OMX_ERRORTYPE OmxEventHandler( OMX_HANDLETYPE omx_handle,
1488     OMX_PTR app_data, OMX_EVENTTYPE event, OMX_U32 data_1,
1489     OMX_U32 data_2, OMX_PTR event_data )
1490 {
1491     decoder_t *p_dec = (decoder_t *)app_data;
1492     decoder_sys_t *p_sys = p_dec->p_sys;
1493     unsigned int i;
1494     (void)omx_handle;
1495
1496     switch (event)
1497     {
1498     case OMX_EventCmdComplete:
1499         switch ((OMX_STATETYPE)data_1)
1500         {
1501         case OMX_CommandStateSet:
1502             msg_Dbg( p_dec, "OmxEventHandler (%s, %s, %s)", EventToString(event),
1503                      CommandToString(data_1), StateToString(data_2) );
1504             break;
1505
1506         default:
1507             msg_Dbg( p_dec, "OmxEventHandler (%s, %s, %u)", EventToString(event),
1508                      CommandToString(data_1), (unsigned int)data_2 );
1509             break;
1510         }
1511         break;
1512
1513     case OMX_EventError:
1514         msg_Dbg( p_dec, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
1515                  ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
1516                  (const char *)event_data);
1517         //p_sys->b_error = true;
1518         break;
1519
1520     case OMX_EventPortSettingsChanged:
1521         msg_Dbg( p_dec, "OmxEventHandler (%s, %u, %u)", EventToString(event),
1522                  (unsigned int)data_1, (unsigned int)data_2 );
1523         for(i = 0; i < p_sys->ports; i++)
1524             if(p_sys->p_ports[i].definition.eDir == OMX_DirOutput)
1525                 p_sys->p_ports[i].b_reconfigure = true;
1526         memset(&p_sys->sentinel_buffer, 0, sizeof(p_sys->sentinel_buffer));
1527         p_sys->sentinel_buffer.nFlags = OMX_BUFFERFLAG_EOS;
1528         OMX_FIFO_PUT(&p_sys->in.fifo, &p_sys->sentinel_buffer);
1529         break;
1530
1531     default:
1532         msg_Dbg( p_dec, "OmxEventHandler (%s, %u, %u)", EventToString(event),
1533                  (unsigned int)data_1, (unsigned int)data_2 );
1534         break;
1535     }
1536
1537     PostOmxEvent(p_dec, event, data_1, data_2, event_data);
1538     return OMX_ErrorNone;
1539 }
1540
1541 static OMX_ERRORTYPE OmxEmptyBufferDone( OMX_HANDLETYPE omx_handle,
1542     OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header )
1543 {
1544     decoder_t *p_dec = (decoder_t *)app_data;
1545     decoder_sys_t *p_sys = p_dec->p_sys;
1546     (void)omx_handle;
1547
1548 #ifdef OMXIL_EXTRA_DEBUG
1549     msg_Dbg( p_dec, "OmxEmptyBufferDone %p, %p", omx_header, omx_header->pBuffer );
1550 #endif
1551
1552     if(omx_header->pAppPrivate || omx_header->pOutputPortPrivate)
1553     {
1554         block_t *p_block = (block_t *)omx_header->pAppPrivate;
1555         omx_header->pBuffer = omx_header->pOutputPortPrivate;
1556         if(p_block) block_Release(p_block);
1557         omx_header->pAppPrivate = 0;
1558     }
1559     OMX_FIFO_PUT(&p_sys->in.fifo, omx_header);
1560
1561     return OMX_ErrorNone;
1562 }
1563
1564 static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE omx_handle,
1565     OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header )
1566 {
1567     decoder_t *p_dec = (decoder_t *)app_data;
1568     decoder_sys_t *p_sys = p_dec->p_sys;
1569     (void)omx_handle;
1570
1571 #ifdef OMXIL_EXTRA_DEBUG
1572     msg_Dbg( p_dec, "OmxFillBufferDone %p, %p, %i", omx_header, omx_header->pBuffer,
1573              (int)omx_header->nFilledLen );
1574 #endif
1575
1576     if(omx_header->pInputPortPrivate)
1577     {
1578         omx_header->pBuffer = omx_header->pInputPortPrivate;
1579     }
1580     OMX_FIFO_PUT(&p_sys->out.fifo, omx_header);
1581
1582     return OMX_ErrorNone;
1583 }