mediacodec: don't write fmt_out video size from input
[vlc.git] / modules / codec / omxil / mediacodec.c
blobcb6a72868cc934a9ff8065507d5aaf7b9a647c44
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 <stdint.h>
31 #include <assert.h>
33 #include <vlc_common.h>
34 #include <vlc_aout.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
37 #include <vlc_block_helper.h>
38 #include <vlc_memory.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"
48 #include "../../video_output/android/display.h"
50 #define BLOCK_FLAG_CSD (0x01 << BLOCK_FLAG_PRIVATE_SHIFT)
52 #define DECODE_FLAG_RESTART (0x01)
53 #define DECODE_FLAG_DRAIN (0x02)
54 /**
55 * Callback called when a new block is processed from DecodeBlock.
56 * It returns -1 in case of error, 0 if block should be dropped, 1 otherwise.
58 typedef int (*dec_on_new_block_cb)(decoder_t *, block_t **);
60 /**
61 * Callback called when decoder is flushing.
63 typedef void (*dec_on_flush_cb)(decoder_t *);
65 /**
66 * Callback called when DecodeBlock try to get an output buffer (pic or block).
67 * It returns -1 in case of error, or the number of output buffer returned.
69 typedef int (*dec_process_output_cb)(decoder_t *, mc_api_out *, picture_t **,
70 block_t **);
72 struct decoder_sys_t
74 mc_api api;
76 /* Codec Specific Data buffer: sent in DecodeBlock after a start or a flush
77 * with the BUFFER_FLAG_CODEC_CONFIG flag.*/
78 #define MAX_CSD_COUNT 3
79 block_t *pp_csd[MAX_CSD_COUNT];
80 size_t i_csd_count;
81 size_t i_csd_send;
83 bool b_has_format;
85 int64_t i_preroll_end;
86 int i_quirks;
88 /* Specific Audio/Video callbacks */
89 dec_on_new_block_cb pf_on_new_block;
90 dec_on_flush_cb pf_on_flush;
91 dec_process_output_cb pf_process_output;
93 vlc_mutex_t lock;
94 vlc_thread_t out_thread;
95 /* Cond used to signal the output thread */
96 vlc_cond_t cond;
97 /* Cond used to signal the decoder thread */
98 vlc_cond_t dec_cond;
99 /* Set to true by pf_flush to signal the output thread to flush */
100 bool b_flush_out;
101 /* If true, the output thread will start to dequeue output pictures */
102 bool b_output_ready;
103 /* If true, the first input block was successfully dequeued */
104 bool b_input_dequeued;
105 bool b_aborted;
106 bool b_drained;
107 bool b_adaptive;
108 int i_decode_flags;
110 union
112 struct
114 void *p_surface, *p_jsurface;
115 unsigned i_angle;
116 unsigned i_input_width, i_input_height;
117 unsigned int i_stride, i_slice_height;
118 int i_pixel_format;
119 struct hxxx_helper hh;
120 /* stores the inflight picture for each output buffer or NULL */
121 picture_sys_t** pp_inflight_pictures;
122 unsigned int i_inflight_pictures;
123 timestamp_fifo_t *timestamp_fifo;
124 } video;
125 struct {
126 date_t i_end_date;
127 int i_channels;
128 bool b_extract;
129 /* Some audio decoders need a valid channel count */
130 bool b_need_channels;
131 int pi_extraction[AOUT_CHAN_MAX];
132 } audio;
136 /*****************************************************************************
137 * Local prototypes
138 *****************************************************************************/
139 static int OpenDecoderJni(vlc_object_t *);
140 static int OpenDecoderNdk(vlc_object_t *);
141 static void CleanDecoder(decoder_t *);
142 static void CloseDecoder(vlc_object_t *);
144 static int Video_OnNewBlock(decoder_t *, block_t **);
145 static int VideoHXXX_OnNewBlock(decoder_t *, block_t **);
146 static int VideoVC1_OnNewBlock(decoder_t *, block_t **);
147 static void Video_OnFlush(decoder_t *);
148 static int Video_ProcessOutput(decoder_t *, mc_api_out *, picture_t **,
149 block_t **);
150 static int DecodeBlock(decoder_t *, block_t *);
152 static int Audio_OnNewBlock(decoder_t *, block_t **);
153 static void Audio_OnFlush(decoder_t *);
154 static int Audio_ProcessOutput(decoder_t *, mc_api_out *, picture_t **,
155 block_t **);
157 static void DecodeFlushLocked(decoder_t *);
158 static void DecodeFlush(decoder_t *);
159 static void StopMediaCodec(decoder_t *);
160 static void *OutThread(void *);
162 static void InvalidateAllPictures(decoder_t *);
163 static void RemoveInflightPictures(decoder_t *);
165 /*****************************************************************************
166 * Module descriptor
167 *****************************************************************************/
168 #define DIRECTRENDERING_TEXT "Android direct rendering"
169 #define DIRECTRENDERING_LONGTEXT \
170 "Enable Android direct rendering using opaque buffers."
172 #define MEDIACODEC_AUDIO_TEXT "Use MediaCodec for audio decoding"
173 #define MEDIACODEC_AUDIO_LONGTEXT "Still experimental."
175 #define MEDIACODEC_TUNNELEDPLAYBACK_TEXT "Use a tunneled surface for playback"
177 #define CFG_PREFIX "mediacodec-"
179 vlc_module_begin ()
180 set_description("Video decoder using Android MediaCodec via NDK")
181 set_category(CAT_INPUT)
182 set_subcategory(SUBCAT_INPUT_VCODEC)
183 set_section(N_("Decoding"), NULL)
184 set_capability("video decoder", 0) /* Only enabled via commandline arguments */
185 add_bool(CFG_PREFIX "dr", true,
186 DIRECTRENDERING_TEXT, DIRECTRENDERING_LONGTEXT, true)
187 add_bool(CFG_PREFIX "audio", false,
188 MEDIACODEC_AUDIO_TEXT, MEDIACODEC_AUDIO_LONGTEXT, true)
189 add_bool(CFG_PREFIX "tunneled-playback", false,
190 MEDIACODEC_TUNNELEDPLAYBACK_TEXT, NULL, true)
191 set_callbacks(OpenDecoderNdk, CloseDecoder)
192 add_shortcut("mediacodec_ndk")
193 add_submodule ()
194 set_capability("audio decoder", 0)
195 set_callbacks(OpenDecoderNdk, CloseDecoder)
196 add_shortcut("mediacodec_ndk")
197 add_submodule ()
198 set_description("Video decoder using Android MediaCodec via JNI")
199 set_capability("video decoder", 0)
200 set_callbacks(OpenDecoderJni, CloseDecoder)
201 add_shortcut("mediacodec_jni")
202 add_submodule ()
203 set_capability("audio decoder", 0)
204 set_callbacks(OpenDecoderJni, CloseDecoder)
205 add_shortcut("mediacodec_jni")
206 vlc_module_end ()
208 static void CSDFree(decoder_t *p_dec)
210 decoder_sys_t *p_sys = p_dec->p_sys;
212 for (unsigned int i = 0; i < p_sys->i_csd_count; ++i)
213 block_Release(p_sys->pp_csd[i]);
214 p_sys->i_csd_count = 0;
217 /* Init the p_sys->p_csd that will be sent from DecodeBlock */
218 static void CSDInit(decoder_t *p_dec, block_t *p_blocks, size_t i_count)
220 decoder_sys_t *p_sys = p_dec->p_sys;
221 assert(i_count >= 0 && i_count <= 3);
223 CSDFree(p_dec);
225 for (size_t i = 0; i < i_count; ++i)
227 assert(p_blocks != NULL);
228 p_sys->pp_csd[i] = p_blocks;
229 p_sys->pp_csd[i]->i_flags = BLOCK_FLAG_CSD;
230 p_blocks = p_blocks->p_next;
231 p_sys->pp_csd[i]->p_next = NULL;
234 p_sys->i_csd_count = i_count;
235 p_sys->i_csd_send = 0;
238 static int CSDDup(decoder_t *p_dec, const void *p_buf, size_t i_buf)
240 block_t *p_block = block_Alloc(i_buf);
241 if (!p_block)
242 return VLC_ENOMEM;
243 memcpy(p_block->p_buffer, p_buf, i_buf);
245 CSDInit(p_dec, p_block, 1);
246 return VLC_SUCCESS;
249 static void HXXXInitSize(decoder_t *p_dec, bool *p_size_changed)
251 if (p_size_changed)
253 decoder_sys_t *p_sys = p_dec->p_sys;
254 struct hxxx_helper *hh = &p_sys->video.hh;
255 unsigned i_w, i_h, i_vw, i_vh;
256 hxxx_helper_get_current_picture_size(hh, &i_w, &i_h, &i_vw, &i_vh);
258 *p_size_changed = (i_w != p_sys->video.i_input_width
259 || i_h != p_sys->video.i_input_height);
260 p_sys->video.i_input_width = i_w;
261 p_sys->video.i_input_height = i_h;
262 /* fmt_out video size will be updated by mediacodec output callback */
266 /* Fill the p_sys->p_csd struct with H264 Parameter Sets */
267 static int H264SetCSD(decoder_t *p_dec, bool *p_size_changed)
269 decoder_sys_t *p_sys = p_dec->p_sys;
270 struct hxxx_helper *hh = &p_sys->video.hh;
271 assert(hh->h264.i_sps_count > 0 || hh->h264.i_pps_count > 0);
273 block_t *p_spspps_blocks = h264_helper_get_annexb_config(hh);
275 if (p_spspps_blocks != NULL)
276 CSDInit(p_dec, p_spspps_blocks, 2);
278 HXXXInitSize(p_dec, p_size_changed);
280 return VLC_SUCCESS;
283 /* Fill the p_sys->p_csd struct with HEVC Parameter Sets */
284 static int HEVCSetCSD(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;
289 assert(hh->hevc.i_vps_count > 0 || hh->hevc.i_sps_count > 0 ||
290 hh->hevc.i_pps_count > 0 );
292 block_t *p_xps_blocks = hevc_helper_get_annexb_config(hh);
293 if (p_xps_blocks != NULL)
295 block_t *p_monolith = block_ChainGather(p_xps_blocks);
296 if (p_monolith == NULL)
298 block_ChainRelease(p_xps_blocks);
299 return VLC_ENOMEM;
301 CSDInit(p_dec, p_monolith, 1);
304 HXXXInitSize(p_dec, p_size_changed);
305 return VLC_SUCCESS;
308 static int ParseVideoExtraH264(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
310 decoder_sys_t *p_sys = p_dec->p_sys;
311 struct hxxx_helper *hh = &p_sys->video.hh;
313 int i_ret = hxxx_helper_set_extra(hh, p_extra, i_extra);
314 if (i_ret != VLC_SUCCESS)
315 return i_ret;
316 assert(hh->pf_process_block != NULL);
318 if (p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
319 p_sys->b_adaptive = true;
321 p_sys->pf_on_new_block = VideoHXXX_OnNewBlock;
323 if (hh->h264.i_sps_count > 0 || hh->h264.i_pps_count > 0)
324 return H264SetCSD(p_dec, NULL);
325 return VLC_SUCCESS;
328 static int ParseVideoExtraHEVC(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
330 decoder_sys_t *p_sys = p_dec->p_sys;
331 struct hxxx_helper *hh = &p_sys->video.hh;
333 int i_ret = hxxx_helper_set_extra(hh, p_extra, i_extra);
334 if (i_ret != VLC_SUCCESS)
335 return i_ret;
336 assert(hh->pf_process_block != NULL);
338 if (p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
339 p_sys->b_adaptive = true;
341 p_sys->pf_on_new_block = VideoHXXX_OnNewBlock;
343 if (hh->hevc.i_vps_count > 0 || hh->hevc.i_sps_count > 0 ||
344 hh->hevc.i_pps_count > 0 )
345 return HEVCSetCSD(p_dec, NULL);
346 return VLC_SUCCESS;
349 static int ParseVideoExtraVc1(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
351 int offset = 0;
353 if (i_extra < 4)
354 return VLC_EGENERIC;
356 /* Initialisation data starts with : 0x00 0x00 0x01 0x0f */
357 /* Skipping unecessary data */
358 static const uint8_t vc1_start_code[4] = {0x00, 0x00, 0x01, 0x0f};
359 for (; offset < i_extra - 4 ; ++offset)
361 if (!memcmp(&p_extra[offset], vc1_start_code, 4))
362 break;
365 /* Could not find the sequence header start code */
366 if (offset >= i_extra - 4)
367 return VLC_EGENERIC;
369 p_dec->p_sys->pf_on_new_block = VideoVC1_OnNewBlock;
370 return CSDDup(p_dec, p_extra + offset, i_extra - offset);
373 static int ParseVideoExtraWmv3(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
375 /* WMV3 initialisation data :
376 * 8 fixed bytes
377 * 4 extradata bytes
378 * 4 height bytes (little endian)
379 * 4 width bytes (little endian)
380 * 16 fixed bytes */
382 if (i_extra < 4)
383 return VLC_EGENERIC;
385 uint8_t p_data[36] = {
386 0x8e, 0x01, 0x00, 0xc5, /* Fixed bytes values */
387 0x04, 0x00, 0x00, 0x00, /* Same */
388 0x00, 0x00, 0x00, 0x00, /* extradata emplacement */
389 0x00, 0x00, 0x00, 0x00, /* height emplacement (little endian) */
390 0x00, 0x00, 0x00, 0x00, /* width emplacement (little endian) */
391 0x0c, 0x00, 0x00, 0x00, /* Fixed byte pattern */
392 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00
397 /* Adding extradata */
398 memcpy(&p_data[8], p_extra, 4);
399 /* Adding height and width, little endian */
400 SetDWLE(&(p_data[12]), p_dec->fmt_in.video.i_height);
401 SetDWLE(&(p_data[16]), p_dec->fmt_in.video.i_width);
403 return CSDDup(p_dec, p_data, sizeof(p_data));
406 static int ParseExtra(decoder_t *p_dec)
408 decoder_sys_t *p_sys = p_dec->p_sys;
409 uint8_t *p_extra = p_dec->fmt_in.p_extra;
410 int i_extra = p_dec->fmt_in.i_extra;
412 switch (p_dec->fmt_in.i_codec)
414 case VLC_CODEC_H264:
415 return ParseVideoExtraH264(p_dec, p_extra, i_extra);
416 case VLC_CODEC_HEVC:
417 return ParseVideoExtraHEVC(p_dec, p_extra, i_extra);
418 case VLC_CODEC_WMV3:
419 return ParseVideoExtraWmv3(p_dec, p_extra, i_extra);
420 case VLC_CODEC_VC1:
421 return ParseVideoExtraVc1(p_dec, p_extra, i_extra);
422 case VLC_CODEC_MP4V:
423 if (!i_extra && p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
424 p_sys->b_adaptive = true;
425 /* fall through */
426 default:
427 /* Set default CSD */
428 if (p_dec->fmt_in.i_extra)
429 return CSDDup(p_dec, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra);
430 else
431 return VLC_SUCCESS;
435 static int UpdateVout(decoder_t *p_dec)
437 decoder_sys_t *p_sys = p_dec->p_sys;
439 /* If MediaCodec can handle the rotation, reset the orientation to
440 * Normal in order to ask the vout not to rotate. */
441 if (p_sys->video.i_angle != 0)
443 assert(p_dec->fmt_out.i_codec == VLC_CODEC_ANDROID_OPAQUE);
444 p_dec->fmt_out.video.orientation = p_dec->fmt_in.video.orientation;
445 video_format_TransformTo(&p_dec->fmt_out.video, ORIENT_NORMAL);
448 if (decoder_UpdateVideoFormat(p_dec) != 0)
449 return VLC_EGENERIC;
451 if (p_dec->fmt_out.i_codec != VLC_CODEC_ANDROID_OPAQUE)
452 return VLC_SUCCESS;
454 /* Direct rendering: get the surface attached to the VOUT */
455 picture_t *p_dummy_hwpic = decoder_NewPicture(p_dec);
456 if (p_dummy_hwpic == NULL)
457 return VLC_EGENERIC;
459 assert(p_dummy_hwpic->p_sys);
460 assert(p_dummy_hwpic->p_sys->hw.p_surface);
461 assert(p_dummy_hwpic->p_sys->hw.p_jsurface);
463 p_sys->video.p_surface = p_dummy_hwpic->p_sys->hw.p_surface;
464 p_sys->video.p_jsurface = p_dummy_hwpic->p_sys->hw.p_jsurface;
465 picture_Release(p_dummy_hwpic);
466 return VLC_SUCCESS;
469 /*****************************************************************************
470 * StartMediaCodec: Create the mediacodec instance
471 *****************************************************************************/
472 static int StartMediaCodec(decoder_t *p_dec)
474 decoder_sys_t *p_sys = p_dec->p_sys;
475 union mc_api_args args;
477 if (p_dec->fmt_in.i_cat == VIDEO_ES)
479 args.video.i_width = p_dec->fmt_out.video.i_width;
480 args.video.i_height = p_dec->fmt_out.video.i_height;
481 args.video.i_angle = p_sys->video.i_angle;
483 args.video.p_surface = p_sys->video.p_surface;
484 args.video.p_jsurface = p_sys->video.p_jsurface;
485 args.video.b_tunneled_playback = args.video.p_surface ?
486 var_InheritBool(p_dec, CFG_PREFIX "tunneled-playback") : false;
487 if (p_sys->b_adaptive)
488 msg_Dbg(p_dec, "mediacodec configured for adaptative playback");
489 args.video.b_adaptive_playback = p_sys->b_adaptive;
491 else
493 date_Set(&p_sys->audio.i_end_date, VLC_TS_INVALID);
495 args.audio.i_sample_rate = p_dec->fmt_in.audio.i_rate;
496 args.audio.i_channel_count = p_dec->p_sys->audio.i_channels;
499 return p_sys->api.start(&p_sys->api, &args);
502 /*****************************************************************************
503 * StopMediaCodec: Close the mediacodec instance
504 *****************************************************************************/
505 static void StopMediaCodec(decoder_t *p_dec)
507 decoder_sys_t *p_sys = p_dec->p_sys;
509 /* Remove all pictures that are currently in flight in order
510 * to prevent the vout from using destroyed output buffers. */
511 if (p_sys->api.b_direct_rendering)
512 RemoveInflightPictures(p_dec);
514 p_sys->api.stop(&p_sys->api);
517 /*****************************************************************************
518 * OpenDecoder: Create the decoder instance
519 *****************************************************************************/
520 static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
522 decoder_t *p_dec = (decoder_t *)p_this;
523 decoder_sys_t *p_sys;
524 int i_ret;
525 int i_profile = p_dec->fmt_in.i_profile;
526 const char *mime = NULL;
528 /* Video or Audio if "mediacodec-audio" bool is true */
529 if (p_dec->fmt_in.i_cat != VIDEO_ES && (p_dec->fmt_in.i_cat != AUDIO_ES
530 || !var_InheritBool(p_dec, CFG_PREFIX "audio")))
531 return VLC_EGENERIC;
533 /* Fail if this module already failed to decode this ES */
534 if (var_Type(p_dec, "mediacodec-failed") != 0)
535 return VLC_EGENERIC;
537 if (p_dec->fmt_in.i_cat == VIDEO_ES)
539 /* Not all mediacodec versions can handle a size of 0. Hopefully, the
540 * packetizer will trigger a decoder restart when a new video size is
541 * found. */
542 if (!p_dec->fmt_in.video.i_width || !p_dec->fmt_in.video.i_height)
543 return VLC_EGENERIC;
545 switch (p_dec->fmt_in.i_codec) {
546 case VLC_CODEC_HEVC:
547 if (i_profile == -1)
549 uint8_t i_hevc_profile;
550 if (hevc_get_profile_level(&p_dec->fmt_in, &i_hevc_profile, NULL, NULL))
551 i_profile = i_hevc_profile;
553 mime = "video/hevc";
554 break;
555 case VLC_CODEC_H264:
556 if (i_profile == -1)
558 uint8_t i_h264_profile;
559 if (h264_get_profile_level(&p_dec->fmt_in, &i_h264_profile, NULL, NULL))
560 i_profile = i_h264_profile;
562 mime = "video/avc";
563 break;
564 case VLC_CODEC_H263: mime = "video/3gpp"; break;
565 case VLC_CODEC_MP4V: mime = "video/mp4v-es"; break;
566 case VLC_CODEC_WMV3: mime = "video/x-ms-wmv"; break;
567 case VLC_CODEC_VC1: mime = "video/wvc1"; break;
568 case VLC_CODEC_VP8: mime = "video/x-vnd.on2.vp8"; break;
569 case VLC_CODEC_VP9: mime = "video/x-vnd.on2.vp9"; break;
570 /* FIXME: mpeg2 is disabled: sar num/den can't be updated from
571 * MediaCodec. Use avcodec instead that will update it. The proper
572 * solution is to update sar from a mpeg2 packetizer.
574 * case VLC_CODEC_MPGV: mime = "video/mpeg2"; break;
578 else
580 switch (p_dec->fmt_in.i_codec) {
581 case VLC_CODEC_AMR_NB: mime = "audio/3gpp"; break;
582 case VLC_CODEC_AMR_WB: mime = "audio/amr-wb"; break;
583 case VLC_CODEC_MPGA:
584 case VLC_CODEC_MP3: mime = "audio/mpeg"; break;
585 case VLC_CODEC_MP2: mime = "audio/mpeg-L2"; break;
586 case VLC_CODEC_MP4A: mime = "audio/mp4a-latm"; break;
587 case VLC_CODEC_QCELP: mime = "audio/qcelp"; break;
588 case VLC_CODEC_VORBIS: mime = "audio/vorbis"; break;
589 case VLC_CODEC_OPUS: mime = "audio/opus"; break;
590 case VLC_CODEC_ALAW: mime = "audio/g711-alaw"; break;
591 case VLC_CODEC_MULAW: mime = "audio/g711-mlaw"; break;
592 case VLC_CODEC_FLAC: mime = "audio/flac"; break;
593 case VLC_CODEC_GSM: mime = "audio/gsm"; break;
594 case VLC_CODEC_A52: mime = "audio/ac3"; break;
595 case VLC_CODEC_EAC3: mime = "audio/eac3"; break;
596 case VLC_CODEC_ALAC: mime = "audio/alac"; break;
597 case VLC_CODEC_DTS: mime = "audio/vnd.dts"; break;
598 /* case VLC_CODEC_: mime = "audio/mpeg-L1"; break; */
599 /* case VLC_CODEC_: mime = "audio/aac-adts"; break; */
602 if (!mime)
604 msg_Dbg(p_dec, "codec %4.4s not supported",
605 (char *)&p_dec->fmt_in.i_codec);
606 return VLC_EGENERIC;
609 /* Allocate the memory needed to store the decoder's structure */
610 if ((p_sys = calloc(1, sizeof(*p_sys))) == NULL)
611 return VLC_ENOMEM;
613 p_sys->api.p_obj = p_this;
614 p_sys->api.i_codec = p_dec->fmt_in.i_codec;
615 p_sys->api.i_cat = p_dec->fmt_in.i_cat;
616 p_sys->api.psz_mime = mime;
618 if (pf_init(&p_sys->api) != 0)
620 free(p_sys);
621 return VLC_EGENERIC;
623 if (p_sys->api.configure(&p_sys->api, i_profile) != 0)
625 /* If the device can't handle video/wvc1,
626 * it can probably handle video/x-ms-wmv */
627 if (!strcmp(mime, "video/wvc1") && p_dec->fmt_in.i_codec == VLC_CODEC_VC1)
629 p_sys->api.psz_mime = "video/x-ms-wmv";
630 if (p_sys->api.configure(&p_sys->api, i_profile) != 0)
632 p_sys->api.clean(&p_sys->api);
633 free(p_sys);
634 return (VLC_EGENERIC);
637 else
639 p_sys->api.clean(&p_sys->api);
640 free(p_sys);
641 return VLC_EGENERIC;
645 p_dec->p_sys = p_sys;
647 vlc_mutex_init(&p_sys->lock);
648 vlc_cond_init(&p_sys->cond);
649 vlc_cond_init(&p_sys->dec_cond);
651 if (p_dec->fmt_in.i_cat == VIDEO_ES)
653 switch (p_dec->fmt_in.i_codec)
655 case VLC_CODEC_H264:
656 case VLC_CODEC_HEVC:
657 hxxx_helper_init(&p_sys->video.hh, VLC_OBJECT(p_dec),
658 p_dec->fmt_in.i_codec, false);
659 break;
661 p_sys->pf_on_new_block = Video_OnNewBlock;
662 p_sys->pf_on_flush = Video_OnFlush;
663 p_sys->pf_process_output = Video_ProcessOutput;
665 p_sys->video.timestamp_fifo = timestamp_FifoNew(32);
666 if (!p_sys->video.timestamp_fifo)
667 goto bailout;
669 TAB_INIT(p_sys->video.i_inflight_pictures,
670 p_sys->video.pp_inflight_pictures);
672 if (var_InheritBool(p_dec, CFG_PREFIX "dr"))
674 /* Direct rendering: Request a valid OPAQUE Vout in order to get
675 * the surface attached to it */
676 p_dec->fmt_out.i_codec = VLC_CODEC_ANDROID_OPAQUE;
678 if (p_sys->api.b_support_rotation)
680 switch (p_dec->fmt_out.video.orientation)
682 case ORIENT_ROTATED_90:
683 p_sys->video.i_angle = 90;
684 break;
685 case ORIENT_ROTATED_180:
686 p_sys->video.i_angle = 180;
687 break;
688 case ORIENT_ROTATED_270:
689 p_sys->video.i_angle = 270;
690 break;
691 default:
692 p_sys->video.i_angle = 0;
693 break;
696 else
697 p_sys->video.i_angle = 0;
699 p_dec->fmt_out.video = p_dec->fmt_in.video;
700 p_sys->video.i_input_width =
701 p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width;
702 p_sys->video.i_input_height =
703 p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height;
705 if (UpdateVout(p_dec) != VLC_SUCCESS)
707 msg_Err(p_dec, "Opaque Vout request failed");
708 goto bailout;
712 else
714 p_sys->pf_on_new_block = Audio_OnNewBlock;
715 p_sys->pf_on_flush = Audio_OnFlush;
716 p_sys->pf_process_output = Audio_ProcessOutput;
717 p_sys->audio.i_channels = p_dec->fmt_in.audio.i_channels;
719 if ((p_sys->api.i_quirks & MC_API_AUDIO_QUIRKS_NEED_CHANNELS)
720 && !p_sys->audio.i_channels)
722 msg_Warn(p_dec, "codec need a valid channel count");
723 goto bailout;
726 p_dec->fmt_out.audio = p_dec->fmt_in.audio;
729 /* Try first to configure CSD */
730 if (ParseExtra(p_dec) != VLC_SUCCESS)
731 goto bailout;
733 if ((p_sys->api.i_quirks & MC_API_QUIRKS_NEED_CSD) && !p_sys->i_csd_count
734 && !p_sys->b_adaptive)
736 switch (p_dec->fmt_in.i_codec)
738 case VLC_CODEC_H264:
739 case VLC_CODEC_HEVC:
740 break; /* CSDs will come from hxxx_helper */
741 default:
742 msg_Warn(p_dec, "Not CSD found for %4.4s",
743 (const char *) &p_dec->fmt_in.i_codec);
744 goto bailout;
748 i_ret = StartMediaCodec(p_dec);
749 if (i_ret != VLC_SUCCESS)
751 msg_Err(p_dec, "StartMediaCodec failed");
752 goto bailout;
755 if (vlc_clone(&p_sys->out_thread, OutThread, p_dec,
756 VLC_THREAD_PRIORITY_LOW))
758 msg_Err(p_dec, "vlc_clone failed");
759 vlc_mutex_unlock(&p_sys->lock);
760 goto bailout;
763 p_dec->pf_decode = DecodeBlock;
764 p_dec->pf_flush = DecodeFlush;
766 return VLC_SUCCESS;
768 bailout:
769 CleanDecoder(p_dec);
770 return VLC_EGENERIC;
773 static int OpenDecoderNdk(vlc_object_t *p_this)
775 return OpenDecoder(p_this, MediaCodecNdk_Init);
778 static int OpenDecoderJni(vlc_object_t *p_this)
780 return OpenDecoder(p_this, MediaCodecJni_Init);
783 static void AbortDecoderLocked(decoder_t *p_dec)
785 decoder_sys_t *p_sys = p_dec->p_sys;
787 if (!p_sys->b_aborted)
789 p_sys->b_aborted = true;
790 vlc_cancel(p_sys->out_thread);
794 static void CleanDecoder(decoder_t *p_dec)
796 decoder_sys_t *p_sys = p_dec->p_sys;
798 vlc_mutex_destroy(&p_sys->lock);
799 vlc_cond_destroy(&p_sys->cond);
800 vlc_cond_destroy(&p_sys->dec_cond);
802 StopMediaCodec(p_dec);
804 CSDFree(p_dec);
805 p_sys->api.clean(&p_sys->api);
807 if (p_dec->fmt_in.i_cat == VIDEO_ES)
809 if (p_dec->fmt_in.i_codec == VLC_CODEC_H264
810 || p_dec->fmt_in.i_codec == VLC_CODEC_HEVC)
811 hxxx_helper_clean(&p_sys->video.hh);
813 if (p_sys->video.timestamp_fifo)
814 timestamp_FifoRelease(p_sys->video.timestamp_fifo);
816 free(p_sys);
819 /*****************************************************************************
820 * CloseDecoder: Close the decoder instance
821 *****************************************************************************/
822 static void CloseDecoder(vlc_object_t *p_this)
824 decoder_t *p_dec = (decoder_t *)p_this;
825 decoder_sys_t *p_sys = p_dec->p_sys;
827 vlc_mutex_lock(&p_sys->lock);
828 /* Unblock output thread waiting in dequeue_out */
829 DecodeFlushLocked(p_dec);
830 /* Cancel the output thread */
831 AbortDecoderLocked(p_dec);
832 vlc_mutex_unlock(&p_sys->lock);
834 vlc_join(p_sys->out_thread, NULL);
836 CleanDecoder(p_dec);
839 /*****************************************************************************
840 * vout callbacks
841 *****************************************************************************/
842 static void ReleasePicture(decoder_t *p_dec, unsigned i_index, bool b_render)
844 decoder_sys_t *p_sys = p_dec->p_sys;
846 p_sys->api.release_out(&p_sys->api, i_index, b_render);
849 static void ReleasePictureTs(decoder_t *p_dec, unsigned i_index, mtime_t i_ts)
851 decoder_sys_t *p_sys = p_dec->p_sys;
852 assert(p_sys->api.release_out_ts);
854 p_sys->api.release_out_ts(&p_sys->api, i_index, i_ts * INT64_C(1000));
857 static void InvalidateAllPictures(decoder_t *p_dec)
859 decoder_sys_t *p_sys = p_dec->p_sys;
861 for (unsigned int i = 0; i < p_sys->video.i_inflight_pictures; ++i)
862 AndroidOpaquePicture_Release(p_sys->video.pp_inflight_pictures[i],
863 false);
866 static int InsertInflightPicture(decoder_t *p_dec, picture_sys_t *p_picsys)
868 decoder_sys_t *p_sys = p_dec->p_sys;
870 if (!p_picsys->hw.p_dec)
872 p_picsys->hw.p_dec = p_dec;
873 p_picsys->hw.pf_release = ReleasePicture;
874 if (p_sys->api.release_out_ts)
875 p_picsys->hw.pf_release_ts = ReleasePictureTs;
876 TAB_APPEND_CAST((picture_sys_t **),
877 p_sys->video.i_inflight_pictures,
878 p_sys->video.pp_inflight_pictures,
879 p_picsys);
880 } /* else already attached */
881 return 0;
884 static void RemoveInflightPictures(decoder_t *p_dec)
886 decoder_sys_t *p_sys = p_dec->p_sys;
888 for (unsigned int i = 0; i < p_sys->video.i_inflight_pictures; ++i)
889 AndroidOpaquePicture_DetachDecoder(p_sys->video.pp_inflight_pictures[i]);
890 TAB_CLEAN(p_sys->video.i_inflight_pictures,
891 p_sys->video.pp_inflight_pictures);
894 static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
895 picture_t **pp_out_pic, block_t **pp_out_block)
897 decoder_sys_t *p_sys = p_dec->p_sys;
898 (void) pp_out_block;
899 assert(pp_out_pic);
901 if (p_out->type == MC_OUT_TYPE_BUF)
903 picture_t *p_pic = NULL;
905 /* If the oldest input block had no PTS, the timestamp of
906 * the frame returned by MediaCodec might be wrong so we
907 * overwrite it with the corresponding dts. Call FifoGet
908 * first in order to avoid a gap if buffers are released
909 * due to an invalid format or a preroll */
910 int64_t forced_ts = timestamp_FifoGet(p_sys->video.timestamp_fifo);
912 if (!p_sys->b_has_format) {
913 msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
914 return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
917 if (p_out->buf.i_ts <= p_sys->i_preroll_end)
918 return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
920 if (!p_sys->api.b_direct_rendering && p_out->buf.p_ptr == NULL)
922 /* This can happen when receiving an EOS buffer */
923 msg_Warn(p_dec, "Invalid buffer, dropping frame");
924 return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
927 p_pic = decoder_NewPicture(p_dec);
928 if (!p_pic) {
929 msg_Warn(p_dec, "NewPicture failed");
930 return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
933 if (forced_ts == VLC_TS_INVALID)
934 p_pic->date = p_out->buf.i_ts;
935 else
936 p_pic->date = forced_ts;
937 p_pic->b_progressive = true;
939 if (p_sys->api.b_direct_rendering)
941 p_pic->p_sys->hw.i_index = p_out->buf.i_index;
942 InsertInflightPicture(p_dec, p_pic->p_sys);
943 } else {
944 unsigned int chroma_div;
945 GetVlcChromaSizes(p_dec->fmt_out.i_codec,
946 p_dec->fmt_out.video.i_width,
947 p_dec->fmt_out.video.i_height,
948 NULL, NULL, &chroma_div);
949 CopyOmxPicture(p_sys->video.i_pixel_format, p_pic,
950 p_sys->video.i_slice_height, p_sys->video.i_stride,
951 (uint8_t *)p_out->buf.p_ptr, chroma_div, NULL);
953 if (p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false))
955 picture_Release(p_pic);
956 return -1;
959 assert(!(*pp_out_pic));
960 *pp_out_pic = p_pic;
961 return 1;
962 } else {
963 assert(p_out->type == MC_OUT_TYPE_CONF);
964 p_sys->video.i_pixel_format = p_out->conf.video.pixel_format;
966 const char *name = "unknown";
967 if (!p_sys->api.b_direct_rendering
968 && !GetVlcChromaFormat(p_sys->video.i_pixel_format,
969 &p_dec->fmt_out.i_codec, &name))
971 msg_Err(p_dec, "color-format not recognized");
972 return -1;
975 msg_Err(p_dec, "output: %d %s, %dx%d stride %d %d, crop %d %d %d %d",
976 p_sys->video.i_pixel_format, name,
977 p_out->conf.video.width, p_out->conf.video.height,
978 p_out->conf.video.stride, p_out->conf.video.slice_height,
979 p_out->conf.video.crop_left, p_out->conf.video.crop_top,
980 p_out->conf.video.crop_right, p_out->conf.video.crop_bottom);
982 int i_width = p_out->conf.video.crop_right + 1
983 - p_out->conf.video.crop_left;
984 int i_height = p_out->conf.video.crop_bottom + 1
985 - p_out->conf.video.crop_top;
986 if (i_width <= 1 || i_height <= 1)
988 i_width = p_out->conf.video.width;
989 i_height = p_out->conf.video.height;
992 p_dec->fmt_out.video.i_visible_width =
993 p_dec->fmt_out.video.i_width = i_width;
994 p_dec->fmt_out.video.i_visible_height =
995 p_dec->fmt_out.video.i_height = i_height;
997 p_sys->video.i_stride = p_out->conf.video.stride;
998 p_sys->video.i_slice_height = p_out->conf.video.slice_height;
999 if (p_sys->video.i_stride <= 0)
1000 p_sys->video.i_stride = p_out->conf.video.width;
1001 if (p_sys->video.i_slice_height <= 0)
1002 p_sys->video.i_slice_height = p_out->conf.video.height;
1004 if (p_sys->video.i_pixel_format == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar)
1005 p_sys->video.i_slice_height -= p_out->conf.video.crop_top/2;
1006 if ((p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_IGNORE_PADDING))
1008 p_sys->video.i_slice_height = 0;
1009 p_sys->video.i_stride = p_dec->fmt_out.video.i_width;
1012 if (UpdateVout(p_dec) != VLC_SUCCESS)
1014 msg_Err(p_dec, "UpdateVout failed");
1015 return -1;
1018 p_sys->b_has_format = true;
1019 return 0;
1023 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
1024 static uint32_t pi_audio_order_src[] =
1026 AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, AOUT_CHAN_LFE,
1027 AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER,
1028 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
1031 static int Audio_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
1032 picture_t **pp_out_pic, block_t **pp_out_block)
1034 decoder_sys_t *p_sys = p_dec->p_sys;
1035 (void) pp_out_pic;
1036 assert(pp_out_block);
1038 if (p_out->type == MC_OUT_TYPE_BUF)
1040 block_t *p_block = NULL;
1041 if (p_out->buf.p_ptr == NULL)
1043 /* This can happen when receiving an EOS buffer */
1044 msg_Warn(p_dec, "Invalid buffer, dropping frame");
1045 return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
1048 if (!p_sys->b_has_format) {
1049 msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
1050 return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
1053 p_block = block_Alloc(p_out->buf.i_size);
1054 if (!p_block)
1055 return -1;
1056 p_block->i_nb_samples = p_out->buf.i_size
1057 / p_dec->fmt_out.audio.i_bytes_per_frame;
1059 if (p_sys->audio.b_extract)
1061 aout_ChannelExtract(p_block->p_buffer,
1062 p_dec->fmt_out.audio.i_channels,
1063 p_out->buf.p_ptr, p_sys->audio.i_channels,
1064 p_block->i_nb_samples, p_sys->audio.pi_extraction,
1065 p_dec->fmt_out.audio.i_bitspersample);
1067 else
1068 memcpy(p_block->p_buffer, p_out->buf.p_ptr, p_out->buf.i_size);
1070 if (p_out->buf.i_ts != 0
1071 && p_out->buf.i_ts != date_Get(&p_sys->audio.i_end_date))
1072 date_Set(&p_sys->audio.i_end_date, p_out->buf.i_ts);
1074 p_block->i_pts = date_Get(&p_sys->audio.i_end_date);
1075 p_block->i_length = date_Increment(&p_sys->audio.i_end_date,
1076 p_block->i_nb_samples)
1077 - p_block->i_pts;
1079 if (p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false))
1081 block_Release(p_block);
1082 return -1;
1084 *pp_out_block = p_block;
1085 return 1;
1086 } else {
1087 uint32_t i_layout_dst;
1088 int i_channels_dst;
1090 assert(p_out->type == MC_OUT_TYPE_CONF);
1092 if (p_out->conf.audio.channel_count <= 0
1093 || p_out->conf.audio.channel_count > 8
1094 || p_out->conf.audio.sample_rate <= 0)
1096 msg_Warn(p_dec, "invalid audio properties channels count %d, sample rate %d",
1097 p_out->conf.audio.channel_count,
1098 p_out->conf.audio.sample_rate);
1099 return -1;
1102 msg_Err(p_dec, "output: channel_count: %d, channel_mask: 0x%X, rate: %d",
1103 p_out->conf.audio.channel_count, p_out->conf.audio.channel_mask,
1104 p_out->conf.audio.sample_rate);
1106 p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
1107 p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
1109 p_dec->fmt_out.audio.i_rate = p_out->conf.audio.sample_rate;
1110 date_Init(&p_sys->audio.i_end_date, p_out->conf.audio.sample_rate, 1);
1112 p_sys->audio.i_channels = p_out->conf.audio.channel_count;
1113 p_sys->audio.b_extract =
1114 aout_CheckChannelExtraction(p_sys->audio.pi_extraction,
1115 &i_layout_dst, &i_channels_dst,
1116 NULL, pi_audio_order_src,
1117 p_sys->audio.i_channels);
1119 if (p_sys->audio.b_extract)
1120 msg_Warn(p_dec, "need channel extraction: %d -> %d",
1121 p_sys->audio.i_channels, i_channels_dst);
1123 p_dec->fmt_out.audio.i_physical_channels = i_layout_dst;
1124 aout_FormatPrepare(&p_dec->fmt_out.audio);
1126 if (decoder_UpdateAudioFormat(p_dec))
1127 return -1;
1129 p_sys->b_has_format = true;
1130 return 0;
1134 static void DecodeFlushLocked(decoder_t *p_dec)
1136 decoder_sys_t *p_sys = p_dec->p_sys;
1137 bool b_had_input = p_sys->b_input_dequeued;
1139 p_sys->b_input_dequeued = false;
1140 p_sys->b_flush_out = true;
1141 p_sys->i_preroll_end = 0;
1142 p_sys->b_output_ready = false;
1143 /* Resend CODEC_CONFIG buffer after a flush */
1144 p_sys->i_csd_send = 0;
1146 p_sys->pf_on_flush(p_dec);
1148 if (b_had_input && p_sys->api.flush(&p_sys->api) != VLC_SUCCESS)
1150 AbortDecoderLocked(p_dec);
1151 return;
1154 vlc_cond_broadcast(&p_sys->cond);
1156 while (!p_sys->b_aborted && p_sys->b_flush_out)
1157 vlc_cond_wait(&p_sys->dec_cond, &p_sys->lock);
1160 static void DecodeFlush(decoder_t *p_dec)
1162 decoder_sys_t *p_sys = p_dec->p_sys;
1164 vlc_mutex_lock(&p_sys->lock);
1165 DecodeFlushLocked(p_dec);
1166 vlc_mutex_unlock(&p_sys->lock);
1169 static void *OutThread(void *data)
1171 decoder_t *p_dec = data;
1172 decoder_sys_t *p_sys = p_dec->p_sys;
1174 vlc_mutex_lock(&p_sys->lock);
1175 mutex_cleanup_push(&p_sys->lock);
1176 for (;;)
1178 int i_index;
1180 /* Wait for output ready */
1181 while (!p_sys->b_flush_out && !p_sys->b_output_ready)
1182 vlc_cond_wait(&p_sys->cond, &p_sys->lock);
1184 if (p_sys->b_flush_out)
1186 /* Acknowledge flushed state */
1187 p_sys->b_flush_out = false;
1188 vlc_cond_broadcast(&p_sys->dec_cond);
1189 continue;
1192 int canc = vlc_savecancel();
1194 vlc_mutex_unlock(&p_sys->lock);
1196 /* Wait for an output buffer. This function returns when a new output
1197 * is available or if output is flushed. */
1198 i_index = p_sys->api.dequeue_out(&p_sys->api, -1);
1200 vlc_mutex_lock(&p_sys->lock);
1202 /* Ignore dequeue_out errors caused by flush */
1203 if (p_sys->b_flush_out)
1205 /* If i_index >= 0, Release it. There is no way to know if i_index
1206 * is owned by us, so don't check the error. */
1207 if (i_index >= 0)
1208 p_sys->api.release_out(&p_sys->api, i_index, false);
1210 /* Parse output format/buffers even when we are flushing */
1211 if (i_index != MC_API_INFO_OUTPUT_FORMAT_CHANGED
1212 && i_index != MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
1214 vlc_restorecancel(canc);
1215 continue;
1219 /* Process output returned by dequeue_out */
1220 if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
1221 || i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
1223 struct mc_api_out out;
1224 int i_ret = p_sys->api.get_out(&p_sys->api, i_index, &out);
1226 if (i_ret == 1)
1228 picture_t *p_pic = NULL;
1229 block_t *p_block = NULL;
1231 if (p_sys->pf_process_output(p_dec, &out, &p_pic,
1232 &p_block) == -1 && !out.b_eos)
1234 msg_Err(p_dec, "pf_process_output failed");
1235 vlc_restorecancel(canc);
1236 break;
1238 if (p_pic)
1239 decoder_QueueVideo(p_dec, p_pic);
1240 else if (p_block)
1241 decoder_QueueAudio(p_dec, p_block);
1243 if (out.b_eos)
1245 msg_Warn(p_dec, "EOS received");
1246 p_sys->b_drained = true;
1247 vlc_cond_signal(&p_sys->dec_cond);
1249 } else if (i_ret != 0)
1251 msg_Err(p_dec, "get_out failed");
1252 vlc_restorecancel(canc);
1253 break;
1256 else
1258 vlc_restorecancel(canc);
1259 break;
1261 vlc_restorecancel(canc);
1263 msg_Warn(p_dec, "OutThread stopped");
1265 /* Signal DecoderFlush that the output thread aborted */
1266 p_sys->b_aborted = true;
1267 vlc_cond_signal(&p_sys->dec_cond);
1269 vlc_cleanup_pop();
1270 vlc_mutex_unlock(&p_sys->lock);
1272 return NULL;
1275 static block_t *GetNextBlock(decoder_sys_t *p_sys, block_t *p_block)
1277 if (p_sys->i_csd_send < p_sys->i_csd_count)
1278 return p_sys->pp_csd[p_sys->i_csd_send++];
1279 else
1280 return p_block;
1283 static int QueueBlockLocked(decoder_t *p_dec, block_t *p_in_block,
1284 bool b_drain)
1286 decoder_sys_t *p_sys = p_dec->p_sys;
1287 block_t *p_block = NULL;
1288 bool b_dequeue_timeout = false;
1290 assert(p_sys->api.b_started);
1292 if ((p_sys->api.i_quirks & MC_API_QUIRKS_NEED_CSD) && !p_sys->i_csd_count
1293 && !p_sys->b_adaptive)
1294 return VLC_EGENERIC; /* Wait for CSDs */
1296 /* Queue CSD blocks and input blocks */
1297 while (b_drain || (p_block = GetNextBlock(p_sys, p_in_block)))
1299 int i_index;
1301 vlc_mutex_unlock(&p_sys->lock);
1302 /* Wait for an input buffer. This function returns when a new input
1303 * buffer is available or after 2secs of timeout. */
1304 i_index = p_sys->api.dequeue_in(&p_sys->api,
1305 p_sys->api.b_direct_rendering ?
1306 INT64_C(2000000) : -1);
1307 vlc_mutex_lock(&p_sys->lock);
1309 if (p_sys->b_aborted)
1310 return VLC_EGENERIC;
1312 bool b_config = false;
1313 mtime_t i_ts = 0;
1314 p_sys->b_input_dequeued = true;
1315 const void *p_buf = NULL;
1316 size_t i_size = 0;
1318 if (i_index >= 0)
1320 assert(b_drain || p_block != NULL);
1321 if (p_block != NULL)
1323 b_config = (p_block->i_flags & BLOCK_FLAG_CSD);
1324 if (!b_config)
1326 i_ts = p_block->i_pts;
1327 if (!i_ts && p_block->i_dts)
1328 i_ts = p_block->i_dts;
1330 p_buf = p_block->p_buffer;
1331 i_size = p_block->i_buffer;
1334 if (p_sys->api.queue_in(&p_sys->api, i_index, p_buf, i_size,
1335 i_ts, b_config) == 0)
1337 if (!b_config && p_block != NULL)
1339 if (p_block->i_flags & BLOCK_FLAG_PREROLL)
1340 p_sys->i_preroll_end = i_ts;
1342 /* One input buffer is queued, signal OutThread that will
1343 * fetch output buffers */
1344 p_sys->b_output_ready = true;
1345 vlc_cond_broadcast(&p_sys->cond);
1347 assert(p_block == p_in_block),
1348 p_in_block = NULL;
1350 b_dequeue_timeout = false;
1351 if (b_drain)
1352 break;
1353 } else
1355 msg_Err(p_dec, "queue_in failed");
1356 goto error;
1359 else if (i_index == MC_API_INFO_TRYAGAIN)
1361 /* HACK: When direct rendering is enabled, there is a possible
1362 * deadlock between the Decoder and the Vout. It happens when the
1363 * Vout is paused and when the Decoder is flushing. In that case,
1364 * the Vout won't release any output buffers, therefore MediaCodec
1365 * won't dequeue any input buffers. To work around this issue,
1366 * release all output buffers if DecodeBlock is waiting more than
1367 * 2secs for a new input buffer. */
1368 if (!b_dequeue_timeout)
1370 msg_Warn(p_dec, "Decoder stuck: invalidate all buffers");
1371 InvalidateAllPictures(p_dec);
1372 b_dequeue_timeout = true;
1373 continue;
1375 else
1377 msg_Err(p_dec, "dequeue_in timeout: no input available for 2secs");
1378 goto error;
1381 else
1383 msg_Err(p_dec, "dequeue_in failed");
1384 goto error;
1388 if (b_drain)
1390 msg_Warn(p_dec, "EOS sent, waiting for OutThread");
1392 /* Wait for the OutThread to stop (and process all remaining output
1393 * frames. Use a timeout here since we can't know if all decoders will
1394 * behave correctly. */
1395 mtime_t deadline = mdate() + INT64_C(3000000);
1396 while (!p_sys->b_aborted && !p_sys->b_drained
1397 && vlc_cond_timedwait(&p_sys->dec_cond, &p_sys->lock, deadline) == 0);
1399 if (!p_sys->b_drained)
1401 msg_Err(p_dec, "OutThread timed out");
1402 AbortDecoderLocked(p_dec);
1404 p_sys->b_drained = false;
1407 return VLC_SUCCESS;
1409 error:
1410 AbortDecoderLocked(p_dec);
1411 return VLC_EGENERIC;
1414 static int DecodeBlock(decoder_t *p_dec, block_t *p_in_block)
1416 decoder_sys_t *p_sys = p_dec->p_sys;
1417 int i_ret;
1419 vlc_mutex_lock(&p_sys->lock);
1421 if (p_sys->b_aborted)
1423 if (p_sys->b_has_format)
1424 goto end;
1425 else
1426 goto reload;
1429 if (p_in_block == NULL)
1431 /* No input block, decoder is draining */
1432 msg_Err(p_dec, "Decoder is draining");
1434 if (p_sys->b_output_ready)
1435 QueueBlockLocked(p_dec, NULL, true);
1436 goto end;
1439 if (p_in_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED))
1441 if (p_sys->b_output_ready)
1442 QueueBlockLocked(p_dec, NULL, true);
1443 DecodeFlushLocked(p_dec);
1444 if (p_sys->b_aborted)
1445 goto end;
1446 if (p_in_block->i_flags & BLOCK_FLAG_CORRUPTED)
1447 goto end;
1450 if (p_in_block->i_flags & BLOCK_FLAG_INTERLACED_MASK
1451 && !(p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_SUPPORT_INTERLACED))
1453 /* Before Android 21 and depending on the vendor, MediaCodec can
1454 * crash or be in an inconsistent state when decoding interlaced
1455 * videos. See OMXCodec_GetQuirks() for a white list of decoders
1456 * that supported interlaced videos before Android 21. */
1457 msg_Warn(p_dec, "codec doesn't support interlaced videos");
1458 goto reload;
1461 /* Parse input block */
1462 if ((i_ret = p_sys->pf_on_new_block(p_dec, &p_in_block)) != 1)
1464 if (i_ret != 0)
1466 AbortDecoderLocked(p_dec);
1467 msg_Err(p_dec, "pf_on_new_block failed");
1469 goto end;
1471 if (p_sys->i_decode_flags & (DECODE_FLAG_DRAIN|DECODE_FLAG_RESTART))
1473 msg_Warn(p_dec, "Draining from DecodeBlock");
1474 const bool b_restart = p_sys->i_decode_flags & DECODE_FLAG_RESTART;
1475 p_sys->i_decode_flags = 0;
1477 /* Drain and flush before restart to unblock OutThread */
1478 if (p_sys->b_output_ready)
1479 QueueBlockLocked(p_dec, NULL, true);
1480 DecodeFlushLocked(p_dec);
1481 if (p_sys->b_aborted)
1482 goto end;
1484 if (b_restart)
1486 StopMediaCodec(p_dec);
1488 int i_ret = StartMediaCodec(p_dec);
1489 switch (i_ret)
1491 case VLC_SUCCESS:
1492 msg_Warn(p_dec, "Restarted from DecodeBlock");
1493 break;
1494 case VLC_ENOOBJ:
1495 break;
1496 default:
1497 msg_Err(p_dec, "StartMediaCodec failed");
1498 AbortDecoderLocked(p_dec);
1499 goto end;
1504 /* Abort if MediaCodec is not yet started */
1505 if (p_sys->api.b_started)
1506 QueueBlockLocked(p_dec, p_in_block, false);
1508 end:
1509 if (p_in_block)
1510 block_Release(p_in_block);
1511 /* Too late to reload here, we already modified/released the input block,
1512 * do it next time. */
1513 int ret = p_sys->b_aborted && p_sys->b_has_format ? VLCDEC_ECRITICAL
1514 : VLCDEC_SUCCESS;
1515 vlc_mutex_unlock(&p_sys->lock);
1516 return ret;
1518 reload:
1519 vlc_mutex_unlock(&p_sys->lock);
1520 /* Add an empty variable so that mediacodec won't be loaded again
1521 * for this ES */
1522 var_Create(p_dec, "mediacodec-failed", VLC_VAR_VOID);
1523 return VLCDEC_RELOAD;
1526 static int Video_OnNewBlock(decoder_t *p_dec, block_t **pp_block)
1528 decoder_sys_t *p_sys = p_dec->p_sys;
1529 block_t *p_block = *pp_block;
1531 timestamp_FifoPut(p_sys->video.timestamp_fifo,
1532 p_block->i_pts ? VLC_TS_INVALID : p_block->i_dts);
1534 return 1;
1537 static int VideoHXXX_OnNewBlock(decoder_t *p_dec, block_t **pp_block)
1539 decoder_sys_t *p_sys = p_dec->p_sys;
1540 struct hxxx_helper *hh = &p_sys->video.hh;
1541 bool b_config_changed = false;
1542 bool *p_config_changed = p_sys->b_adaptive ? NULL : &b_config_changed;
1544 *pp_block = hh->pf_process_block(hh, *pp_block, p_config_changed);
1545 if (!*pp_block)
1546 return 0;
1547 if (b_config_changed)
1549 bool b_size_changed;
1550 int i_ret;
1551 switch (p_dec->fmt_in.i_codec)
1553 case VLC_CODEC_H264:
1554 if (hh->h264.i_sps_count > 0 || hh->h264.i_pps_count > 0)
1555 i_ret = H264SetCSD(p_dec, &b_size_changed);
1556 else
1557 i_ret = VLC_EGENERIC;
1558 break;
1559 case VLC_CODEC_HEVC:
1560 if (hh->hevc.i_vps_count > 0 || hh->hevc.i_sps_count > 0 ||
1561 hh->hevc.i_pps_count > 0 )
1562 i_ret = HEVCSetCSD(p_dec, &b_size_changed);
1563 else
1564 i_ret = VLC_EGENERIC;
1565 break;
1567 if (i_ret != VLC_SUCCESS)
1568 return i_ret;
1569 if (b_size_changed || !p_sys->api.b_started)
1571 if (p_sys->api.b_started)
1572 msg_Err(p_dec, "SPS/PPS changed during playback and "
1573 "video size are different. Restart it !");
1574 p_sys->i_decode_flags |= DECODE_FLAG_RESTART;
1575 } else
1577 msg_Err(p_dec, "SPS/PPS changed during playback. Drain it");
1578 p_sys->i_decode_flags |= DECODE_FLAG_DRAIN;
1582 return Video_OnNewBlock(p_dec, pp_block);
1585 static int VideoVC1_OnNewBlock(decoder_t *p_dec, block_t **pp_block)
1587 block_t *p_block = *pp_block;
1589 /* Adding frame start code */
1590 p_block = *pp_block = block_Realloc(p_block, 4, p_block->i_buffer);
1591 if (p_block == NULL)
1592 return VLC_ENOMEM;
1593 p_block->p_buffer[0] = 0x00;
1594 p_block->p_buffer[1] = 0x00;
1595 p_block->p_buffer[2] = 0x01;
1596 p_block->p_buffer[3] = 0x0d;
1598 return Video_OnNewBlock(p_dec, pp_block);
1601 static void Video_OnFlush(decoder_t *p_dec)
1603 decoder_sys_t *p_sys = p_dec->p_sys;
1605 timestamp_FifoEmpty(p_sys->video.timestamp_fifo);
1606 /* Invalidate all pictures that are currently in flight
1607 * since flushing make all previous indices returned by
1608 * MediaCodec invalid. */
1609 if (p_sys->api.b_direct_rendering)
1610 InvalidateAllPictures(p_dec);
1613 static int Audio_OnNewBlock(decoder_t *p_dec, block_t **pp_block)
1615 decoder_sys_t *p_sys = p_dec->p_sys;
1616 block_t *p_block = *pp_block;
1618 /* We've just started the stream, wait for the first PTS. */
1619 if (!date_Get(&p_sys->audio.i_end_date))
1621 if (p_block->i_pts <= VLC_TS_INVALID)
1622 return 0;
1623 date_Set(&p_sys->audio.i_end_date, p_block->i_pts);
1626 return 1;
1629 static void Audio_OnFlush(decoder_t *p_dec)
1631 decoder_sys_t *p_sys = p_dec->p_sys;
1633 date_Set(&p_sys->audio.i_end_date, VLC_TS_INVALID);