]> git.sesse.net Git - vlc/blob - modules/codec/omxil/omxil.c
nativewindowpriv: add is_hw arg in setup
[vlc] / modules / codec / omxil / omxil.c
1 /*****************************************************************************
2  * omxil.c: Video decoder module making use of OpenMAX IL components.
3  *****************************************************************************
4  * Copyright (C) 2010 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <limits.h>
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_block_helper.h>
37 #include <vlc_cpu.h>
38 #include "../h264_nal.h"
39 #include "../hevc_nal.h"
40
41 #include "omxil.h"
42 #include "omxil_core.h"
43 #include "OMX_Broadcom.h"
44
45 #if defined(USE_IOMX)
46 #include <dlfcn.h>
47 #include <jni.h>
48 #include "android_opaque.h"
49 #endif
50
51 #ifndef NDEBUG
52 # define OMX_DBG(...) msg_Dbg( p_dec, __VA_ARGS__ )
53 #else
54 # define OMX_DBG(...)
55 #endif
56
57 #define SENTINEL_FLAG 0x10000
58
59 /* Defined in the broadcom version of OMX_Index.h */
60 #define OMX_IndexConfigRequestCallback 0x7f000063
61 #define OMX_IndexParamBrcmPixelAspectRatio 0x7f00004d
62 #define OMX_IndexParamBrcmVideoDecodeErrorConcealment 0x7f000080
63
64 /* Defined in the broadcom version of OMX_Core.h */
65 #define OMX_EventParamOrConfigChanged 0x7F000001
66
67 #if defined(USE_IOMX)
68 /* JNI functions to get/set an Android Surface object. */
69 #define THREAD_NAME "omxil"
70 extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
71 extern void jni_detach_thread();
72 extern jobject jni_LockAndGetAndroidJavaSurface();
73 extern void jni_UnlockAndroidSurface();
74 extern void jni_SetAndroidSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
75 extern bool jni_IsVideoPlayerActivityCreated();
76 #endif
77
78 /*****************************************************************************
79  * Local prototypes
80  *****************************************************************************/
81 static int  OpenDecoder( vlc_object_t * );
82 static int  OpenEncoder( vlc_object_t * );
83 static int  OpenGeneric( vlc_object_t *, bool b_encode );
84 static void CloseGeneric( vlc_object_t * );
85
86 static picture_t *DecodeVideo( decoder_t *, block_t ** );
87 static block_t *DecodeAudio ( decoder_t *, block_t ** );
88 static block_t *EncodeVideo( encoder_t *, picture_t * );
89
90 static OMX_ERRORTYPE OmxEventHandler( OMX_HANDLETYPE, OMX_PTR, OMX_EVENTTYPE,
91                                       OMX_U32, OMX_U32, OMX_PTR );
92 static OMX_ERRORTYPE OmxEmptyBufferDone( OMX_HANDLETYPE, OMX_PTR,
93                                          OMX_BUFFERHEADERTYPE * );
94 static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE, OMX_PTR,
95                                         OMX_BUFFERHEADERTYPE * );
96
97 #if defined(USE_IOMX)
98 static void *DequeueThread( void *data );
99 static void DisplayCallback( picture_sys_t* p_picsys );
100 static void UnlockCallback( picture_sys_t* p_picsys );
101 static void HwBuffer_Init( decoder_t *p_dec, OmxPort *p_port );
102 static void HwBuffer_Destroy( decoder_t *p_dec, OmxPort *p_port );
103 static int  HwBuffer_AllocateBuffers( decoder_t *p_dec, OmxPort *p_port );
104 static int  HwBuffer_FreeBuffers( decoder_t *p_dec, OmxPort *p_port );
105 static int  HwBuffer_Start( decoder_t *p_dec, OmxPort *p_port );
106 static int  HwBuffer_Stop( decoder_t *p_dec, OmxPort *p_port );
107 static int  HwBuffer_Join( decoder_t *p_dec, OmxPort *p_port );
108 static int  HwBuffer_GetPic( decoder_t *p_dec, OmxPort *p_port,
109                              picture_t **pp_pic );
110 static void HwBuffer_SetCrop( decoder_t *p_dec, OmxPort *p_port,
111                               OMX_CONFIG_RECTTYPE *p_rect );
112 static void HwBuffer_ChangeState( decoder_t *p_dec, OmxPort *p_port,
113                                   int i_index, int i_state );
114
115 #define HWBUFFER_LOCK() vlc_mutex_lock( get_android_opaque_mutex() )
116 #define HWBUFFER_UNLOCK() vlc_mutex_unlock( get_android_opaque_mutex() )
117 #define HWBUFFER_WAIT(p_port) vlc_cond_wait( &(p_port)->p_hwbuf->wait, \
118                                               get_android_opaque_mutex() )
119 #define HWBUFFER_BROADCAST(p_port) vlc_cond_broadcast( &(p_port)->p_hwbuf->wait )
120
121 #else
122 static inline int HwBuffer_dummy( )
123 {
124     return 0;
125 }
126 #define HwBuffer_Init(p_dec, p_port) do { } while (0)
127 #define HwBuffer_Destroy(p_dec, p_port) do { } while (0)
128 #define HwBuffer_AllocateBuffers(p_dec, p_port) HwBuffer_dummy()
129 #define HwBuffer_FreeBuffers(p_dec, p_port) HwBuffer_dummy()
130 #define HwBuffer_Start(p_dec, p_port) HwBuffer_dummy()
131 #define HwBuffer_Stop(p_dec, p_port) HwBuffer_dummy()
132 #define HwBuffer_Join(p_dec, p_port) HwBuffer_dummy()
133 #define HwBuffer_GetPic(p_dec, p_port, pp_pic) HwBuffer_dummy()
134 #define HwBuffer_SetCrop(p_dec, p_port, p_rect) do { } while (0)
135
136 #define HWBUFFER_LOCK() do { } while (0)
137 #define HWBUFFER_UNLOCK() do { } while (0)
138 #define HWBUFFER_WAIT(p_port) do { } while (0)
139 #define HWBUFFER_BROADCAST(p_port) do { } while (0)
140 #endif
141
142 /*****************************************************************************
143  * Module descriptor
144  *****************************************************************************/
145 #define DIRECTRENDERING_TEXT N_("OMX direct rendering")
146 #define DIRECTRENDERING_LONGTEXT N_(\
147         "Enable OMX direct rendering.")
148
149 #define CFG_PREFIX "omxil-"
150 vlc_module_begin ()
151     set_description( N_("Audio/Video decoder (using OpenMAX IL)") )
152     set_category( CAT_INPUT )
153     set_subcategory( SUBCAT_INPUT_VCODEC )
154     set_section( N_("Decoding") , NULL )
155 #if defined(USE_IOMX)
156     /* For IOMX, don't enable it automatically via priorities,
157      * enable it only via the --codec iomx command line parameter when
158      * wanted. */
159     set_capability( "decoder", 0 )
160     add_bool(CFG_PREFIX "dr", true,
161              DIRECTRENDERING_TEXT, DIRECTRENDERING_LONGTEXT, true)
162 #else
163     set_capability( "decoder", 80 )
164 #endif
165     set_callbacks( OpenDecoder, CloseGeneric )
166
167     add_submodule ()
168     set_section( N_("Encoding") , NULL )
169     set_description( N_("Video encoder (using OpenMAX IL)") )
170     set_capability( "encoder", 0 )
171     set_callbacks( OpenEncoder, CloseGeneric )
172 vlc_module_end ()
173
174 /*****************************************************************************
175  * ImplementationSpecificWorkarounds: place-holder for implementation
176  * specific workarounds
177  *****************************************************************************/
178 static OMX_ERRORTYPE ImplementationSpecificWorkarounds(decoder_t *p_dec,
179     OmxPort *p_port, es_format_t *p_fmt)
180 {
181     decoder_sys_t *p_sys = p_dec->p_sys;
182     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
183     size_t i_profile = 0xFFFF, i_level = 0xFFFF;
184
185     /* Try to find out the profile of the video */
186     if(p_fmt->i_cat == VIDEO_ES && def->eDir == OMX_DirInput &&
187             p_fmt->i_codec == VLC_CODEC_H264)
188         h264_get_profile_level(&p_dec->fmt_in, &i_profile, &i_level, &p_sys->i_nal_size_length);
189
190     if(!strcmp(p_sys->psz_component, "OMX.TI.Video.Decoder"))
191     {
192         if(p_fmt->i_cat == VIDEO_ES && def->eDir == OMX_DirInput &&
193            p_fmt->i_codec == VLC_CODEC_H264 &&
194            (i_profile != 66 || i_level > 30))
195         {
196             msg_Dbg(p_dec, "h264 profile/level not supported (0x%x, 0x%x)",
197                     i_profile, i_level);
198             return OMX_ErrorNotImplemented;
199         }
200
201         if(p_fmt->i_cat == VIDEO_ES && def->eDir == OMX_DirOutput &&
202            p_fmt->i_codec == VLC_CODEC_I420)
203         {
204             /* I420 xvideo is slow on OMAP */
205             def->format.video.eColorFormat = OMX_COLOR_FormatCbYCrY;
206             GetVlcChromaFormat( def->format.video.eColorFormat,
207                                 &p_fmt->i_codec, 0 );
208             GetVlcChromaSizes( p_fmt->i_codec,
209                                def->format.video.nFrameWidth,
210                                def->format.video.nFrameHeight,
211                                &p_port->i_frame_size, &p_port->i_frame_stride,
212                                &p_port->i_frame_stride_chroma_div );
213             def->format.video.nStride = p_port->i_frame_stride;
214             def->nBufferSize = p_port->i_frame_size;
215         }
216     }
217     else if(!strcmp(p_sys->psz_component, "OMX.st.video_encoder"))
218     {
219         if(p_fmt->i_cat == VIDEO_ES)
220         {
221             /* Bellagio's encoder doesn't encode the framerate in Q16 */
222             def->format.video.xFramerate >>= 16;
223         }
224     }
225 #if 0 /* FIXME: doesn't apply for HP Touchpad */
226     else if (!strncmp(p_sys->psz_component, "OMX.qcom.video.decoder.",
227                       strlen("OMX.qcom.video.decoder")))
228     {
229         /* qdsp6 refuses buffer size larger than 450K on input port */
230         if (def->nBufferSize > 450 * 1024)
231         {
232             def->nBufferSize = 450 * 1024;
233             p_port->i_frame_size = def->nBufferSize;
234         }
235     }
236 #endif
237 #ifdef RPI_OMX
238     else if (!strcmp(p_sys->psz_component, "OMX.broadcom.video_decode"))
239     {
240         /* Clear these fields before setting parameters, to allow the codec
241          * fill in what it wants (instead of rejecting whatever happened to
242          * be there. */
243         def->format.video.nStride = def->format.video.nSliceHeight = 0;
244     }
245 #endif
246
247     return OMX_ErrorNone;
248 }
249
250 /*****************************************************************************
251  * SetPortDefinition: set definition of the omx port based on the vlc format
252  *****************************************************************************/
253 static OMX_ERRORTYPE SetPortDefinition(decoder_t *p_dec, OmxPort *p_port,
254                                        es_format_t *p_fmt)
255 {
256     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
257     OMX_ERRORTYPE omx_error;
258
259     omx_error = OMX_GetParameter(p_port->omx_handle,
260                                  OMX_IndexParamPortDefinition, def);
261     CHECK_ERROR(omx_error, "OMX_GetParameter failed (%x : %s)",
262                 omx_error, ErrorToString(omx_error));
263
264     switch(p_fmt->i_cat)
265     {
266     case VIDEO_ES:
267         def->format.video.nFrameWidth = p_fmt->video.i_width;
268         def->format.video.nFrameHeight = p_fmt->video.i_height;
269         if(def->format.video.eCompressionFormat == OMX_VIDEO_CodingUnused)
270             def->format.video.nStride = def->format.video.nFrameWidth;
271         if( p_fmt->video.i_frame_rate > 0 &&
272             p_fmt->video.i_frame_rate_base > 0 )
273             def->format.video.xFramerate = (p_fmt->video.i_frame_rate << 16) /
274                 p_fmt->video.i_frame_rate_base;
275
276         if(def->eDir == OMX_DirInput || p_dec->p_sys->b_enc)
277         {
278             if (def->eDir == OMX_DirInput && p_dec->p_sys->b_enc)
279                 def->nBufferSize = def->format.video.nFrameWidth *
280                   def->format.video.nFrameHeight * 2;
281             p_port->i_frame_size = def->nBufferSize;
282
283             if(!GetOmxVideoFormat(p_fmt->i_codec,
284                                   &def->format.video.eCompressionFormat, 0) )
285             {
286                 if(!GetOmxChromaFormat(p_fmt->i_codec,
287                                        &def->format.video.eColorFormat, 0) )
288                 {
289                     omx_error = OMX_ErrorNotImplemented;
290                     CHECK_ERROR(omx_error, "codec %4.4s doesn't match any OMX format",
291                                 (char *)&p_fmt->i_codec );
292                 }
293                 GetVlcChromaSizes( p_fmt->i_codec,
294                                    def->format.video.nFrameWidth,
295                                    def->format.video.nFrameHeight,
296                                    &p_port->i_frame_size, &p_port->i_frame_stride,
297                                    &p_port->i_frame_stride_chroma_div );
298                 def->format.video.nStride = p_port->i_frame_stride;
299                 def->nBufferSize = p_port->i_frame_size;
300             }
301         }
302         else
303         {
304             if( p_port->p_hwbuf )
305             {
306                 p_fmt->i_codec = VLC_CODEC_ANDROID_OPAQUE;
307                 break;
308             }
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             if (p_port->i_frame_size > def->nBufferSize)
324                 def->nBufferSize = p_port->i_frame_size;
325         }
326         break;
327
328     case AUDIO_ES:
329         p_port->i_frame_size = def->nBufferSize;
330         if(def->eDir == OMX_DirInput)
331         {
332             if(!GetOmxAudioFormat(p_fmt->i_codec,
333                                   &def->format.audio.eEncoding, 0) )
334             {
335                 omx_error = OMX_ErrorNotImplemented;
336                 CHECK_ERROR(omx_error, "codec %4.4s doesn't match any OMX format",
337                             (char *)&p_fmt->i_codec );
338             }
339         }
340         else
341         {
342             if( !OmxToVlcAudioFormat(def->format.audio.eEncoding,
343                                    &p_fmt->i_codec, 0 ) )
344             {
345                 omx_error = OMX_ErrorNotImplemented;
346                 CHECK_ERROR(omx_error, "OMX audio encoding %i not supported",
347                             (int)def->format.audio.eEncoding );
348             }
349         }
350         break;
351
352     default: return OMX_ErrorNotImplemented;
353     }
354
355     omx_error = ImplementationSpecificWorkarounds(p_dec, p_port, p_fmt);
356     CHECK_ERROR(omx_error, "ImplementationSpecificWorkarounds failed (%x : %s)",
357                 omx_error, ErrorToString(omx_error));
358
359     omx_error = OMX_SetParameter(p_port->omx_handle,
360                                  OMX_IndexParamPortDefinition, def);
361     CHECK_ERROR(omx_error, "OMX_SetParameter failed (%x : %s)",
362                 omx_error, ErrorToString(omx_error));
363
364     omx_error = OMX_GetParameter(p_port->omx_handle,
365                                  OMX_IndexParamPortDefinition, def);
366     CHECK_ERROR(omx_error, "OMX_GetParameter failed (%x : %s)",
367                 omx_error, ErrorToString(omx_error));
368
369     if(p_port->i_frame_size > def->nBufferSize)
370         def->nBufferSize = p_port->i_frame_size;
371     p_port->i_frame_size = def->nBufferSize;
372
373     /* Deal with audio params */
374     if(p_fmt->i_cat == AUDIO_ES)
375     {
376         omx_error = SetAudioParameters(p_port->omx_handle,
377                                        &p_port->format_param, def->nPortIndex,
378                                        def->format.audio.eEncoding,
379                                        p_fmt->i_codec,
380                                        p_fmt->audio.i_channels,
381                                        p_fmt->audio.i_rate,
382                                        p_fmt->i_bitrate,
383                                        p_fmt->audio.i_bitspersample,
384                                        p_fmt->audio.i_blockalign);
385         if (def->eDir == OMX_DirInput) {
386             CHECK_ERROR(omx_error, "SetAudioParameters failed (%x : %s)",
387                         omx_error, ErrorToString(omx_error));
388         } else if (omx_error != OMX_ErrorNone) {
389             msg_Warn(p_dec, "SetAudioParameters failed (%x : %s) on output port",
390                      omx_error, ErrorToString(omx_error));
391             omx_error = OMX_ErrorNone;
392         }
393     }
394     if (!strcmp(p_dec->p_sys->psz_component, "OMX.TI.DUCATI1.VIDEO.DECODER") &&
395                 def->eDir == OMX_DirOutput && !p_port->p_hwbuf)
396     {
397         /* When setting the output buffer size above, the decoder actually
398          * sets the buffer size to a lower value than what was chosen. If
399          * we try to allocate buffers of this size, it fails. Thus, forcibly
400          * use a larger buffer size. */
401         def->nBufferSize *= 2;
402     }
403
404  error:
405     return omx_error;
406 }
407
408
409 /*****************************************************************************
410  * UpdatePixelAspect: Update vlc pixel aspect based on the aspect reported on
411  * the omx port - NOTE: Broadcom specific
412  *****************************************************************************/
413 static OMX_ERRORTYPE UpdatePixelAspect(decoder_t *p_dec)
414 {
415     decoder_sys_t *p_sys = p_dec->p_sys;
416     OMX_CONFIG_POINTTYPE pixel_aspect;
417     OMX_INIT_STRUCTURE(pixel_aspect);
418     OMX_ERRORTYPE omx_err;
419
420     if (strncmp(p_sys->psz_component, "OMX.broadcom.", 13))
421         return OMX_ErrorNotImplemented;
422
423     pixel_aspect.nPortIndex = p_sys->out.i_port_index;
424     omx_err = OMX_GetParameter(p_sys->omx_handle,
425             OMX_IndexParamBrcmPixelAspectRatio, &pixel_aspect);
426     if (omx_err != OMX_ErrorNone) {
427         msg_Warn(p_dec, "Failed to retrieve aspect ratio");
428     } else {
429         p_dec->fmt_out.video.i_sar_num = pixel_aspect.nX;
430         p_dec->fmt_out.video.i_sar_den = pixel_aspect.nY;
431     }
432
433     return omx_err;
434 }
435
436 /*****************************************************************************
437  * AllocateBuffers: Allocate Omx buffers
438  *****************************************************************************/
439 static OMX_ERRORTYPE AllocateBuffers(decoder_t *p_dec, OmxPort *p_port)
440 {
441     decoder_sys_t *p_sys = p_dec->p_sys;
442     OMX_ERRORTYPE omx_error = OMX_ErrorUndefined;
443     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
444     unsigned int i = 0;
445
446     OMX_DBG( "AllocateBuffers(%d)", def->eDir );
447
448     p_port->i_buffers = p_port->definition.nBufferCountActual;
449
450     p_port->pp_buffers = calloc(p_port->i_buffers, sizeof(OMX_BUFFERHEADERTYPE*));
451     if( !p_port->pp_buffers )
452     {
453         p_port->i_buffers = 0;
454         return OMX_ErrorInsufficientResources;
455     }
456
457     for(i = 0; i < p_port->i_buffers; i++)
458     {
459 #if 0
460 #define ALIGN(x,BLOCKLIGN) (((x) + BLOCKLIGN - 1) & ~(BLOCKLIGN - 1))
461         char *p_buf = malloc(p_port->definition.nBufferSize +
462                              p_port->definition.nBufferAlignment);
463         p_port->pp_buffers[i] = (void *)ALIGN((uintptr_t)p_buf, p_port->definition.nBufferAlignment);
464 #endif
465
466         if( p_port->p_hwbuf )
467         {
468             omx_error =
469                 OMX_UseBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
470                                p_port->i_port_index, 0,
471                                p_port->definition.nBufferSize,
472                                p_port->p_hwbuf->pp_handles[i] );
473             OMX_DBG( "OMX_UseBuffer(%d) %p, %p", def->eDir,
474                      p_port->pp_buffers[i], p_port->p_hwbuf->pp_handles[i] );
475         }
476         else if( p_port->b_direct )
477         {
478             omx_error =
479                 OMX_UseBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
480                                p_port->i_port_index, 0,
481                                p_port->definition.nBufferSize, (void*)1);
482             OMX_DBG( "OMX_UseBuffer(%d) %p, %p", def->eDir,
483                      p_port->pp_buffers[i], p_port->pp_buffers[i] ?
484                      p_port->pp_buffers[i]->pBuffer : NULL );
485         }
486         else
487         {
488             omx_error =
489                 OMX_AllocateBuffer( p_sys->omx_handle, &p_port->pp_buffers[i],
490                                     p_port->i_port_index, 0,
491                                     p_port->definition.nBufferSize);
492             OMX_DBG( "OMX_AllocateBuffer(%d) %p, %p", def->eDir,
493                      p_port->pp_buffers[i], p_port->pp_buffers[i] ? 
494                      p_port->pp_buffers[i]->pBuffer : NULL );
495         }
496
497         if(omx_error != OMX_ErrorNone)
498         {
499             p_port->i_buffers = i;
500             break;
501         }
502         if( !p_port->p_hwbuf )
503             OMX_FIFO_PUT(&p_port->fifo, p_port->pp_buffers[i]);
504     }
505
506     CHECK_ERROR(omx_error, "AllocateBuffers failed (%x, %i)",
507                 omx_error, (int)p_port->i_port_index );
508
509
510     OMX_DBG( "AllocateBuffers(%d)::done", def->eDir );
511 error:
512     return omx_error;
513 }
514
515 /*****************************************************************************
516  * FreeBuffers: Free Omx buffers
517  *****************************************************************************/
518 static OMX_ERRORTYPE FreeBuffers(decoder_t *p_dec, OmxPort *p_port)
519 {
520     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
521     OMX_ERRORTYPE omx_error = OMX_ErrorNone;
522     OMX_BUFFERHEADERTYPE *p_buffer;
523     unsigned int i, i_wait_buffers;
524
525     /* Normally, all buffers are in the port fifo, or given to the codec that
526      * will return them when disabling the port or changing state, therefore we
527      * normally wait for all buffers. For IOMX direct rendering (HwBuffer),
528      * only a few buffers are given to the codec at a time, thus we can only
529      * wait for that many buffers. And after that, we can still free all OMX
530      * buffers since we either got some of them returned via OMX_FIFO_GET, or
531      * never passed them to the codec at all. */
532     if( p_port->p_hwbuf )
533         i_wait_buffers = p_port->p_hwbuf->i_owned;
534     else
535         i_wait_buffers = p_port->i_buffers;
536
537     OMX_DBG( "FreeBuffers(%d), waiting for %u buffers", def->eDir,
538              i_wait_buffers);
539
540     for(i = 0; i < i_wait_buffers; i++)
541     {
542         OMX_FIFO_GET(&p_port->fifo, p_buffer);
543         if (p_buffer->nFlags & SENTINEL_FLAG) {
544             free(p_buffer);
545             i--;
546             continue;
547         }
548     }
549
550     for(i = 0; i < p_port->i_buffers; i++)
551     {
552         p_buffer = p_port->pp_buffers[i];
553         if( p_buffer )
554         {
555             if (p_buffer->pAppPrivate != NULL)
556                 picture_Release( p_buffer->pAppPrivate );
557
558             omx_error = OMX_FreeBuffer( p_port->omx_handle,
559                                         p_port->i_port_index, p_buffer );
560             OMX_DBG( "OMX_FreeBuffer(%d) %p, %p", def->eDir,
561                      p_buffer, p_buffer->pBuffer );
562
563             if(omx_error != OMX_ErrorNone) break;
564         }
565     }
566
567     if( omx_error != OMX_ErrorNone )
568        msg_Err( p_dec, "OMX_FreeBuffer failed (%x, %i, %i)",
569                 omx_error, (int)p_port->i_port_index, i );
570
571     p_port->i_buffers = 0;
572     free( p_port->pp_buffers );
573     p_port->pp_buffers = NULL;
574
575     OMX_DBG( "FreeBuffers(%d)::done", def->eDir );
576
577     return omx_error;
578 }
579
580 /*****************************************************************************
581  * GetPortDefinition: set vlc format based on the definition of the omx port
582  *****************************************************************************/
583 static OMX_ERRORTYPE GetPortDefinition(decoder_t *p_dec, OmxPort *p_port,
584                                        es_format_t *p_fmt)
585 {
586     decoder_sys_t *p_sys = p_dec->p_sys;
587     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
588     OMX_ERRORTYPE omx_error;
589     OMX_CONFIG_RECTTYPE crop_rect;
590
591     omx_error = OMX_GetParameter(p_port->omx_handle,
592                                  OMX_IndexParamPortDefinition, def);
593     CHECK_ERROR(omx_error, "OMX_GetParameter failed (%x : %s)",
594                 omx_error, ErrorToString(omx_error));
595
596     switch(p_fmt->i_cat)
597     {
598     case VIDEO_ES:
599         p_fmt->video.i_width = def->format.video.nFrameWidth;
600         p_fmt->video.i_visible_width = def->format.video.nFrameWidth;
601         p_fmt->video.i_height = def->format.video.nFrameHeight;
602         p_fmt->video.i_visible_height = def->format.video.nFrameHeight;
603         p_fmt->video.i_frame_rate = p_dec->fmt_in.video.i_frame_rate;
604         p_fmt->video.i_frame_rate_base = p_dec->fmt_in.video.i_frame_rate_base;
605
606         OMX_INIT_STRUCTURE(crop_rect);
607         crop_rect.nPortIndex = def->nPortIndex;
608         omx_error = OMX_GetConfig(p_port->omx_handle, OMX_IndexConfigCommonOutputCrop, &crop_rect);
609         if (omx_error == OMX_ErrorNone)
610         {
611             if (!def->format.video.nSliceHeight)
612                 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
613             if (!def->format.video.nStride)
614                 def->format.video.nStride = def->format.video.nFrameWidth;
615             p_fmt->video.i_width = crop_rect.nWidth;
616             p_fmt->video.i_visible_width = crop_rect.nWidth;
617             p_fmt->video.i_height = crop_rect.nHeight;
618             p_fmt->video.i_visible_height = crop_rect.nHeight;
619             if (def->format.video.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar)
620                 def->format.video.nSliceHeight -= crop_rect.nTop/2;
621
622             if( p_port->p_hwbuf )
623                 HwBuffer_SetCrop( p_dec, p_port, &crop_rect );
624         }
625         else
626         {
627             /* Don't pass the error back to the caller, this isn't mandatory */
628             omx_error = OMX_ErrorNone;
629         }
630
631         if( p_port->p_hwbuf )
632         {
633             UpdatePixelAspect(p_dec);
634             break;
635         }
636         /* Hack: Nexus One (stock firmware with binary OMX driver blob)
637          * claims to output 420Planar even though it in in practice is
638          * NV21. */
639         if(def->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar &&
640            !strncmp(p_sys->psz_component, "OMX.qcom.video.decoder",
641                     strlen("OMX.qcom.video.decoder")))
642             def->format.video.eColorFormat = OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
643
644         if (IgnoreOmxDecoderPadding(p_sys->psz_component)) {
645             def->format.video.nSliceHeight = 0;
646             def->format.video.nStride = p_fmt->video.i_width;
647         }
648
649         if(!GetVlcVideoFormat( def->format.video.eCompressionFormat,
650                                &p_fmt->i_codec, 0 ) )
651         {
652             if( !GetVlcChromaFormat( def->format.video.eColorFormat,
653                                      &p_fmt->i_codec, 0 ) )
654             {
655                 omx_error = OMX_ErrorNotImplemented;
656                 CHECK_ERROR(omx_error, "OMX color format %i not supported",
657                             (int)def->format.video.eColorFormat );
658             }
659             GetVlcChromaSizes( p_fmt->i_codec,
660                                def->format.video.nFrameWidth,
661                                def->format.video.nFrameHeight,
662                                &p_port->i_frame_size, &p_port->i_frame_stride,
663                                &p_port->i_frame_stride_chroma_div );
664         }
665         if(p_port->i_frame_size > def->nBufferSize)
666             def->nBufferSize = p_port->i_frame_size;
667         p_port->i_frame_size = def->nBufferSize;
668 #if 0
669         if((int)p_port->i_frame_stride > def->format.video.nStride)
670             def->format.video.nStride = p_port->i_frame_stride;
671 #endif
672         p_port->i_frame_stride = def->format.video.nStride;
673         UpdatePixelAspect(p_dec);
674         break;
675
676     case AUDIO_ES:
677         if( !OmxToVlcAudioFormat( def->format.audio.eEncoding,
678                                 &p_fmt->i_codec, 0 ) )
679         {
680             omx_error = OMX_ErrorNotImplemented;
681             CHECK_ERROR(omx_error, "OMX audio format %i not supported",
682                         (int)def->format.audio.eEncoding );
683         }
684
685         omx_error = GetAudioParameters(p_port->omx_handle,
686                                        &p_port->format_param, def->nPortIndex,
687                                        def->format.audio.eEncoding,
688                                        &p_fmt->audio.i_channels,
689                                        &p_fmt->audio.i_rate,
690                                        &p_fmt->i_bitrate,
691                                        &p_fmt->audio.i_bitspersample,
692                                        &p_fmt->audio.i_blockalign);
693         CHECK_ERROR(omx_error, "GetAudioParameters failed (%x : %s)",
694                     omx_error, ErrorToString(omx_error));
695
696         if(p_fmt->audio.i_channels < 9)
697         {
698             static const int pi_channels_maps[9] =
699             {
700                 0, AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
701                 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
702                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
703                 | AOUT_CHAN_REARRIGHT,
704                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
705                 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
706                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
707                 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
708                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
709                 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
710                 | AOUT_CHAN_MIDDLERIGHT,
711                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
712                 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
713                 | AOUT_CHAN_LFE
714             };
715             p_fmt->audio.i_physical_channels =
716                 p_fmt->audio.i_original_channels =
717                     pi_channels_maps[p_fmt->audio.i_channels];
718         }
719
720         date_Init( &p_dec->p_sys->end_date, p_fmt->audio.i_rate, 1 );
721
722         break;
723
724     default: return OMX_ErrorNotImplemented;
725     }
726
727  error:
728     return omx_error;
729 }
730
731 /*****************************************************************************
732  * DeinitialiseComponent: Deinitialise and unload an OMX component
733  *****************************************************************************/
734 static OMX_ERRORTYPE DeinitialiseComponent(decoder_t *p_dec,
735                                            OMX_HANDLETYPE omx_handle)
736 {
737     decoder_sys_t *p_sys = p_dec->p_sys;
738     OMX_BUFFERHEADERTYPE *p_buffer;
739     OMX_ERRORTYPE omx_error;
740     OMX_STATETYPE state;
741     unsigned int i;
742
743     if(!omx_handle) return OMX_ErrorNone;
744
745     omx_error = OMX_GetState(omx_handle, &state);
746     CHECK_ERROR(omx_error, "OMX_GetState failed (%x)", omx_error );
747
748     if( p_sys->out.p_hwbuf && HwBuffer_Stop( p_dec, &p_sys->out ) != 0 )
749         msg_Warn( p_dec, "HwBuffer_Stop failed" );
750
751     if(state == OMX_StateExecuting)
752     {
753         omx_error = OMX_SendCommand( omx_handle, OMX_CommandStateSet,
754                                      OMX_StateIdle, 0 );
755         CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x)", omx_error );
756         while (1) {
757             OMX_U32 cmd, state;
758             omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, &cmd, &state, 0);
759             CHECK_ERROR(omx_error, "Wait for Idle failed (%x)", omx_error );
760             // The event queue can contain other OMX_EventCmdComplete items,
761             // such as for OMX_CommandFlush
762             if (cmd == OMX_CommandStateSet && state == OMX_StateIdle)
763                 break;
764         }
765     }
766
767     omx_error = OMX_GetState(omx_handle, &state);
768     CHECK_ERROR(omx_error, "OMX_GetState failed (%x)", omx_error );
769
770     if(state == OMX_StateIdle)
771     {
772         omx_error = OMX_SendCommand( omx_handle, OMX_CommandStateSet,
773                                      OMX_StateLoaded, 0 );
774         CHECK_ERROR(omx_error, "OMX_CommandStateSet Loaded failed (%x)", omx_error );
775
776         for(i = 0; i < p_sys->ports; i++)
777         {
778             OmxPort *p_port = &p_sys->p_ports[i];
779
780             omx_error = FreeBuffers( p_dec, p_port );
781             CHECK_ERROR(omx_error, "FreeBuffers failed (%x, %i)",
782                         omx_error, (int)p_port->i_port_index );
783             if( p_port->p_hwbuf )
784             {
785                 HwBuffer_FreeBuffers( p_dec, p_port );
786                 HwBuffer_Join( p_dec, p_port );
787             }
788         }
789
790         omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
791         CHECK_ERROR(omx_error, "Wait for Loaded failed (%x)", omx_error );
792     }
793
794  error:
795     for(i = 0; i < p_sys->ports; i++)
796     {
797         OmxPort *p_port = &p_sys->p_ports[i];
798         free(p_port->pp_buffers);
799         p_port->pp_buffers = 0;
800
801         while (1) {
802             OMX_FIFO_PEEK(&p_port->fifo, p_buffer);
803             if (!p_buffer) break;
804
805             OMX_FIFO_GET(&p_port->fifo, p_buffer);
806             if (p_buffer->nFlags & SENTINEL_FLAG) {
807                 free(p_buffer);
808                 continue;
809             }
810             msg_Warn( p_dec, "Stray buffer left in fifo, %p", p_buffer );
811         }
812         HwBuffer_Destroy( p_dec, p_port );
813     }
814     omx_error = pf_free_handle( omx_handle );
815     return omx_error;
816 }
817
818 /*****************************************************************************
819  * InitialiseComponent: Load and initialise an OMX component
820  *****************************************************************************/
821 static OMX_ERRORTYPE InitialiseComponent(decoder_t *p_dec,
822     OMX_STRING psz_component, OMX_HANDLETYPE *p_handle)
823 {
824     static OMX_CALLBACKTYPE callbacks =
825         { OmxEventHandler, OmxEmptyBufferDone, OmxFillBufferDone };
826     decoder_sys_t *p_sys = p_dec->p_sys;
827     OMX_HANDLETYPE omx_handle;
828     OMX_ERRORTYPE omx_error;
829     unsigned int i;
830     OMX_U8 psz_role[OMX_MAX_STRINGNAME_SIZE];
831     OMX_PARAM_COMPONENTROLETYPE role;
832     OMX_PARAM_PORTDEFINITIONTYPE definition;
833     OMX_PORT_PARAM_TYPE param;
834
835     /* Load component */
836     omx_error = pf_get_handle( &omx_handle, psz_component, p_dec, &callbacks );
837     if(omx_error != OMX_ErrorNone)
838     {
839         msg_Warn( p_dec, "OMX_GetHandle(%s) failed (%x: %s)", psz_component,
840                   omx_error, ErrorToString(omx_error) );
841         return omx_error;
842     }
843     strncpy(p_sys->psz_component, psz_component, OMX_MAX_STRINGNAME_SIZE-1);
844
845     omx_error = OMX_ComponentRoleEnum(omx_handle, psz_role, 0);
846     if(omx_error == OMX_ErrorNone)
847         msg_Dbg(p_dec, "loaded component %s of role %s", psz_component, psz_role);
848     else
849         msg_Dbg(p_dec, "loaded component %s", psz_component);
850     PrintOmx(p_dec, omx_handle, OMX_ALL);
851
852     /* Set component role */
853     OMX_INIT_STRUCTURE(role);
854     strcpy((char*)role.cRole,
855            GetOmxRole(p_sys->b_enc ? p_dec->fmt_out.i_codec : p_dec->fmt_in.i_codec,
856                       p_dec->fmt_in.i_cat, p_sys->b_enc));
857
858     omx_error = OMX_SetParameter(omx_handle, OMX_IndexParamStandardComponentRole,
859                                  &role);
860     omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamStandardComponentRole,
861                                  &role);
862     if(omx_error == OMX_ErrorNone)
863         msg_Dbg(p_dec, "component standard role set to %s", role.cRole);
864
865     /* Find the input / output ports */
866     OMX_INIT_STRUCTURE(param);
867     OMX_INIT_STRUCTURE(definition);
868     omx_error = OMX_GetParameter(omx_handle, p_dec->fmt_in.i_cat == VIDEO_ES ?
869                                  OMX_IndexParamVideoInit : OMX_IndexParamAudioInit, &param);
870     if(omx_error != OMX_ErrorNone) {
871 #ifdef __ANDROID__
872         param.nPorts = 2;
873         param.nStartPortNumber = 0;
874 #else
875         param.nPorts = 0;
876 #endif
877     }
878
879     for(i = 0; i < param.nPorts; i++)
880     {
881         OmxPort *p_port;
882
883         /* Get port definition */
884         definition.nPortIndex = param.nStartPortNumber + i;
885         omx_error = OMX_GetParameter(omx_handle, OMX_IndexParamPortDefinition,
886                                      &definition);
887         if(omx_error != OMX_ErrorNone) continue;
888
889         if(definition.eDir == OMX_DirInput) p_port = &p_sys->in;
890         else  p_port = &p_sys->out;
891
892         p_port->b_valid = true;
893         p_port->i_port_index = definition.nPortIndex;
894         p_port->definition = definition;
895         p_port->omx_handle = omx_handle;
896         HwBuffer_Init( p_dec, p_port );
897     }
898
899     if(!p_sys->in.b_valid || !p_sys->out.b_valid)
900     {
901         omx_error = OMX_ErrorInvalidComponent;
902         CHECK_ERROR(omx_error, "couldn't find an input and output port");
903     }
904
905     if( !p_sys->out.p_hwbuf && !strncmp(p_sys->psz_component, "OMX.SEC.", 8) &&
906        p_dec->fmt_in.i_cat == VIDEO_ES )
907     {
908         OMX_INDEXTYPE index;
909         omx_error = OMX_GetExtensionIndex(omx_handle, (OMX_STRING) "OMX.SEC.index.ThumbnailMode", &index);
910         if(omx_error == OMX_ErrorNone)
911         {
912             OMX_BOOL enable = OMX_TRUE;
913             omx_error = OMX_SetConfig(omx_handle, index, &enable);
914             CHECK_ERROR(omx_error, "Unable to set ThumbnailMode");
915         } else {
916             OMX_BOOL enable = OMX_TRUE;
917             /* Needed on Samsung Galaxy S II */
918             omx_error = OMX_SetConfig(omx_handle, OMX_IndexVendorSetYUV420pMode, &enable);
919             if (omx_error == OMX_ErrorNone)
920                 msg_Dbg(p_dec, "Set OMX_IndexVendorSetYUV420pMode successfully");
921             else
922                 msg_Dbg(p_dec, "Unable to set OMX_IndexVendorSetYUV420pMode: %x", omx_error);
923         }
924     }
925
926     if(!strncmp(p_sys->psz_component, "OMX.broadcom.", 13))
927     {
928         OMX_CONFIG_REQUESTCALLBACKTYPE notifications;
929         OMX_INIT_STRUCTURE(notifications);
930
931         notifications.nPortIndex = p_sys->out.i_port_index;
932         notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio;
933         notifications.bEnable = OMX_TRUE;
934
935         omx_error = OMX_SetParameter(omx_handle,
936                 OMX_IndexConfigRequestCallback, &notifications);
937         if (omx_error == OMX_ErrorNone) {
938             msg_Dbg(p_dec, "Enabled aspect ratio notifications");
939             p_sys->b_aspect_ratio_handled = true;
940         } else
941             msg_Dbg(p_dec, "Could not enable aspect ratio notifications");
942     }
943
944     /* Set port definitions */
945     for(i = 0; i < p_sys->ports; i++)
946     {
947         omx_error = SetPortDefinition(p_dec, &p_sys->p_ports[i],
948                                       p_sys->p_ports[i].p_fmt);
949         if(omx_error != OMX_ErrorNone) goto error;
950     }
951
952     if(!strncmp(p_sys->psz_component, "OMX.broadcom.", 13) &&
953         p_sys->in.p_fmt->i_codec == VLC_CODEC_H264)
954     {
955         OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam;
956         OMX_INIT_STRUCTURE(concanParam);
957         concanParam.bStartWithValidFrame = OMX_FALSE;
958
959         omx_error = OMX_SetParameter(omx_handle,
960                 OMX_IndexParamBrcmVideoDecodeErrorConcealment, &concanParam);
961         if (omx_error == OMX_ErrorNone)
962             msg_Dbg(p_dec, "StartWithValidFrame disabled.");
963         else
964             msg_Dbg(p_dec, "Could not disable StartWithValidFrame.");
965     }
966
967     /* Allocate our array for the omx buffers and enable ports */
968     for(i = 0; i < p_sys->ports; i++)
969     {
970         OmxPort *p_port = &p_sys->p_ports[i];
971
972         /* Enable port */
973         if(!p_port->definition.bEnabled)
974         {
975             omx_error = OMX_SendCommand( omx_handle, OMX_CommandPortEnable,
976                                          p_port->i_port_index, NULL);
977             CHECK_ERROR(omx_error, "OMX_CommandPortEnable on %i failed (%x)",
978                         (int)p_port->i_port_index, omx_error );
979             omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
980             CHECK_ERROR(omx_error, "Wait for PortEnable on %i failed (%x)",
981                         (int)p_port->i_port_index, omx_error );
982         }
983     }
984
985     *p_handle = omx_handle;
986     return OMX_ErrorNone;
987
988  error:
989     DeinitialiseComponent(p_dec, omx_handle);
990     *p_handle = 0;
991     return omx_error;
992 }
993
994 /*****************************************************************************
995  * OpenDecoder: Create the decoder instance
996  *****************************************************************************/
997 static int OpenDecoder( vlc_object_t *p_this )
998 {
999     decoder_t *p_dec = (decoder_t*)p_this;
1000     int status;
1001
1002 #ifdef __ANDROID__
1003     if( p_dec->fmt_in.i_cat == AUDIO_ES )
1004         return VLC_EGENERIC;
1005 #endif
1006
1007     if( 0 || !GetOmxRole(p_dec->fmt_in.i_codec, p_dec->fmt_in.i_cat, false) )
1008         return VLC_EGENERIC;
1009
1010     status = OpenGeneric( p_this, false );
1011     if(status != VLC_SUCCESS) return status;
1012
1013     p_dec->pf_decode_video = DecodeVideo;
1014     p_dec->pf_decode_audio = DecodeAudio;
1015
1016     return VLC_SUCCESS;
1017 }
1018
1019 /*****************************************************************************
1020  * OpenEncoder: Create the encoder instance
1021  *****************************************************************************/
1022 static int OpenEncoder( vlc_object_t *p_this )
1023 {
1024     encoder_t *p_enc = (encoder_t*)p_this;
1025     int status;
1026
1027     if( !GetOmxRole(p_enc->fmt_out.i_codec, p_enc->fmt_in.i_cat, true) )
1028         return VLC_EGENERIC;
1029
1030     status = OpenGeneric( p_this, true );
1031     if(status != VLC_SUCCESS) return status;
1032
1033     p_enc->pf_encode_video = EncodeVideo;
1034
1035     return VLC_SUCCESS;
1036 }
1037
1038 /*****************************************************************************
1039  * OpenGeneric: Create the generic decoder/encoder instance
1040  *****************************************************************************/
1041 static int OpenGeneric( vlc_object_t *p_this, bool b_encode )
1042 {
1043     decoder_t *p_dec = (decoder_t*)p_this;
1044     decoder_sys_t *p_sys;
1045     OMX_ERRORTYPE omx_error;
1046     OMX_BUFFERHEADERTYPE *p_header;
1047     unsigned int i;
1048
1049     if (InitOmxCore(p_this) != VLC_SUCCESS) {
1050         return VLC_EGENERIC;
1051     }
1052
1053     /* Allocate the memory needed to store the decoder's structure */
1054     if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL )
1055     {
1056         DeinitOmxCore();
1057         return VLC_ENOMEM;
1058     }
1059
1060     /* Initialise the thread properties */
1061     if(!b_encode)
1062     {
1063         p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
1064         p_dec->fmt_out.video = p_dec->fmt_in.video;
1065         p_dec->fmt_out.audio = p_dec->fmt_in.audio;
1066         p_dec->fmt_out.i_codec = 0;
1067
1068         /* set default aspect of 1, if parser did not set it */
1069         if (p_dec->fmt_out.video.i_sar_num == 0)
1070             p_dec->fmt_out.video.i_sar_num = 1;
1071         if (p_dec->fmt_out.video.i_sar_den == 0)
1072             p_dec->fmt_out.video.i_sar_den = 1;
1073     }
1074     p_sys->b_enc = b_encode;
1075     InitOmxEventQueue(&p_sys->event_queue);
1076     OMX_FIFO_INIT (&p_sys->in.fifo, pOutputPortPrivate );
1077     p_sys->in.b_direct = false;
1078     p_sys->in.b_flushed = true;
1079     p_sys->in.p_fmt = &p_dec->fmt_in;
1080     OMX_FIFO_INIT (&p_sys->out.fifo, pInputPortPrivate );
1081 #if defined(USE_IOMX)
1082     p_sys->out.b_direct = jni_IsVideoPlayerActivityCreated() && var_InheritBool(p_dec, CFG_PREFIX "dr");
1083 #else
1084     p_sys->out.b_direct = false;
1085 #endif
1086     p_sys->out.b_flushed = true;
1087     p_sys->out.p_fmt = &p_dec->fmt_out;
1088     p_sys->ports = 2;
1089     p_sys->p_ports = &p_sys->in;
1090     p_sys->b_use_pts = 1;
1091
1092     msg_Dbg(p_dec, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec->fmt_in.i_codec,
1093             (char *)&p_dec->fmt_out.i_codec);
1094
1095     /* Enumerate components and build a list of the one we want to try */
1096     p_sys->components =
1097         CreateComponentsList(p_this,
1098              GetOmxRole(p_sys->b_enc ? p_dec->fmt_out.i_codec :
1099                         p_dec->fmt_in.i_codec, p_dec->fmt_in.i_cat,
1100                         p_sys->b_enc), p_sys->ppsz_components);
1101     if( !p_sys->components )
1102     {
1103         msg_Warn( p_this, "couldn't find an omx component for codec %4.4s",
1104                   (char *)&p_dec->fmt_in.i_codec );
1105         CloseGeneric(p_this);
1106         return VLC_EGENERIC;
1107     }
1108
1109     /* Try to load and initialise a component */
1110     omx_error = OMX_ErrorUndefined;
1111     for(i = 0; i < p_sys->components; i++)
1112     {
1113 #ifdef __ANDROID__
1114         /* ignore OpenCore software codecs */
1115         if (!strncmp(p_sys->ppsz_components[i], "OMX.PV.", 7))
1116             continue;
1117         /* The same sw codecs, renamed in ICS (perhaps also in honeycomb) */
1118         if (!strncmp(p_sys->ppsz_components[i], "OMX.google.", 11))
1119             continue;
1120         /* This one has been seen on HTC One V - it behaves like it works,
1121          * but FillBufferDone returns buffers filled with 0 bytes. The One V
1122          * has got a working OMX.qcom.video.decoder.avc instead though. */
1123         if (!strncmp(p_sys->ppsz_components[i], "OMX.ARICENT.", 12))
1124             continue;
1125         /* Codecs with DRM, that don't output plain YUV data but only
1126          * support direct rendering where the output can't be intercepted. */
1127         if (strstr(p_sys->ppsz_components[i], ".secure"))
1128             continue;
1129         /* Use VC1 decoder for WMV3 for now */
1130         if (!strcmp(p_sys->ppsz_components[i], "OMX.SEC.WMV.Decoder"))
1131             continue;
1132         /* This decoder does work, but has an insane latency (leading to errors
1133          * about "main audio output playback way too late" and dropped frames).
1134          * At least Samsung Galaxy S III (where this decoder is present) has
1135          * got another one, OMX.SEC.mp3.dec, that works well and has a
1136          * sensible latency. (Also, even if that one isn't found, in general,
1137          * using SW codecs is usually more than fast enough for MP3.) */
1138         if (!strcmp(p_sys->ppsz_components[i], "OMX.SEC.MP3.Decoder"))
1139             continue;
1140         /* This codec should be able to handle both VC1 and WMV3, but
1141          * for VC1 it doesn't output any buffers at all (in the way we use
1142          * it) and for WMV3 it outputs plain black buffers. Thus ignore
1143          * it until we can make it work properly. */
1144         if (!strcmp(p_sys->ppsz_components[i], "OMX.Nvidia.vc1.decode"))
1145             continue;
1146 #endif
1147         omx_error = InitialiseComponent(p_dec, p_sys->ppsz_components[i],
1148                                         &p_sys->omx_handle);
1149         if(omx_error == OMX_ErrorNone) break;
1150     }
1151     CHECK_ERROR(omx_error, "no component could be initialised" );
1152
1153     /* Move component to Idle then Executing state */
1154     OMX_SendCommand( p_sys->omx_handle, OMX_CommandStateSet, OMX_StateIdle, 0 );
1155     CHECK_ERROR(omx_error, "OMX_CommandStateSet Idle failed (%x)", omx_error );
1156
1157     /* Allocate omx buffers */
1158     for(i = 0; i < p_sys->ports; i++)
1159     {
1160         OmxPort *p_port = &p_sys->p_ports[i];
1161         if( p_port->p_hwbuf )
1162         {
1163             if( HwBuffer_AllocateBuffers( p_dec, p_port ) != 0 )
1164             {
1165                 omx_error = OMX_ErrorInsufficientResources;
1166                 goto error;
1167             }
1168         }
1169         omx_error = AllocateBuffers( p_dec, p_port );
1170         CHECK_ERROR(omx_error, "AllocateBuffers failed (%x, %i)",
1171                     omx_error, (int)p_port->i_port_index );
1172     }
1173
1174     omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
1175     CHECK_ERROR(omx_error, "Wait for Idle failed (%x)", omx_error );
1176
1177     omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandStateSet,
1178                                  OMX_StateExecuting, 0);
1179     CHECK_ERROR(omx_error, "OMX_CommandStateSet Executing failed (%x)", omx_error );
1180     omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
1181     CHECK_ERROR(omx_error, "Wait for Executing failed (%x)", omx_error );
1182
1183     if( p_sys->out.p_hwbuf && HwBuffer_Start( p_dec, &p_sys->out ) != 0 )
1184     {
1185         omx_error = OMX_ErrorUndefined;
1186         goto error;
1187     }
1188
1189     /* Send codec configuration data */
1190     if( p_dec->fmt_in.i_extra )
1191     {
1192         OMX_FIFO_GET(&p_sys->in.fifo, p_header);
1193         p_header->nFilledLen = p_dec->fmt_in.i_extra;
1194
1195         /* Convert H.264 NAL format to annex b */
1196         if( p_sys->i_nal_size_length && !p_sys->in.b_direct )
1197         {
1198             p_header->nFilledLen = 0;
1199             convert_sps_pps( p_dec, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra,
1200                              p_header->pBuffer, p_header->nAllocLen,
1201                              (uint32_t*) &p_header->nFilledLen, NULL );
1202         }
1203         else if( p_dec->fmt_in.i_codec == VLC_CODEC_HEVC && !p_sys->in.b_direct )
1204         {
1205             p_header->nFilledLen = 0;
1206             convert_hevc_nal_units( p_dec, p_dec->fmt_in.p_extra,
1207                                     p_dec->fmt_in.i_extra,
1208                                     p_header->pBuffer, p_header->nAllocLen,
1209                                     (uint32_t*) &p_header->nFilledLen,
1210                                     &p_sys->i_nal_size_length );
1211         }
1212         else if(p_sys->in.b_direct)
1213         {
1214             p_header->pOutputPortPrivate = p_header->pBuffer;
1215             p_header->pBuffer = p_dec->fmt_in.p_extra;
1216         }
1217         else if (p_dec->fmt_in.i_codec == VLC_CODEC_WMV3 &&
1218                  p_dec->fmt_in.i_extra >= 4 &&
1219                  p_header->nAllocLen >= 36)
1220         {
1221             int profile;
1222             // According to OMX IL 1.2.0 spec (4.3.33.2), the codec config
1223             // data for VC-1 Main/Simple (aka WMV3) is according to table 265
1224             // in the VC-1 spec. Most of the fields are just set with placeholders
1225             // (like framerate, hrd_buffer/rate).
1226             static const uint8_t wmv3seq[] = {
1227                 0xff, 0xff, 0xff, 0xc5, // numframes=ffffff, marker byte
1228                 0x04, 0x00, 0x00, 0x00, // marker byte
1229                 0x00, 0x00, 0x00, 0x00, // struct C, almost equal to p_extra
1230                 0x00, 0x00, 0x00, 0x00, // struct A, vert size
1231                 0x00, 0x00, 0x00, 0x00, // struct A, horiz size
1232                 0x0c, 0x00, 0x00, 0x00, // marker byte
1233                 0xff, 0xff, 0x00, 0x80, // struct B, level=4, cbr=0, hrd_buffer=ffff
1234                 0xff, 0xff, 0x00, 0x00, // struct B, hrd_rate=ffff
1235                 0xff, 0xff, 0xff, 0xff, // struct B, framerate=ffffffff
1236             };
1237             p_header->nFilledLen = sizeof(wmv3seq);
1238             memcpy(p_header->pBuffer, wmv3seq, p_header->nFilledLen);
1239             // Struct C - almost equal to the extradata
1240             memcpy(&p_header->pBuffer[8], p_dec->fmt_in.p_extra, 4);
1241             // Expand profile from the highest 2 bits to the highest 4 bits
1242             profile = p_header->pBuffer[8] >> 6;
1243             p_header->pBuffer[8] = (p_header->pBuffer[8] & 0x0f) | (profile << 4);
1244             // Fill in the height/width for struct A
1245             SetDWLE(&p_header->pBuffer[12], p_dec->fmt_in.video.i_height);
1246             SetDWLE(&p_header->pBuffer[16], p_dec->fmt_in.video.i_width);
1247         }
1248         else
1249         {
1250             if(p_header->nFilledLen > p_header->nAllocLen)
1251             {
1252                 msg_Dbg(p_dec, "buffer too small (%i,%i)", (int)p_header->nFilledLen,
1253                         (int)p_header->nAllocLen);
1254                 p_header->nFilledLen = p_header->nAllocLen;
1255             }
1256             memcpy(p_header->pBuffer, p_dec->fmt_in.p_extra, p_header->nFilledLen);
1257         }
1258
1259         p_header->nOffset = 0;
1260         p_header->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
1261         msg_Dbg(p_dec, "sending codec config data %p, %p, %i", p_header,
1262                 p_header->pBuffer, (int)p_header->nFilledLen);
1263         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
1264     }
1265
1266     /* Get back output port definition */
1267     omx_error = GetPortDefinition(p_dec, &p_sys->out, p_sys->out.p_fmt);
1268     if(omx_error != OMX_ErrorNone) goto error;
1269
1270     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->in.i_port_index);
1271     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->out.i_port_index);
1272
1273     if(p_sys->b_error) goto error;
1274
1275     p_dec->b_need_packetized = true;
1276
1277     if (!p_sys->b_use_pts)
1278         msg_Dbg( p_dec, "using dts timestamp mode for %s", p_sys->psz_component);
1279
1280     return VLC_SUCCESS;
1281
1282  error:
1283     CloseGeneric(p_this);
1284     return VLC_EGENERIC;
1285 }
1286
1287 /*****************************************************************************
1288  * PortReconfigure
1289  *****************************************************************************/
1290 static OMX_ERRORTYPE PortReconfigure(decoder_t *p_dec, OmxPort *p_port)
1291 {
1292     decoder_sys_t *p_sys = p_dec->p_sys;
1293     OMX_PARAM_PORTDEFINITIONTYPE definition;
1294     OMX_ERRORTYPE omx_error;
1295
1296     OMX_DBG( "PortReconfigure(%d)", p_port->definition.eDir );
1297
1298     /* Sanity checking */
1299     OMX_INIT_STRUCTURE(definition);
1300     definition.nPortIndex = p_port->i_port_index;
1301     omx_error = OMX_GetParameter(p_dec->p_sys->omx_handle, OMX_IndexParamPortDefinition,
1302                                  &definition);
1303     if(omx_error != OMX_ErrorNone || (p_dec->fmt_in.i_cat == VIDEO_ES &&
1304        (!definition.format.video.nFrameWidth ||
1305        !definition.format.video.nFrameHeight)) )
1306         return OMX_ErrorUndefined;
1307
1308     if( p_port->p_hwbuf && HwBuffer_Stop( p_dec, p_port ) != 0 )
1309         msg_Warn( p_dec, "HwBuffer_Stop failed" );
1310
1311     omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandPortDisable,
1312                                  p_port->i_port_index, NULL);
1313     CHECK_ERROR(omx_error, "OMX_CommandPortDisable on %i failed (%x)",
1314                 (int)p_port->i_port_index, omx_error );
1315
1316     omx_error = FreeBuffers( p_dec, p_port );
1317     CHECK_ERROR(omx_error, "FreeBuffers failed (%x, %i)",
1318                 omx_error, (int)p_port->i_port_index );
1319
1320     if( p_port->p_hwbuf )
1321     {
1322         HwBuffer_FreeBuffers( p_dec, p_port );
1323         HwBuffer_Join( p_dec, p_port );
1324     }
1325
1326     omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
1327     CHECK_ERROR(omx_error, "Wait for PortDisable failed (%x)", omx_error );
1328
1329     /* Get the new port definition */
1330     omx_error = GetPortDefinition(p_dec, &p_sys->out, p_sys->out.p_fmt);
1331     if(omx_error != OMX_ErrorNone) goto error;
1332
1333     if( p_port->p_hwbuf )
1334     {
1335         if( HwBuffer_AllocateBuffers( p_dec, p_port ) != 0 )
1336         {
1337             omx_error = OMX_ErrorInsufficientResources;
1338             goto error;
1339         }
1340     }
1341     else if( p_dec->fmt_in.i_cat != AUDIO_ES )
1342     {
1343         /* Don't explicitly set the new parameters that we got with
1344          * OMX_GetParameter above when using audio codecs.
1345          * That struct hasn't been changed since, so there should be
1346          * no need to set it here, unless some codec expects the
1347          * SetParameter call as a trigger event for some part of
1348          * the reconfiguration.
1349          * This fixes using audio decoders on Samsung Galaxy S II,
1350          *
1351          * Only skipping this for audio codecs, to minimize the
1352          * change for current working configurations for video.
1353          */
1354         omx_error = OMX_SetParameter(p_dec->p_sys->omx_handle, OMX_IndexParamPortDefinition,
1355                                      &definition);
1356         CHECK_ERROR(omx_error, "OMX_SetParameter failed (%x : %s)",
1357                     omx_error, ErrorToString(omx_error));
1358     }
1359
1360     omx_error = OMX_SendCommand( p_sys->omx_handle, OMX_CommandPortEnable,
1361                                  p_port->i_port_index, NULL);
1362     CHECK_ERROR(omx_error, "OMX_CommandPortEnable on %i failed (%x)",
1363                 (int)p_port->i_port_index, omx_error );
1364
1365     omx_error = AllocateBuffers( p_dec, p_port );
1366     CHECK_ERROR(omx_error, "OMX_AllocateBuffers failed (%x, %i)",
1367                 omx_error, (int)p_port->i_port_index );
1368
1369     omx_error = WaitForSpecificOmxEvent(&p_sys->event_queue, OMX_EventCmdComplete, 0, 0, 0);
1370     CHECK_ERROR(omx_error, "Wait for PortEnable failed (%x)", omx_error );
1371
1372     if( p_port->p_hwbuf && HwBuffer_Start( p_dec, p_port ) != 0 )
1373     {
1374         omx_error = OMX_ErrorUndefined;
1375         goto error;
1376     }
1377
1378     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->in.i_port_index);
1379     PrintOmx(p_dec, p_sys->omx_handle, p_dec->p_sys->out.i_port_index);
1380
1381     OMX_DBG( "PortReconfigure(%d)::done", p_port->definition.eDir );
1382  error:
1383     return omx_error;
1384 }
1385
1386 /*****************************************************************************
1387  * DecodeVideoOutput
1388  *****************************************************************************/
1389 static int DecodeVideoOutput( decoder_t *p_dec, OmxPort *p_port, picture_t **pp_pic )
1390 {
1391     VLC_UNUSED( p_dec );
1392     OMX_BUFFERHEADERTYPE *p_header;
1393     picture_t *p_pic = NULL, *p_next_pic;
1394     OMX_ERRORTYPE omx_error;
1395
1396     while(!p_pic)
1397     {
1398         OMX_FIFO_PEEK(&p_port->fifo, p_header);
1399         if(!p_header) break; /* No frame available */
1400
1401         if(p_port->b_update_def)
1402         {
1403             omx_error = GetPortDefinition(p_dec, p_port, p_port->p_fmt);
1404             p_port->b_update_def = 0;
1405             CHECK_ERROR(omx_error, "GetPortDefinition failed");
1406         }
1407
1408         if( p_port->p_hwbuf )
1409         {
1410             if( HwBuffer_GetPic( p_dec, p_port, &p_pic ) != 0 )
1411                 goto error;
1412             else
1413                 continue;
1414         }
1415
1416         if(p_header->nFilledLen)
1417         {
1418             p_pic = p_header->pAppPrivate;
1419             if(!p_pic)
1420             {
1421                 /* We're not in direct rendering mode.
1422                  * Get a new picture and copy the content */
1423                 p_pic = decoder_NewPicture( p_dec );
1424
1425                 if (p_pic)
1426                     CopyOmxPicture(p_port->definition.format.video.eColorFormat,
1427                                    p_pic, p_port->definition.format.video.nSliceHeight,
1428                                    p_port->i_frame_stride,
1429                                    p_header->pBuffer + p_header->nOffset,
1430                                    p_port->i_frame_stride_chroma_div, NULL);
1431             }
1432
1433             if (p_pic)
1434                 p_pic->date = FromOmxTicks(p_header->nTimeStamp);
1435             p_header->nFilledLen = 0;
1436             p_header->pAppPrivate = 0;
1437         }
1438
1439         /* Get a new picture */
1440         if(p_port->b_direct && !p_header->pAppPrivate)
1441         {
1442             p_next_pic = decoder_NewPicture( p_dec );
1443             if(!p_next_pic) break;
1444
1445             OMX_FIFO_GET(&p_port->fifo, p_header);
1446             p_header->pAppPrivate = p_next_pic;
1447             p_header->pInputPortPrivate = p_header->pBuffer;
1448             p_header->pBuffer = p_next_pic->p[0].p_pixels;
1449         }
1450         else
1451         {
1452             OMX_FIFO_GET(&p_port->fifo, p_header);
1453         }
1454         OMX_DBG( "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
1455         OMX_FillThisBuffer(p_port->omx_handle, p_header);
1456     }
1457
1458     *pp_pic = p_pic;
1459     return 0;
1460 error:
1461     return -1;
1462 }
1463
1464 static int DecodeVideoInput( decoder_t *p_dec, OmxPort *p_port, block_t **pp_block,
1465                              unsigned int i_input_used, bool *p_reconfig )
1466 {
1467     decoder_sys_t *p_sys = p_dec->p_sys;
1468     OMX_BUFFERHEADERTYPE *p_header;
1469     struct H264ConvertState convert_state = { 0, 0 };
1470     block_t *p_block = *pp_block;
1471
1472     /* Send the input buffer to the component */
1473     OMX_FIFO_GET_TIMEOUT(&p_port->fifo, p_header, 10000);
1474
1475     if (p_header && p_header->nFlags & SENTINEL_FLAG) {
1476         free(p_header);
1477         *p_reconfig = true;
1478         return 0;
1479     }
1480     *p_reconfig = false;
1481
1482     if(p_header)
1483     {
1484         bool decode_more = false;
1485         p_header->nFilledLen = p_block->i_buffer - i_input_used;
1486         p_header->nOffset = 0;
1487         p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
1488         if (p_sys->b_use_pts && p_block->i_pts)
1489             p_header->nTimeStamp = ToOmxTicks(p_block->i_pts);
1490         else
1491             p_header->nTimeStamp = ToOmxTicks(p_block->i_dts);
1492
1493         /* In direct mode we pass the input pointer as is.
1494          * Otherwise we memcopy the data */
1495         if(p_port->b_direct)
1496         {
1497             p_header->pOutputPortPrivate = p_header->pBuffer;
1498             p_header->pBuffer = p_block->p_buffer;
1499             p_header->pAppPrivate = p_block;
1500             i_input_used = p_header->nFilledLen;
1501         }
1502         else
1503         {
1504             if(p_header->nFilledLen > p_header->nAllocLen)
1505             {
1506                 p_header->nFilledLen = p_header->nAllocLen;
1507             }
1508             memcpy(p_header->pBuffer, p_block->p_buffer + i_input_used, p_header->nFilledLen);
1509             i_input_used += p_header->nFilledLen;
1510             if (i_input_used == p_block->i_buffer)
1511             {
1512                 block_Release(p_block);
1513             }
1514             else
1515             {
1516                 decode_more = true;
1517                 p_header->nFlags &= ~OMX_BUFFERFLAG_ENDOFFRAME;
1518             }
1519         }
1520
1521         /* Convert H.264 NAL format to annex b. Doesn't do anything if
1522          * i_nal_size_length == 0, which is the case for codecs other
1523          * than H.264 */
1524         convert_h264_to_annexb( p_header->pBuffer, p_header->nFilledLen,
1525                                 p_sys->i_nal_size_length, &convert_state );
1526         OMX_DBG( "EmptyThisBuffer %p, %p, %i, %"PRId64, p_header, p_header->pBuffer,
1527                  (int)p_header->nFilledLen, FromOmxTicks(p_header->nTimeStamp) );
1528         OMX_EmptyThisBuffer(p_port->omx_handle, p_header);
1529         p_port->b_flushed = false;
1530         if (decode_more)
1531             return DecodeVideoInput( p_dec, p_port, pp_block, i_input_used,
1532                                      p_reconfig );
1533         else
1534             *pp_block = NULL; /* Avoid being fed the same packet again */
1535     }
1536
1537     return 0;
1538 }
1539
1540 /*****************************************************************************
1541  * DecodeVideo: Called to decode one frame
1542  *****************************************************************************/
1543 static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
1544 {
1545     decoder_sys_t *p_sys = p_dec->p_sys;
1546     picture_t *p_pic = NULL;
1547     OMX_ERRORTYPE omx_error;
1548     unsigned int i;
1549     block_t *p_block;
1550
1551     if( !pp_block || !*pp_block )
1552         return NULL;
1553
1554     p_block = *pp_block;
1555
1556     /* Check for errors from codec */
1557     if(p_sys->b_error)
1558     {
1559         msg_Dbg(p_dec, "error during decoding");
1560         block_Release( p_block );
1561         return 0;
1562     }
1563
1564     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
1565     {
1566         block_Release( p_block );
1567         if(!p_sys->in.b_flushed)
1568         {
1569             msg_Dbg(p_dec, "flushing");
1570             OMX_SendCommand( p_sys->omx_handle, OMX_CommandFlush,
1571                              p_sys->in.definition.nPortIndex, 0 );
1572         }
1573         p_sys->in.b_flushed = true;
1574         return NULL;
1575     }
1576
1577     /* Use the aspect ratio provided by the input (ie read from packetizer).
1578      * In case the we get aspect ratio info from the decoder (as in the
1579      * broadcom OMX implementation on RPi), don't let the packetizer values
1580      * override what the decoder says, if anything - otherwise always update
1581      * even if it already is set (since it can change within a stream). */
1582     if((p_dec->fmt_in.video.i_sar_num != 0 && p_dec->fmt_in.video.i_sar_den != 0) &&
1583        (p_dec->fmt_out.video.i_sar_num == 0 || p_dec->fmt_out.video.i_sar_den == 0 ||
1584              !p_sys->b_aspect_ratio_handled))
1585     {
1586         p_dec->fmt_out.video.i_sar_num = p_dec->fmt_in.video.i_sar_num;
1587         p_dec->fmt_out.video.i_sar_den = p_dec->fmt_in.video.i_sar_den;
1588     }
1589
1590     /* Take care of decoded frames first */
1591     if( DecodeVideoOutput( p_dec, &p_sys->out, &p_pic ) != 0 )
1592         goto error;
1593
1594     /* Loop as long as we haven't either got an input buffer (and cleared
1595      * *pp_block) or got an output picture */
1596     int max_polling_attempts = 100;
1597     int attempts = 0;
1598     while( *pp_block && !p_pic ) {
1599         bool b_reconfig = false;
1600
1601         if( DecodeVideoInput( p_dec, &p_sys->in, pp_block, 0, &b_reconfig ) != 0 )
1602             goto error;
1603
1604         /* If we don't have a p_pic from the first try. Try again */
1605         if( !b_reconfig && !p_pic &&
1606             DecodeVideoOutput( p_dec, &p_sys->out, &p_pic ) != 0 )
1607             goto error;
1608
1609         /* Handle the PortSettingsChanged events */
1610         for(i = 0; i < p_sys->ports; i++)
1611         {
1612             OmxPort *p_port = &p_sys->p_ports[i];
1613             if(p_port->b_reconfigure)
1614             {
1615                 omx_error = PortReconfigure(p_dec, p_port);
1616                 p_port->b_reconfigure = 0;
1617                 CHECK_ERROR(omx_error, "PortReconfigure failed");
1618             }
1619             if(p_port->b_update_def)
1620             {
1621                 omx_error = GetPortDefinition(p_dec, p_port, p_port->p_fmt);
1622                 p_port->b_update_def = 0;
1623                 CHECK_ERROR(omx_error, "GetPortDefinition failed");
1624             }
1625         }
1626
1627         attempts++;
1628         /* With opaque DR the output buffers are released by the
1629            vout therefore we implement a timeout for polling in
1630            order to avoid being indefinitely stalled in this loop, if
1631            playback is paused. */
1632         if( p_sys->out.p_hwbuf && attempts == max_polling_attempts ) {
1633 #ifdef USE_IOMX
1634             picture_t *invalid_picture = decoder_NewPicture(p_dec);
1635             if (invalid_picture) {
1636                 invalid_picture->date = VLC_TS_INVALID;
1637                 picture_sys_t *p_picsys = invalid_picture->p_sys;
1638                 p_picsys->pf_display_callback = NULL;
1639                 p_picsys->pf_unlock_callback = NULL;
1640                 p_picsys->p_dec = NULL;
1641                 p_picsys->i_index = -1;
1642                 p_picsys->b_valid = false;
1643             } else {
1644                 /* If we cannot return a picture we must free the
1645                    block since the decoder will proceed with the
1646                    next block. */
1647                 block_Release(p_block);
1648                 *pp_block = NULL;
1649             }
1650             return invalid_picture;
1651 #endif
1652         }
1653     }
1654
1655     return p_pic;
1656 error:
1657     p_sys->b_error = true;
1658     return NULL;
1659 }
1660
1661 /*****************************************************************************
1662  * DecodeAudio: Called to decode one frame
1663  *****************************************************************************/
1664 block_t *DecodeAudio ( decoder_t *p_dec, block_t **pp_block )
1665 {
1666     decoder_sys_t *p_sys = p_dec->p_sys;
1667     block_t *p_buffer = NULL;
1668     OMX_BUFFERHEADERTYPE *p_header;
1669     OMX_ERRORTYPE omx_error;
1670     block_t *p_block;
1671     unsigned int i;
1672
1673     if( !pp_block || !*pp_block ) return NULL;
1674
1675     p_block = *pp_block;
1676
1677     /* Check for errors from codec */
1678     if(p_sys->b_error)
1679     {
1680         msg_Dbg(p_dec, "error during decoding");
1681         block_Release( p_block );
1682         return 0;
1683     }
1684
1685     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
1686     {
1687         block_Release( p_block );
1688         date_Set( &p_sys->end_date, 0 );
1689         if(!p_sys->in.b_flushed)
1690         {
1691             msg_Dbg(p_dec, "flushing");
1692             OMX_SendCommand( p_sys->omx_handle, OMX_CommandFlush,
1693                              p_sys->in.definition.nPortIndex, 0 );
1694         }
1695         p_sys->in.b_flushed = true;
1696         return NULL;
1697     }
1698
1699     if( !date_Get( &p_sys->end_date ) )
1700     {
1701         if( !p_block->i_pts )
1702         {
1703             /* We've just started the stream, wait for the first PTS. */
1704             block_Release( p_block );
1705             return NULL;
1706         }
1707         date_Set( &p_sys->end_date, p_block->i_pts );
1708     }
1709
1710     /* Take care of decoded frames first */
1711     while(!p_buffer)
1712     {
1713         unsigned int i_samples = 0;
1714
1715         OMX_FIFO_PEEK(&p_sys->out.fifo, p_header);
1716         if(!p_header) break; /* No frame available */
1717
1718         if (p_sys->out.p_fmt->audio.i_channels)
1719             i_samples = p_header->nFilledLen / p_sys->out.p_fmt->audio.i_channels / 2;
1720         if(i_samples)
1721         {
1722             p_buffer = decoder_NewAudioBuffer( p_dec, i_samples );
1723             if( !p_buffer ) break; /* No audio buffer available */
1724
1725             memcpy( p_buffer->p_buffer, p_header->pBuffer, p_buffer->i_buffer );
1726             p_header->nFilledLen = 0;
1727
1728             int64_t timestamp = FromOmxTicks(p_header->nTimeStamp);
1729             if( timestamp != 0 &&
1730                 timestamp != date_Get( &p_sys->end_date ) )
1731                 date_Set( &p_sys->end_date, timestamp );
1732
1733             p_buffer->i_pts = date_Get( &p_sys->end_date );
1734             p_buffer->i_length = date_Increment( &p_sys->end_date, i_samples ) -
1735                 p_buffer->i_pts;
1736         }
1737
1738         OMX_DBG( "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
1739         OMX_FIFO_GET(&p_sys->out.fifo, p_header);
1740         OMX_FillThisBuffer(p_sys->omx_handle, p_header);
1741     }
1742
1743
1744     /* Send the input buffer to the component */
1745     OMX_FIFO_GET_TIMEOUT(&p_sys->in.fifo, p_header, 200000);
1746
1747     if (p_header && p_header->nFlags & SENTINEL_FLAG) {
1748         free(p_header);
1749         goto reconfig;
1750     }
1751
1752     if(p_header)
1753     {
1754         p_header->nFilledLen = p_block->i_buffer;
1755         p_header->nOffset = 0;
1756         p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
1757         p_header->nTimeStamp = ToOmxTicks(p_block->i_dts);
1758
1759         /* In direct mode we pass the input pointer as is.
1760          * Otherwise we memcopy the data */
1761         if(p_sys->in.b_direct)
1762         {
1763             p_header->pOutputPortPrivate = p_header->pBuffer;
1764             p_header->pBuffer = p_block->p_buffer;
1765             p_header->pAppPrivate = p_block;
1766         }
1767         else
1768         {
1769             if(p_header->nFilledLen > p_header->nAllocLen)
1770             {
1771                 msg_Dbg(p_dec, "buffer too small (%i,%i)",
1772                         (int)p_header->nFilledLen, (int)p_header->nAllocLen);
1773                 p_header->nFilledLen = p_header->nAllocLen;
1774             }
1775             memcpy(p_header->pBuffer, p_block->p_buffer, p_header->nFilledLen );
1776             block_Release(p_block);
1777         }
1778
1779         OMX_DBG( "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
1780                  (int)p_header->nFilledLen );
1781         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
1782         p_sys->in.b_flushed = false;
1783         *pp_block = NULL; /* Avoid being fed the same packet again */
1784     }
1785
1786 reconfig:
1787     /* Handle the PortSettingsChanged events */
1788     for(i = 0; i < p_sys->ports; i++)
1789     {
1790         OmxPort *p_port = &p_sys->p_ports[i];
1791         if(!p_port->b_reconfigure) continue;
1792         p_port->b_reconfigure = 0;
1793         omx_error = PortReconfigure(p_dec, p_port);
1794         CHECK_ERROR(omx_error, "PortReconfigure failed");
1795     }
1796
1797     return p_buffer;
1798 error:
1799     p_sys->b_error = true;
1800     return NULL;
1801 }
1802
1803 /*****************************************************************************
1804  * EncodeVideo: Called to encode one frame
1805  *****************************************************************************/
1806 static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
1807 {
1808     decoder_t *p_dec = ( decoder_t *)p_enc;
1809     decoder_sys_t *p_sys = p_dec->p_sys;
1810     OMX_ERRORTYPE omx_error;
1811     unsigned int i;
1812
1813     OMX_BUFFERHEADERTYPE *p_header;
1814     block_t *p_block = 0;
1815
1816     if( !p_pic ) return NULL;
1817
1818     /* Check for errors from codec */
1819     if(p_sys->b_error)
1820     {
1821         msg_Dbg(p_dec, "error during encoding");
1822         return NULL;
1823     }
1824
1825     /* Send the input buffer to the component */
1826     OMX_FIFO_GET(&p_sys->in.fifo, p_header);
1827     if(p_header)
1828     {
1829         /* In direct mode we pass the input pointer as is.
1830          * Otherwise we memcopy the data */
1831         if(p_sys->in.b_direct)
1832         {
1833             p_header->pOutputPortPrivate = p_header->pBuffer;
1834             p_header->pBuffer = p_pic->p[0].p_pixels;
1835         }
1836         else
1837         {
1838             CopyVlcPicture(p_dec, p_header, p_pic);
1839         }
1840
1841         p_header->nFilledLen = p_sys->in.i_frame_size;
1842         p_header->nOffset = 0;
1843         p_header->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
1844         p_header->nTimeStamp = ToOmxTicks(p_pic->date);
1845         OMX_DBG( "EmptyThisBuffer %p, %p, %i", p_header, p_header->pBuffer,
1846                  (int)p_header->nFilledLen );
1847         OMX_EmptyThisBuffer(p_sys->omx_handle, p_header);
1848         p_sys->in.b_flushed = false;
1849     }
1850
1851     /* Handle the PortSettingsChanged events */
1852     for(i = 0; i < p_sys->ports; i++)
1853     {
1854         OmxPort *p_port = &p_sys->p_ports[i];
1855         if(!p_port->b_reconfigure) continue;
1856         p_port->b_reconfigure = 0;
1857         omx_error = PortReconfigure(p_dec, p_port);
1858         CHECK_ERROR(omx_error, "PortReconfigure failed");
1859     }
1860
1861     /* Wait for the decoded frame */
1862     while(!p_block)
1863     {
1864         OMX_FIFO_GET(&p_sys->out.fifo, p_header);
1865
1866         if(p_header->nFilledLen)
1867         {
1868             if(p_header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
1869             {
1870                 /* TODO: need to store codec config */
1871                 msg_Dbg(p_dec, "received codec config %i", (int)p_header->nFilledLen);
1872             }
1873
1874             p_block = p_header->pAppPrivate;
1875             if(!p_block)
1876             {
1877                 /* We're not in direct rendering mode.
1878                  * Get a new block and copy the content */
1879                 p_block = block_Alloc( p_header->nFilledLen );
1880                 memcpy(p_block->p_buffer, p_header->pBuffer, p_header->nFilledLen );
1881             }
1882
1883             p_block->i_buffer = p_header->nFilledLen;
1884             p_block->i_pts = p_block->i_dts = FromOmxTicks(p_header->nTimeStamp);
1885             p_header->nFilledLen = 0;
1886             p_header->pAppPrivate = 0;
1887         }
1888
1889         OMX_DBG( "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
1890         OMX_FillThisBuffer(p_sys->omx_handle, p_header);
1891     }
1892
1893     msg_Dbg(p_dec, "done");
1894     return p_block;
1895 error:
1896     p_sys->b_error = true;
1897     return NULL;
1898 }
1899
1900 /*****************************************************************************
1901  * CloseGeneric: omxil decoder destruction
1902  *****************************************************************************/
1903 static void CloseGeneric( vlc_object_t *p_this )
1904 {
1905     decoder_t *p_dec = (decoder_t *)p_this;
1906     decoder_sys_t *p_sys = p_dec->p_sys;
1907
1908     if(p_sys->omx_handle) DeinitialiseComponent(p_dec, p_sys->omx_handle);
1909
1910     DeinitOmxCore();
1911
1912     DeinitOmxEventQueue(&p_sys->event_queue);
1913
1914     OMX_FIFO_DESTROY( &p_sys->in.fifo );
1915     OMX_FIFO_DESTROY( &p_sys->out.fifo );
1916
1917     free( p_sys );
1918 }
1919
1920 /*****************************************************************************
1921  * OmxEventHandler:
1922  *****************************************************************************/
1923 static OMX_ERRORTYPE OmxEventHandler( OMX_HANDLETYPE omx_handle,
1924     OMX_PTR app_data, OMX_EVENTTYPE event, OMX_U32 data_1,
1925     OMX_U32 data_2, OMX_PTR event_data )
1926 {
1927     decoder_t *p_dec = (decoder_t *)app_data;
1928     decoder_sys_t *p_sys = p_dec->p_sys;
1929     unsigned int i;
1930     (void)omx_handle;
1931
1932     PrintOmxEvent((vlc_object_t *) p_dec, event, data_1, data_2, event_data);
1933     switch (event)
1934     {
1935     case OMX_EventError:
1936         //p_sys->b_error = true;
1937         break;
1938
1939     case OMX_EventPortSettingsChanged:
1940         if( data_2 == 0 || data_2 == OMX_IndexParamPortDefinition ||
1941             data_2 == OMX_IndexParamAudioPcm )
1942         {
1943             OMX_BUFFERHEADERTYPE *sentinel;
1944             for(i = 0; i < p_sys->ports; i++)
1945                 if(p_sys->p_ports[i].definition.eDir == OMX_DirOutput)
1946                     p_sys->p_ports[i].b_reconfigure = true;
1947             sentinel = calloc(1, sizeof(*sentinel));
1948             if (sentinel) {
1949                 sentinel->nFlags = SENTINEL_FLAG;
1950                 OMX_FIFO_PUT(&p_sys->in.fifo, sentinel);
1951             }
1952         }
1953         else if( data_2 == OMX_IndexConfigCommonOutputCrop )
1954         {
1955             for(i = 0; i < p_sys->ports; i++)
1956                 if(p_sys->p_ports[i].definition.nPortIndex == data_1)
1957                     p_sys->p_ports[i].b_update_def = true;
1958         }
1959         else
1960         {
1961             msg_Dbg( p_dec, "Unhandled setting change %x", (unsigned int)data_2 );
1962         }
1963         break;
1964     case OMX_EventParamOrConfigChanged:
1965         UpdatePixelAspect(p_dec);
1966         break;
1967
1968     default:
1969         break;
1970     }
1971
1972     PostOmxEvent(&p_sys->event_queue, event, data_1, data_2, event_data);
1973     return OMX_ErrorNone;
1974 }
1975
1976 static OMX_ERRORTYPE OmxEmptyBufferDone( OMX_HANDLETYPE omx_handle,
1977     OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header )
1978 {
1979     decoder_t *p_dec = (decoder_t *)app_data;
1980     decoder_sys_t *p_sys = p_dec->p_sys;
1981     (void)omx_handle;
1982
1983     OMX_DBG( "OmxEmptyBufferDone %p, %p", omx_header, omx_header->pBuffer );
1984
1985     if(omx_header->pAppPrivate || omx_header->pOutputPortPrivate)
1986     {
1987         block_t *p_block = (block_t *)omx_header->pAppPrivate;
1988         omx_header->pBuffer = omx_header->pOutputPortPrivate;
1989         if(p_block) block_Release(p_block);
1990         omx_header->pAppPrivate = 0;
1991     }
1992     OMX_FIFO_PUT(&p_sys->in.fifo, omx_header);
1993
1994     return OMX_ErrorNone;
1995 }
1996
1997 static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE omx_handle,
1998     OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header )
1999 {
2000     decoder_t *p_dec = (decoder_t *)app_data;
2001     decoder_sys_t *p_sys = p_dec->p_sys;
2002     (void)omx_handle;
2003
2004     OMX_DBG( "OmxFillBufferDone %p, %p, %i, %"PRId64, omx_header, omx_header->pBuffer,
2005              (int)omx_header->nFilledLen, FromOmxTicks(omx_header->nTimeStamp) );
2006
2007     if(omx_header->pInputPortPrivate)
2008     {
2009         omx_header->pBuffer = omx_header->pInputPortPrivate;
2010     }
2011     OMX_FIFO_PUT(&p_sys->out.fifo, omx_header);
2012
2013     return OMX_ErrorNone;
2014 }
2015
2016 #if defined(USE_IOMX)
2017
2018 /* Life cycle of buffers when using IOMX direct rendering (HwBuffer):
2019  *
2020  * <- android display
2021  * DequeueThread owned++
2022  * -> OMX_FillThisBuffer
2023  * ...
2024  * <- FillBufferDone OMX_FIFO_PUT
2025  * ...
2026  * DecodeVideoOutput OMX_FIFO_GET
2027  * -> vlc core
2028  * ...
2029  * DisplayBuffer
2030  * -> android display owned--
2031  */
2032
2033 /*****************************************************************************
2034  * HwBuffer_ChangeState
2035  *****************************************************************************/
2036 static void HwBuffer_ChangeState( decoder_t *p_dec, OmxPort *p_port,
2037                                   int i_index, int i_state )
2038 {
2039     VLC_UNUSED( p_dec );
2040     p_port->p_hwbuf->i_states[i_index] = i_state;
2041     if( i_state == BUF_STATE_OWNED )
2042         p_port->p_hwbuf->i_owned++;
2043     else
2044         p_port->p_hwbuf->i_owned--;
2045
2046     OMX_DBG( "buffer[%d]: state -> %d, owned buffers: %u",
2047              i_index, i_state, p_port->p_hwbuf->i_owned );
2048 }
2049
2050 /*****************************************************************************
2051  * HwBuffer_Init
2052  *****************************************************************************/
2053 static void HwBuffer_Init( decoder_t *p_dec, OmxPort *p_port )
2054 {
2055     VLC_UNUSED( p_dec );
2056     void *surf;
2057     JNIEnv *p_env;
2058     OMX_ERRORTYPE omx_error;
2059
2060     if( !p_port->b_direct || p_port->definition.eDir != OMX_DirOutput ||
2061         p_port->p_fmt->i_cat != VIDEO_ES )
2062         return;
2063
2064     msg_Dbg( p_dec, "HwBuffer_Init");
2065
2066     if( !(pf_enable_graphic_buffers && pf_get_graphic_buffer_usage &&
2067           pf_get_hal_format &&
2068           ((OMX_COMPONENTTYPE*)p_port->omx_handle)->UseBuffer) )
2069     {
2070         msg_Warn( p_dec, "direct output port enabled but can't find "
2071                           "extra symbols, switch back to non direct" );
2072         goto error;
2073     }
2074
2075     p_port->p_hwbuf = calloc(1, sizeof(HwBuffer));
2076     if( !p_port->p_hwbuf )
2077     {
2078         goto error;
2079     }
2080     vlc_cond_init (&p_port->p_hwbuf->wait);
2081     p_port->p_hwbuf->p_library = LoadNativeWindowAPI( &p_port->p_hwbuf->native_window );
2082     if( !p_port->p_hwbuf->p_library )
2083     {
2084         msg_Warn( p_dec, "LoadNativeWindowAPI failed" );
2085         goto error;
2086     }
2087     if( LoadNativeWindowPrivAPI( &p_port->p_hwbuf->anwpriv ) != 0 )
2088     {
2089         msg_Warn( p_dec, "LoadNativeWindowPrivAPI failed" );
2090         goto error;
2091     }
2092
2093     surf = jni_LockAndGetAndroidJavaSurface();
2094     if( !surf ) {
2095         jni_UnlockAndroidSurface();
2096         msg_Warn( p_dec, "jni_LockAndGetAndroidJavaSurface failed" );
2097         goto error;
2098     }
2099
2100     jni_attach_thread( &p_env, THREAD_NAME );
2101     p_port->p_hwbuf->window = p_port->p_hwbuf->native_window.winFromSurface( p_env, surf );
2102     jni_detach_thread();
2103
2104     jni_UnlockAndroidSurface();
2105     if( !p_port->p_hwbuf->window ) {
2106         msg_Warn( p_dec, "winFromSurface failed" );
2107         goto error;
2108     }
2109     p_port->p_hwbuf->window_priv =
2110         p_port->p_hwbuf->anwpriv.connect( p_port->p_hwbuf->window );
2111     if( !p_port->p_hwbuf->window_priv ) {
2112         msg_Warn( p_dec, "connect failed" );
2113         p_port->p_hwbuf->native_window.winRelease( p_port->p_hwbuf->window );
2114         p_port->p_hwbuf->window = NULL;
2115         goto error;
2116     }
2117
2118     omx_error = pf_enable_graphic_buffers( p_port->omx_handle,
2119                                            p_port->i_port_index, OMX_TRUE );
2120     CHECK_ERROR( omx_error, "can't enable graphic buffers" );
2121
2122     /* PortDefinition may change after pf_enable_graphic_buffers call */
2123     omx_error = OMX_GetParameter( p_port->omx_handle,
2124                                   OMX_IndexParamPortDefinition,
2125                                   &p_port->definition );
2126     CHECK_ERROR( omx_error, "OMX_GetParameter failed (GraphicBuffers) (%x : %s)",
2127                  omx_error, ErrorToString(omx_error) );
2128
2129
2130     msg_Dbg( p_dec, "direct output port enabled" );
2131     return;
2132 error:
2133     /* if HwBuffer_Init fails, we can fall back to non direct buffers */
2134     HwBuffer_Destroy( p_dec, p_port );
2135 }
2136
2137 /*****************************************************************************
2138  * HwBuffer_Destroy
2139  *****************************************************************************/
2140 static void HwBuffer_Destroy( decoder_t *p_dec, OmxPort *p_port )
2141 {
2142     if( p_port->p_hwbuf )
2143     {
2144         if( p_port->p_hwbuf->p_library )
2145         {
2146             if( p_port->p_hwbuf->window )
2147             {
2148                 HwBuffer_Stop( p_dec, p_port );
2149                 HwBuffer_FreeBuffers( p_dec, p_port );
2150                 HwBuffer_Join( p_dec, p_port );
2151                 p_port->p_hwbuf->anwpriv.disconnect( p_port->p_hwbuf->window_priv );
2152                 pf_enable_graphic_buffers( p_port->omx_handle,
2153                                            p_port->i_port_index, OMX_FALSE );
2154                 p_port->p_hwbuf->native_window.winRelease( p_port->p_hwbuf->window );
2155             }
2156             dlclose( p_port->p_hwbuf->p_library );
2157         }
2158
2159         vlc_cond_destroy( &p_port->p_hwbuf->wait );
2160         free( p_port->p_hwbuf );
2161         p_port->p_hwbuf = NULL;
2162     }
2163     p_port->b_direct = false;
2164 }
2165
2166 /*****************************************************************************
2167  * HwBuffer_AllocateBuffers
2168  *****************************************************************************/
2169 static int HwBuffer_AllocateBuffers( decoder_t *p_dec, OmxPort *p_port )
2170 {
2171     decoder_sys_t *p_sys = p_dec->p_sys;
2172     OMX_PARAM_PORTDEFINITIONTYPE *def = &p_port->definition;
2173     unsigned int min_undequeued = 0;
2174     unsigned int i = 0;
2175     int colorFormat = def->format.video.eColorFormat;
2176     OMX_ERRORTYPE omx_error;
2177     OMX_U32 i_hw_usage;
2178
2179     if( !p_port->p_hwbuf )
2180         return 0;
2181
2182     omx_error = pf_get_hal_format( p_sys->psz_component, &colorFormat );
2183     if( omx_error != OMX_ErrorNone )
2184     {
2185         msg_Warn( p_dec, "pf_get_hal_format failed (Not fatal)" );
2186     }
2187
2188     omx_error = pf_get_graphic_buffer_usage( p_port->omx_handle,
2189                                              p_port->i_port_index,
2190                                              &i_hw_usage );
2191     if( omx_error != OMX_ErrorNone )
2192     {
2193         msg_Warn( p_dec, "pf_get_graphic_buffer_usage failed (Not fatal)" );
2194         i_hw_usage = 0;
2195     }
2196
2197     if( p_port->p_fmt->video.orientation != ORIENT_NORMAL )
2198     {
2199         int i_angle;
2200
2201         switch( p_port->p_fmt->video.orientation )
2202         {
2203             case ORIENT_ROTATED_90:
2204                 i_angle = 90;
2205                 break;
2206             case ORIENT_ROTATED_180:
2207                 i_angle = 180;
2208                 break;
2209             case ORIENT_ROTATED_270:
2210                 i_angle = 270;
2211                 break;
2212             default:
2213                 i_angle = 0;
2214         }
2215         p_port->p_hwbuf->anwpriv.setOrientation( p_port->p_hwbuf->window_priv,
2216                                                  i_angle );
2217         video_format_ApplyRotation( &p_port->p_hwbuf->fmt_out,
2218                                     &p_port->p_fmt->video );
2219     } else
2220         p_port->p_hwbuf->fmt_out = p_port->p_fmt->video;
2221
2222     if( p_port->p_hwbuf->anwpriv.setup( p_port->p_hwbuf->window_priv,
2223                                         def->format.video.nFrameWidth,
2224                                         def->format.video.nFrameHeight,
2225                                         colorFormat,
2226                                         true,
2227                                         (int) i_hw_usage ) != 0 )
2228     {
2229         msg_Err( p_dec, "can't setup OMXHWBuffer" );
2230         goto error;
2231     }
2232
2233     if( p_port->p_hwbuf->anwpriv.getMinUndequeued( p_port->p_hwbuf->window_priv,
2234                                                    &min_undequeued ) != 0 )
2235     {
2236         msg_Err( p_dec, "can't get min_undequeued" );
2237         goto error;
2238     }
2239
2240     if( def->nBufferCountActual < def->nBufferCountMin + min_undequeued )
2241     {
2242         unsigned int new_frames_num = def->nBufferCountMin + min_undequeued;
2243
2244         OMX_DBG( "AllocateBuffers: video out wants more frames: %lu vs %u",
2245                  p_port->definition.nBufferCountActual, new_frames_num );
2246
2247         p_port->definition.nBufferCountActual = new_frames_num;
2248         omx_error = OMX_SetParameter( p_dec->p_sys->omx_handle,
2249                                       OMX_IndexParamPortDefinition,
2250                                       &p_port->definition );
2251         CHECK_ERROR( omx_error, "OMX_SetParameter failed (%x : %s)",
2252                      omx_error, ErrorToString(omx_error) );
2253     }
2254
2255     if( p_port->p_hwbuf->anwpriv.setBufferCount( p_port->p_hwbuf->window_priv,
2256                                                  def->nBufferCountActual ) != 0 )
2257     {
2258         msg_Err( p_dec, "can't set buffer_count" );
2259         goto error;
2260     }
2261
2262     jni_SetAndroidSurfaceSize( p_port->p_hwbuf->fmt_out.i_width,
2263                                p_port->p_hwbuf->fmt_out.i_height,
2264                                p_port->p_hwbuf->fmt_out.i_visible_width,
2265                                p_port->p_hwbuf->fmt_out.i_visible_height,
2266                                p_port->p_hwbuf->fmt_out.i_sar_num,
2267                                p_port->p_hwbuf->fmt_out.i_sar_den );
2268
2269     p_port->p_hwbuf->i_buffers = p_port->definition.nBufferCountActual;
2270     p_port->p_hwbuf->i_max_owned = p_port->p_hwbuf->i_buffers - min_undequeued;
2271
2272     p_port->p_hwbuf->pp_handles = calloc( p_port->p_hwbuf->i_buffers,
2273                                           sizeof(void *) );
2274     if( !p_port->p_hwbuf->pp_handles )
2275         goto error;
2276
2277     p_port->p_hwbuf->i_states = calloc( p_port->p_hwbuf->i_buffers, sizeof(int) );
2278     if( !p_port->p_hwbuf->i_states )
2279         goto error;
2280
2281     p_port->p_hwbuf->inflight_picture = calloc( p_port->p_hwbuf->i_buffers,
2282                                                 sizeof(picture_t*) );
2283     if( !p_port->p_hwbuf->inflight_picture )
2284         goto error;
2285
2286     for(i = 0; i < p_port->p_hwbuf->i_buffers; i++)
2287     {
2288         void *p_handle = NULL;
2289
2290         if( p_port->p_hwbuf->anwpriv.dequeue( p_port->p_hwbuf->window_priv,
2291                                               &p_handle ) != 0 )
2292         {
2293             msg_Err( p_dec, "OMXHWBuffer_dequeue Fail" );
2294             goto error;
2295         }
2296         p_port->p_hwbuf->pp_handles[i] = p_handle;
2297     }
2298     for(i = 0; i < p_port->p_hwbuf->i_max_owned; i++)
2299         HwBuffer_ChangeState( p_dec, p_port, i, BUF_STATE_OWNED );
2300     for(; i < p_port->p_hwbuf->i_buffers; i++)
2301     {
2302         OMX_DBG( "canceling buffer(%d)", i );
2303         p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv,
2304                                          p_port->p_hwbuf->pp_handles[i] );
2305     }
2306
2307     return 0;
2308
2309 error:
2310
2311     msg_Err( p_dec, "HwBuffer_AllocateBuffers(%d) failed", def->eDir );
2312     return -1;
2313 }
2314
2315 /*****************************************************************************
2316  * HwBuffer_FreeBuffers
2317  *****************************************************************************/
2318 static int HwBuffer_FreeBuffers( decoder_t *p_dec, OmxPort *p_port )
2319 {
2320     msg_Dbg( p_dec, "HwBuffer_FreeBuffers");
2321
2322     HWBUFFER_LOCK();
2323
2324     p_port->p_hwbuf->b_run = false;
2325
2326     if( p_port->p_hwbuf->pp_handles )
2327     {
2328         for(unsigned int i = 0; i < p_port->p_hwbuf->i_buffers; i++)
2329         {
2330             void *p_handle = p_port->p_hwbuf->pp_handles[i];
2331
2332             if( p_handle && p_port->p_hwbuf->i_states[i] == BUF_STATE_OWNED )
2333             {
2334                 p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle );
2335                 HwBuffer_ChangeState( p_dec, p_port, i, BUF_STATE_NOT_OWNED );
2336             }
2337         }
2338     }
2339     HWBUFFER_BROADCAST( p_port );
2340
2341     HWBUFFER_UNLOCK();
2342
2343     p_port->p_hwbuf->i_buffers = 0;
2344
2345     free( p_port->p_hwbuf->pp_handles );
2346     p_port->p_hwbuf->pp_handles = NULL;
2347
2348     free( p_port->p_hwbuf->i_states );
2349     p_port->p_hwbuf->i_states = NULL;
2350
2351     free( p_port->p_hwbuf->inflight_picture );
2352     p_port->p_hwbuf->inflight_picture = NULL;
2353
2354     return 0;
2355 }
2356
2357 /*****************************************************************************
2358  * HwBuffer_Start
2359  *****************************************************************************/
2360 static int HwBuffer_Start( decoder_t *p_dec, OmxPort *p_port )
2361 {
2362     OMX_BUFFERHEADERTYPE *p_header;
2363
2364     msg_Dbg( p_dec, "HwBuffer_Start" );
2365     HWBUFFER_LOCK();
2366
2367     /* fill all owned buffers dequeued by HwBuffer_AllocatesBuffers */
2368     for(unsigned int i = 0; i < p_port->p_hwbuf->i_buffers; i++)
2369     {
2370         p_header = p_port->pp_buffers[i];
2371
2372         if( p_header && p_port->p_hwbuf->i_states[i] == BUF_STATE_OWNED )
2373         {
2374             if( p_port->p_hwbuf->anwpriv.lock( p_port->p_hwbuf->window_priv,
2375                                                p_header->pBuffer ) != 0 )
2376             {
2377                 msg_Err( p_dec, "lock failed" );
2378                 HWBUFFER_UNLOCK();
2379                 return -1;
2380             }
2381             OMX_DBG( "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
2382             OMX_FillThisBuffer( p_port->omx_handle, p_header );
2383         }
2384     }
2385
2386     p_port->p_hwbuf->b_run = true;
2387     if( vlc_clone( &p_port->p_hwbuf->dequeue_thread,
2388                    DequeueThread, p_dec, VLC_THREAD_PRIORITY_LOW ) )
2389     {
2390         p_port->p_hwbuf->b_run = false;
2391         HWBUFFER_UNLOCK();
2392         return -1;
2393     }
2394
2395     HWBUFFER_UNLOCK();
2396
2397     return 0;
2398 }
2399
2400 /*****************************************************************************
2401  * HwBuffer_Stop: stop DequeueThread and invalidate all pictures that are sent
2402  * to vlc core. The thread can be stuck in dequeue, so don't
2403  * join it now since it can be unblocked later by HwBuffer_FreeBuffers.
2404  *****************************************************************************/
2405 static int HwBuffer_Stop( decoder_t *p_dec, OmxPort *p_port )
2406 {
2407     VLC_UNUSED( p_dec );
2408
2409     msg_Dbg( p_dec, "HwBuffer_Stop" );
2410     HWBUFFER_LOCK();
2411
2412     p_port->p_hwbuf->b_run = false;
2413
2414     /* invalidate and release all inflight pictures */
2415     if( p_port->p_hwbuf->inflight_picture ) {
2416         for( unsigned int i = 0; i < p_port->i_buffers; ++i ) {
2417             picture_t *p_pic = p_port->p_hwbuf->inflight_picture[i];
2418             if( p_pic ) {
2419                 picture_sys_t *p_picsys = p_pic->p_sys;
2420                 if( p_picsys ) {
2421                     void *p_handle = p_port->pp_buffers[p_picsys->i_index]->pBuffer;
2422                     if( p_handle )
2423                     {
2424                         p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle );
2425                         HwBuffer_ChangeState( p_dec, p_port, p_picsys->i_index,
2426                                               BUF_STATE_NOT_OWNED );
2427                     }
2428                     p_picsys->b_valid = false;
2429                 }
2430                 p_port->p_hwbuf->inflight_picture[i] = NULL;
2431             }
2432         }
2433     }
2434
2435     HWBUFFER_BROADCAST( p_port );
2436
2437     HWBUFFER_UNLOCK();
2438
2439     return 0;
2440 }
2441
2442 /*****************************************************************************
2443  * HwBuffer_Join: join DequeueThread previously stopped by HwBuffer_Stop.
2444  *****************************************************************************/
2445 static int HwBuffer_Join( decoder_t *p_dec, OmxPort *p_port )
2446 {
2447     VLC_UNUSED( p_dec );
2448
2449     if( p_port->p_hwbuf->dequeue_thread )
2450     {
2451         vlc_join( p_port->p_hwbuf->dequeue_thread, NULL );
2452         p_port->p_hwbuf->dequeue_thread = NULL;
2453     }
2454     return 0;
2455 }
2456
2457 /*****************************************************************************
2458  * HwBuffer_GetPic
2459  *****************************************************************************/
2460 static int HwBuffer_GetPic( decoder_t *p_dec, OmxPort *p_port,
2461                             picture_t **pp_pic)
2462 {
2463     int i_index = -1;
2464     picture_t *p_pic;
2465     picture_sys_t *p_picsys;
2466     OMX_BUFFERHEADERTYPE *p_header;
2467
2468     OMX_FIFO_PEEK(&p_port->fifo, p_header);
2469
2470     if( !p_header )
2471         return 0;
2472
2473     for(unsigned int i = 0; i < p_port->i_buffers; i++)
2474     {
2475         if( p_port->pp_buffers[i] == p_header )
2476         {
2477             i_index = i;
2478             break;
2479         }
2480     }
2481     if( i_index == -1 )
2482     {
2483         msg_Err( p_dec, "output buffer not found" );
2484         return -1;
2485     }
2486
2487     p_pic = decoder_NewPicture( p_dec );
2488     if(!p_pic)
2489     {
2490         msg_Err( p_dec, "decoder_NewPicture failed" );
2491         return -1;
2492     }
2493     p_pic->date = FromOmxTicks( p_header->nTimeStamp );
2494
2495     p_picsys = p_pic->p_sys;
2496     p_picsys->pf_display_callback = DisplayCallback;
2497     p_picsys->pf_unlock_callback = UnlockCallback;
2498     p_picsys->p_dec = p_dec;
2499     p_picsys->i_index = i_index;
2500     p_picsys->b_valid = true;
2501
2502     HWBUFFER_LOCK();
2503     p_port->p_hwbuf->inflight_picture[i_index] = p_pic;
2504     HWBUFFER_UNLOCK();
2505
2506     *pp_pic = p_pic;
2507     OMX_FIFO_GET( &p_port->fifo, p_header );
2508     return 0;
2509 }
2510
2511 /*****************************************************************************
2512  * HwBuffer_SetCrop
2513  *****************************************************************************/
2514 static void HwBuffer_SetCrop( decoder_t *p_dec, OmxPort *p_port,
2515                               OMX_CONFIG_RECTTYPE *p_rect )
2516 {
2517     VLC_UNUSED( p_dec );
2518
2519     p_port->p_hwbuf->anwpriv.setCrop( p_port->p_hwbuf->window_priv,
2520                                       p_rect->nLeft, p_rect->nTop,
2521                                       p_rect->nWidth, p_rect->nHeight );
2522 }
2523
2524 /*****************************************************************************
2525  * DequeueThread
2526  *****************************************************************************/
2527 static void *DequeueThread( void *data )
2528 {
2529     decoder_t *p_dec = data;
2530     decoder_sys_t *p_sys = p_dec->p_sys;;
2531     OmxPort *p_port = &p_sys->out;
2532     unsigned int i;
2533     int i_index = -1;
2534     int err;
2535     void *p_handle = NULL;
2536     OMX_BUFFERHEADERTYPE *p_header;
2537
2538     msg_Dbg( p_dec, "DequeueThread running");
2539     HWBUFFER_LOCK();
2540     while( p_port->p_hwbuf->b_run )
2541     {
2542         while( p_port->p_hwbuf->b_run &&
2543                p_port->p_hwbuf->i_owned >= p_port->p_hwbuf->i_max_owned )
2544             HWBUFFER_WAIT( p_port );
2545
2546         if( !p_port->p_hwbuf->b_run ) continue;
2547
2548         HWBUFFER_UNLOCK();
2549
2550
2551         /* The thread can be stuck here. It shouldn't happen since we make sure
2552          * we call the dequeue function if there is at least one buffer
2553          * available. */
2554         err = p_port->p_hwbuf->anwpriv.dequeue( p_port->p_hwbuf->window_priv, &p_handle );
2555         if( err == 0 )
2556             err = p_port->p_hwbuf->anwpriv.lock( p_port->p_hwbuf->window_priv, p_handle );
2557
2558         HWBUFFER_LOCK();
2559
2560         if( err != 0 ) {
2561             if( err != -EBUSY )
2562                 p_port->p_hwbuf->b_run = false;
2563             continue;
2564         }
2565
2566         if( !p_port->p_hwbuf->b_run )
2567         {
2568             p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle );
2569             continue;
2570         }
2571
2572         for(i = 0; i < p_port->i_buffers; i++)
2573         {
2574             if( p_port->pp_buffers[i]->pBuffer == p_handle )
2575             {
2576                 i_index = i;
2577                 p_header = p_port->pp_buffers[i_index];
2578                 break;
2579             }
2580         }
2581         if( i_index == -1 )
2582         {
2583             msg_Err( p_dec, "p_port->p_hwbuf->anwpriv.dequeue returned unknown handle" );
2584             continue;
2585         }
2586
2587         HwBuffer_ChangeState( p_dec, p_port, i_index, BUF_STATE_OWNED );
2588
2589         OMX_DBG( "FillThisBuffer %p, %p", p_header, p_header->pBuffer );
2590         OMX_FillThisBuffer( p_sys->omx_handle, p_header );
2591
2592         HWBUFFER_BROADCAST( p_port );
2593     }
2594     HWBUFFER_UNLOCK();
2595
2596     msg_Dbg( p_dec, "DequeueThread stopped");
2597     return NULL;
2598 }
2599
2600 /*****************************************************************************
2601  * vout callbacks
2602  *****************************************************************************/
2603 static void DisplayBuffer( picture_sys_t* p_picsys, bool b_render )
2604 {
2605     decoder_t *p_dec = p_picsys->p_dec;
2606     decoder_sys_t *p_sys = p_dec->p_sys;
2607     OmxPort *p_port = &p_sys->out;
2608     void *p_handle;
2609
2610     if( !p_picsys->b_valid ) return;
2611
2612     HWBUFFER_LOCK();
2613
2614     /* Picture might have been invalidated while waiting on the mutex. */
2615     if (!p_picsys->b_valid) {
2616         HWBUFFER_UNLOCK();
2617         return;
2618     }
2619
2620     p_handle = p_port->pp_buffers[p_picsys->i_index]->pBuffer;
2621
2622     OMX_DBG( "DisplayBuffer: %s %p",
2623              b_render ? "render" : "cancel", p_handle );
2624
2625     if( !p_handle )
2626     {
2627         msg_Err( p_dec, "DisplayBuffer: buffer handle invalid" );
2628         goto end;
2629     }
2630
2631     if( b_render )
2632         p_port->p_hwbuf->anwpriv.queue( p_port->p_hwbuf->window_priv, p_handle );
2633     else
2634         p_port->p_hwbuf->anwpriv.cancel( p_port->p_hwbuf->window_priv, p_handle );
2635
2636     HwBuffer_ChangeState( p_dec, p_port, p_picsys->i_index, BUF_STATE_NOT_OWNED );
2637     HWBUFFER_BROADCAST( p_port );
2638
2639     p_port->p_hwbuf->inflight_picture[p_picsys->i_index] = NULL;
2640
2641 end:
2642     p_picsys->b_valid = false;
2643     p_picsys->i_index = -1;
2644
2645     HWBUFFER_UNLOCK();
2646 }
2647
2648 static void UnlockCallback( picture_sys_t* p_picsys )
2649 {
2650     DisplayBuffer( p_picsys, false );
2651 }
2652
2653 static void DisplayCallback( picture_sys_t* p_picsys )
2654 {
2655     DisplayBuffer( p_picsys, true );
2656 }
2657
2658 #endif // USE_IOMX