qt: playlist: use item title if available
[vlc.git] / modules / codec / omxil / mediacodec.c
blob18e761d53a9973c23c62afa4e5f24a35ef93b209
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 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <stdatomic.h>
31 #include <stdint.h>
32 #include <assert.h>
34 #include <vlc_common.h>
35 #include <vlc_aout.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>
41 #include <vlc_bits.h>
43 #include "mediacodec.h"
44 #include "../codec/hxxx_helper.h"
45 #include <OMX_Core.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)
54 #define MAX_PIC 64
56 /**
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 **);
62 /**
63 * Callback called when decoder is flushing.
65 struct decoder_sys_t;
66 typedef void (*dec_on_flush_cb)(struct decoder_sys_t *);
68 /**
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 **,
73 block_t **);
75 struct android_picture_ctx
77 picture_context_t s;
78 atomic_uint refs;
79 atomic_int index;
82 typedef struct decoder_sys_t
84 mc_api api;
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];
90 size_t i_csd_count;
91 size_t i_csd_send;
93 bool b_has_format;
95 int64_t i_preroll_end;
96 int i_quirks;
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;
103 vlc_mutex_t lock;
104 vlc_thread_t out_thread;
105 /* Cond used to signal the output thread */
106 vlc_cond_t cond;
107 /* Cond used to signal the decoder thread */
108 vlc_cond_t dec_cond;
109 /* Set to true by pf_flush to signal the output thread to flush */
110 bool b_flush_out;
111 /* If true, the output thread will start to dequeue output pictures */
112 bool b_output_ready;
113 /* If true, the first input block was successfully dequeued */
114 bool b_input_dequeued;
115 bool b_aborted;
116 bool b_drained;
117 bool b_adaptive;
119 /* If true, the decoder_t object has been closed and decoder_* functions
120 * are now unavailable. */
121 bool b_decoder_dead;
123 int i_decode_flags;
125 enum es_format_category_e cat;
126 union
128 struct
130 vlc_video_context *ctx;
131 struct android_picture_ctx apic_ctxs[MAX_PIC];
132 void *p_surface, *p_jsurface;
133 unsigned i_angle;
134 unsigned i_input_width, i_input_height;
135 unsigned int i_stride, i_slice_height;
136 int i_pixel_format;
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;
141 } video;
142 struct {
143 date_t i_end_date;
144 int i_channels;
145 bool b_extract;
146 /* Some audio decoders need a valid channel count */
147 bool b_need_channels;
148 int pi_extraction[AOUT_CHAN_MAX];
149 } audio;
151 } decoder_sys_t;
153 /*****************************************************************************
154 * Local prototypes
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 **,
167 block_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 **,
173 block_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 /*****************************************************************************
183 * Module descriptor
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-"
198 vlc_module_begin ()
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")
213 add_submodule ()
214 set_capability("audio decoder", 0)
215 set_callbacks(OpenDecoderNdk, CloseDecoder)
216 add_shortcut("mediacodec_ndk")
217 add_submodule ()
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")
222 add_submodule ()
223 set_capability("audio decoder", 0)
224 set_callbacks(OpenDecoderJni, CloseDecoder)
225 add_shortcut("mediacodec_jni")
226 vlc_module_end ()
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);
240 CSDFree(p_sys);
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);
258 if (!p_block)
259 return VLC_ENOMEM;
260 memcpy(p_block->p_buffer, p_buf, i_buf);
262 CSDInit(p_sys, p_block, 1);
263 return VLC_SUCCESS;
266 static void HXXXInitSize(decoder_t *p_dec, bool *p_size_changed)
268 if (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);
297 return VLC_SUCCESS;
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);
316 return VLC_ENOMEM;
318 CSDInit(p_sys, p_monolith, 1);
321 HXXXInitSize(p_dec, p_size_changed);
322 return VLC_SUCCESS;
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)
332 return i_ret;
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);
342 return VLC_SUCCESS;
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)
352 return i_ret;
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);
363 return VLC_SUCCESS;
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;
369 int offset = 0;
371 if (i_extra < 4)
372 return VLC_EGENERIC;
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))
380 break;
383 /* Could not find the sequence header start code */
384 if (offset >= i_extra - 4)
385 return VLC_EGENERIC;
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 :
394 * 8 fixed bytes
395 * 4 extradata bytes
396 * 4 height bytes (little endian)
397 * 4 width bytes (little endian)
398 * 16 fixed bytes */
400 if (i_extra < 4)
401 return VLC_EGENERIC;
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)
432 case VLC_CODEC_H264:
433 return ParseVideoExtraH264(p_dec, p_extra, i_extra);
434 case VLC_CODEC_HEVC:
435 return ParseVideoExtraHEVC(p_dec, p_extra, i_extra);
436 case VLC_CODEC_WMV3:
437 return ParseVideoExtraWmv3(p_dec, p_extra, i_extra);
438 case VLC_CODEC_VC1:
439 return ParseVideoExtraVc1(p_dec, p_extra, i_extra);
440 case VLC_CODEC_MP4V:
441 if (!i_extra && p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
442 p_sys->b_adaptive = true;
443 break;
444 case VLC_CODEC_MPGV:
445 case VLC_CODEC_MP2V:
446 p_sys->pf_on_new_block = VideoMPEG2_OnNewBlock;
447 break;
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);
452 else
453 return VLC_SUCCESS;
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;
479 else
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)
489 return MC_API_ERROR;
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,
509 bool render)
511 int index = atomic_exchange(&apctx->index, -1);
512 if (index >= 0)
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);
519 return true;
521 return false;
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,
533 vlc_tick_t ts)
535 struct android_picture_ctx *apctx =
536 container_of(ctx, struct android_picture_ctx, s);
538 int index = atomic_exchange(&apctx->index, -1);
539 if (index >= 0)
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));
546 return true;
548 return false;
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);
577 return ctx;
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);
595 CleanDecoder(p_sys);
598 static void ReleaseAllPictureContexts(decoder_sys_t *p_sys)
600 /* No picture context if no direct rendering. */
601 if (p_sys->video.ctx == NULL)
602 return;
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;
619 bool slept = false;
621 for (;;)
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)))
634 return apctx;
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 */
646 if (!slept)
647 msg_Warn(p_dec, "waiting for more picture contexts (unlikely)");
648 vlc_tick_sleep(VOUT_OUTMEM_SLEEP);
649 slept = true;
653 static int
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");
662 return VLC_EGENERIC;
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");
690 goto error;
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)
699 goto error;
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,
710 p_sys->video.ctx =
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)
716 return VLC_EGENERIC;
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,
731 p_sys->video.ctx,
733 atomic_init(&apctx->index, -1);
734 atomic_init(&apctx->refs, 0);
737 return VLC_SUCCESS;
739 error:
740 vlc_decoder_device_Release(dec_dev);
741 return VLC_EGENERIC;
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"))
767 return VLC_EGENERIC;
769 decoder_sys_t *p_sys;
770 int i_ret;
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")))
777 return VLC_EGENERIC;
779 /* Fail if this module already failed to decode this ES */
780 if (var_Type(p_dec, "mediacodec-failed") != 0)
781 return VLC_EGENERIC;
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
787 * found. */
788 if (!p_dec->fmt_in.video.i_width || !p_dec->fmt_in.video.i_height)
789 return VLC_EGENERIC;
791 switch (p_dec->fmt_in.i_codec) {
792 case VLC_CODEC_HEVC:
793 if (i_profile == -1)
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;
799 mime = "video/hevc";
800 break;
801 case VLC_CODEC_H264:
802 if (i_profile == -1)
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;
808 mime = "video/avc";
809 break;
810 case VLC_CODEC_H263: mime = "video/3gpp"; break;
811 case VLC_CODEC_MP4V: mime = "video/mp4v-es"; break;
812 case VLC_CODEC_MPGV:
813 case VLC_CODEC_MP2V:
814 mime = "video/mpeg2";
815 break;
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;
822 else
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;
827 case VLC_CODEC_MPGA:
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; */
846 if (!mime)
848 msg_Dbg(p_dec, "codec %4.4s not supported",
849 (char *)&p_dec->fmt_in.i_codec);
850 return VLC_EGENERIC;
853 /* Allocate the memory needed to store the decoder's structure */
854 if ((p_sys = calloc(1, sizeof(*p_sys))) == NULL)
855 return VLC_ENOMEM;
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)
868 free(p_sys);
869 return VLC_EGENERIC;
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);
881 free(p_sys);
882 return (VLC_EGENERIC);
885 else
887 p_sys->api.clean(&p_sys->api);
888 free(p_sys);
889 return VLC_EGENERIC;
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)
903 case VLC_CODEC_H264:
904 case VLC_CODEC_HEVC:
905 hxxx_helper_init(&p_sys->video.hh, VLC_OBJECT(p_dec),
906 p_dec->fmt_in.i_codec, false);
907 break;
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)
915 goto bailout;
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");
938 goto bailout;
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;
947 break;
948 case ORIENT_ROTATED_180:
949 p_sys->video.i_angle = 180;
950 break;
951 case ORIENT_ROTATED_270:
952 p_sys->video.i_angle = 270;
953 break;
954 default:
955 p_sys->video.i_angle = 0;
956 break;
959 else
961 /* Let the GL vout handle the rotation */
962 p_sys->video.i_angle = 0;
966 else
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;
973 else
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");
984 goto bailout;
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)
993 goto bailout;
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 */
1003 default:
1004 msg_Warn(p_dec, "Not CSD found for %4.4s",
1005 (const char *) &p_dec->fmt_in.i_codec);
1006 goto bailout;
1010 i_ret = StartMediaCodec(p_dec);
1011 if (i_ret != VLC_SUCCESS)
1013 msg_Err(p_dec, "StartMediaCodec failed");
1014 goto bailout;
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);
1022 goto bailout;
1025 p_dec->pf_decode = DecodeBlock;
1026 p_dec->pf_flush = DecodeFlush;
1028 return VLC_SUCCESS;
1030 bailout:
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);
1059 CSDFree(p_sys);
1060 p_sys->api.clean(&p_sys->api);
1062 if (p_sys->video.surfacetexture)
1063 vlc_asurfacetexture_Delete(p_sys->video.surfacetexture);
1065 free(p_sys);
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);
1088 return;
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;
1109 assert(pp_out_pic);
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);
1138 if (!p_pic) {
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;
1145 else
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);
1153 assert(apctx);
1154 assert(apctx->s.vctx);
1155 vlc_video_context_Hold(apctx->s.vctx);
1156 p_pic->context = &apctx->s;
1157 } else {
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);
1170 return -1;
1173 assert(!(*pp_out_pic));
1174 *pp_out_pic = p_pic;
1175 return 1;
1176 } else {
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");
1186 return -1;
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;
1213 else
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");
1260 return -1;
1263 p_sys->b_has_format = true;
1264 return 0;
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;
1280 (void) pp_out_pic;
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);
1299 if (!p_block)
1300 return -1;
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);
1312 else
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)
1322 - p_block->i_pts;
1324 if (p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false))
1326 block_Release(p_block);
1327 return -1;
1329 *pp_out_block = p_block;
1330 return 1;
1331 } else {
1332 uint32_t i_layout_dst;
1333 int i_channels_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);
1344 return -1;
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))
1372 return -1;
1374 p_sys->b_has_format = true;
1375 return 0;
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);
1395 return;
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)
1421 int i_index;
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);
1426 continue;
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);
1434 continue;
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. */
1451 if (i_index >= 0)
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)
1457 continue;
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);
1467 if (i_ret == 1)
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");
1476 break;
1478 if (p_pic)
1479 decoder_QueueVideo(p_dec, p_pic);
1480 else if (p_block)
1481 decoder_QueueAudio(p_dec, p_block);
1483 if (out.b_eos)
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");
1492 break;
1495 else
1496 break;
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);
1505 return NULL;
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++];
1512 else
1513 return p_block;
1516 static int QueueBlockLocked(decoder_t *p_dec, block_t *p_in_block,
1517 bool b_drain)
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;
1542 size_t i_size = 0;
1544 if (i_index >= 0)
1546 assert(b_drain || p_block != NULL);
1547 if (p_block != NULL)
1549 b_config = (p_block->i_flags & BLOCK_FLAG_CSD);
1550 if (!b_config)
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),
1574 p_in_block = NULL;
1576 if (b_drain)
1577 break;
1578 } else
1580 msg_Err(p_dec, "queue_in failed");
1581 goto error;
1584 else
1586 msg_Err(p_dec, "dequeue_in failed");
1587 goto error;
1591 if (b_drain)
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;
1610 return VLC_SUCCESS;
1612 error:
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;
1620 int i_ret;
1622 vlc_mutex_lock(&p_sys->lock);
1624 if (p_sys->b_aborted)
1626 if (p_sys->b_has_format)
1627 goto end;
1628 else
1629 goto reload;
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);
1639 goto end;
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)
1648 goto end;
1649 if (p_in_block->i_flags & BLOCK_FLAG_CORRUPTED)
1650 goto end;
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");
1661 goto reload;
1664 /* Parse input block */
1665 if ((i_ret = p_sys->pf_on_new_block(p_dec, &p_in_block)) != 1)
1667 if (i_ret != 0)
1669 AbortDecoderLocked(p_sys);
1670 msg_Err(p_dec, "pf_on_new_block failed");
1672 goto end;
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)
1685 goto end;
1687 if (b_restart)
1689 StopMediaCodec(p_sys);
1691 int i_ret = StartMediaCodec(p_dec);
1692 switch (i_ret)
1694 case VLC_SUCCESS:
1695 msg_Warn(p_dec, "Restarted from DecodeBlock");
1696 break;
1697 default:
1698 msg_Err(p_dec, "StartMediaCodec failed");
1699 AbortDecoderLocked(p_sys);
1700 goto end;
1705 /* Abort if MediaCodec is not yet started */
1706 if (p_sys->api.b_started)
1707 QueueBlockLocked(p_dec, p_in_block, false);
1709 end:
1710 if (p_in_block)
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
1715 : VLCDEC_SUCCESS;
1716 vlc_mutex_unlock(&p_sys->lock);
1717 return ret;
1719 reload:
1720 vlc_mutex_unlock(&p_sys->lock);
1721 /* Add an empty variable so that mediacodec won't be loaded again
1722 * for this ES */
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);
1735 return 1;
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);
1746 if (!*pp_block)
1747 return 0;
1748 if (b_config_changed)
1750 bool b_size_changed;
1751 int i_ret;
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);
1757 else
1758 i_ret = VLC_EGENERIC;
1759 break;
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);
1764 else
1765 i_ret = VLC_EGENERIC;
1766 break;
1768 if (i_ret != VLC_SUCCESS)
1769 return i_ret;
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;
1776 } else
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)
1789 return 1;
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},
1800 /* reserved */
1801 {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
1802 {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)
1810 return 0;
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];
1816 return 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)
1826 return VLC_ENOMEM;
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)
1853 return 0;
1854 date_Set(&p_sys->audio.i_end_date, p_block->i_pts);
1857 return 1;
1860 static void Audio_OnFlush(decoder_sys_t *p_sys)
1862 date_Set(&p_sys->audio.i_end_date, VLC_TICK_INVALID);