1 /*****************************************************************************
2 * mediacodec.c: Video decoder module using the Android MediaCodec API
3 *****************************************************************************
4 * Copyright (C) 2012 Martin Storsjo
6 * Authors: Martin Storsjo <martin@martin.st>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <stdatomic.h>
34 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_codec.h>
38 #include <vlc_block_helper.h>
39 #include <vlc_timestamp_helper.h>
40 #include <vlc_threads.h>
43 #include "mediacodec.h"
44 #include "../codec/hxxx_helper.h"
46 #include <OMX_Component.h>
47 #include "omxil_utils.h"
49 #define BLOCK_FLAG_CSD (0x01 << BLOCK_FLAG_PRIVATE_SHIFT)
51 #define DECODE_FLAG_RESTART (0x01)
52 #define DECODE_FLAG_DRAIN (0x02)
57 * Callback called when a new block is processed from DecodeBlock.
58 * It returns -1 in case of error, 0 if block should be dropped, 1 otherwise.
60 typedef int (*dec_on_new_block_cb
)(decoder_t
*, block_t
**);
63 * Callback called when decoder is flushing.
66 typedef void (*dec_on_flush_cb
)(struct decoder_sys_t
*);
69 * Callback called when DecodeBlock try to get an output buffer (pic or block).
70 * It returns -1 in case of error, or the number of output buffer returned.
72 typedef int (*dec_process_output_cb
)(decoder_t
*, mc_api_out
*, picture_t
**,
75 struct android_picture_ctx
82 typedef struct decoder_sys_t
86 /* Codec Specific Data buffer: sent in DecodeBlock after a start or a flush
87 * with the BUFFER_FLAG_CODEC_CONFIG flag.*/
88 #define MAX_CSD_COUNT 3
89 block_t
*pp_csd
[MAX_CSD_COUNT
];
95 int64_t i_preroll_end
;
98 /* Specific Audio/Video callbacks */
99 dec_on_new_block_cb pf_on_new_block
;
100 dec_on_flush_cb pf_on_flush
;
101 dec_process_output_cb pf_process_output
;
104 vlc_thread_t out_thread
;
105 /* Cond used to signal the output thread */
107 /* Cond used to signal the decoder thread */
109 /* Set to true by pf_flush to signal the output thread to flush */
111 /* If true, the output thread will start to dequeue output pictures */
113 /* If true, the first input block was successfully dequeued */
114 bool b_input_dequeued
;
119 /* If true, the decoder_t object has been closed and decoder_* functions
120 * are now unavailable. */
125 enum es_format_category_e cat
;
130 vlc_video_context
*ctx
;
131 struct android_picture_ctx apic_ctxs
[MAX_PIC
];
132 void *p_surface
, *p_jsurface
;
134 unsigned i_input_width
, i_input_height
;
135 unsigned int i_stride
, i_slice_height
;
137 struct hxxx_helper hh
;
138 timestamp_fifo_t
*timestamp_fifo
;
139 int i_mpeg_dar_num
, i_mpeg_dar_den
;
140 struct vlc_asurfacetexture
*surfacetexture
;
146 /* Some audio decoders need a valid channel count */
147 bool b_need_channels
;
148 int pi_extraction
[AOUT_CHAN_MAX
];
153 /*****************************************************************************
155 *****************************************************************************/
156 static int OpenDecoderJni(vlc_object_t
*);
157 static int OpenDecoderNdk(vlc_object_t
*);
158 static void CleanDecoder(decoder_sys_t
*);
159 static void CloseDecoder(vlc_object_t
*);
161 static int Video_OnNewBlock(decoder_t
*, block_t
**);
162 static int VideoHXXX_OnNewBlock(decoder_t
*, block_t
**);
163 static int VideoMPEG2_OnNewBlock(decoder_t
*, block_t
**);
164 static int VideoVC1_OnNewBlock(decoder_t
*, block_t
**);
165 static void Video_OnFlush(decoder_sys_t
*);
166 static int Video_ProcessOutput(decoder_t
*, mc_api_out
*, picture_t
**,
168 static int DecodeBlock(decoder_t
*, block_t
*);
170 static int Audio_OnNewBlock(decoder_t
*, block_t
**);
171 static void Audio_OnFlush(decoder_sys_t
*);
172 static int Audio_ProcessOutput(decoder_t
*, mc_api_out
*, picture_t
**,
175 static void DecodeFlushLocked(decoder_sys_t
*);
176 static void DecodeFlush(decoder_t
*);
177 static void StopMediaCodec(decoder_sys_t
*);
178 static void *OutThread(void *);
180 static void ReleaseAllPictureContexts(decoder_sys_t
*);
182 /*****************************************************************************
184 *****************************************************************************/
185 #define MEDIACODEC_ENABLE_TEXT N_("Enable hardware acceleration")
187 #define DIRECTRENDERING_TEXT "Android direct rendering"
188 #define DIRECTRENDERING_LONGTEXT \
189 "Enable Android direct rendering using opaque buffers."
191 #define MEDIACODEC_AUDIO_TEXT "Use MediaCodec for audio decoding"
192 #define MEDIACODEC_AUDIO_LONGTEXT "Still experimental."
194 #define MEDIACODEC_TUNNELEDPLAYBACK_TEXT "Use a tunneled surface for playback"
196 #define CFG_PREFIX "mediacodec-"
199 set_description("Video decoder using Android MediaCodec via NDK")
200 set_category(CAT_INPUT
)
201 set_subcategory(SUBCAT_INPUT_VCODEC
)
202 set_section(N_("Decoding"), NULL
)
203 set_capability("video decoder", 800)
204 add_bool("mediacodec", true, MEDIACODEC_ENABLE_TEXT
, NULL
, false)
205 add_bool(CFG_PREFIX
"dr", true,
206 DIRECTRENDERING_TEXT
, DIRECTRENDERING_LONGTEXT
, true)
207 add_bool(CFG_PREFIX
"audio", false,
208 MEDIACODEC_AUDIO_TEXT
, MEDIACODEC_AUDIO_LONGTEXT
, true)
209 add_bool(CFG_PREFIX
"tunneled-playback", false,
210 MEDIACODEC_TUNNELEDPLAYBACK_TEXT
, NULL
, true)
211 set_callbacks(OpenDecoderNdk
, CloseDecoder
)
212 add_shortcut("mediacodec_ndk")
214 set_capability("audio decoder", 0)
215 set_callbacks(OpenDecoderNdk
, CloseDecoder
)
216 add_shortcut("mediacodec_ndk")
218 set_description("Video decoder using Android MediaCodec via JNI")
219 set_capability("video decoder", 0)
220 set_callbacks(OpenDecoderJni
, CloseDecoder
)
221 add_shortcut("mediacodec_jni")
223 set_capability("audio decoder", 0)
224 set_callbacks(OpenDecoderJni
, CloseDecoder
)
225 add_shortcut("mediacodec_jni")
228 static void CSDFree(decoder_sys_t
*p_sys
)
230 for (unsigned int i
= 0; i
< p_sys
->i_csd_count
; ++i
)
231 block_Release(p_sys
->pp_csd
[i
]);
232 p_sys
->i_csd_count
= 0;
235 /* Init the p_sys->p_csd that will be sent from DecodeBlock */
236 static void CSDInit(decoder_sys_t
*p_sys
, block_t
*p_blocks
, size_t i_count
)
238 assert(i_count
<= MAX_CSD_COUNT
);
242 for (size_t i
= 0; i
< i_count
; ++i
)
244 assert(p_blocks
!= NULL
);
245 p_sys
->pp_csd
[i
] = p_blocks
;
246 p_sys
->pp_csd
[i
]->i_flags
= BLOCK_FLAG_CSD
;
247 p_blocks
= p_blocks
->p_next
;
248 p_sys
->pp_csd
[i
]->p_next
= NULL
;
251 p_sys
->i_csd_count
= i_count
;
252 p_sys
->i_csd_send
= 0;
255 static int CSDDup(decoder_sys_t
*p_sys
, const void *p_buf
, size_t i_buf
)
257 block_t
*p_block
= block_Alloc(i_buf
);
260 memcpy(p_block
->p_buffer
, p_buf
, i_buf
);
262 CSDInit(p_sys
, p_block
, 1);
266 static void HXXXInitSize(decoder_t
*p_dec
, bool *p_size_changed
)
270 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
271 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
272 unsigned i_w
, i_h
, i_vw
, i_vh
;
273 hxxx_helper_get_current_picture_size(hh
, &i_w
, &i_h
, &i_vw
, &i_vh
);
275 *p_size_changed
= (i_w
!= p_sys
->video
.i_input_width
276 || i_h
!= p_sys
->video
.i_input_height
);
277 p_sys
->video
.i_input_width
= i_w
;
278 p_sys
->video
.i_input_height
= i_h
;
279 /* fmt_out video size will be updated by mediacodec output callback */
283 /* Fill the p_sys->p_csd struct with H264 Parameter Sets */
284 static int H264SetCSD(decoder_t
*p_dec
, bool *p_size_changed
)
286 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
287 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
288 assert(hh
->h264
.i_sps_count
> 0 || hh
->h264
.i_pps_count
> 0);
290 block_t
*p_spspps_blocks
= h264_helper_get_annexb_config(hh
);
292 if (p_spspps_blocks
!= NULL
)
293 CSDInit(p_sys
, p_spspps_blocks
, 2);
295 HXXXInitSize(p_dec
, p_size_changed
);
300 /* Fill the p_sys->p_csd struct with HEVC Parameter Sets */
301 static int HEVCSetCSD(decoder_t
*p_dec
, bool *p_size_changed
)
303 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
304 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
306 assert(hh
->hevc
.i_vps_count
> 0 || hh
->hevc
.i_sps_count
> 0 ||
307 hh
->hevc
.i_pps_count
> 0 );
309 block_t
*p_xps_blocks
= hevc_helper_get_annexb_config(hh
);
310 if (p_xps_blocks
!= NULL
)
312 block_t
*p_monolith
= block_ChainGather(p_xps_blocks
);
313 if (p_monolith
== NULL
)
315 block_ChainRelease(p_xps_blocks
);
318 CSDInit(p_sys
, p_monolith
, 1);
321 HXXXInitSize(p_dec
, p_size_changed
);
325 static int ParseVideoExtraH264(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
327 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
328 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
330 int i_ret
= hxxx_helper_set_extra(hh
, p_extra
, i_extra
);
331 if (i_ret
!= VLC_SUCCESS
)
333 assert(hh
->pf_process_block
!= NULL
);
335 if (p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
336 p_sys
->b_adaptive
= true;
338 p_sys
->pf_on_new_block
= VideoHXXX_OnNewBlock
;
340 if (hh
->h264
.i_sps_count
> 0 || hh
->h264
.i_pps_count
> 0)
341 return H264SetCSD(p_dec
, NULL
);
345 static int ParseVideoExtraHEVC(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
347 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
348 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
350 int i_ret
= hxxx_helper_set_extra(hh
, p_extra
, i_extra
);
351 if (i_ret
!= VLC_SUCCESS
)
353 assert(hh
->pf_process_block
!= NULL
);
355 if (p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
356 p_sys
->b_adaptive
= true;
358 p_sys
->pf_on_new_block
= VideoHXXX_OnNewBlock
;
360 if (hh
->hevc
.i_vps_count
> 0 || hh
->hevc
.i_sps_count
> 0 ||
361 hh
->hevc
.i_pps_count
> 0 )
362 return HEVCSetCSD(p_dec
, NULL
);
366 static int ParseVideoExtraVc1(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
368 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
374 /* Initialisation data starts with : 0x00 0x00 0x01 0x0f */
375 /* Skipping unecessary data */
376 static const uint8_t vc1_start_code
[4] = {0x00, 0x00, 0x01, 0x0f};
377 for (; offset
< i_extra
- 4 ; ++offset
)
379 if (!memcmp(&p_extra
[offset
], vc1_start_code
, 4))
383 /* Could not find the sequence header start code */
384 if (offset
>= i_extra
- 4)
387 p_sys
->pf_on_new_block
= VideoVC1_OnNewBlock
;
388 return CSDDup(p_sys
, p_extra
+ offset
, i_extra
- offset
);
391 static int ParseVideoExtraWmv3(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
393 /* WMV3 initialisation data :
396 * 4 height bytes (little endian)
397 * 4 width bytes (little endian)
403 uint8_t p_data
[36] = {
404 0x8e, 0x01, 0x00, 0xc5, /* Fixed bytes values */
405 0x04, 0x00, 0x00, 0x00, /* Same */
406 0x00, 0x00, 0x00, 0x00, /* extradata emplacement */
407 0x00, 0x00, 0x00, 0x00, /* height emplacement (little endian) */
408 0x00, 0x00, 0x00, 0x00, /* width emplacement (little endian) */
409 0x0c, 0x00, 0x00, 0x00, /* Fixed byte pattern */
410 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00
415 /* Adding extradata */
416 memcpy(&p_data
[8], p_extra
, 4);
417 /* Adding height and width, little endian */
418 SetDWLE(&(p_data
[12]), p_dec
->fmt_in
.video
.i_height
);
419 SetDWLE(&(p_data
[16]), p_dec
->fmt_in
.video
.i_width
);
421 return CSDDup(p_dec
->p_sys
, p_data
, sizeof(p_data
));
424 static int ParseExtra(decoder_t
*p_dec
)
426 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
427 uint8_t *p_extra
= p_dec
->fmt_in
.p_extra
;
428 int i_extra
= p_dec
->fmt_in
.i_extra
;
430 switch (p_dec
->fmt_in
.i_codec
)
433 return ParseVideoExtraH264(p_dec
, p_extra
, i_extra
);
435 return ParseVideoExtraHEVC(p_dec
, p_extra
, i_extra
);
437 return ParseVideoExtraWmv3(p_dec
, p_extra
, i_extra
);
439 return ParseVideoExtraVc1(p_dec
, p_extra
, i_extra
);
441 if (!i_extra
&& p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
442 p_sys
->b_adaptive
= true;
446 p_sys
->pf_on_new_block
= VideoMPEG2_OnNewBlock
;
449 /* Set default CSD */
450 if (p_dec
->fmt_in
.i_extra
)
451 return CSDDup(p_sys
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
456 /*****************************************************************************
457 * StartMediaCodec: Create the mediacodec instance
458 *****************************************************************************/
459 static int StartMediaCodec(decoder_t
*p_dec
)
461 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
462 union mc_api_args args
;
464 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
466 args
.video
.i_width
= p_dec
->fmt_out
.video
.i_width
;
467 args
.video
.i_height
= p_dec
->fmt_out
.video
.i_height
;
468 args
.video
.i_angle
= p_sys
->video
.i_angle
;
470 args
.video
.p_surface
= p_sys
->video
.p_surface
;
471 args
.video
.p_jsurface
= p_sys
->video
.p_jsurface
;
473 args
.video
.b_tunneled_playback
= args
.video
.p_surface
?
474 var_InheritBool(p_dec
, CFG_PREFIX
"tunneled-playback") : false;
475 if (p_sys
->b_adaptive
)
476 msg_Dbg(p_dec
, "mediacodec configured for adaptative playback");
477 args
.video
.b_adaptive_playback
= p_sys
->b_adaptive
;
481 date_Set(&p_sys
->audio
.i_end_date
, VLC_TICK_INVALID
);
483 args
.audio
.i_sample_rate
= p_dec
->fmt_in
.audio
.i_rate
;
484 args
.audio
.i_channel_count
= p_sys
->audio
.i_channels
;
487 if (p_sys
->api
.configure_decoder(&p_sys
->api
, &args
) != 0)
492 return p_sys
->api
.start(&p_sys
->api
);
495 /*****************************************************************************
496 * StopMediaCodec: Close the mediacodec instance
497 *****************************************************************************/
498 static void StopMediaCodec(decoder_sys_t
*p_sys
)
500 /* Remove all pictures that are currently in flight in order
501 * to prevent the vout from using destroyed output buffers. */
502 if (p_sys
->cat
== VIDEO_ES
)
503 ReleaseAllPictureContexts(p_sys
);
505 p_sys
->api
.stop(&p_sys
->api
);
508 static bool AndroidPictureContextRelease(struct android_picture_ctx
*apctx
,
511 int index
= atomic_exchange(&apctx
->index
, -1);
514 android_video_context_t
*avctx
=
515 vlc_video_context_GetPrivate(apctx
->s
.vctx
, VLC_VIDEO_CONTEXT_AWINDOW
);
516 decoder_sys_t
*p_sys
= avctx
->dec_opaque
;
518 p_sys
->api
.release_out(&p_sys
->api
, index
, render
);
524 static bool PictureContextRenderPic(struct picture_context_t
*ctx
)
526 struct android_picture_ctx
*apctx
=
527 container_of(ctx
, struct android_picture_ctx
, s
);
529 return AndroidPictureContextRelease(apctx
, true);
532 static bool PictureContextRenderPicTs(struct picture_context_t
*ctx
,
535 struct android_picture_ctx
*apctx
=
536 container_of(ctx
, struct android_picture_ctx
, s
);
538 int index
= atomic_exchange(&apctx
->index
, -1);
541 android_video_context_t
*avctx
=
542 vlc_video_context_GetPrivate(ctx
->vctx
, VLC_VIDEO_CONTEXT_AWINDOW
);
543 decoder_sys_t
*p_sys
= avctx
->dec_opaque
;
545 p_sys
->api
.release_out_ts(&p_sys
->api
, index
, ts
* INT64_C(1000));
551 static struct vlc_asurfacetexture
*
552 PictureContextGetTexture(picture_context_t
*context
)
554 android_video_context_t
*avctx
=
555 vlc_video_context_GetPrivate(context
->vctx
, VLC_VIDEO_CONTEXT_AWINDOW
);
556 decoder_sys_t
*p_sys
= avctx
->dec_opaque
;
558 return p_sys
->video
.surfacetexture
;
561 static void PictureContextDestroy(struct picture_context_t
*ctx
)
563 struct android_picture_ctx
*apctx
=
564 container_of(ctx
, struct android_picture_ctx
, s
);
566 if (atomic_fetch_sub_explicit(&apctx
->refs
, 1, memory_order_acq_rel
) == 1)
567 AndroidPictureContextRelease(apctx
, false);
570 static struct picture_context_t
*PictureContextCopy(struct picture_context_t
*ctx
)
572 struct android_picture_ctx
*apctx
=
573 container_of(ctx
, struct android_picture_ctx
, s
);
575 atomic_fetch_add_explicit(&apctx
->refs
, 1, memory_order_relaxed
);
576 vlc_video_context_Hold(ctx
->vctx
);
580 static void AbortDecoderLocked(decoder_sys_t
*p_dec
);
581 static void CleanFromVideoContext(void *priv
)
583 android_video_context_t
*avctx
= priv
;
584 decoder_sys_t
*p_sys
= avctx
->dec_opaque
;
586 vlc_mutex_lock(&p_sys
->lock
);
587 /* Unblock output thread waiting in dequeue_out */
588 DecodeFlushLocked(p_sys
);
589 /* Cancel the output thread */
590 AbortDecoderLocked(p_sys
);
591 vlc_mutex_unlock(&p_sys
->lock
);
593 vlc_join(p_sys
->out_thread
, NULL
);
598 static void ReleaseAllPictureContexts(decoder_sys_t
*p_sys
)
600 /* No picture context if no direct rendering. */
601 if (p_sys
->video
.ctx
== NULL
)
604 for (size_t i
= 0; i
< ARRAY_SIZE(p_sys
->video
.apic_ctxs
); ++i
)
606 struct android_picture_ctx
*apctx
= &p_sys
->video
.apic_ctxs
[i
];
608 /* Don't decrement apctx->refs, the picture_context should stay valid
609 * even if the underlying buffer is released since it might still be
610 * used by the vout (but the vout won't be able to render it). */
611 AndroidPictureContextRelease(apctx
, false);
615 static struct android_picture_ctx
*
616 GetPictureContext(decoder_t
*p_dec
, unsigned index
)
618 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
623 for (size_t i
= 0; i
< ARRAY_SIZE(p_sys
->video
.apic_ctxs
); ++i
)
625 struct android_picture_ctx
*apctx
= &p_sys
->video
.apic_ctxs
[i
];
626 /* Find an available picture context (ie. refs == 0) */
627 unsigned expected_refs
= 0;
628 if (atomic_compare_exchange_strong(&apctx
->refs
, &expected_refs
, 1))
630 int expected_index
= -1;
631 /* Store the new index */
632 if (likely(atomic_compare_exchange_strong(&apctx
->index
,
633 &expected_index
, index
)))
636 /* Unlikely: Restore the ref count and try a next one, since
637 * this picture context is being released. Cf.
638 * PictureContextDestroy(), this function first decrement the
639 * ref count before releasing the index. */
640 atomic_store(&apctx
->refs
, 0);
644 /* This is very unlikely since there are generally more picture
645 * contexts than android MediaCodec buffers */
647 msg_Warn(p_dec
, "waiting for more picture contexts (unlikely)");
648 vlc_tick_sleep(VOUT_OUTMEM_SLEEP
);
654 CreateVideoContext(decoder_t
*p_dec
)
656 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
658 vlc_decoder_device
*dec_dev
= decoder_GetDecoderDevice(p_dec
);
659 if (!dec_dev
|| dec_dev
->type
!= VLC_DECODER_DEVICE_AWINDOW
)
661 msg_Err(p_dec
, "Could not find an AWINDOW decoder device");
665 assert(dec_dev
->opaque
);
666 AWindowHandler
*awh
= dec_dev
->opaque
;
668 const bool has_subtitle_surface
=
669 AWindowHandler_getANativeWindow(awh
, AWindow_Subtitles
) != NULL
;
671 /* Force OpenGL interop (via AWindow_SurfaceTexture) if there is a
672 * projection or an orientation to handle, if the Surface owner is not able
673 * to modify its layout, or if there is no external subtitle surfaces. */
675 p_sys
->video
.surfacetexture
= NULL
;
676 bool use_surfacetexture
=
677 p_dec
->fmt_out
.video
.projection_mode
!= PROJECTION_MODE_RECTANGULAR
678 || (!p_sys
->api
.b_support_rotation
&& p_dec
->fmt_out
.video
.orientation
!= ORIENT_NORMAL
)
679 || !AWindowHandler_canSetVideoLayout(awh
)
680 || !has_subtitle_surface
;
682 if (!use_surfacetexture
)
684 p_sys
->video
.p_surface
= AWindowHandler_getANativeWindow(awh
, AWindow_Video
);
685 p_sys
->video
.p_jsurface
= AWindowHandler_getSurface(awh
, AWindow_Video
);
686 assert (p_sys
->video
.p_surface
);
687 if (!p_sys
->video
.p_surface
)
689 msg_Err(p_dec
, "Could not find a valid ANativeWindow");
694 if (use_surfacetexture
|| p_sys
->video
.p_surface
== NULL
)
696 p_sys
->video
.surfacetexture
= vlc_asurfacetexture_New(awh
, false);
697 assert(p_sys
->video
.surfacetexture
);
698 if (p_sys
->video
.surfacetexture
== NULL
)
700 p_sys
->video
.p_surface
= p_sys
->video
.surfacetexture
->window
;
701 p_sys
->video
.p_jsurface
= p_sys
->video
.surfacetexture
->jsurface
;
702 assert(p_sys
->video
.p_surface
);
703 assert(p_sys
->video
.p_jsurface
);
706 static const struct vlc_video_context_operations ops
=
708 .destroy
= CleanFromVideoContext
,
711 vlc_video_context_Create(dec_dev
, VLC_VIDEO_CONTEXT_AWINDOW
,
712 sizeof(android_video_context_t
), &ops
);
713 vlc_decoder_device_Release(dec_dev
);
715 if (!p_sys
->video
.ctx
)
718 android_video_context_t
*avctx
=
719 vlc_video_context_GetPrivate(p_sys
->video
.ctx
, VLC_VIDEO_CONTEXT_AWINDOW
);
720 avctx
->dec_opaque
= p_dec
->p_sys
;
721 avctx
->render
= PictureContextRenderPic
;
722 avctx
->render_ts
= p_sys
->api
.release_out_ts
? PictureContextRenderPicTs
: NULL
;
723 avctx
->get_texture
= p_sys
->video
.surfacetexture
? PictureContextGetTexture
: NULL
;
725 for (size_t i
= 0; i
< ARRAY_SIZE(p_sys
->video
.apic_ctxs
); ++i
)
727 struct android_picture_ctx
*apctx
= &p_sys
->video
.apic_ctxs
[i
];
729 apctx
->s
= (picture_context_t
) {
730 PictureContextDestroy
, PictureContextCopy
,
733 atomic_init(&apctx
->index
, -1);
734 atomic_init(&apctx
->refs
, 0);
740 vlc_decoder_device_Release(dec_dev
);
744 static void CleanInputVideo(decoder_t
*p_dec
)
746 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
748 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
750 if (p_dec
->fmt_in
.i_codec
== VLC_CODEC_H264
751 || p_dec
->fmt_in
.i_codec
== VLC_CODEC_HEVC
)
752 hxxx_helper_clean(&p_sys
->video
.hh
);
754 if (p_sys
->video
.timestamp_fifo
)
755 timestamp_FifoRelease(p_sys
->video
.timestamp_fifo
);
759 /*****************************************************************************
760 * OpenDecoder: Create the decoder instance
761 *****************************************************************************/
762 static int OpenDecoder(vlc_object_t
*p_this
, pf_MediaCodecApi_init pf_init
)
764 decoder_t
*p_dec
= (decoder_t
*)p_this
;
766 if (!var_InheritBool(p_dec
, "mediacodec"))
769 decoder_sys_t
*p_sys
;
771 int i_profile
= p_dec
->fmt_in
.i_profile
;
772 const char *mime
= NULL
;
774 /* Video or Audio if "mediacodec-audio" bool is true */
775 if (p_dec
->fmt_in
.i_cat
!= VIDEO_ES
&& (p_dec
->fmt_in
.i_cat
!= AUDIO_ES
776 || !var_InheritBool(p_dec
, CFG_PREFIX
"audio")))
779 /* Fail if this module already failed to decode this ES */
780 if (var_Type(p_dec
, "mediacodec-failed") != 0)
783 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
785 /* Not all mediacodec versions can handle a size of 0. Hopefully, the
786 * packetizer will trigger a decoder restart when a new video size is
788 if (!p_dec
->fmt_in
.video
.i_width
|| !p_dec
->fmt_in
.video
.i_height
)
791 switch (p_dec
->fmt_in
.i_codec
) {
795 uint8_t i_hevc_profile
;
796 if (hevc_get_profile_level(&p_dec
->fmt_in
, &i_hevc_profile
, NULL
, NULL
))
797 i_profile
= i_hevc_profile
;
804 uint8_t i_h264_profile
;
805 if (h264_get_profile_level(&p_dec
->fmt_in
, &i_h264_profile
, NULL
, NULL
))
806 i_profile
= i_h264_profile
;
810 case VLC_CODEC_H263
: mime
= "video/3gpp"; break;
811 case VLC_CODEC_MP4V
: mime
= "video/mp4v-es"; break;
814 mime
= "video/mpeg2";
816 case VLC_CODEC_WMV3
: mime
= "video/x-ms-wmv"; break;
817 case VLC_CODEC_VC1
: mime
= "video/wvc1"; break;
818 case VLC_CODEC_VP8
: mime
= "video/x-vnd.on2.vp8"; break;
819 case VLC_CODEC_VP9
: mime
= "video/x-vnd.on2.vp9"; break;
824 switch (p_dec
->fmt_in
.i_codec
) {
825 case VLC_CODEC_AMR_NB
: mime
= "audio/3gpp"; break;
826 case VLC_CODEC_AMR_WB
: mime
= "audio/amr-wb"; break;
828 case VLC_CODEC_MP3
: mime
= "audio/mpeg"; break;
829 case VLC_CODEC_MP2
: mime
= "audio/mpeg-L2"; break;
830 case VLC_CODEC_MP4A
: mime
= "audio/mp4a-latm"; break;
831 case VLC_CODEC_QCELP
: mime
= "audio/qcelp"; break;
832 case VLC_CODEC_VORBIS
: mime
= "audio/vorbis"; break;
833 case VLC_CODEC_OPUS
: mime
= "audio/opus"; break;
834 case VLC_CODEC_ALAW
: mime
= "audio/g711-alaw"; break;
835 case VLC_CODEC_MULAW
: mime
= "audio/g711-mlaw"; break;
836 case VLC_CODEC_FLAC
: mime
= "audio/flac"; break;
837 case VLC_CODEC_GSM
: mime
= "audio/gsm"; break;
838 case VLC_CODEC_A52
: mime
= "audio/ac3"; break;
839 case VLC_CODEC_EAC3
: mime
= "audio/eac3"; break;
840 case VLC_CODEC_ALAC
: mime
= "audio/alac"; break;
841 case VLC_CODEC_DTS
: mime
= "audio/vnd.dts"; break;
842 /* case VLC_CODEC_: mime = "audio/mpeg-L1"; break; */
843 /* case VLC_CODEC_: mime = "audio/aac-adts"; break; */
848 msg_Dbg(p_dec
, "codec %4.4s not supported",
849 (char *)&p_dec
->fmt_in
.i_codec
);
853 /* Allocate the memory needed to store the decoder's structure */
854 if ((p_sys
= calloc(1, sizeof(*p_sys
))) == NULL
)
857 p_sys
->api
.p_obj
= p_this
;
858 p_sys
->api
.i_codec
= p_dec
->fmt_in
.i_codec
;
859 p_sys
->api
.i_cat
= p_dec
->fmt_in
.i_cat
;
860 p_sys
->api
.psz_mime
= mime
;
861 p_sys
->video
.i_mpeg_dar_num
= 0;
862 p_sys
->video
.i_mpeg_dar_den
= 0;
863 p_sys
->video
.surfacetexture
= NULL
;
864 p_sys
->b_decoder_dead
= false;
866 if (pf_init(&p_sys
->api
) != 0)
871 if (p_sys
->api
.prepare(&p_sys
->api
, i_profile
) != 0)
873 /* If the device can't handle video/wvc1,
874 * it can probably handle video/x-ms-wmv */
875 if (!strcmp(mime
, "video/wvc1") && p_dec
->fmt_in
.i_codec
== VLC_CODEC_VC1
)
877 p_sys
->api
.psz_mime
= "video/x-ms-wmv";
878 if (p_sys
->api
.prepare(&p_sys
->api
, i_profile
) != 0)
880 p_sys
->api
.clean(&p_sys
->api
);
882 return (VLC_EGENERIC
);
887 p_sys
->api
.clean(&p_sys
->api
);
893 p_dec
->p_sys
= p_sys
;
895 vlc_mutex_init(&p_sys
->lock
);
896 vlc_cond_init(&p_sys
->cond
);
897 vlc_cond_init(&p_sys
->dec_cond
);
899 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
901 switch (p_dec
->fmt_in
.i_codec
)
905 hxxx_helper_init(&p_sys
->video
.hh
, VLC_OBJECT(p_dec
),
906 p_dec
->fmt_in
.i_codec
, false);
909 p_sys
->pf_on_new_block
= Video_OnNewBlock
;
910 p_sys
->pf_on_flush
= Video_OnFlush
;
911 p_sys
->pf_process_output
= Video_ProcessOutput
;
913 p_sys
->video
.timestamp_fifo
= timestamp_FifoNew(32);
914 if (!p_sys
->video
.timestamp_fifo
)
917 if (var_InheritBool(p_dec
, CFG_PREFIX
"dr"))
919 /* Direct rendering: Request a valid OPAQUE Vout in order to get
920 * the surface attached to it */
921 p_dec
->fmt_out
.i_codec
= VLC_CODEC_ANDROID_OPAQUE
;
923 p_dec
->fmt_out
.video
= p_dec
->fmt_in
.video
;
924 if (p_dec
->fmt_out
.video
.i_sar_num
* p_dec
->fmt_out
.video
.i_sar_den
== 0)
926 p_dec
->fmt_out
.video
.i_sar_num
= 1;
927 p_dec
->fmt_out
.video
.i_sar_den
= 1;
930 p_sys
->video
.i_input_width
=
931 p_dec
->fmt_out
.video
.i_visible_width
= p_dec
->fmt_out
.video
.i_width
;
932 p_sys
->video
.i_input_height
=
933 p_dec
->fmt_out
.video
.i_visible_height
= p_dec
->fmt_out
.video
.i_height
;
935 if (CreateVideoContext(p_dec
) != VLC_SUCCESS
)
937 msg_Err(p_dec
, "video context creation failed");
941 if (p_sys
->api
.b_support_rotation
&& p_sys
->video
.surfacetexture
== NULL
)
943 switch (p_dec
->fmt_in
.video
.orientation
)
945 case ORIENT_ROTATED_90
:
946 p_sys
->video
.i_angle
= 90;
948 case ORIENT_ROTATED_180
:
949 p_sys
->video
.i_angle
= 180;
951 case ORIENT_ROTATED_270
:
952 p_sys
->video
.i_angle
= 270;
955 p_sys
->video
.i_angle
= 0;
961 /* Let the GL vout handle the rotation */
962 p_sys
->video
.i_angle
= 0;
968 p_dec
->fmt_out
.video
.i_width
= p_dec
->fmt_in
.video
.i_width
;
969 p_dec
->fmt_out
.video
.i_height
= p_dec
->fmt_in
.video
.i_height
;
971 p_sys
->cat
= VIDEO_ES
;
975 p_sys
->pf_on_new_block
= Audio_OnNewBlock
;
976 p_sys
->pf_on_flush
= Audio_OnFlush
;
977 p_sys
->pf_process_output
= Audio_ProcessOutput
;
978 p_sys
->audio
.i_channels
= p_dec
->fmt_in
.audio
.i_channels
;
980 if ((p_sys
->api
.i_quirks
& MC_API_AUDIO_QUIRKS_NEED_CHANNELS
)
981 && !p_sys
->audio
.i_channels
)
983 msg_Warn(p_dec
, "codec need a valid channel count");
987 p_dec
->fmt_out
.audio
= p_dec
->fmt_in
.audio
;
988 p_sys
->cat
= AUDIO_ES
;
991 /* Try first to configure CSD */
992 if (ParseExtra(p_dec
) != VLC_SUCCESS
)
995 if ((p_sys
->api
.i_quirks
& MC_API_QUIRKS_NEED_CSD
) && !p_sys
->i_csd_count
996 && !p_sys
->b_adaptive
)
998 switch (p_dec
->fmt_in
.i_codec
)
1000 case VLC_CODEC_H264
:
1001 case VLC_CODEC_HEVC
:
1002 break; /* CSDs will come from hxxx_helper */
1004 msg_Warn(p_dec
, "Not CSD found for %4.4s",
1005 (const char *) &p_dec
->fmt_in
.i_codec
);
1010 i_ret
= StartMediaCodec(p_dec
);
1011 if (i_ret
!= VLC_SUCCESS
)
1013 msg_Err(p_dec
, "StartMediaCodec failed");
1017 if (vlc_clone(&p_sys
->out_thread
, OutThread
, p_dec
,
1018 VLC_THREAD_PRIORITY_LOW
))
1020 msg_Err(p_dec
, "vlc_clone failed");
1021 vlc_mutex_unlock(&p_sys
->lock
);
1025 p_dec
->pf_decode
= DecodeBlock
;
1026 p_dec
->pf_flush
= DecodeFlush
;
1031 CleanInputVideo(p_dec
);
1032 CleanDecoder(p_sys
);
1033 return VLC_EGENERIC
;
1036 static int OpenDecoderNdk(vlc_object_t
*p_this
)
1038 return OpenDecoder(p_this
, MediaCodecNdk_Init
);
1041 static int OpenDecoderJni(vlc_object_t
*p_this
)
1043 return OpenDecoder(p_this
, MediaCodecJni_Init
);
1046 static void AbortDecoderLocked(decoder_sys_t
*p_sys
)
1048 if (!p_sys
->b_aborted
)
1050 p_sys
->b_aborted
= true;
1051 vlc_cond_broadcast(&p_sys
->cond
);
1055 static void CleanDecoder(decoder_sys_t
*p_sys
)
1057 StopMediaCodec(p_sys
);
1060 p_sys
->api
.clean(&p_sys
->api
);
1062 if (p_sys
->video
.surfacetexture
)
1063 vlc_asurfacetexture_Delete(p_sys
->video
.surfacetexture
);
1068 /*****************************************************************************
1069 * CloseDecoder: Close the decoder instance
1070 *****************************************************************************/
1071 static void CloseDecoder(vlc_object_t
*p_this
)
1073 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1074 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1076 vlc_mutex_lock(&p_sys
->lock
);
1077 p_sys
->b_decoder_dead
= true;
1078 vlc_mutex_unlock(&p_sys
->lock
);
1080 if (p_sys
->video
.ctx
)
1082 /* If we have a video context, we're using Surface with inflight
1083 * pictures, which might already have been queued, and flushing
1084 * them would make them invalid, breaking mechanism like waiting
1085 * on OnFrameAvailableListener.*/
1086 vlc_video_context_Release(p_sys
->video
.ctx
);
1087 CleanInputVideo(p_dec
);
1091 vlc_mutex_lock(&p_sys
->lock
);
1092 /* Unblock output thread waiting in dequeue_out */
1093 DecodeFlushLocked(p_sys
);
1094 /* Cancel the output thread */
1095 AbortDecoderLocked(p_sys
);
1096 vlc_mutex_unlock(&p_sys
->lock
);
1098 vlc_join(p_sys
->out_thread
, NULL
);
1100 CleanInputVideo(p_dec
);
1101 CleanDecoder(p_sys
);
1104 static int Video_ProcessOutput(decoder_t
*p_dec
, mc_api_out
*p_out
,
1105 picture_t
**pp_out_pic
, block_t
**pp_out_block
)
1107 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1108 (void) pp_out_block
;
1111 if (p_out
->type
== MC_OUT_TYPE_BUF
)
1113 picture_t
*p_pic
= NULL
;
1115 /* If the oldest input block had no PTS, the timestamp of
1116 * the frame returned by MediaCodec might be wrong so we
1117 * overwrite it with the corresponding dts. Call FifoGet
1118 * first in order to avoid a gap if buffers are released
1119 * due to an invalid format or a preroll */
1120 int64_t forced_ts
= timestamp_FifoGet(p_sys
->video
.timestamp_fifo
);
1122 if (!p_sys
->b_has_format
) {
1123 msg_Warn(p_dec
, "Buffers returned before output format is set, dropping frame");
1124 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1127 if (p_out
->buf
.i_ts
<= p_sys
->i_preroll_end
)
1128 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1130 if (!p_sys
->api
.b_direct_rendering
&& p_out
->buf
.p_ptr
== NULL
)
1132 /* This can happen when receiving an EOS buffer */
1133 msg_Warn(p_dec
, "Invalid buffer, dropping frame");
1134 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1137 p_pic
= decoder_NewPicture(p_dec
);
1139 msg_Warn(p_dec
, "NewPicture failed");
1140 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1143 if (forced_ts
== VLC_TICK_INVALID
)
1144 p_pic
->date
= p_out
->buf
.i_ts
;
1146 p_pic
->date
= forced_ts
;
1147 p_pic
->b_progressive
= true;
1149 if (p_sys
->api
.b_direct_rendering
)
1151 struct android_picture_ctx
*apctx
=
1152 GetPictureContext(p_dec
,p_out
->buf
.i_index
);
1154 assert(apctx
->s
.vctx
);
1155 vlc_video_context_Hold(apctx
->s
.vctx
);
1156 p_pic
->context
= &apctx
->s
;
1158 unsigned int chroma_div
;
1159 GetVlcChromaSizes(p_dec
->fmt_out
.i_codec
,
1160 p_dec
->fmt_out
.video
.i_width
,
1161 p_dec
->fmt_out
.video
.i_height
,
1162 NULL
, NULL
, &chroma_div
);
1163 CopyOmxPicture(p_sys
->video
.i_pixel_format
, p_pic
,
1164 p_sys
->video
.i_slice_height
, p_sys
->video
.i_stride
,
1165 (uint8_t *)p_out
->buf
.p_ptr
, chroma_div
, NULL
);
1167 if (p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false))
1169 picture_Release(p_pic
);
1173 assert(!(*pp_out_pic
));
1174 *pp_out_pic
= p_pic
;
1177 assert(p_out
->type
== MC_OUT_TYPE_CONF
);
1178 p_sys
->video
.i_pixel_format
= p_out
->conf
.video
.pixel_format
;
1180 const char *name
= "unknown";
1181 if (!p_sys
->api
.b_direct_rendering
1182 && !GetVlcChromaFormat(p_sys
->video
.i_pixel_format
,
1183 &p_dec
->fmt_out
.i_codec
, &name
))
1185 msg_Err(p_dec
, "color-format not recognized");
1189 msg_Err(p_dec
, "output: %d %s, %dx%d stride %d %d, crop %d %d %d %d",
1190 p_sys
->video
.i_pixel_format
, name
,
1191 p_out
->conf
.video
.width
, p_out
->conf
.video
.height
,
1192 p_out
->conf
.video
.stride
, p_out
->conf
.video
.slice_height
,
1193 p_out
->conf
.video
.crop_left
, p_out
->conf
.video
.crop_top
,
1194 p_out
->conf
.video
.crop_right
, p_out
->conf
.video
.crop_bottom
);
1196 int i_width
= p_out
->conf
.video
.crop_right
+ 1
1197 - p_out
->conf
.video
.crop_left
;
1198 int i_height
= p_out
->conf
.video
.crop_bottom
+ 1
1199 - p_out
->conf
.video
.crop_top
;
1200 if (i_width
<= 1 || i_height
<= 1)
1202 i_width
= p_out
->conf
.video
.width
;
1203 i_height
= p_out
->conf
.video
.height
;
1206 if (!(p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_IGNORE_SIZE
))
1208 p_dec
->fmt_out
.video
.i_visible_width
=
1209 p_dec
->fmt_out
.video
.i_width
= i_width
;
1210 p_dec
->fmt_out
.video
.i_visible_height
=
1211 p_dec
->fmt_out
.video
.i_height
= i_height
;
1215 p_dec
->fmt_out
.video
.i_visible_width
=
1216 p_dec
->fmt_out
.video
.i_width
= p_sys
->video
.i_input_width
;
1217 p_dec
->fmt_out
.video
.i_visible_height
=
1218 p_dec
->fmt_out
.video
.i_height
= p_sys
->video
.i_input_height
;
1219 msg_Dbg(p_dec
, "video size ignored from MediaCodec");
1222 p_sys
->video
.i_stride
= p_out
->conf
.video
.stride
;
1223 p_sys
->video
.i_slice_height
= p_out
->conf
.video
.slice_height
;
1224 if (p_sys
->video
.i_stride
<= 0)
1225 p_sys
->video
.i_stride
= p_out
->conf
.video
.width
;
1226 if (p_sys
->video
.i_slice_height
<= 0)
1227 p_sys
->video
.i_slice_height
= p_out
->conf
.video
.height
;
1229 if (p_sys
->video
.i_pixel_format
== OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
)
1230 p_sys
->video
.i_slice_height
-= p_out
->conf
.video
.crop_top
/2;
1231 if ((p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_IGNORE_PADDING
))
1233 p_sys
->video
.i_slice_height
= 0;
1234 p_sys
->video
.i_stride
= p_dec
->fmt_out
.video
.i_width
;
1238 if ((p_dec
->fmt_in
.i_codec
== VLC_CODEC_MPGV
||
1239 p_dec
->fmt_in
.i_codec
== VLC_CODEC_MP2V
) &&
1240 (p_sys
->video
.i_mpeg_dar_num
* p_sys
->video
.i_mpeg_dar_den
!= 0))
1242 p_dec
->fmt_out
.video
.i_sar_num
=
1243 p_sys
->video
.i_mpeg_dar_num
* p_dec
->fmt_out
.video
.i_height
;
1244 p_dec
->fmt_out
.video
.i_sar_den
=
1245 p_sys
->video
.i_mpeg_dar_den
* p_dec
->fmt_out
.video
.i_width
;
1248 /* If MediaCodec can handle the rotation, reset the orientation to
1249 * Normal in order to ask the vout not to rotate. */
1250 p_dec
->fmt_out
.video
.orientation
= p_dec
->fmt_in
.video
.orientation
;
1251 if (p_sys
->video
.i_angle
!= 0)
1253 assert(p_dec
->fmt_out
.i_codec
== VLC_CODEC_ANDROID_OPAQUE
);
1254 video_format_TransformTo(&p_dec
->fmt_out
.video
, ORIENT_NORMAL
);
1257 if (decoder_UpdateVideoOutput(p_dec
, p_sys
->video
.ctx
) != 0)
1259 msg_Err(p_dec
, "UpdateVout failed");
1263 p_sys
->b_has_format
= true;
1268 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
1269 static uint32_t pi_audio_order_src
[] =
1271 AOUT_CHAN_LEFT
, AOUT_CHAN_RIGHT
, AOUT_CHAN_CENTER
, AOUT_CHAN_LFE
,
1272 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
, AOUT_CHAN_REARCENTER
,
1273 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
,
1276 static int Audio_ProcessOutput(decoder_t
*p_dec
, mc_api_out
*p_out
,
1277 picture_t
**pp_out_pic
, block_t
**pp_out_block
)
1279 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1281 assert(pp_out_block
);
1283 if (p_out
->type
== MC_OUT_TYPE_BUF
)
1285 block_t
*p_block
= NULL
;
1286 if (p_out
->buf
.p_ptr
== NULL
)
1288 /* This can happen when receiving an EOS buffer */
1289 msg_Warn(p_dec
, "Invalid buffer, dropping frame");
1290 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1293 if (!p_sys
->b_has_format
) {
1294 msg_Warn(p_dec
, "Buffers returned before output format is set, dropping frame");
1295 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1298 p_block
= block_Alloc(p_out
->buf
.i_size
);
1301 p_block
->i_nb_samples
= p_out
->buf
.i_size
1302 / p_dec
->fmt_out
.audio
.i_bytes_per_frame
;
1304 if (p_sys
->audio
.b_extract
)
1306 aout_ChannelExtract(p_block
->p_buffer
,
1307 p_dec
->fmt_out
.audio
.i_channels
,
1308 p_out
->buf
.p_ptr
, p_sys
->audio
.i_channels
,
1309 p_block
->i_nb_samples
, p_sys
->audio
.pi_extraction
,
1310 p_dec
->fmt_out
.audio
.i_bitspersample
);
1313 memcpy(p_block
->p_buffer
, p_out
->buf
.p_ptr
, p_out
->buf
.i_size
);
1315 if (p_out
->buf
.i_ts
!= 0
1316 && p_out
->buf
.i_ts
!= date_Get(&p_sys
->audio
.i_end_date
))
1317 date_Set(&p_sys
->audio
.i_end_date
, p_out
->buf
.i_ts
);
1319 p_block
->i_pts
= date_Get(&p_sys
->audio
.i_end_date
);
1320 p_block
->i_length
= date_Increment(&p_sys
->audio
.i_end_date
,
1321 p_block
->i_nb_samples
)
1324 if (p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false))
1326 block_Release(p_block
);
1329 *pp_out_block
= p_block
;
1332 uint32_t i_layout_dst
;
1335 assert(p_out
->type
== MC_OUT_TYPE_CONF
);
1337 if (p_out
->conf
.audio
.channel_count
<= 0
1338 || p_out
->conf
.audio
.channel_count
> 8
1339 || p_out
->conf
.audio
.sample_rate
<= 0)
1341 msg_Warn(p_dec
, "invalid audio properties channels count %d, sample rate %d",
1342 p_out
->conf
.audio
.channel_count
,
1343 p_out
->conf
.audio
.sample_rate
);
1347 msg_Err(p_dec
, "output: channel_count: %d, channel_mask: 0x%X, rate: %d",
1348 p_out
->conf
.audio
.channel_count
, p_out
->conf
.audio
.channel_mask
,
1349 p_out
->conf
.audio
.sample_rate
);
1351 p_dec
->fmt_out
.i_codec
= VLC_CODEC_S16N
;
1352 p_dec
->fmt_out
.audio
.i_format
= p_dec
->fmt_out
.i_codec
;
1354 p_dec
->fmt_out
.audio
.i_rate
= p_out
->conf
.audio
.sample_rate
;
1355 date_Init(&p_sys
->audio
.i_end_date
, p_out
->conf
.audio
.sample_rate
, 1);
1357 p_sys
->audio
.i_channels
= p_out
->conf
.audio
.channel_count
;
1358 p_sys
->audio
.b_extract
=
1359 aout_CheckChannelExtraction(p_sys
->audio
.pi_extraction
,
1360 &i_layout_dst
, &i_channels_dst
,
1361 NULL
, pi_audio_order_src
,
1362 p_sys
->audio
.i_channels
);
1364 if (p_sys
->audio
.b_extract
)
1365 msg_Warn(p_dec
, "need channel extraction: %d -> %d",
1366 p_sys
->audio
.i_channels
, i_channels_dst
);
1368 p_dec
->fmt_out
.audio
.i_physical_channels
= i_layout_dst
;
1369 aout_FormatPrepare(&p_dec
->fmt_out
.audio
);
1371 if (decoder_UpdateAudioFormat(p_dec
))
1374 p_sys
->b_has_format
= true;
1379 static void DecodeFlushLocked(decoder_sys_t
*p_sys
)
1381 bool b_had_input
= p_sys
->b_input_dequeued
;
1383 p_sys
->b_input_dequeued
= false;
1384 p_sys
->b_flush_out
= true;
1385 p_sys
->i_preroll_end
= 0;
1386 p_sys
->b_output_ready
= false;
1387 /* Resend CODEC_CONFIG buffer after a flush */
1388 p_sys
->i_csd_send
= 0;
1390 p_sys
->pf_on_flush(p_sys
);
1392 if (b_had_input
&& p_sys
->api
.flush(&p_sys
->api
) != VLC_SUCCESS
)
1394 AbortDecoderLocked(p_sys
);
1398 vlc_cond_broadcast(&p_sys
->cond
);
1400 while (!p_sys
->b_aborted
&& p_sys
->b_flush_out
)
1401 vlc_cond_wait(&p_sys
->dec_cond
, &p_sys
->lock
);
1404 static void DecodeFlush(decoder_t
*p_dec
)
1406 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1408 vlc_mutex_lock(&p_sys
->lock
);
1409 DecodeFlushLocked(p_dec
->p_sys
);
1410 vlc_mutex_unlock(&p_sys
->lock
);
1413 static void *OutThread(void *data
)
1415 decoder_t
*p_dec
= data
;
1416 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1418 vlc_mutex_lock(&p_sys
->lock
);
1419 while (!p_sys
->b_aborted
)
1423 /* Wait for output ready */
1424 if (!p_sys
->b_flush_out
&& !p_sys
->b_output_ready
) {
1425 vlc_cond_wait(&p_sys
->cond
, &p_sys
->lock
);
1429 if (p_sys
->b_flush_out
)
1431 /* Acknowledge flushed state */
1432 p_sys
->b_flush_out
= false;
1433 vlc_cond_broadcast(&p_sys
->dec_cond
);
1437 vlc_mutex_unlock(&p_sys
->lock
);
1439 /* Wait for an output buffer. This function returns when a new output
1440 * is available or if output is flushed. */
1441 i_index
= p_sys
->api
.dequeue_out(&p_sys
->api
, -1);
1443 vlc_mutex_lock(&p_sys
->lock
);
1445 /* Ignore dequeue_out errors caused by flush, or late picture being
1446 * dequeued after close. */
1447 if (p_sys
->b_flush_out
|| p_sys
->b_decoder_dead
)
1449 /* If i_index >= 0, Release it. There is no way to know if i_index
1450 * is owned by us, so don't check the error. */
1452 p_sys
->api
.release_out(&p_sys
->api
, i_index
, false);
1454 /* Parse output format/buffers even when we are flushing */
1455 if (i_index
!= MC_API_INFO_OUTPUT_FORMAT_CHANGED
1456 && i_index
!= MC_API_INFO_OUTPUT_BUFFERS_CHANGED
)
1460 /* Process output returned by dequeue_out */
1461 if (i_index
>= 0 || i_index
== MC_API_INFO_OUTPUT_FORMAT_CHANGED
1462 || i_index
== MC_API_INFO_OUTPUT_BUFFERS_CHANGED
)
1464 struct mc_api_out out
;
1465 int i_ret
= p_sys
->api
.get_out(&p_sys
->api
, i_index
, &out
);
1469 picture_t
*p_pic
= NULL
;
1470 block_t
*p_block
= NULL
;
1472 if (p_sys
->pf_process_output(p_dec
, &out
, &p_pic
,
1473 &p_block
) == -1 && !out
.b_eos
)
1475 msg_Err(p_dec
, "pf_process_output failed");
1479 decoder_QueueVideo(p_dec
, p_pic
);
1481 decoder_QueueAudio(p_dec
, p_block
);
1485 msg_Warn(p_dec
, "EOS received");
1486 p_sys
->b_drained
= true;
1487 vlc_cond_signal(&p_sys
->dec_cond
);
1489 } else if (i_ret
!= 0)
1491 msg_Err(p_dec
, "get_out failed");
1498 msg_Warn(p_dec
, "OutThread stopped");
1500 /* Signal DecoderFlush that the output thread aborted */
1501 p_sys
->b_aborted
= true;
1502 vlc_cond_signal(&p_sys
->dec_cond
);
1503 vlc_mutex_unlock(&p_sys
->lock
);
1508 static block_t
*GetNextBlock(decoder_sys_t
*p_sys
, block_t
*p_block
)
1510 if (p_sys
->i_csd_send
< p_sys
->i_csd_count
)
1511 return p_sys
->pp_csd
[p_sys
->i_csd_send
++];
1516 static int QueueBlockLocked(decoder_t
*p_dec
, block_t
*p_in_block
,
1519 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1520 block_t
*p_block
= NULL
;
1522 assert(p_sys
->api
.b_started
);
1524 if ((p_sys
->api
.i_quirks
& MC_API_QUIRKS_NEED_CSD
) && !p_sys
->i_csd_count
1525 && !p_sys
->b_adaptive
)
1526 return VLC_EGENERIC
; /* Wait for CSDs */
1528 /* Queue CSD blocks and input blocks */
1529 while (b_drain
|| (p_block
= GetNextBlock(p_sys
, p_in_block
)))
1531 vlc_mutex_unlock(&p_sys
->lock
);
1532 int i_index
= p_sys
->api
.dequeue_in(&p_sys
->api
, -1);
1533 vlc_mutex_lock(&p_sys
->lock
);
1535 if (p_sys
->b_aborted
)
1536 return VLC_EGENERIC
;
1538 bool b_config
= false;
1539 vlc_tick_t i_ts
= 0;
1540 p_sys
->b_input_dequeued
= true;
1541 const void *p_buf
= NULL
;
1546 assert(b_drain
|| p_block
!= NULL
);
1547 if (p_block
!= NULL
)
1549 b_config
= (p_block
->i_flags
& BLOCK_FLAG_CSD
);
1552 i_ts
= p_block
->i_pts
;
1553 if (!i_ts
&& p_block
->i_dts
)
1554 i_ts
= p_block
->i_dts
;
1556 p_buf
= p_block
->p_buffer
;
1557 i_size
= p_block
->i_buffer
;
1560 if (p_sys
->api
.queue_in(&p_sys
->api
, i_index
, p_buf
, i_size
,
1561 i_ts
, b_config
) == 0)
1563 if (!b_config
&& p_block
!= NULL
)
1565 if (p_block
->i_flags
& BLOCK_FLAG_PREROLL
)
1566 p_sys
->i_preroll_end
= i_ts
;
1568 /* One input buffer is queued, signal OutThread that will
1569 * fetch output buffers */
1570 p_sys
->b_output_ready
= true;
1571 vlc_cond_broadcast(&p_sys
->cond
);
1573 assert(p_block
== p_in_block
),
1580 msg_Err(p_dec
, "queue_in failed");
1586 msg_Err(p_dec
, "dequeue_in failed");
1593 msg_Warn(p_dec
, "EOS sent, waiting for OutThread");
1595 /* Wait for the OutThread to stop (and process all remaining output
1596 * frames. Use a timeout here since we can't know if all decoders will
1597 * behave correctly. */
1598 vlc_tick_t deadline
= vlc_tick_now() + INT64_C(3000000);
1599 while (!p_sys
->b_aborted
&& !p_sys
->b_drained
1600 && vlc_cond_timedwait(&p_sys
->dec_cond
, &p_sys
->lock
, deadline
) == 0);
1602 if (!p_sys
->b_drained
)
1604 msg_Err(p_dec
, "OutThread timed out");
1605 AbortDecoderLocked(p_sys
);
1607 p_sys
->b_drained
= false;
1613 AbortDecoderLocked(p_sys
);
1614 return VLC_EGENERIC
;
1617 static int DecodeBlock(decoder_t
*p_dec
, block_t
*p_in_block
)
1619 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1622 vlc_mutex_lock(&p_sys
->lock
);
1624 if (p_sys
->b_aborted
)
1626 if (p_sys
->b_has_format
)
1632 if (p_in_block
== NULL
)
1634 /* No input block, decoder is draining */
1635 msg_Err(p_dec
, "Decoder is draining");
1637 if (p_sys
->b_output_ready
)
1638 QueueBlockLocked(p_dec
, NULL
, true);
1642 if (p_in_block
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
))
1644 if (p_sys
->b_output_ready
)
1645 QueueBlockLocked(p_dec
, NULL
, true);
1646 DecodeFlushLocked(p_sys
);
1647 if (p_sys
->b_aborted
)
1649 if (p_in_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
1653 if (p_in_block
->i_flags
& BLOCK_FLAG_INTERLACED_MASK
1654 && !(p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_SUPPORT_INTERLACED
))
1656 /* Before Android 21 and depending on the vendor, MediaCodec can
1657 * crash or be in an inconsistent state when decoding interlaced
1658 * videos. See OMXCodec_GetQuirks() for a white list of decoders
1659 * that supported interlaced videos before Android 21. */
1660 msg_Warn(p_dec
, "codec doesn't support interlaced videos");
1664 /* Parse input block */
1665 if ((i_ret
= p_sys
->pf_on_new_block(p_dec
, &p_in_block
)) != 1)
1669 AbortDecoderLocked(p_sys
);
1670 msg_Err(p_dec
, "pf_on_new_block failed");
1674 if (p_sys
->i_decode_flags
& (DECODE_FLAG_DRAIN
|DECODE_FLAG_RESTART
))
1676 msg_Warn(p_dec
, "Draining from DecodeBlock");
1677 const bool b_restart
= p_sys
->i_decode_flags
& DECODE_FLAG_RESTART
;
1678 p_sys
->i_decode_flags
= 0;
1680 /* Drain and flush before restart to unblock OutThread */
1681 if (p_sys
->b_output_ready
)
1682 QueueBlockLocked(p_dec
, NULL
, true);
1683 DecodeFlushLocked(p_sys
);
1684 if (p_sys
->b_aborted
)
1689 StopMediaCodec(p_sys
);
1691 int i_ret
= StartMediaCodec(p_dec
);
1695 msg_Warn(p_dec
, "Restarted from DecodeBlock");
1698 msg_Err(p_dec
, "StartMediaCodec failed");
1699 AbortDecoderLocked(p_sys
);
1705 /* Abort if MediaCodec is not yet started */
1706 if (p_sys
->api
.b_started
)
1707 QueueBlockLocked(p_dec
, p_in_block
, false);
1711 block_Release(p_in_block
);
1712 /* Too late to reload here, we already modified/released the input block,
1713 * do it next time. */
1714 int ret
= p_sys
->b_aborted
&& p_sys
->b_has_format
? VLCDEC_ECRITICAL
1716 vlc_mutex_unlock(&p_sys
->lock
);
1720 vlc_mutex_unlock(&p_sys
->lock
);
1721 /* Add an empty variable so that mediacodec won't be loaded again
1723 var_Create(p_dec
, "mediacodec-failed", VLC_VAR_VOID
);
1724 return VLCDEC_RELOAD
;
1727 static int Video_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1729 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1730 block_t
*p_block
= *pp_block
;
1732 timestamp_FifoPut(p_sys
->video
.timestamp_fifo
,
1733 p_block
->i_pts
? VLC_TICK_INVALID
: p_block
->i_dts
);
1738 static int VideoHXXX_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1740 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1741 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
1742 bool b_config_changed
= false;
1743 bool *p_config_changed
= p_sys
->b_adaptive
? NULL
: &b_config_changed
;
1745 *pp_block
= hh
->pf_process_block(hh
, *pp_block
, p_config_changed
);
1748 if (b_config_changed
)
1750 bool b_size_changed
;
1752 switch (p_dec
->fmt_in
.i_codec
)
1754 case VLC_CODEC_H264
:
1755 if (hh
->h264
.i_sps_count
> 0 || hh
->h264
.i_pps_count
> 0)
1756 i_ret
= H264SetCSD(p_dec
, &b_size_changed
);
1758 i_ret
= VLC_EGENERIC
;
1760 case VLC_CODEC_HEVC
:
1761 if (hh
->hevc
.i_vps_count
> 0 || hh
->hevc
.i_sps_count
> 0 ||
1762 hh
->hevc
.i_pps_count
> 0 )
1763 i_ret
= HEVCSetCSD(p_dec
, &b_size_changed
);
1765 i_ret
= VLC_EGENERIC
;
1768 if (i_ret
!= VLC_SUCCESS
)
1770 if (b_size_changed
|| !p_sys
->api
.b_started
)
1772 if (p_sys
->api
.b_started
)
1773 msg_Err(p_dec
, "SPS/PPS changed during playback and "
1774 "video size are different. Restart it !");
1775 p_sys
->i_decode_flags
|= DECODE_FLAG_RESTART
;
1778 msg_Err(p_dec
, "SPS/PPS changed during playback. Drain it");
1779 p_sys
->i_decode_flags
|= DECODE_FLAG_DRAIN
;
1783 return Video_OnNewBlock(p_dec
, pp_block
);
1786 static int VideoMPEG2_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1788 if (pp_block
== NULL
|| (*pp_block
)->i_buffer
<= 7)
1791 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1792 const int startcode
= (*pp_block
)->p_buffer
[3];
1794 /* DAR aspect ratio from the DVD MPEG2 standard */
1795 static const int mpeg2_aspect
[16][2] =
1797 {0,0}, /* reserved */
1798 {0,0}, /* DAR = 0:0 will result in SAR = 1:1 */
1799 {4,3}, {16,9}, {221,100},
1801 {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
1805 if (startcode
== 0xB3 /* SEQUENCE_HEADER_STARTCODE */)
1807 int mpeg_dar_code
= (*pp_block
)->p_buffer
[7] >> 4;
1809 if (mpeg_dar_code
>= 16)
1812 p_sys
->video
.i_mpeg_dar_num
= mpeg2_aspect
[mpeg_dar_code
][0];
1813 p_sys
->video
.i_mpeg_dar_den
= mpeg2_aspect
[mpeg_dar_code
][1];
1819 static int VideoVC1_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1821 block_t
*p_block
= *pp_block
;
1823 /* Adding frame start code */
1824 p_block
= *pp_block
= block_Realloc(p_block
, 4, p_block
->i_buffer
);
1825 if (p_block
== NULL
)
1827 p_block
->p_buffer
[0] = 0x00;
1828 p_block
->p_buffer
[1] = 0x00;
1829 p_block
->p_buffer
[2] = 0x01;
1830 p_block
->p_buffer
[3] = 0x0d;
1832 return Video_OnNewBlock(p_dec
, pp_block
);
1835 static void Video_OnFlush(decoder_sys_t
*p_sys
)
1837 timestamp_FifoEmpty(p_sys
->video
.timestamp_fifo
);
1838 /* Invalidate all pictures that are currently in flight
1839 * since flushing make all previous indices returned by
1840 * MediaCodec invalid. */
1841 ReleaseAllPictureContexts(p_sys
);
1844 static int Audio_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1846 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1847 block_t
*p_block
= *pp_block
;
1849 /* We've just started the stream, wait for the first PTS. */
1850 if (date_Get(&p_sys
->audio
.i_end_date
) == VLC_TICK_INVALID
)
1852 if (p_block
->i_pts
== VLC_TICK_INVALID
)
1854 date_Set(&p_sys
->audio
.i_end_date
, p_block
->i_pts
);
1860 static void Audio_OnFlush(decoder_sys_t
*p_sys
)
1862 date_Set(&p_sys
->audio
.i_end_date
, VLC_TICK_INVALID
);