1 /*****************************************************************************
2 * omxil.c: Video decoder module making use of OpenMAX IL components.
3 *****************************************************************************
4 * Copyright (C) 2010 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_block_helper.h>
38 #include "../../packetizer/h264_nal.h"
39 #include "../../packetizer/hevc_nal.h"
42 #include "omxil_core.h"
43 #include "OMX_Broadcom.h"
48 #include "../../video_output/android/display.h"
52 # define OMX_DBG(...) msg_Dbg( p_dec, __VA_ARGS__ )
57 #define SENTINEL_FLAG 0x10000
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
64 /* Defined in the broadcom version of OMX_Core.h */
65 #define OMX_EventParamOrConfigChanged 0x7F000001
68 /* JNI functions to get/set an Android Surface object. */
69 #define THREAD_NAME "omxil"
72 /*****************************************************************************
74 *****************************************************************************/
75 static int OpenDecoder( vlc_object_t
* );
76 static int OpenEncoder( vlc_object_t
* );
77 static int OpenGeneric( vlc_object_t
*, bool b_encode
);
78 static void CloseGeneric( vlc_object_t
* );
80 static int DecodeVideo( decoder_t
*, block_t
* );
81 static int DecodeAudio ( decoder_t
*, block_t
* );
82 static block_t
*EncodeVideo( encoder_t
*, picture_t
* );
83 static void Flush( decoder_t
* );
85 static OMX_ERRORTYPE
OmxEventHandler( OMX_HANDLETYPE
, OMX_PTR
, OMX_EVENTTYPE
,
86 OMX_U32
, OMX_U32
, OMX_PTR
);
87 static OMX_ERRORTYPE
OmxEmptyBufferDone( OMX_HANDLETYPE
, OMX_PTR
,
88 OMX_BUFFERHEADERTYPE
* );
89 static OMX_ERRORTYPE
OmxFillBufferDone( OMX_HANDLETYPE
, OMX_PTR
,
90 OMX_BUFFERHEADERTYPE
* );
93 static void *DequeueThread( void *data
);
94 static void ReleasePicture( decoder_t
*p_dec
, unsigned int i_index
, bool b_render
);
95 static void HwBuffer_Init( decoder_t
*p_dec
, OmxPort
*p_port
);
96 static void HwBuffer_Destroy( decoder_t
*p_dec
, OmxPort
*p_port
);
97 static int HwBuffer_AllocateBuffers( decoder_t
*p_dec
, OmxPort
*p_port
);
98 static int HwBuffer_FreeBuffers( decoder_t
*p_dec
, OmxPort
*p_port
);
99 static int HwBuffer_Start( decoder_t
*p_dec
, OmxPort
*p_port
);
100 static int HwBuffer_Stop( decoder_t
*p_dec
, OmxPort
*p_port
);
101 static int HwBuffer_Join( decoder_t
*p_dec
, OmxPort
*p_port
);
102 static int HwBuffer_GetPic( decoder_t
*p_dec
, OmxPort
*p_port
,
103 picture_t
**pp_pic
);
104 static void HwBuffer_SetCrop( decoder_t
*p_dec
, OmxPort
*p_port
,
105 OMX_CONFIG_RECTTYPE
*p_rect
);
106 static void HwBuffer_ChangeState( decoder_t
*p_dec
, OmxPort
*p_port
,
107 int i_index
, int i_state
);
109 #define HWBUFFER_LOCK(p_port) vlc_mutex_lock( &(p_port)->p_hwbuf->lock )
110 #define HWBUFFER_UNLOCK(p_port) vlc_mutex_unlock( &(p_port)->p_hwbuf->lock )
111 #define HWBUFFER_WAIT(p_port) vlc_cond_wait( &(p_port)->p_hwbuf->wait, \
112 &(p_port)->p_hwbuf->lock )
113 #define HWBUFFER_BROADCAST(p_port) vlc_cond_broadcast( &(p_port)->p_hwbuf->wait )
116 static inline int HwBuffer_dummy( )
120 #define HwBuffer_Init(p_dec, p_port) do { } while (0)
121 #define HwBuffer_Destroy(p_dec, p_port) do { } while (0)
122 #define HwBuffer_AllocateBuffers(p_dec, p_port) HwBuffer_dummy()
123 #define HwBuffer_FreeBuffers(p_dec, p_port) HwBuffer_dummy()
124 #define HwBuffer_Start(p_dec, p_port) HwBuffer_dummy()
125 #define HwBuffer_Stop(p_dec, p_port) HwBuffer_dummy()
126 #define HwBuffer_Join(p_dec, p_port) HwBuffer_dummy()
127 #define HwBuffer_GetPic(p_dec, p_port, pp_pic) HwBuffer_dummy()
128 #define HwBuffer_SetCrop(p_dec, p_port, p_rect) do { } while (0)
130 #define HWBUFFER_LOCK(p_port) do { } while (0)
131 #define HWBUFFER_UNLOCK(p_port) do { } while (0)
132 #define HWBUFFER_WAIT(p_port) do { } while (0)
133 #define HWBUFFER_BROADCAST(p_port) do { } while (0)
136 /*****************************************************************************
138 *****************************************************************************/
139 #define DIRECTRENDERING_TEXT N_("OMX direct rendering")
140 #define DIRECTRENDERING_LONGTEXT N_(\
141 "Enable OMX direct rendering.")
143 #define CFG_PREFIX "omxil-"
145 set_description( N_("Audio/Video decoder (using OpenMAX IL)") )
146 set_category( CAT_INPUT
)
147 set_subcategory( SUBCAT_INPUT_VCODEC
)
148 set_section( N_("Decoding") , NULL
)
149 #if defined(USE_IOMX)
150 /* For IOMX, don't enable it automatically via priorities,
151 * enable it only via the --codec iomx command line parameter when
153 set_capability( "video decoder", 0 )
154 add_bool(CFG_PREFIX
"dr", true,
155 DIRECTRENDERING_TEXT
, DIRECTRENDERING_LONGTEXT
, true)
157 set_capability( "video decoder", 80 )
159 set_callbacks( OpenDecoder
, CloseGeneric
)
162 # if defined(USE_IOMX)
163 set_capability("audio decoder", 0)
165 set_capability("audio decoder", 80)
167 set_callbacks(OpenDecoder
, CloseGeneric
)
171 set_section( N_("Encoding") , NULL
)
172 set_description( N_("Video encoder (using OpenMAX IL)") )
173 set_capability( "encoder", 0 )
174 set_callbacks( OpenEncoder
, CloseGeneric
)
177 /*****************************************************************************
178 * ImplementationSpecificWorkarounds: place-holder for implementation
179 * specific workarounds
180 *****************************************************************************/
181 static OMX_ERRORTYPE
ImplementationSpecificWorkarounds(decoder_t
*p_dec
,
182 OmxPort
*p_port
, es_format_t
*p_fmt
)
184 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
185 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
186 uint8_t i_profile
= 0xFF, i_level
= 0xFF;
188 /* Try to find out the profile of the video */
189 if(p_fmt
->i_cat
== VIDEO_ES
&& def
->eDir
== OMX_DirInput
&&
190 p_fmt
->i_codec
== VLC_CODEC_H264
)
191 h264_get_profile_level(&p_dec
->fmt_in
, &i_profile
, &i_level
, &p_sys
->i_nal_size_length
);
193 if(!strcmp(p_sys
->psz_component
, "OMX.TI.Video.Decoder"))
195 if(p_fmt
->i_cat
== VIDEO_ES
&& def
->eDir
== OMX_DirInput
&&
196 p_fmt
->i_codec
== VLC_CODEC_H264
&&
197 (i_profile
!= PROFILE_H264_BASELINE
|| i_level
> 30))
199 msg_Dbg(p_dec
, "h264 profile/level not supported (0x" PRIx8
", 0x" PRIx8
")",
201 return OMX_ErrorNotImplemented
;
204 if(p_fmt
->i_cat
== VIDEO_ES
&& def
->eDir
== OMX_DirOutput
&&
205 p_fmt
->i_codec
== VLC_CODEC_I420
)
207 /* I420 xvideo is slow on OMAP */
208 def
->format
.video
.eColorFormat
= OMX_COLOR_FormatCbYCrY
;
209 GetVlcChromaFormat( def
->format
.video
.eColorFormat
,
210 &p_fmt
->i_codec
, 0 );
211 GetVlcChromaSizes( p_fmt
->i_codec
,
212 def
->format
.video
.nFrameWidth
,
213 def
->format
.video
.nFrameHeight
,
214 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
215 &p_port
->i_frame_stride_chroma_div
);
216 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
217 def
->nBufferSize
= p_port
->i_frame_size
;
220 else if(!strcmp(p_sys
->psz_component
, "OMX.st.video_encoder"))
222 if(p_fmt
->i_cat
== VIDEO_ES
)
224 /* Bellagio's encoder doesn't encode the framerate in Q16 */
225 def
->format
.video
.xFramerate
>>= 16;
228 #if 0 /* FIXME: doesn't apply for HP Touchpad */
229 else if (!strncmp(p_sys
->psz_component
, "OMX.qcom.video.decoder.",
230 strlen("OMX.qcom.video.decoder")))
232 /* qdsp6 refuses buffer size larger than 450K on input port */
233 if (def
->nBufferSize
> 450 * 1024)
235 def
->nBufferSize
= 450 * 1024;
236 p_port
->i_frame_size
= def
->nBufferSize
;
241 else if (!strcmp(p_sys
->psz_component
, "OMX.broadcom.video_decode"))
243 /* Clear these fields before setting parameters, to allow the codec
244 * fill in what it wants (instead of rejecting whatever happened to
246 def
->format
.video
.nStride
= def
->format
.video
.nSliceHeight
= 0;
250 return OMX_ErrorNone
;
253 /*****************************************************************************
254 * SetPortDefinition: set definition of the omx port based on the vlc format
255 *****************************************************************************/
256 static OMX_ERRORTYPE
SetPortDefinition(decoder_t
*p_dec
, OmxPort
*p_port
,
259 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
260 OMX_ERRORTYPE omx_error
;
262 omx_error
= OMX_GetParameter(p_port
->omx_handle
,
263 OMX_IndexParamPortDefinition
, def
);
264 CHECK_ERROR(omx_error
, "OMX_GetParameter failed (%x : %s)",
265 omx_error
, ErrorToString(omx_error
));
270 def
->format
.video
.nFrameWidth
= p_fmt
->video
.i_width
;
271 def
->format
.video
.nFrameHeight
= p_fmt
->video
.i_height
;
272 if(def
->format
.video
.eCompressionFormat
== OMX_VIDEO_CodingUnused
)
273 def
->format
.video
.nStride
= def
->format
.video
.nFrameWidth
;
274 if( p_fmt
->video
.i_frame_rate
> 0 &&
275 p_fmt
->video
.i_frame_rate_base
> 0 )
276 def
->format
.video
.xFramerate
= (p_fmt
->video
.i_frame_rate
<< 16) /
277 p_fmt
->video
.i_frame_rate_base
;
279 if(def
->eDir
== OMX_DirInput
|| p_dec
->p_sys
->b_enc
)
281 if (def
->eDir
== OMX_DirInput
&& p_dec
->p_sys
->b_enc
)
282 def
->nBufferSize
= def
->format
.video
.nFrameWidth
*
283 def
->format
.video
.nFrameHeight
* 2;
284 p_port
->i_frame_size
= def
->nBufferSize
;
286 if(!GetOmxVideoFormat(p_fmt
->i_codec
,
287 &def
->format
.video
.eCompressionFormat
, 0) )
289 if(!GetOmxChromaFormat(p_fmt
->i_codec
,
290 &def
->format
.video
.eColorFormat
, 0) )
292 omx_error
= OMX_ErrorNotImplemented
;
293 CHECK_ERROR(omx_error
, "codec %4.4s doesn't match any OMX format",
294 (char *)&p_fmt
->i_codec
);
296 GetVlcChromaSizes( p_fmt
->i_codec
,
297 def
->format
.video
.nFrameWidth
,
298 def
->format
.video
.nFrameHeight
,
299 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
300 &p_port
->i_frame_stride_chroma_div
);
301 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
302 def
->nBufferSize
= p_port
->i_frame_size
;
307 if( p_port
->p_hwbuf
)
309 p_fmt
->i_codec
= VLC_CODEC_ANDROID_OPAQUE
;
313 if( !GetVlcChromaFormat( def
->format
.video
.eColorFormat
,
314 &p_fmt
->i_codec
, 0 ) )
316 omx_error
= OMX_ErrorNotImplemented
;
317 CHECK_ERROR(omx_error
, "OMX color format %i not supported",
318 (int)def
->format
.video
.eColorFormat
);
320 GetVlcChromaSizes( p_fmt
->i_codec
,
321 def
->format
.video
.nFrameWidth
,
322 def
->format
.video
.nFrameHeight
,
323 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
324 &p_port
->i_frame_stride_chroma_div
);
325 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
326 if (p_port
->i_frame_size
> def
->nBufferSize
)
327 def
->nBufferSize
= p_port
->i_frame_size
;
332 p_port
->i_frame_size
= def
->nBufferSize
;
333 if(def
->eDir
== OMX_DirInput
)
335 if(!GetOmxAudioFormat(p_fmt
->i_codec
,
336 &def
->format
.audio
.eEncoding
, 0) )
338 omx_error
= OMX_ErrorNotImplemented
;
339 CHECK_ERROR(omx_error
, "codec %4.4s doesn't match any OMX format",
340 (char *)&p_fmt
->i_codec
);
345 if( !OmxToVlcAudioFormat(def
->format
.audio
.eEncoding
,
346 &p_fmt
->i_codec
, 0 ) )
348 omx_error
= OMX_ErrorNotImplemented
;
349 CHECK_ERROR(omx_error
, "OMX audio encoding %i not supported",
350 (int)def
->format
.audio
.eEncoding
);
355 default: return OMX_ErrorNotImplemented
;
358 omx_error
= ImplementationSpecificWorkarounds(p_dec
, p_port
, p_fmt
);
359 CHECK_ERROR(omx_error
, "ImplementationSpecificWorkarounds failed (%x : %s)",
360 omx_error
, ErrorToString(omx_error
));
362 omx_error
= OMX_SetParameter(p_port
->omx_handle
,
363 OMX_IndexParamPortDefinition
, def
);
364 CHECK_ERROR(omx_error
, "OMX_SetParameter failed (%x : %s)",
365 omx_error
, ErrorToString(omx_error
));
367 omx_error
= OMX_GetParameter(p_port
->omx_handle
,
368 OMX_IndexParamPortDefinition
, def
);
369 CHECK_ERROR(omx_error
, "OMX_GetParameter failed (%x : %s)",
370 omx_error
, ErrorToString(omx_error
));
372 if(p_port
->i_frame_size
> def
->nBufferSize
)
373 def
->nBufferSize
= p_port
->i_frame_size
;
374 p_port
->i_frame_size
= def
->nBufferSize
;
376 /* Deal with audio params */
377 if(p_fmt
->i_cat
== AUDIO_ES
)
379 omx_error
= SetAudioParameters(p_port
->omx_handle
,
380 &p_port
->format_param
, def
->nPortIndex
,
381 def
->format
.audio
.eEncoding
,
383 p_fmt
->audio
.i_channels
,
386 p_fmt
->audio
.i_bitspersample
,
387 p_fmt
->audio
.i_blockalign
);
388 if (def
->eDir
== OMX_DirInput
) {
389 CHECK_ERROR(omx_error
, "SetAudioParameters failed (%x : %s)",
390 omx_error
, ErrorToString(omx_error
));
391 } else if (omx_error
!= OMX_ErrorNone
) {
392 msg_Warn(p_dec
, "SetAudioParameters failed (%x : %s) on output port",
393 omx_error
, ErrorToString(omx_error
));
394 omx_error
= OMX_ErrorNone
;
397 if (!strcmp(p_dec
->p_sys
->psz_component
, "OMX.TI.DUCATI1.VIDEO.DECODER") &&
398 def
->eDir
== OMX_DirOutput
&& !p_port
->p_hwbuf
)
400 /* When setting the output buffer size above, the decoder actually
401 * sets the buffer size to a lower value than what was chosen. If
402 * we try to allocate buffers of this size, it fails. Thus, forcibly
403 * use a larger buffer size. */
404 def
->nBufferSize
*= 2;
412 /*****************************************************************************
413 * UpdatePixelAspect: Update vlc pixel aspect based on the aspect reported on
414 * the omx port - NOTE: Broadcom specific
415 *****************************************************************************/
416 static OMX_ERRORTYPE
UpdatePixelAspect(decoder_t
*p_dec
)
418 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
419 OMX_CONFIG_POINTTYPE pixel_aspect
;
420 OMX_INIT_STRUCTURE(pixel_aspect
);
421 OMX_ERRORTYPE omx_err
;
423 if (strncmp(p_sys
->psz_component
, "OMX.broadcom.", 13))
424 return OMX_ErrorNotImplemented
;
426 pixel_aspect
.nPortIndex
= p_sys
->out
.i_port_index
;
427 omx_err
= OMX_GetParameter(p_sys
->omx_handle
,
428 OMX_IndexParamBrcmPixelAspectRatio
, &pixel_aspect
);
429 if (omx_err
!= OMX_ErrorNone
) {
430 msg_Warn(p_dec
, "Failed to retrieve aspect ratio");
432 p_dec
->fmt_out
.video
.i_sar_num
= pixel_aspect
.nX
;
433 p_dec
->fmt_out
.video
.i_sar_den
= pixel_aspect
.nY
;
439 /*****************************************************************************
440 * AllocateBuffers: Allocate Omx buffers
441 *****************************************************************************/
442 static OMX_ERRORTYPE
AllocateBuffers(decoder_t
*p_dec
, OmxPort
*p_port
)
444 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
445 OMX_ERRORTYPE omx_error
= OMX_ErrorUndefined
;
446 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
449 OMX_DBG( "AllocateBuffers(%d)", def
->eDir
);
451 p_port
->i_buffers
= p_port
->definition
.nBufferCountActual
;
453 p_port
->pp_buffers
= calloc(p_port
->i_buffers
, sizeof(OMX_BUFFERHEADERTYPE
*));
454 if( !p_port
->pp_buffers
)
456 p_port
->i_buffers
= 0;
457 return OMX_ErrorInsufficientResources
;
460 for(i
= 0; i
< p_port
->i_buffers
; i
++)
463 #define ALIGN(x,BLOCKLIGN) (((x) + BLOCKLIGN - 1) & ~(BLOCKLIGN - 1))
464 char *p_buf
= malloc(p_port
->definition
.nBufferSize
+
465 p_port
->definition
.nBufferAlignment
);
466 p_port
->pp_buffers
[i
] = (void *)ALIGN((uintptr_t)p_buf
, p_port
->definition
.nBufferAlignment
);
469 if( p_port
->p_hwbuf
)
472 OMX_UseBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[i
],
473 p_port
->i_port_index
, 0,
474 p_port
->definition
.nBufferSize
,
475 p_port
->p_hwbuf
->pp_handles
[i
] );
476 OMX_DBG( "OMX_UseBuffer(%d) %p, %p", def
->eDir
,
477 (void *)p_port
->pp_buffers
[i
],
478 p_port
->p_hwbuf
->pp_handles
[i
] );
480 else if( p_port
->b_direct
)
483 OMX_UseBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[i
],
484 p_port
->i_port_index
, 0,
485 p_port
->definition
.nBufferSize
, (void*)1);
486 OMX_DBG( "OMX_UseBuffer(%d) %p, %p", def
->eDir
,
487 (void *)p_port
->pp_buffers
[i
], p_port
->pp_buffers
[i
] ?
488 (void *)p_port
->pp_buffers
[i
]->pBuffer
: NULL
);
493 OMX_AllocateBuffer( p_sys
->omx_handle
, &p_port
->pp_buffers
[i
],
494 p_port
->i_port_index
, 0,
495 p_port
->definition
.nBufferSize
);
496 OMX_DBG( "OMX_AllocateBuffer(%d) %p, %p", def
->eDir
,
497 (void *)p_port
->pp_buffers
[i
], p_port
->pp_buffers
[i
] ?
498 (void *)p_port
->pp_buffers
[i
]->pBuffer
: NULL
);
501 if(omx_error
!= OMX_ErrorNone
)
503 p_port
->i_buffers
= i
;
506 if( !p_port
->p_hwbuf
)
507 OMX_FIFO_PUT(&p_port
->fifo
, p_port
->pp_buffers
[i
]);
510 CHECK_ERROR(omx_error
, "AllocateBuffers failed (%x, %i)",
511 omx_error
, (int)p_port
->i_port_index
);
514 OMX_DBG( "AllocateBuffers(%d)::done", def
->eDir
);
519 /*****************************************************************************
520 * FreeBuffers: Free Omx buffers
521 *****************************************************************************/
522 static OMX_ERRORTYPE
FreeBuffers(decoder_t
*p_dec
, OmxPort
*p_port
)
524 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
525 OMX_ERRORTYPE omx_error
= OMX_ErrorNone
;
526 OMX_BUFFERHEADERTYPE
*p_buffer
;
527 unsigned int i
, i_wait_buffers
;
529 /* Normally, all buffers are in the port fifo, or given to the codec that
530 * will return them when disabling the port or changing state, therefore we
531 * normally wait for all buffers. For IOMX direct rendering (HwBuffer),
532 * only a few buffers are given to the codec at a time, thus we can only
533 * wait for that many buffers. And after that, we can still free all OMX
534 * buffers since we either got some of them returned via OMX_FIFO_GET, or
535 * never passed them to the codec at all. */
536 if( p_port
->p_hwbuf
)
537 i_wait_buffers
= p_port
->p_hwbuf
->i_owned
;
539 i_wait_buffers
= p_port
->i_buffers
;
541 OMX_DBG( "FreeBuffers(%d), waiting for %u buffers", def
->eDir
,
544 for(i
= 0; i
< i_wait_buffers
; i
++)
546 OMX_FIFO_GET(&p_port
->fifo
, p_buffer
);
547 if (p_buffer
->nFlags
& SENTINEL_FLAG
) {
554 for(i
= 0; i
< p_port
->i_buffers
; i
++)
556 p_buffer
= p_port
->pp_buffers
[i
];
559 if (p_buffer
->pAppPrivate
!= NULL
)
560 picture_Release( p_buffer
->pAppPrivate
);
562 omx_error
= OMX_FreeBuffer( p_port
->omx_handle
,
563 p_port
->i_port_index
, p_buffer
);
564 OMX_DBG( "OMX_FreeBuffer(%d) %p, %p", def
->eDir
,
565 (void *)p_buffer
, (void *)p_buffer
->pBuffer
);
567 if(omx_error
!= OMX_ErrorNone
) break;
571 if( omx_error
!= OMX_ErrorNone
)
572 msg_Err( p_dec
, "OMX_FreeBuffer failed (%x, %i, %i)",
573 omx_error
, (int)p_port
->i_port_index
, i
);
575 p_port
->i_buffers
= 0;
576 free( p_port
->pp_buffers
);
577 p_port
->pp_buffers
= NULL
;
579 OMX_DBG( "FreeBuffers(%d)::done", def
->eDir
);
584 /*****************************************************************************
585 * GetPortDefinition: set vlc format based on the definition of the omx port
586 *****************************************************************************/
587 static OMX_ERRORTYPE
GetPortDefinition(decoder_t
*p_dec
, OmxPort
*p_port
,
590 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
591 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
592 OMX_ERRORTYPE omx_error
;
593 OMX_CONFIG_RECTTYPE crop_rect
;
595 omx_error
= OMX_GetParameter(p_port
->omx_handle
,
596 OMX_IndexParamPortDefinition
, def
);
597 CHECK_ERROR(omx_error
, "OMX_GetParameter failed (%x : %s)",
598 omx_error
, ErrorToString(omx_error
));
603 p_fmt
->video
.i_width
= def
->format
.video
.nFrameWidth
;
604 p_fmt
->video
.i_visible_width
= def
->format
.video
.nFrameWidth
;
605 p_fmt
->video
.i_height
= def
->format
.video
.nFrameHeight
;
606 p_fmt
->video
.i_visible_height
= def
->format
.video
.nFrameHeight
;
607 p_fmt
->video
.i_frame_rate
= p_dec
->fmt_in
.video
.i_frame_rate
;
608 p_fmt
->video
.i_frame_rate_base
= p_dec
->fmt_in
.video
.i_frame_rate_base
;
610 OMX_INIT_STRUCTURE(crop_rect
);
611 crop_rect
.nPortIndex
= def
->nPortIndex
;
612 omx_error
= OMX_GetConfig(p_port
->omx_handle
, OMX_IndexConfigCommonOutputCrop
, &crop_rect
);
613 if (omx_error
== OMX_ErrorNone
)
615 if (!def
->format
.video
.nSliceHeight
)
616 def
->format
.video
.nSliceHeight
= def
->format
.video
.nFrameHeight
;
617 if (!def
->format
.video
.nStride
)
618 def
->format
.video
.nStride
= def
->format
.video
.nFrameWidth
;
619 p_fmt
->video
.i_width
= crop_rect
.nWidth
;
620 p_fmt
->video
.i_visible_width
= crop_rect
.nWidth
;
621 p_fmt
->video
.i_height
= crop_rect
.nHeight
;
622 p_fmt
->video
.i_visible_height
= crop_rect
.nHeight
;
623 if (def
->format
.video
.eColorFormat
== OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
)
624 def
->format
.video
.nSliceHeight
-= crop_rect
.nTop
/2;
626 if( p_port
->p_hwbuf
)
627 HwBuffer_SetCrop( p_dec
, p_port
, &crop_rect
);
631 /* Don't pass the error back to the caller, this isn't mandatory */
632 omx_error
= OMX_ErrorNone
;
635 if( p_port
->p_hwbuf
)
637 UpdatePixelAspect(p_dec
);
640 /* Hack: Nexus One (stock firmware with binary OMX driver blob)
641 * claims to output 420Planar even though it in in practice is
643 if(def
->format
.video
.eColorFormat
== OMX_COLOR_FormatYUV420Planar
&&
644 !strncmp(p_sys
->psz_component
, "OMX.qcom.video.decoder",
645 strlen("OMX.qcom.video.decoder")))
646 def
->format
.video
.eColorFormat
= OMX_QCOM_COLOR_FormatYVU420SemiPlanar
;
648 if ((p_sys
->i_quirks
& OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING
)) {
649 def
->format
.video
.nSliceHeight
= 0;
650 def
->format
.video
.nStride
= p_fmt
->video
.i_width
;
653 if(!GetVlcVideoFormat( def
->format
.video
.eCompressionFormat
,
654 &p_fmt
->i_codec
, 0 ) )
656 if( !GetVlcChromaFormat( def
->format
.video
.eColorFormat
,
657 &p_fmt
->i_codec
, 0 ) )
659 omx_error
= OMX_ErrorNotImplemented
;
660 CHECK_ERROR(omx_error
, "OMX color format %i not supported",
661 (int)def
->format
.video
.eColorFormat
);
663 GetVlcChromaSizes( p_fmt
->i_codec
,
664 def
->format
.video
.nFrameWidth
,
665 def
->format
.video
.nFrameHeight
,
666 &p_port
->i_frame_size
, &p_port
->i_frame_stride
,
667 &p_port
->i_frame_stride_chroma_div
);
669 if(p_port
->i_frame_size
> def
->nBufferSize
)
670 def
->nBufferSize
= p_port
->i_frame_size
;
671 p_port
->i_frame_size
= def
->nBufferSize
;
673 if((int)p_port
->i_frame_stride
> def
->format
.video
.nStride
)
674 def
->format
.video
.nStride
= p_port
->i_frame_stride
;
676 p_port
->i_frame_stride
= def
->format
.video
.nStride
;
677 UpdatePixelAspect(p_dec
);
681 if( !OmxToVlcAudioFormat( def
->format
.audio
.eEncoding
,
682 &p_fmt
->i_codec
, 0 ) )
684 omx_error
= OMX_ErrorNotImplemented
;
685 CHECK_ERROR(omx_error
, "OMX audio format %i not supported",
686 (int)def
->format
.audio
.eEncoding
);
689 omx_error
= GetAudioParameters(p_port
->omx_handle
,
690 &p_port
->format_param
, def
->nPortIndex
,
691 def
->format
.audio
.eEncoding
,
692 &p_fmt
->audio
.i_channels
,
693 &p_fmt
->audio
.i_rate
,
695 &p_fmt
->audio
.i_bitspersample
,
696 &p_fmt
->audio
.i_blockalign
);
697 CHECK_ERROR(omx_error
, "GetAudioParameters failed (%x : %s)",
698 omx_error
, ErrorToString(omx_error
));
700 if(p_fmt
->audio
.i_channels
< 9)
702 static const int pi_channels_maps
[9] =
704 0, AOUT_CHAN_CENTER
, AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
705 AOUT_CHAN_CENTER
| AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
706 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT
707 | AOUT_CHAN_REARRIGHT
,
708 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
709 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
,
710 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
711 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE
,
712 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
713 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
714 | AOUT_CHAN_MIDDLERIGHT
,
715 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT
716 | AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT
719 p_fmt
->audio
.i_physical_channels
=
720 pi_channels_maps
[p_fmt
->audio
.i_channels
];
723 date_Init( &p_dec
->p_sys
->end_date
, p_fmt
->audio
.i_rate
, 1 );
727 default: return OMX_ErrorNotImplemented
;
734 /*****************************************************************************
735 * DeinitialiseComponent: Deinitialise and unload an OMX component
736 *****************************************************************************/
737 static OMX_ERRORTYPE
DeinitialiseComponent(decoder_t
*p_dec
,
738 OMX_HANDLETYPE omx_handle
)
740 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
741 OMX_BUFFERHEADERTYPE
*p_buffer
;
742 OMX_ERRORTYPE omx_error
;
746 if(!omx_handle
) return OMX_ErrorNone
;
748 omx_error
= OMX_GetState(omx_handle
, &state
);
749 CHECK_ERROR(omx_error
, "OMX_GetState failed (%x)", omx_error
);
751 if( p_sys
->out
.p_hwbuf
&& HwBuffer_Stop( p_dec
, &p_sys
->out
) != 0 )
752 msg_Warn( p_dec
, "HwBuffer_Stop failed" );
754 if(state
== OMX_StateExecuting
)
756 omx_error
= OMX_SendCommand( omx_handle
, OMX_CommandStateSet
,
758 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Idle failed (%x)", omx_error
);
761 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, &cmd
, &state
, 0);
762 CHECK_ERROR(omx_error
, "Wait for Idle failed (%x)", omx_error
);
763 // The event queue can contain other OMX_EventCmdComplete items,
764 // such as for OMX_CommandFlush
765 if (cmd
== OMX_CommandStateSet
&& state
== OMX_StateIdle
)
770 omx_error
= OMX_GetState(omx_handle
, &state
);
771 CHECK_ERROR(omx_error
, "OMX_GetState failed (%x)", omx_error
);
773 if(state
== OMX_StateIdle
)
775 omx_error
= OMX_SendCommand( omx_handle
, OMX_CommandStateSet
,
776 OMX_StateLoaded
, 0 );
777 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Loaded failed (%x)", omx_error
);
779 for(i
= 0; i
< p_sys
->ports
; i
++)
781 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
783 omx_error
= FreeBuffers( p_dec
, p_port
);
784 CHECK_ERROR(omx_error
, "FreeBuffers failed (%x, %i)",
785 omx_error
, (int)p_port
->i_port_index
);
786 if( p_port
->p_hwbuf
)
788 HwBuffer_FreeBuffers( p_dec
, p_port
);
789 HwBuffer_Join( p_dec
, p_port
);
793 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, 0, 0, 0);
794 CHECK_ERROR(omx_error
, "Wait for Loaded failed (%x)", omx_error
);
798 for(i
= 0; i
< p_sys
->ports
; i
++)
800 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
801 free(p_port
->pp_buffers
);
802 p_port
->pp_buffers
= 0;
805 OMX_FIFO_PEEK(&p_port
->fifo
, p_buffer
);
806 if (!p_buffer
) break;
808 OMX_FIFO_GET(&p_port
->fifo
, p_buffer
);
809 if (p_buffer
->nFlags
& SENTINEL_FLAG
) {
813 msg_Warn( p_dec
, "Stray buffer left in fifo, %p",
816 HwBuffer_Destroy( p_dec
, p_port
);
818 omx_error
= pf_free_handle( omx_handle
);
822 /*****************************************************************************
823 * InitialiseComponent: Load and initialise an OMX component
824 *****************************************************************************/
825 static OMX_ERRORTYPE
InitialiseComponent(decoder_t
*p_dec
,
826 OMX_STRING psz_component
, OMX_HANDLETYPE
*p_handle
)
828 static OMX_CALLBACKTYPE callbacks
=
829 { OmxEventHandler
, OmxEmptyBufferDone
, OmxFillBufferDone
};
830 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
831 OMX_HANDLETYPE omx_handle
;
832 OMX_ERRORTYPE omx_error
;
835 OMX_U8 psz_role
[OMX_MAX_STRINGNAME_SIZE
];
836 OMX_PARAM_COMPONENTROLETYPE role
;
837 OMX_PARAM_PORTDEFINITIONTYPE definition
;
838 OMX_PORT_PARAM_TYPE param
;
841 omx_error
= pf_get_handle( &omx_handle
, psz_component
, p_dec
, &callbacks
);
842 if(omx_error
!= OMX_ErrorNone
)
844 msg_Warn( p_dec
, "OMX_GetHandle(%s) failed (%x: %s)", psz_component
,
845 omx_error
, ErrorToString(omx_error
) );
848 strncpy(p_sys
->psz_component
, psz_component
, OMX_MAX_STRINGNAME_SIZE
-1);
849 i_quirks
= OMXCodec_GetQuirks(p_dec
->fmt_in
.i_cat
,
850 p_sys
->b_enc
? p_dec
->fmt_out
.i_codec
: p_dec
->fmt_in
.i_codec
,
851 p_sys
->psz_component
,
852 strlen(p_sys
->psz_component
));
853 if ((i_quirks
& OMXCODEC_QUIRKS_NEED_CSD
)
854 && !p_dec
->fmt_in
.i_extra
)
856 /* TODO handle late configuration */
857 msg_Warn( p_dec
, "codec need CSD" );
858 return OMX_ErrorUndefined
;
861 omx_error
= OMX_ComponentRoleEnum(omx_handle
, psz_role
, 0);
862 if(omx_error
== OMX_ErrorNone
)
863 msg_Dbg(p_dec
, "loaded component %s of role %s", psz_component
, psz_role
);
865 msg_Dbg(p_dec
, "loaded component %s", psz_component
);
866 PrintOmx(p_dec
, omx_handle
, OMX_ALL
);
868 /* Set component role */
869 OMX_INIT_STRUCTURE(role
);
870 strcpy((char*)role
.cRole
,
871 GetOmxRole(p_sys
->b_enc
? p_dec
->fmt_out
.i_codec
: p_dec
->fmt_in
.i_codec
,
872 p_dec
->fmt_in
.i_cat
, p_sys
->b_enc
));
874 omx_error
= OMX_SetParameter(omx_handle
, OMX_IndexParamStandardComponentRole
,
876 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamStandardComponentRole
,
878 if(omx_error
== OMX_ErrorNone
)
879 msg_Dbg(p_dec
, "component standard role set to %s", role
.cRole
);
881 /* Find the input / output ports */
882 OMX_INIT_STRUCTURE(param
);
883 OMX_INIT_STRUCTURE(definition
);
884 omx_error
= OMX_GetParameter(omx_handle
, p_dec
->fmt_in
.i_cat
== VIDEO_ES
?
885 OMX_IndexParamVideoInit
: OMX_IndexParamAudioInit
, ¶m
);
886 if(omx_error
!= OMX_ErrorNone
) {
889 param
.nStartPortNumber
= 0;
895 for(i
= 0; i
< param
.nPorts
; i
++)
899 /* Get port definition */
900 definition
.nPortIndex
= param
.nStartPortNumber
+ i
;
901 omx_error
= OMX_GetParameter(omx_handle
, OMX_IndexParamPortDefinition
,
903 if(omx_error
!= OMX_ErrorNone
) continue;
905 if(definition
.eDir
== OMX_DirInput
) p_port
= &p_sys
->in
;
906 else p_port
= &p_sys
->out
;
908 p_port
->b_valid
= true;
909 p_port
->i_port_index
= definition
.nPortIndex
;
910 p_port
->definition
= definition
;
911 p_port
->omx_handle
= omx_handle
;
912 HwBuffer_Init( p_dec
, p_port
);
915 if(!p_sys
->in
.b_valid
|| !p_sys
->out
.b_valid
)
917 omx_error
= OMX_ErrorInvalidComponent
;
918 CHECK_ERROR(omx_error
, "couldn't find an input and output port");
921 if( !p_sys
->out
.p_hwbuf
&& !strncmp(p_sys
->psz_component
, "OMX.SEC.", 8) &&
922 p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
925 omx_error
= OMX_GetExtensionIndex(omx_handle
, (OMX_STRING
) "OMX.SEC.index.ThumbnailMode", &index
);
926 if(omx_error
== OMX_ErrorNone
)
928 OMX_BOOL enable
= OMX_TRUE
;
929 omx_error
= OMX_SetConfig(omx_handle
, index
, &enable
);
930 CHECK_ERROR(omx_error
, "Unable to set ThumbnailMode");
932 OMX_BOOL enable
= OMX_TRUE
;
933 /* Needed on Samsung Galaxy S II */
934 omx_error
= OMX_SetConfig(omx_handle
, OMX_IndexVendorSetYUV420pMode
, &enable
);
935 if (omx_error
== OMX_ErrorNone
)
936 msg_Dbg(p_dec
, "Set OMX_IndexVendorSetYUV420pMode successfully");
938 msg_Dbg(p_dec
, "Unable to set OMX_IndexVendorSetYUV420pMode: %x", omx_error
);
942 if(!strncmp(p_sys
->psz_component
, "OMX.broadcom.", 13))
944 OMX_CONFIG_REQUESTCALLBACKTYPE notifications
;
945 OMX_INIT_STRUCTURE(notifications
);
947 notifications
.nPortIndex
= p_sys
->out
.i_port_index
;
948 notifications
.nIndex
= OMX_IndexParamBrcmPixelAspectRatio
;
949 notifications
.bEnable
= OMX_TRUE
;
951 omx_error
= OMX_SetParameter(omx_handle
,
952 OMX_IndexConfigRequestCallback
, ¬ifications
);
953 if (omx_error
== OMX_ErrorNone
) {
954 msg_Dbg(p_dec
, "Enabled aspect ratio notifications");
955 p_sys
->b_aspect_ratio_handled
= true;
957 msg_Dbg(p_dec
, "Could not enable aspect ratio notifications");
960 /* Set port definitions */
961 for(i
= 0; i
< p_sys
->ports
; i
++)
963 omx_error
= SetPortDefinition(p_dec
, &p_sys
->p_ports
[i
],
964 p_sys
->p_ports
[i
].p_fmt
);
965 if(omx_error
!= OMX_ErrorNone
) goto error
;
968 if(!strncmp(p_sys
->psz_component
, "OMX.broadcom.", 13) &&
969 p_sys
->in
.p_fmt
->i_codec
== VLC_CODEC_H264
)
971 OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam
;
972 OMX_INIT_STRUCTURE(concanParam
);
973 concanParam
.bStartWithValidFrame
= OMX_FALSE
;
975 omx_error
= OMX_SetParameter(omx_handle
,
976 OMX_IndexParamBrcmVideoDecodeErrorConcealment
, &concanParam
);
977 if (omx_error
== OMX_ErrorNone
)
978 msg_Dbg(p_dec
, "StartWithValidFrame disabled.");
980 msg_Dbg(p_dec
, "Could not disable StartWithValidFrame.");
983 /* Allocate our array for the omx buffers and enable ports */
984 for(i
= 0; i
< p_sys
->ports
; i
++)
986 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
989 if(!p_port
->definition
.bEnabled
)
991 omx_error
= OMX_SendCommand( omx_handle
, OMX_CommandPortEnable
,
992 p_port
->i_port_index
, NULL
);
993 CHECK_ERROR(omx_error
, "OMX_CommandPortEnable on %i failed (%x)",
994 (int)p_port
->i_port_index
, omx_error
);
995 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, 0, 0, 0);
996 CHECK_ERROR(omx_error
, "Wait for PortEnable on %i failed (%x)",
997 (int)p_port
->i_port_index
, omx_error
);
1001 p_sys
->i_quirks
= i_quirks
;
1002 *p_handle
= omx_handle
;
1003 return OMX_ErrorNone
;
1006 DeinitialiseComponent(p_dec
, omx_handle
);
1011 /*****************************************************************************
1012 * OpenDecoder: Create the decoder instance
1013 *****************************************************************************/
1014 static int OpenDecoder( vlc_object_t
*p_this
)
1016 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1019 if( 0 || !GetOmxRole(p_dec
->fmt_in
.i_codec
, p_dec
->fmt_in
.i_cat
, false) )
1020 return VLC_EGENERIC
;
1022 status
= OpenGeneric( p_this
, false );
1023 if(status
!= VLC_SUCCESS
) return status
;
1025 switch( p_dec
->fmt_in
.i_cat
)
1027 case AUDIO_ES
: p_dec
->pf_decode
= DecodeAudio
; break;
1028 case VIDEO_ES
: p_dec
->pf_decode
= DecodeVideo
; break;
1029 default: vlc_assert_unreachable();
1031 p_dec
->pf_flush
= Flush
;
1036 /*****************************************************************************
1037 * OpenEncoder: Create the encoder instance
1038 *****************************************************************************/
1039 static int OpenEncoder( vlc_object_t
*p_this
)
1041 encoder_t
*p_enc
= (encoder_t
*)p_this
;
1044 if( !GetOmxRole(p_enc
->fmt_out
.i_codec
, p_enc
->fmt_in
.i_cat
, true) )
1045 return VLC_EGENERIC
;
1047 status
= OpenGeneric( p_this
, true );
1048 if(status
!= VLC_SUCCESS
) return status
;
1050 p_enc
->pf_encode_video
= EncodeVideo
;
1055 /*****************************************************************************
1056 * OpenGeneric: Create the generic decoder/encoder instance
1057 *****************************************************************************/
1058 static int OpenGeneric( vlc_object_t
*p_this
, bool b_encode
)
1060 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1061 decoder_sys_t
*p_sys
;
1062 OMX_ERRORTYPE omx_error
;
1063 OMX_BUFFERHEADERTYPE
*p_header
;
1066 if (InitOmxCore(p_this
) != VLC_SUCCESS
) {
1067 return VLC_EGENERIC
;
1070 /* Allocate the memory needed to store the decoder's structure */
1071 if( ( p_dec
->p_sys
= p_sys
= calloc( 1, sizeof(*p_sys
)) ) == NULL
)
1077 /* Initialise the thread properties */
1080 p_dec
->fmt_out
.video
= p_dec
->fmt_in
.video
;
1081 p_dec
->fmt_out
.audio
= p_dec
->fmt_in
.audio
;
1082 p_dec
->fmt_out
.i_codec
= 0;
1084 /* set default aspect of 1, if parser did not set it */
1085 if (p_dec
->fmt_out
.video
.i_sar_num
== 0)
1086 p_dec
->fmt_out
.video
.i_sar_num
= 1;
1087 if (p_dec
->fmt_out
.video
.i_sar_den
== 0)
1088 p_dec
->fmt_out
.video
.i_sar_den
= 1;
1090 p_sys
->b_enc
= b_encode
;
1091 InitOmxEventQueue(&p_sys
->event_queue
);
1092 OMX_FIFO_INIT (&p_sys
->in
.fifo
, pOutputPortPrivate
);
1093 p_sys
->in
.b_direct
= false;
1094 p_sys
->in
.b_flushed
= true;
1095 p_sys
->in
.p_fmt
= &p_dec
->fmt_in
;
1096 OMX_FIFO_INIT (&p_sys
->out
.fifo
, pInputPortPrivate
);
1097 #if defined(USE_IOMX)
1098 p_sys
->out
.b_direct
= var_InheritBool(p_dec
, CFG_PREFIX
"dr");
1100 p_sys
->out
.b_direct
= false;
1102 p_sys
->out
.b_flushed
= true;
1103 p_sys
->out
.p_fmt
= &p_dec
->fmt_out
;
1105 p_sys
->p_ports
= &p_sys
->in
;
1106 p_sys
->b_use_pts
= 1;
1108 msg_Dbg(p_dec
, "fmt in:%4.4s, out: %4.4s", (char *)&p_dec
->fmt_in
.i_codec
,
1109 (char *)&p_dec
->fmt_out
.i_codec
);
1111 /* Enumerate components and build a list of the one we want to try */
1113 CreateComponentsList(p_this
,
1114 GetOmxRole(p_sys
->b_enc
? p_dec
->fmt_out
.i_codec
:
1115 p_dec
->fmt_in
.i_codec
, p_dec
->fmt_in
.i_cat
,
1116 p_sys
->b_enc
), p_sys
->ppsz_components
);
1117 if( !p_sys
->components
)
1119 msg_Warn( p_this
, "couldn't find an omx component for codec %4.4s",
1120 (char *)&p_dec
->fmt_in
.i_codec
);
1121 CloseGeneric(p_this
);
1122 return VLC_EGENERIC
;
1125 /* Try to load and initialise a component */
1126 omx_error
= OMX_ErrorUndefined
;
1127 for(i
= 0; i
< p_sys
->components
; i
++)
1130 if (OMXCodec_IsBlacklisted(p_sys
->ppsz_components
[i
], strlen(p_sys
->ppsz_components
[i
])))
1133 omx_error
= InitialiseComponent(p_dec
, p_sys
->ppsz_components
[i
],
1134 &p_sys
->omx_handle
);
1135 if(omx_error
== OMX_ErrorNone
) break;
1137 CHECK_ERROR(omx_error
, "no component could be initialised" );
1139 /* Move component to Idle then Executing state */
1140 OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandStateSet
, OMX_StateIdle
, 0 );
1141 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Idle failed (%x)", omx_error
);
1143 /* Allocate omx buffers */
1144 for(i
= 0; i
< p_sys
->ports
; i
++)
1146 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1147 if( p_port
->p_hwbuf
)
1149 if( HwBuffer_AllocateBuffers( p_dec
, p_port
) != 0 )
1151 omx_error
= OMX_ErrorInsufficientResources
;
1155 omx_error
= AllocateBuffers( p_dec
, p_port
);
1156 CHECK_ERROR(omx_error
, "AllocateBuffers failed (%x, %i)",
1157 omx_error
, (int)p_port
->i_port_index
);
1160 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, 0, 0, 0);
1161 CHECK_ERROR(omx_error
, "Wait for Idle failed (%x)", omx_error
);
1163 omx_error
= OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandStateSet
,
1164 OMX_StateExecuting
, 0);
1165 CHECK_ERROR(omx_error
, "OMX_CommandStateSet Executing failed (%x)", omx_error
);
1166 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, 0, 0, 0);
1167 CHECK_ERROR(omx_error
, "Wait for Executing failed (%x)", omx_error
);
1169 if( p_sys
->out
.p_hwbuf
&& HwBuffer_Start( p_dec
, &p_sys
->out
) != 0 )
1171 omx_error
= OMX_ErrorUndefined
;
1175 /* Send codec configuration data */
1176 if( p_dec
->fmt_in
.i_extra
)
1178 OMX_FIFO_GET(&p_sys
->in
.fifo
, p_header
);
1179 p_header
->nFilledLen
= p_dec
->fmt_in
.i_extra
;
1181 /* Convert H.264 NAL format to annex b */
1182 if( p_sys
->i_nal_size_length
&& !p_sys
->in
.b_direct
&&
1183 h264_isavcC(p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
) )
1185 size_t i_filled_len
= 0;
1186 p_header
->pBuffer
= h264_avcC_to_AnnexB_NAL(
1187 p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
,
1188 &i_filled_len
, NULL
);
1189 p_header
->nFilledLen
= i_filled_len
;
1191 else if( p_dec
->fmt_in
.i_codec
== VLC_CODEC_HEVC
&& !p_sys
->in
.b_direct
)
1193 size_t i_filled_len
= 0;
1194 p_header
->pBuffer
= hevc_hvcC_to_AnnexB_NAL(
1195 p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
,
1196 &i_filled_len
, &p_sys
->i_nal_size_length
);
1197 p_header
->nFilledLen
= i_filled_len
;
1199 else if(p_sys
->in
.b_direct
)
1201 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1202 p_header
->pBuffer
= p_dec
->fmt_in
.p_extra
;
1204 else if (p_dec
->fmt_in
.i_codec
== VLC_CODEC_WMV3
&&
1205 p_dec
->fmt_in
.i_extra
>= 4 &&
1206 p_header
->nAllocLen
>= 36)
1209 // According to OMX IL 1.2.0 spec (4.3.33.2), the codec config
1210 // data for VC-1 Main/Simple (aka WMV3) is according to table 265
1211 // in the VC-1 spec. Most of the fields are just set with placeholders
1212 // (like framerate, hrd_buffer/rate).
1213 static const uint8_t wmv3seq
[] = {
1214 0xff, 0xff, 0xff, 0xc5, // numframes=ffffff, marker byte
1215 0x04, 0x00, 0x00, 0x00, // marker byte
1216 0x00, 0x00, 0x00, 0x00, // struct C, almost equal to p_extra
1217 0x00, 0x00, 0x00, 0x00, // struct A, vert size
1218 0x00, 0x00, 0x00, 0x00, // struct A, horiz size
1219 0x0c, 0x00, 0x00, 0x00, // marker byte
1220 0xff, 0xff, 0x00, 0x80, // struct B, level=4, cbr=0, hrd_buffer=ffff
1221 0xff, 0xff, 0x00, 0x00, // struct B, hrd_rate=ffff
1222 0xff, 0xff, 0xff, 0xff, // struct B, framerate=ffffffff
1224 p_header
->nFilledLen
= sizeof(wmv3seq
);
1225 memcpy(p_header
->pBuffer
, wmv3seq
, p_header
->nFilledLen
);
1226 // Struct C - almost equal to the extradata
1227 memcpy(&p_header
->pBuffer
[8], p_dec
->fmt_in
.p_extra
, 4);
1228 // Expand profile from the highest 2 bits to the highest 4 bits
1229 profile
= p_header
->pBuffer
[8] >> 6;
1230 p_header
->pBuffer
[8] = (p_header
->pBuffer
[8] & 0x0f) | (profile
<< 4);
1231 // Fill in the height/width for struct A
1232 SetDWLE(&p_header
->pBuffer
[12], p_dec
->fmt_in
.video
.i_height
);
1233 SetDWLE(&p_header
->pBuffer
[16], p_dec
->fmt_in
.video
.i_width
);
1237 if(p_header
->nFilledLen
> p_header
->nAllocLen
)
1239 msg_Dbg(p_dec
, "buffer too small (%i,%i)", (int)p_header
->nFilledLen
,
1240 (int)p_header
->nAllocLen
);
1241 p_header
->nFilledLen
= p_header
->nAllocLen
;
1243 memcpy(p_header
->pBuffer
, p_dec
->fmt_in
.p_extra
, p_header
->nFilledLen
);
1246 p_header
->nOffset
= 0;
1247 p_header
->nFlags
= OMX_BUFFERFLAG_CODECCONFIG
| OMX_BUFFERFLAG_ENDOFFRAME
;
1248 msg_Dbg(p_dec
, "sending codec config data %p, %p, %u",
1249 (void *)p_header
, (void *)p_header
->pBuffer
,
1250 (unsigned)p_header
->nFilledLen
);
1251 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
1254 /* Get back output port definition */
1255 omx_error
= GetPortDefinition(p_dec
, &p_sys
->out
, p_sys
->out
.p_fmt
);
1256 if(omx_error
!= OMX_ErrorNone
) goto error
;
1258 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->in
.i_port_index
);
1259 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->out
.i_port_index
);
1261 if(p_sys
->b_error
) goto error
;
1263 if (!p_sys
->b_use_pts
)
1264 msg_Dbg( p_dec
, "using dts timestamp mode for %s", p_sys
->psz_component
);
1269 CloseGeneric(p_this
);
1270 return VLC_EGENERIC
;
1273 /*****************************************************************************
1275 *****************************************************************************/
1276 static OMX_ERRORTYPE
PortReconfigure(decoder_t
*p_dec
, OmxPort
*p_port
)
1278 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1279 OMX_PARAM_PORTDEFINITIONTYPE definition
;
1280 OMX_ERRORTYPE omx_error
;
1282 OMX_DBG( "PortReconfigure(%d)", p_port
->definition
.eDir
);
1284 /* Sanity checking */
1285 OMX_INIT_STRUCTURE(definition
);
1286 definition
.nPortIndex
= p_port
->i_port_index
;
1287 omx_error
= OMX_GetParameter(p_dec
->p_sys
->omx_handle
, OMX_IndexParamPortDefinition
,
1289 if(omx_error
!= OMX_ErrorNone
|| (p_dec
->fmt_in
.i_cat
== VIDEO_ES
&&
1290 (!definition
.format
.video
.nFrameWidth
||
1291 !definition
.format
.video
.nFrameHeight
)) )
1292 return OMX_ErrorUndefined
;
1294 if( p_port
->p_hwbuf
&& HwBuffer_Stop( p_dec
, p_port
) != 0 )
1295 msg_Warn( p_dec
, "HwBuffer_Stop failed" );
1297 omx_error
= OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandPortDisable
,
1298 p_port
->i_port_index
, NULL
);
1299 CHECK_ERROR(omx_error
, "OMX_CommandPortDisable on %i failed (%x)",
1300 (int)p_port
->i_port_index
, omx_error
);
1302 omx_error
= FreeBuffers( p_dec
, p_port
);
1303 CHECK_ERROR(omx_error
, "FreeBuffers failed (%x, %i)",
1304 omx_error
, (int)p_port
->i_port_index
);
1306 if( p_port
->p_hwbuf
)
1308 HwBuffer_FreeBuffers( p_dec
, p_port
);
1309 HwBuffer_Join( p_dec
, p_port
);
1312 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, 0, 0, 0);
1313 CHECK_ERROR(omx_error
, "Wait for PortDisable failed (%x)", omx_error
);
1315 /* Get the new port definition */
1316 omx_error
= GetPortDefinition(p_dec
, &p_sys
->out
, p_sys
->out
.p_fmt
);
1317 if(omx_error
!= OMX_ErrorNone
) goto error
;
1319 if( p_port
->p_hwbuf
)
1321 if( HwBuffer_AllocateBuffers( p_dec
, p_port
) != 0 )
1323 omx_error
= OMX_ErrorInsufficientResources
;
1327 else if( p_dec
->fmt_in
.i_cat
!= AUDIO_ES
)
1329 /* Don't explicitly set the new parameters that we got with
1330 * OMX_GetParameter above when using audio codecs.
1331 * That struct hasn't been changed since, so there should be
1332 * no need to set it here, unless some codec expects the
1333 * SetParameter call as a trigger event for some part of
1334 * the reconfiguration.
1335 * This fixes using audio decoders on Samsung Galaxy S II,
1337 * Only skipping this for audio codecs, to minimize the
1338 * change for current working configurations for video.
1340 omx_error
= OMX_SetParameter(p_dec
->p_sys
->omx_handle
, OMX_IndexParamPortDefinition
,
1342 CHECK_ERROR(omx_error
, "OMX_SetParameter failed (%x : %s)",
1343 omx_error
, ErrorToString(omx_error
));
1346 omx_error
= OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandPortEnable
,
1347 p_port
->i_port_index
, NULL
);
1348 CHECK_ERROR(omx_error
, "OMX_CommandPortEnable on %i failed (%x)",
1349 (int)p_port
->i_port_index
, omx_error
);
1351 omx_error
= AllocateBuffers( p_dec
, p_port
);
1352 CHECK_ERROR(omx_error
, "OMX_AllocateBuffers failed (%x, %i)",
1353 omx_error
, (int)p_port
->i_port_index
);
1355 omx_error
= WaitForSpecificOmxEvent(&p_sys
->event_queue
, OMX_EventCmdComplete
, 0, 0, 0);
1356 CHECK_ERROR(omx_error
, "Wait for PortEnable failed (%x)", omx_error
);
1358 if( p_port
->p_hwbuf
&& HwBuffer_Start( p_dec
, p_port
) != 0 )
1360 omx_error
= OMX_ErrorUndefined
;
1364 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->in
.i_port_index
);
1365 PrintOmx(p_dec
, p_sys
->omx_handle
, p_dec
->p_sys
->out
.i_port_index
);
1367 OMX_DBG( "PortReconfigure(%d)::done", p_port
->definition
.eDir
);
1372 /*****************************************************************************
1374 *****************************************************************************/
1375 static int DecodeVideoOutput( decoder_t
*p_dec
, OmxPort
*p_port
, picture_t
**pp_pic
)
1377 VLC_UNUSED( p_dec
);
1378 OMX_BUFFERHEADERTYPE
*p_header
;
1379 picture_t
*p_pic
= NULL
, *p_next_pic
;
1380 OMX_ERRORTYPE omx_error
;
1384 OMX_FIFO_PEEK(&p_port
->fifo
, p_header
);
1385 if(!p_header
) break; /* No frame available */
1387 if(p_port
->b_update_def
)
1389 omx_error
= GetPortDefinition(p_dec
, p_port
, p_port
->p_fmt
);
1390 p_port
->b_update_def
= 0;
1391 CHECK_ERROR(omx_error
, "GetPortDefinition failed");
1393 if( decoder_UpdateVideoFormat( p_dec
) )
1396 if( p_port
->p_hwbuf
)
1398 if( HwBuffer_GetPic( p_dec
, p_port
, &p_pic
) != 0 )
1404 if(p_header
->nFilledLen
)
1406 p_pic
= p_header
->pAppPrivate
;
1409 /* We're not in direct rendering mode.
1410 * Get a new picture and copy the content */
1411 p_pic
= decoder_NewPicture( p_dec
);
1414 CopyOmxPicture(p_port
->definition
.format
.video
.eColorFormat
,
1415 p_pic
, p_port
->definition
.format
.video
.nSliceHeight
,
1416 p_port
->i_frame_stride
,
1417 p_header
->pBuffer
+ p_header
->nOffset
,
1418 p_port
->i_frame_stride_chroma_div
, NULL
);
1422 p_pic
->date
= FromOmxTicks(p_header
->nTimeStamp
);
1423 p_header
->nFilledLen
= 0;
1424 p_header
->pAppPrivate
= 0;
1427 /* Get a new picture */
1428 if(p_port
->b_direct
&& !p_header
->pAppPrivate
)
1430 p_next_pic
= decoder_NewPicture( p_dec
);
1431 if(!p_next_pic
) break;
1433 OMX_FIFO_GET(&p_port
->fifo
, p_header
);
1434 p_header
->pAppPrivate
= p_next_pic
;
1435 p_header
->pInputPortPrivate
= p_header
->pBuffer
;
1436 p_header
->pBuffer
= p_next_pic
->p
[0].p_pixels
;
1440 OMX_FIFO_GET(&p_port
->fifo
, p_header
);
1442 OMX_DBG( "FillThisBuffer %p, %p", (void *)p_header
,
1443 (void *)p_header
->pBuffer
);
1444 OMX_FillThisBuffer(p_port
->omx_handle
, p_header
);
1453 static int DecodeVideoInput( decoder_t
*p_dec
, OmxPort
*p_port
, block_t
**pp_block
,
1454 unsigned int i_input_used
, bool *p_reconfig
)
1456 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1457 OMX_BUFFERHEADERTYPE
*p_header
;
1458 block_t
*p_block
= *pp_block
;
1460 /* Send the input buffer to the component */
1461 OMX_FIFO_GET_TIMEOUT(&p_port
->fifo
, p_header
, 10000);
1463 if (p_header
&& p_header
->nFlags
& SENTINEL_FLAG
) {
1468 *p_reconfig
= false;
1472 bool decode_more
= false;
1473 p_header
->nFilledLen
= p_block
->i_buffer
- i_input_used
;
1474 p_header
->nOffset
= 0;
1475 p_header
->nFlags
= OMX_BUFFERFLAG_ENDOFFRAME
;
1476 if (p_sys
->b_use_pts
&& p_block
->i_pts
)
1477 p_header
->nTimeStamp
= ToOmxTicks(p_block
->i_pts
);
1479 p_header
->nTimeStamp
= ToOmxTicks(p_block
->i_dts
);
1481 /* In direct mode we pass the input pointer as is.
1482 * Otherwise we memcopy the data */
1483 if(p_port
->b_direct
)
1485 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1486 p_header
->pBuffer
= p_block
->p_buffer
;
1487 p_header
->pAppPrivate
= p_block
;
1488 i_input_used
= p_header
->nFilledLen
;
1492 if(p_header
->nFilledLen
> p_header
->nAllocLen
)
1494 p_header
->nFilledLen
= p_header
->nAllocLen
;
1496 memcpy(p_header
->pBuffer
, p_block
->p_buffer
+ i_input_used
, p_header
->nFilledLen
);
1497 i_input_used
+= p_header
->nFilledLen
;
1498 if (i_input_used
== p_block
->i_buffer
)
1500 block_Release(p_block
);
1505 p_header
->nFlags
&= ~OMX_BUFFERFLAG_ENDOFFRAME
;
1509 /* Convert H.264 NAL format to annex b. Doesn't do anything if
1510 * i_nal_size_length == 0, which is the case for codecs other
1512 h264_AVC_to_AnnexB( p_header
->pBuffer
, p_header
->nFilledLen
,
1513 p_sys
->i_nal_size_length
);
1514 OMX_DBG( "EmptyThisBuffer %p, %p, %u, %"PRId64
, (void *)p_header
,
1515 (void *)p_header
->pBuffer
, (unsigned)p_header
->nFilledLen
,
1516 FromOmxTicks(p_header
->nTimeStamp
) );
1517 OMX_EmptyThisBuffer(p_port
->omx_handle
, p_header
);
1518 p_port
->b_flushed
= false;
1520 return DecodeVideoInput( p_dec
, p_port
, pp_block
, i_input_used
,
1523 *pp_block
= NULL
; /* Avoid being fed the same packet again */
1529 /*****************************************************************************
1531 *****************************************************************************/
1532 static void Flush( decoder_t
*p_dec
)
1534 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1536 if(!p_sys
->in
.b_flushed
)
1538 msg_Dbg(p_dec
, "flushing");
1539 OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandFlush
,
1540 p_sys
->in
.definition
.nPortIndex
, 0 );
1542 p_sys
->in
.b_flushed
= true;
1544 /*****************************************************************************
1545 * DecodeVideo: Called to decode one frame
1546 *****************************************************************************/
1547 static int DecodeVideo( decoder_t
*p_dec
, block_t
*p_block
)
1549 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1550 OMX_ERRORTYPE omx_error
;
1553 if( p_block
== NULL
) /* No Drain */
1554 return VLCDEC_SUCCESS
;
1556 /* Check for errors from codec */
1559 msg_Dbg(p_dec
, "error during decoding");
1560 block_Release( p_block
);
1561 return VLCDEC_SUCCESS
;
1564 if( p_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
1566 block_Release( p_block
);
1568 return VLCDEC_SUCCESS
;
1571 /* Use the aspect ratio provided by the input (ie read from packetizer).
1572 * In case the we get aspect ratio info from the decoder (as in the
1573 * broadcom OMX implementation on RPi), don't let the packetizer values
1574 * override what the decoder says, if anything - otherwise always update
1575 * even if it already is set (since it can change within a stream). */
1576 if((p_dec
->fmt_in
.video
.i_sar_num
!= 0 && p_dec
->fmt_in
.video
.i_sar_den
!= 0) &&
1577 (p_dec
->fmt_out
.video
.i_sar_num
== 0 || p_dec
->fmt_out
.video
.i_sar_den
== 0 ||
1578 !p_sys
->b_aspect_ratio_handled
))
1580 p_dec
->fmt_out
.video
.i_sar_num
= p_dec
->fmt_in
.video
.i_sar_num
;
1581 p_dec
->fmt_out
.video
.i_sar_den
= p_dec
->fmt_in
.video
.i_sar_den
;
1584 /* Loop as long as we haven't either got an input buffer (and cleared
1585 * *pp_block) or got an output picture */
1586 int max_polling_attempts
= 100;
1589 bool b_reconfig
= false;
1591 if( DecodeVideoInput( p_dec
, &p_sys
->in
, &p_block
, 0, &b_reconfig
) != 0 )
1594 picture_t
*p_pic
= NULL
;
1595 /* If we don't have a p_pic from the first try. Try again */
1597 DecodeVideoOutput( p_dec
, &p_sys
->out
, &p_pic
) != 0 )
1600 /* Handle the PortSettingsChanged events */
1601 for(i
= 0; i
< p_sys
->ports
; i
++)
1603 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1604 if(p_port
->b_reconfigure
)
1606 omx_error
= PortReconfigure(p_dec
, p_port
);
1607 p_port
->b_reconfigure
= 0;
1608 CHECK_ERROR(omx_error
, "PortReconfigure failed");
1610 if(p_port
->b_update_def
)
1612 omx_error
= GetPortDefinition(p_dec
, p_port
, p_port
->p_fmt
);
1613 p_port
->b_update_def
= 0;
1614 CHECK_ERROR(omx_error
, "GetPortDefinition failed");
1620 decoder_QueueVideo( p_dec
, p_pic
);
1624 /* With opaque DR the output buffers are released by the
1625 vout therefore we implement a timeout for polling in
1626 order to avoid being indefinitely stalled in this loop, if
1627 playback is paused. */
1628 if( p_sys
->out
.p_hwbuf
&& attempts
== max_polling_attempts
) {
1630 picture_t
*invalid_picture
= NULL
;
1631 if( !decoder_UpdateVideoFormat(p_dec
))
1632 invalid_picture
= decoder_NewPicture(p_dec
);
1633 if (invalid_picture
) {
1634 invalid_picture
->date
= VLC_TS_INVALID
;
1635 picture_sys_t
*p_picsys
= invalid_picture
->p_sys
;
1636 p_picsys
->hw
.p_dec
= NULL
;
1637 p_picsys
->hw
.i_index
= -1;
1638 return VLCDEC_SUCCESS
;
1640 /* If we cannot return a picture we must free the
1641 block since the decoder will proceed with the
1643 block_Release(p_block
);
1645 return VLCDEC_SUCCESS
;
1651 return VLCDEC_SUCCESS
;
1653 p_sys
->b_error
= true;
1654 return VLCDEC_SUCCESS
;
1657 /*****************************************************************************
1658 * DecodeAudio: Called to decode one frame
1659 *****************************************************************************/
1660 int DecodeAudio ( decoder_t
*p_dec
, block_t
*p_block
)
1662 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1663 OMX_BUFFERHEADERTYPE
*p_header
;
1664 OMX_ERRORTYPE omx_error
;
1667 if( p_block
== NULL
) /* No Drain */
1668 return VLCDEC_SUCCESS
;
1670 /* Check for errors from codec */
1673 msg_Dbg(p_dec
, "error during decoding");
1674 block_Release( p_block
);
1675 return VLCDEC_SUCCESS
;
1678 if( p_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
1680 block_Release( p_block
);
1681 date_Set( &p_sys
->end_date
, 0 );
1682 if(!p_sys
->in
.b_flushed
)
1684 msg_Dbg(p_dec
, "flushing");
1685 OMX_SendCommand( p_sys
->omx_handle
, OMX_CommandFlush
,
1686 p_sys
->in
.definition
.nPortIndex
, 0 );
1688 p_sys
->in
.b_flushed
= true;
1689 return VLCDEC_SUCCESS
;
1692 if( !date_Get( &p_sys
->end_date
) )
1694 if( !p_block
->i_pts
)
1696 /* We've just started the stream, wait for the first PTS. */
1697 block_Release( p_block
);
1698 return VLCDEC_SUCCESS
;
1700 date_Set( &p_sys
->end_date
, p_block
->i_pts
);
1703 /* Take care of decoded frames first */
1704 while (p_block
!= NULL
)
1706 unsigned int i_samples
= 0;
1708 OMX_FIFO_PEEK(&p_sys
->out
.fifo
, p_header
);
1709 if(!p_header
) break; /* No frame available */
1711 if (p_sys
->out
.p_fmt
->audio
.i_channels
)
1712 i_samples
= p_header
->nFilledLen
/ p_sys
->out
.p_fmt
->audio
.i_channels
/ 2;
1715 if( decoder_UpdateAudioFormat( p_dec
) )
1717 block_t
*p_buffer
= decoder_NewAudioBuffer( p_dec
, i_samples
);
1718 if( !p_buffer
) break; /* No audio buffer available */
1720 memcpy( p_buffer
->p_buffer
, p_header
->pBuffer
, p_buffer
->i_buffer
);
1721 p_header
->nFilledLen
= 0;
1723 int64_t timestamp
= FromOmxTicks(p_header
->nTimeStamp
);
1724 if( timestamp
!= 0 &&
1725 timestamp
!= date_Get( &p_sys
->end_date
) )
1726 date_Set( &p_sys
->end_date
, timestamp
);
1728 p_buffer
->i_pts
= date_Get( &p_sys
->end_date
);
1729 p_buffer
->i_length
= date_Increment( &p_sys
->end_date
, i_samples
) -
1731 decoder_QueueAudio( p_dec
, p_buffer
);
1734 OMX_DBG( "FillThisBuffer %p, %p", (void *)p_header
,
1735 (void *)p_header
->pBuffer
);
1736 OMX_FIFO_GET(&p_sys
->out
.fifo
, p_header
);
1737 OMX_FillThisBuffer(p_sys
->omx_handle
, p_header
);
1739 /* Send the input buffer to the component */
1740 OMX_FIFO_GET_TIMEOUT(&p_sys
->in
.fifo
, p_header
, 200000);
1742 if (p_header
&& p_header
->nFlags
& SENTINEL_FLAG
) {
1750 p_header
->nFilledLen
= p_block
->i_buffer
;
1751 p_header
->nOffset
= 0;
1752 p_header
->nFlags
= OMX_BUFFERFLAG_ENDOFFRAME
;
1753 p_header
->nTimeStamp
= ToOmxTicks(p_block
->i_dts
);
1755 /* In direct mode we pass the input pointer as is.
1756 * Otherwise we memcopy the data */
1757 if(p_sys
->in
.b_direct
)
1759 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1760 p_header
->pBuffer
= p_block
->p_buffer
;
1761 p_header
->pAppPrivate
= p_block
;
1765 if(p_header
->nFilledLen
> p_header
->nAllocLen
)
1767 msg_Dbg(p_dec
, "buffer too small (%u,%u)",
1768 (unsigned)p_header
->nFilledLen
,
1769 (unsigned)p_header
->nAllocLen
);
1770 p_header
->nFilledLen
= p_header
->nAllocLen
;
1772 memcpy(p_header
->pBuffer
, p_block
->p_buffer
, p_header
->nFilledLen
);
1773 block_Release(p_block
);
1776 OMX_DBG( "EmptyThisBuffer %p, %p, %u", (void *)p_header
,
1777 (void *)p_header
->pBuffer
, (unsigned)p_header
->nFilledLen
);
1778 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
1779 p_sys
->in
.b_flushed
= false;
1784 /* Handle the PortSettingsChanged events */
1785 for(i
= 0; i
< p_sys
->ports
; i
++)
1787 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1788 if(!p_port
->b_reconfigure
) continue;
1789 p_port
->b_reconfigure
= 0;
1790 omx_error
= PortReconfigure(p_dec
, p_port
);
1791 CHECK_ERROR(omx_error
, "PortReconfigure failed");
1794 return VLCDEC_SUCCESS
;
1796 p_sys
->b_error
= true;
1797 return VLCDEC_SUCCESS
;
1800 /*****************************************************************************
1801 * EncodeVideo: Called to encode one frame
1802 *****************************************************************************/
1803 static block_t
*EncodeVideo( encoder_t
*p_enc
, picture_t
*p_pic
)
1805 decoder_t
*p_dec
= ( decoder_t
*)p_enc
;
1806 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1807 OMX_ERRORTYPE omx_error
;
1810 OMX_BUFFERHEADERTYPE
*p_header
;
1811 block_t
*p_block
= 0;
1813 if( !p_pic
) return NULL
;
1815 /* Check for errors from codec */
1818 msg_Dbg(p_dec
, "error during encoding");
1822 /* Send the input buffer to the component */
1823 OMX_FIFO_GET(&p_sys
->in
.fifo
, p_header
);
1826 /* In direct mode we pass the input pointer as is.
1827 * Otherwise we memcopy the data */
1828 if(p_sys
->in
.b_direct
)
1830 p_header
->pOutputPortPrivate
= p_header
->pBuffer
;
1831 p_header
->pBuffer
= p_pic
->p
[0].p_pixels
;
1835 CopyVlcPicture(p_dec
, p_header
, p_pic
);
1838 p_header
->nFilledLen
= p_sys
->in
.i_frame_size
;
1839 p_header
->nOffset
= 0;
1840 p_header
->nFlags
= OMX_BUFFERFLAG_ENDOFFRAME
;
1841 p_header
->nTimeStamp
= ToOmxTicks(p_pic
->date
);
1842 OMX_DBG( "EmptyThisBuffer %p, %p, %u", (void *)p_header
,
1843 (void *)p_header
->pBuffer
, (unsigned)p_header
->nFilledLen
);
1844 OMX_EmptyThisBuffer(p_sys
->omx_handle
, p_header
);
1845 p_sys
->in
.b_flushed
= false;
1848 /* Handle the PortSettingsChanged events */
1849 for(i
= 0; i
< p_sys
->ports
; i
++)
1851 OmxPort
*p_port
= &p_sys
->p_ports
[i
];
1852 if(!p_port
->b_reconfigure
) continue;
1853 p_port
->b_reconfigure
= 0;
1854 omx_error
= PortReconfigure(p_dec
, p_port
);
1855 CHECK_ERROR(omx_error
, "PortReconfigure failed");
1858 /* Wait for the decoded frame */
1861 OMX_FIFO_GET(&p_sys
->out
.fifo
, p_header
);
1863 if(p_header
->nFilledLen
)
1865 if(p_header
->nFlags
& OMX_BUFFERFLAG_CODECCONFIG
)
1867 /* TODO: need to store codec config */
1868 msg_Dbg(p_dec
, "received codec config %i", (int)p_header
->nFilledLen
);
1871 p_block
= p_header
->pAppPrivate
;
1874 /* We're not in direct rendering mode.
1875 * Get a new block and copy the content */
1876 p_block
= block_Alloc( p_header
->nFilledLen
);
1877 memcpy(p_block
->p_buffer
, p_header
->pBuffer
, p_header
->nFilledLen
);
1880 p_block
->i_buffer
= p_header
->nFilledLen
;
1881 p_block
->i_pts
= p_block
->i_dts
= FromOmxTicks(p_header
->nTimeStamp
);
1882 p_header
->nFilledLen
= 0;
1883 p_header
->pAppPrivate
= 0;
1886 OMX_DBG( "FillThisBuffer %p, %p", (void *)p_header
,
1887 (void *)p_header
->pBuffer
);
1888 OMX_FillThisBuffer(p_sys
->omx_handle
, p_header
);
1891 msg_Dbg(p_dec
, "done");
1894 p_sys
->b_error
= true;
1898 /*****************************************************************************
1899 * CloseGeneric: omxil decoder destruction
1900 *****************************************************************************/
1901 static void CloseGeneric( vlc_object_t
*p_this
)
1903 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1904 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1906 if(p_sys
->omx_handle
) DeinitialiseComponent(p_dec
, p_sys
->omx_handle
);
1910 DeinitOmxEventQueue(&p_sys
->event_queue
);
1912 OMX_FIFO_DESTROY( &p_sys
->in
.fifo
);
1913 OMX_FIFO_DESTROY( &p_sys
->out
.fifo
);
1918 /*****************************************************************************
1920 *****************************************************************************/
1921 static OMX_ERRORTYPE
OmxEventHandler( OMX_HANDLETYPE omx_handle
,
1922 OMX_PTR app_data
, OMX_EVENTTYPE event
, OMX_U32 data_1
,
1923 OMX_U32 data_2
, OMX_PTR event_data
)
1925 decoder_t
*p_dec
= (decoder_t
*)app_data
;
1926 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1930 PrintOmxEvent((vlc_object_t
*) p_dec
, event
, data_1
, data_2
, event_data
);
1933 case OMX_EventError
:
1934 //p_sys->b_error = true;
1937 case OMX_EventPortSettingsChanged
:
1938 if( data_2
== 0 || data_2
== OMX_IndexParamPortDefinition
||
1939 data_2
== OMX_IndexParamAudioPcm
)
1941 OMX_BUFFERHEADERTYPE
*sentinel
;
1942 for(i
= 0; i
< p_sys
->ports
; i
++)
1943 if(p_sys
->p_ports
[i
].definition
.eDir
== OMX_DirOutput
)
1944 p_sys
->p_ports
[i
].b_reconfigure
= true;
1945 sentinel
= calloc(1, sizeof(*sentinel
));
1947 sentinel
->nFlags
= SENTINEL_FLAG
;
1948 OMX_FIFO_PUT(&p_sys
->in
.fifo
, sentinel
);
1951 else if( data_2
== OMX_IndexConfigCommonOutputCrop
)
1953 for(i
= 0; i
< p_sys
->ports
; i
++)
1954 if(p_sys
->p_ports
[i
].definition
.nPortIndex
== data_1
)
1955 p_sys
->p_ports
[i
].b_update_def
= true;
1959 msg_Dbg( p_dec
, "Unhandled setting change %x", (unsigned int)data_2
);
1962 case OMX_EventParamOrConfigChanged
:
1963 UpdatePixelAspect(p_dec
);
1970 PostOmxEvent(&p_sys
->event_queue
, event
, data_1
, data_2
, event_data
);
1971 return OMX_ErrorNone
;
1974 static OMX_ERRORTYPE
OmxEmptyBufferDone( OMX_HANDLETYPE omx_handle
,
1975 OMX_PTR app_data
, OMX_BUFFERHEADERTYPE
*omx_header
)
1977 decoder_t
*p_dec
= (decoder_t
*)app_data
;
1978 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1981 OMX_DBG( "OmxEmptyBufferDone %p, %p", (void *)omx_header
,
1982 (void *)omx_header
->pBuffer
);
1984 if(omx_header
->pAppPrivate
|| omx_header
->pOutputPortPrivate
)
1986 block_t
*p_block
= (block_t
*)omx_header
->pAppPrivate
;
1987 omx_header
->pBuffer
= omx_header
->pOutputPortPrivate
;
1988 if(p_block
) block_Release(p_block
);
1989 omx_header
->pAppPrivate
= 0;
1991 OMX_FIFO_PUT(&p_sys
->in
.fifo
, omx_header
);
1993 return OMX_ErrorNone
;
1996 static OMX_ERRORTYPE
OmxFillBufferDone( OMX_HANDLETYPE omx_handle
,
1997 OMX_PTR app_data
, OMX_BUFFERHEADERTYPE
*omx_header
)
1999 decoder_t
*p_dec
= (decoder_t
*)app_data
;
2000 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
2003 OMX_DBG( "OmxFillBufferDone %p, %p, %u, %"PRId64
, (void *)omx_header
,
2004 (void *)omx_header
->pBuffer
, (unsigned)omx_header
->nFilledLen
,
2005 FromOmxTicks(omx_header
->nTimeStamp
) );
2007 if(omx_header
->pInputPortPrivate
)
2009 omx_header
->pBuffer
= omx_header
->pInputPortPrivate
;
2011 OMX_FIFO_PUT(&p_sys
->out
.fifo
, omx_header
);
2013 return OMX_ErrorNone
;
2016 #if defined(USE_IOMX)
2018 /* Life cycle of buffers when using IOMX direct rendering (HwBuffer):
2020 * <- android display
2021 * DequeueThread owned++
2022 * -> OMX_FillThisBuffer
2024 * <- FillBufferDone OMX_FIFO_PUT
2026 * DecodeVideoOutput OMX_FIFO_GET
2030 * -> android display owned--
2033 /*****************************************************************************
2034 * HwBuffer_ChangeState
2035 *****************************************************************************/
2036 static void HwBuffer_ChangeState( decoder_t
*p_dec
, OmxPort
*p_port
,
2037 int i_index
, int i_state
)
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
++;
2044 p_port
->p_hwbuf
->i_owned
--;
2046 OMX_DBG( "buffer[%d]: state -> %d, owned buffers: %u",
2047 i_index
, i_state
, p_port
->p_hwbuf
->i_owned
);
2050 /*****************************************************************************
2052 *****************************************************************************/
2053 static void HwBuffer_Init( decoder_t
*p_dec
, OmxPort
*p_port
)
2055 VLC_UNUSED( p_dec
);
2056 OMX_ERRORTYPE omx_error
;
2057 picture_t
*p_dummy_hwpic
= NULL
;
2059 if( !p_port
->b_direct
|| p_port
->definition
.eDir
!= OMX_DirOutput
||
2060 p_port
->p_fmt
->i_cat
!= VIDEO_ES
)
2063 msg_Dbg( p_dec
, "HwBuffer_Init");
2065 if( !(pf_enable_graphic_buffers
&& pf_get_graphic_buffer_usage
&&
2066 pf_get_hal_format
&&
2067 ((OMX_COMPONENTTYPE
*)p_port
->omx_handle
)->UseBuffer
) )
2069 msg_Warn( p_dec
, "direct output port enabled but can't find "
2070 "extra symbols, switch back to non direct" );
2074 p_dec
->fmt_out
.i_codec
= VLC_CODEC_ANDROID_OPAQUE
;
2075 if (decoder_UpdateVideoFormat(p_dec
) != 0
2076 || (p_dummy_hwpic
= decoder_NewPicture(p_dec
)) == NULL
)
2078 msg_Err(p_dec
, "Opaque Vout request failed");
2081 ANativeWindow
*p_anw
= p_dummy_hwpic
->p_sys
->hw
.p_surface
;
2085 p_port
->p_hwbuf
= calloc(1, sizeof(HwBuffer
));
2086 if( !p_port
->p_hwbuf
)
2090 vlc_mutex_init (&p_port
->p_hwbuf
->lock
);
2091 vlc_cond_init (&p_port
->p_hwbuf
->wait
);
2093 if( android_loadNativeWindowPrivApi( &p_port
->p_hwbuf
->anwpriv
) )
2095 msg_Warn( p_dec
, "android_loadNativeWindowPrivApi failed" );
2099 p_port
->p_hwbuf
->window_priv
= p_port
->p_hwbuf
->anwpriv
.connect( p_anw
);
2100 if( !p_port
->p_hwbuf
->window_priv
) {
2101 msg_Warn( p_dec
, "connect failed" );
2105 omx_error
= pf_enable_graphic_buffers( p_port
->omx_handle
,
2106 p_port
->i_port_index
, OMX_TRUE
);
2107 CHECK_ERROR( omx_error
, "can't enable graphic buffers" );
2109 /* PortDefinition may change after pf_enable_graphic_buffers call */
2110 omx_error
= OMX_GetParameter( p_port
->omx_handle
,
2111 OMX_IndexParamPortDefinition
,
2112 &p_port
->definition
);
2113 CHECK_ERROR( omx_error
, "OMX_GetParameter failed (GraphicBuffers) (%x : %s)",
2114 omx_error
, ErrorToString(omx_error
) );
2117 msg_Dbg( p_dec
, "direct output port enabled" );
2118 if (p_dummy_hwpic
!= NULL
)
2119 picture_Release(p_dummy_hwpic
);
2122 if (p_dummy_hwpic
!= NULL
)
2123 picture_Release(p_dummy_hwpic
);
2124 /* if HwBuffer_Init fails, we can fall back to non direct buffers */
2125 HwBuffer_Destroy( p_dec
, p_port
);
2128 /*****************************************************************************
2130 *****************************************************************************/
2131 static void HwBuffer_Destroy( decoder_t
*p_dec
, OmxPort
*p_port
)
2133 if( p_port
->p_hwbuf
)
2135 if( p_port
->p_hwbuf
->window_priv
)
2137 HwBuffer_Stop( p_dec
, p_port
);
2138 HwBuffer_FreeBuffers( p_dec
, p_port
);
2139 HwBuffer_Join( p_dec
, p_port
);
2140 p_port
->p_hwbuf
->anwpriv
.disconnect( p_port
->p_hwbuf
->window_priv
);
2141 pf_enable_graphic_buffers( p_port
->omx_handle
,
2142 p_port
->i_port_index
, OMX_FALSE
);
2145 vlc_cond_destroy( &p_port
->p_hwbuf
->wait
);
2146 vlc_mutex_destroy( &p_port
->p_hwbuf
->lock
);
2147 free( p_port
->p_hwbuf
);
2148 p_port
->p_hwbuf
= NULL
;
2150 p_port
->b_direct
= false;
2153 /*****************************************************************************
2154 * HwBuffer_AllocateBuffers
2155 *****************************************************************************/
2156 static int HwBuffer_AllocateBuffers( decoder_t
*p_dec
, OmxPort
*p_port
)
2158 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
2159 OMX_PARAM_PORTDEFINITIONTYPE
*def
= &p_port
->definition
;
2160 unsigned int min_undequeued
= 0;
2162 int colorFormat
= def
->format
.video
.eColorFormat
;
2163 OMX_ERRORTYPE omx_error
;
2166 if( !p_port
->p_hwbuf
)
2169 omx_error
= pf_get_hal_format( p_sys
->psz_component
, &colorFormat
);
2170 if( omx_error
!= OMX_ErrorNone
)
2172 msg_Warn( p_dec
, "pf_get_hal_format failed (Not fatal)" );
2175 omx_error
= pf_get_graphic_buffer_usage( p_port
->omx_handle
,
2176 p_port
->i_port_index
,
2178 if( omx_error
!= OMX_ErrorNone
)
2180 msg_Warn( p_dec
, "pf_get_graphic_buffer_usage failed (Not fatal)" );
2184 if( p_port
->p_fmt
->video
.orientation
!= ORIENT_NORMAL
)
2188 switch( p_port
->p_fmt
->video
.orientation
)
2190 case ORIENT_ROTATED_90
:
2193 case ORIENT_ROTATED_180
:
2196 case ORIENT_ROTATED_270
:
2202 p_port
->p_hwbuf
->anwpriv
.setOrientation( p_port
->p_hwbuf
->window_priv
,
2206 if( p_port
->p_hwbuf
->anwpriv
.setUsage( p_port
->p_hwbuf
->window_priv
,
2207 true, (int) i_hw_usage
) != 0 )
2209 msg_Err( p_dec
, "can't set usage" );
2212 if( p_port
->p_hwbuf
->anwpriv
.setBuffersGeometry( p_port
->p_hwbuf
->window_priv
,
2213 def
->format
.video
.nFrameWidth
,
2214 def
->format
.video
.nFrameHeight
,
2215 colorFormat
) != 0 )
2217 msg_Err( p_dec
, "can't set buffers geometry" );
2221 if( p_port
->p_hwbuf
->anwpriv
.getMinUndequeued( p_port
->p_hwbuf
->window_priv
,
2222 &min_undequeued
) != 0 )
2224 msg_Err( p_dec
, "can't get min_undequeued" );
2228 if( def
->nBufferCountActual
< def
->nBufferCountMin
+ min_undequeued
)
2230 unsigned int new_frames_num
= def
->nBufferCountMin
+ min_undequeued
;
2232 OMX_DBG( "AllocateBuffers: video out wants more frames: %lu vs %u",
2233 p_port
->definition
.nBufferCountActual
, new_frames_num
);
2235 p_port
->definition
.nBufferCountActual
= new_frames_num
;
2236 omx_error
= OMX_SetParameter( p_dec
->p_sys
->omx_handle
,
2237 OMX_IndexParamPortDefinition
,
2238 &p_port
->definition
);
2239 CHECK_ERROR( omx_error
, "OMX_SetParameter failed (%x : %s)",
2240 omx_error
, ErrorToString(omx_error
) );
2243 if( p_port
->p_hwbuf
->anwpriv
.setBufferCount( p_port
->p_hwbuf
->window_priv
,
2244 def
->nBufferCountActual
) != 0 )
2246 msg_Err( p_dec
, "can't set buffer_count" );
2250 p_port
->p_hwbuf
->i_buffers
= p_port
->definition
.nBufferCountActual
;
2251 p_port
->p_hwbuf
->i_max_owned
= p_port
->p_hwbuf
->i_buffers
- min_undequeued
;
2253 p_port
->p_hwbuf
->pp_handles
= calloc( p_port
->p_hwbuf
->i_buffers
,
2255 if( !p_port
->p_hwbuf
->pp_handles
)
2258 p_port
->p_hwbuf
->i_states
= calloc( p_port
->p_hwbuf
->i_buffers
, sizeof(int) );
2259 if( !p_port
->p_hwbuf
->i_states
)
2262 p_port
->p_hwbuf
->inflight_picture
= calloc( p_port
->p_hwbuf
->i_buffers
,
2263 sizeof(picture_sys_t
*) );
2264 if( !p_port
->p_hwbuf
->inflight_picture
)
2267 for(i
= 0; i
< p_port
->p_hwbuf
->i_buffers
; i
++)
2269 void *p_handle
= NULL
;
2271 if( p_port
->p_hwbuf
->anwpriv
.dequeue( p_port
->p_hwbuf
->window_priv
,
2274 msg_Err( p_dec
, "OMXHWBuffer_dequeue Fail" );
2277 p_port
->p_hwbuf
->pp_handles
[i
] = p_handle
;
2279 for(i
= 0; i
< p_port
->p_hwbuf
->i_max_owned
; i
++)
2280 HwBuffer_ChangeState( p_dec
, p_port
, i
, BUF_STATE_OWNED
);
2281 for(; i
< p_port
->p_hwbuf
->i_buffers
; i
++)
2283 OMX_DBG( "canceling buffer(%d)", i
);
2284 p_port
->p_hwbuf
->anwpriv
.cancel( p_port
->p_hwbuf
->window_priv
,
2285 p_port
->p_hwbuf
->pp_handles
[i
] );
2292 msg_Err( p_dec
, "HwBuffer_AllocateBuffers(%d) failed", def
->eDir
);
2296 /*****************************************************************************
2297 * HwBuffer_FreeBuffers
2298 *****************************************************************************/
2299 static int HwBuffer_FreeBuffers( decoder_t
*p_dec
, OmxPort
*p_port
)
2301 msg_Dbg( p_dec
, "HwBuffer_FreeBuffers");
2303 HWBUFFER_LOCK( p_port
);
2305 p_port
->p_hwbuf
->b_run
= false;
2307 if( p_port
->p_hwbuf
->pp_handles
)
2309 for(unsigned int i
= 0; i
< p_port
->p_hwbuf
->i_buffers
; i
++)
2311 void *p_handle
= p_port
->p_hwbuf
->pp_handles
[i
];
2313 if( p_handle
&& p_port
->p_hwbuf
->i_states
[i
] == BUF_STATE_OWNED
)
2315 p_port
->p_hwbuf
->anwpriv
.cancel( p_port
->p_hwbuf
->window_priv
, p_handle
);
2316 HwBuffer_ChangeState( p_dec
, p_port
, i
, BUF_STATE_NOT_OWNED
);
2320 HWBUFFER_BROADCAST( p_port
);
2322 HWBUFFER_UNLOCK( p_port
);
2324 p_port
->p_hwbuf
->i_buffers
= 0;
2326 free( p_port
->p_hwbuf
->pp_handles
);
2327 p_port
->p_hwbuf
->pp_handles
= NULL
;
2329 free( p_port
->p_hwbuf
->i_states
);
2330 p_port
->p_hwbuf
->i_states
= NULL
;
2332 free( p_port
->p_hwbuf
->inflight_picture
);
2333 p_port
->p_hwbuf
->inflight_picture
= NULL
;
2338 /*****************************************************************************
2340 *****************************************************************************/
2341 static int HwBuffer_Start( decoder_t
*p_dec
, OmxPort
*p_port
)
2343 OMX_BUFFERHEADERTYPE
*p_header
;
2345 msg_Dbg( p_dec
, "HwBuffer_Start" );
2346 HWBUFFER_LOCK( p_port
);
2348 /* fill all owned buffers dequeued by HwBuffer_AllocatesBuffers */
2349 for(unsigned int i
= 0; i
< p_port
->p_hwbuf
->i_buffers
; i
++)
2351 p_header
= p_port
->pp_buffers
[i
];
2353 if( p_header
&& p_port
->p_hwbuf
->i_states
[i
] == BUF_STATE_OWNED
)
2355 if( p_port
->p_hwbuf
->anwpriv
.lock( p_port
->p_hwbuf
->window_priv
,
2356 p_header
->pBuffer
) != 0 )
2358 msg_Err( p_dec
, "lock failed" );
2359 HWBUFFER_UNLOCK( p_port
);
2362 OMX_DBG( "FillThisBuffer %p, %p", (void *)p_header
,
2363 (void *)p_header
->pBuffer
);
2364 OMX_FillThisBuffer( p_port
->omx_handle
, p_header
);
2368 p_port
->p_hwbuf
->b_run
= true;
2369 if( vlc_clone( &p_port
->p_hwbuf
->dequeue_thread
,
2370 DequeueThread
, p_dec
, VLC_THREAD_PRIORITY_LOW
) )
2372 p_port
->p_hwbuf
->b_run
= false;
2373 HWBUFFER_UNLOCK( p_port
);
2377 HWBUFFER_UNLOCK( p_port
);
2382 /*****************************************************************************
2383 * HwBuffer_Stop: stop DequeueThread and invalidate all pictures that are sent
2384 * to vlc core. The thread can be stuck in dequeue, so don't
2385 * join it now since it can be unblocked later by HwBuffer_FreeBuffers.
2386 *****************************************************************************/
2387 static int HwBuffer_Stop( decoder_t
*p_dec
, OmxPort
*p_port
)
2389 VLC_UNUSED( p_dec
);
2391 msg_Dbg( p_dec
, "HwBuffer_Stop" );
2392 HWBUFFER_LOCK( p_port
);
2394 p_port
->p_hwbuf
->b_run
= false;
2396 /* invalidate and release all inflight pictures */
2397 if( p_port
->p_hwbuf
->inflight_picture
) {
2398 for( unsigned int i
= 0; i
< p_port
->i_buffers
; ++i
) {
2399 picture_sys_t
*p_picsys
= p_port
->p_hwbuf
->inflight_picture
[i
];
2402 AndroidOpaquePicture_DetachDecoder(p_picsys
);
2403 p_port
->p_hwbuf
->inflight_picture
[i
] = NULL
;
2408 HWBUFFER_BROADCAST( p_port
);
2410 HWBUFFER_UNLOCK( p_port
);
2415 /*****************************************************************************
2416 * HwBuffer_Join: join DequeueThread previously stopped by HwBuffer_Stop.
2417 *****************************************************************************/
2418 static int HwBuffer_Join( decoder_t
*p_dec
, OmxPort
*p_port
)
2420 VLC_UNUSED( p_dec
);
2422 if( p_port
->p_hwbuf
->dequeue_thread
)
2424 vlc_join( p_port
->p_hwbuf
->dequeue_thread
, NULL
);
2425 p_port
->p_hwbuf
->dequeue_thread
= NULL
;
2430 /*****************************************************************************
2432 *****************************************************************************/
2433 static int HwBuffer_GetPic( decoder_t
*p_dec
, OmxPort
*p_port
,
2438 picture_sys_t
*p_picsys
;
2439 OMX_BUFFERHEADERTYPE
*p_header
;
2441 OMX_FIFO_PEEK(&p_port
->fifo
, p_header
);
2446 for(unsigned int i
= 0; i
< p_port
->i_buffers
; i
++)
2448 if( p_port
->pp_buffers
[i
] == p_header
)
2456 msg_Err( p_dec
, "output buffer not found" );
2460 p_pic
= decoder_NewPicture( p_dec
);
2463 msg_Err( p_dec
, "decoder_NewPicture failed" );
2466 p_pic
->date
= FromOmxTicks( p_header
->nTimeStamp
);
2468 p_picsys
= p_pic
->p_sys
;
2469 p_picsys
->hw
.i_index
= i_index
;
2470 p_picsys
->hw
.p_dec
= p_dec
;
2471 p_picsys
->hw
.pf_release
= ReleasePicture
;
2473 p_port
->p_hwbuf
->inflight_picture
[i_index
] = p_picsys
;
2476 OMX_FIFO_GET( &p_port
->fifo
, p_header
);
2480 /*****************************************************************************
2482 *****************************************************************************/
2483 static void HwBuffer_SetCrop( decoder_t
*p_dec
, OmxPort
*p_port
,
2484 OMX_CONFIG_RECTTYPE
*p_rect
)
2486 VLC_UNUSED( p_dec
);
2488 p_port
->p_hwbuf
->anwpriv
.setCrop( p_port
->p_hwbuf
->window_priv
,
2489 p_rect
->nLeft
, p_rect
->nTop
,
2490 p_rect
->nWidth
, p_rect
->nHeight
);
2493 /*****************************************************************************
2495 *****************************************************************************/
2496 static void *DequeueThread( void *data
)
2498 decoder_t
*p_dec
= data
;
2499 decoder_sys_t
*p_sys
= p_dec
->p_sys
;;
2500 OmxPort
*p_port
= &p_sys
->out
;
2504 void *p_handle
= NULL
;
2505 OMX_BUFFERHEADERTYPE
*p_header
;
2507 msg_Dbg( p_dec
, "DequeueThread running");
2508 HWBUFFER_LOCK( p_port
);
2509 while( p_port
->p_hwbuf
->b_run
)
2511 while( p_port
->p_hwbuf
->b_run
&&
2512 p_port
->p_hwbuf
->i_owned
>= p_port
->p_hwbuf
->i_max_owned
)
2513 HWBUFFER_WAIT( p_port
);
2515 if( !p_port
->p_hwbuf
->b_run
) continue;
2517 HWBUFFER_UNLOCK( p_port
);
2520 /* The thread can be stuck here. It shouldn't happen since we make sure
2521 * we call the dequeue function if there is at least one buffer
2523 err
= p_port
->p_hwbuf
->anwpriv
.dequeue( p_port
->p_hwbuf
->window_priv
, &p_handle
);
2525 err
= p_port
->p_hwbuf
->anwpriv
.lock( p_port
->p_hwbuf
->window_priv
, p_handle
);
2527 HWBUFFER_LOCK( p_port
);
2531 p_port
->p_hwbuf
->b_run
= false;
2535 if( !p_port
->p_hwbuf
->b_run
)
2537 p_port
->p_hwbuf
->anwpriv
.cancel( p_port
->p_hwbuf
->window_priv
, p_handle
);
2541 for(i
= 0; i
< p_port
->i_buffers
; i
++)
2543 if( p_port
->pp_buffers
[i
]->pBuffer
== p_handle
)
2546 p_header
= p_port
->pp_buffers
[i_index
];
2552 msg_Err( p_dec
, "p_port->p_hwbuf->anwpriv.dequeue returned unknown handle" );
2556 HwBuffer_ChangeState( p_dec
, p_port
, i_index
, BUF_STATE_OWNED
);
2558 OMX_DBG( "FillThisBuffer %p, %p", (void *)p_header
,
2559 (void *)p_header
->pBuffer
);
2560 OMX_FillThisBuffer( p_sys
->omx_handle
, p_header
);
2562 HWBUFFER_BROADCAST( p_port
);
2564 HWBUFFER_UNLOCK( p_port
);
2566 msg_Dbg( p_dec
, "DequeueThread stopped");
2570 /*****************************************************************************
2572 *****************************************************************************/
2573 static void ReleasePicture( decoder_t
*p_dec
, unsigned int i_index
,
2576 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
2577 OmxPort
*p_port
= &p_sys
->out
;
2580 p_handle
= p_port
->pp_buffers
[i_index
]->pBuffer
;
2582 OMX_DBG( "DisplayBuffer: %s %p",
2583 b_render
? "render" : "cancel", p_handle
);
2587 msg_Err( p_dec
, "DisplayBuffer: buffer handle invalid" );
2592 p_port
->p_hwbuf
->anwpriv
.queue( p_port
->p_hwbuf
->window_priv
, p_handle
);
2594 p_port
->p_hwbuf
->anwpriv
.cancel( p_port
->p_hwbuf
->window_priv
, p_handle
);
2596 HwBuffer_ChangeState( p_dec
, p_port
, i_index
, BUF_STATE_NOT_OWNED
);
2597 HWBUFFER_BROADCAST( p_port
);