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