1 /*****************************************************************************
2 * mediacodec.c: Video decoder module using the Android MediaCodec API
3 *****************************************************************************
4 * Copyright (C) 2012 Martin Storsjo
6 * Authors: Martin Storsjo <martin@martin.st>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
33 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
37 #include <vlc_block_helper.h>
38 #include <vlc_timestamp_helper.h>
39 #include <vlc_threads.h>
42 #include "mediacodec.h"
43 #include "../codec/hxxx_helper.h"
45 #include <OMX_Component.h>
46 #include "omxil_utils.h"
47 #include "../../video_output/android/display.h"
49 #define BLOCK_FLAG_CSD (0x01 << BLOCK_FLAG_PRIVATE_SHIFT)
51 #define DECODE_FLAG_RESTART (0x01)
52 #define DECODE_FLAG_DRAIN (0x02)
54 * Callback called when a new block is processed from DecodeBlock.
55 * It returns -1 in case of error, 0 if block should be dropped, 1 otherwise.
57 typedef int (*dec_on_new_block_cb
)(decoder_t
*, block_t
**);
60 * Callback called when decoder is flushing.
62 typedef void (*dec_on_flush_cb
)(decoder_t
*);
65 * Callback called when DecodeBlock try to get an output buffer (pic or block).
66 * It returns -1 in case of error, or the number of output buffer returned.
68 typedef int (*dec_process_output_cb
)(decoder_t
*, mc_api_out
*, picture_t
**,
75 /* Codec Specific Data buffer: sent in DecodeBlock after a start or a flush
76 * with the BUFFER_FLAG_CODEC_CONFIG flag.*/
77 #define MAX_CSD_COUNT 3
78 block_t
*pp_csd
[MAX_CSD_COUNT
];
84 int64_t i_preroll_end
;
87 /* Specific Audio/Video callbacks */
88 dec_on_new_block_cb pf_on_new_block
;
89 dec_on_flush_cb pf_on_flush
;
90 dec_process_output_cb pf_process_output
;
93 vlc_thread_t out_thread
;
94 /* Cond used to signal the output thread */
96 /* Cond used to signal the decoder thread */
98 /* Set to true by pf_flush to signal the output thread to flush */
100 /* If true, the output thread will start to dequeue output pictures */
102 /* If true, the first input block was successfully dequeued */
103 bool b_input_dequeued
;
113 void *p_surface
, *p_jsurface
;
115 unsigned i_input_width
, i_input_height
;
116 unsigned int i_stride
, i_slice_height
;
118 struct hxxx_helper hh
;
119 /* stores the inflight picture for each output buffer or NULL */
120 picture_sys_t
** pp_inflight_pictures
;
121 unsigned int i_inflight_pictures
;
122 timestamp_fifo_t
*timestamp_fifo
;
123 int i_mpeg_dar_num
, i_mpeg_dar_den
;
129 /* Some audio decoders need a valid channel count */
130 bool b_need_channels
;
131 int pi_extraction
[AOUT_CHAN_MAX
];
136 /*****************************************************************************
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 VideoMPEG2_OnNewBlock(decoder_t
*, block_t
**);
147 static int VideoVC1_OnNewBlock(decoder_t
*, block_t
**);
148 static void Video_OnFlush(decoder_t
*);
149 static int Video_ProcessOutput(decoder_t
*, mc_api_out
*, picture_t
**,
151 static int DecodeBlock(decoder_t
*, block_t
*);
153 static int Audio_OnNewBlock(decoder_t
*, block_t
**);
154 static void Audio_OnFlush(decoder_t
*);
155 static int Audio_ProcessOutput(decoder_t
*, mc_api_out
*, picture_t
**,
158 static void DecodeFlushLocked(decoder_t
*);
159 static void DecodeFlush(decoder_t
*);
160 static void StopMediaCodec(decoder_t
*);
161 static void *OutThread(void *);
163 static void InvalidateAllPictures(decoder_t
*);
164 static void RemoveInflightPictures(decoder_t
*);
166 /*****************************************************************************
168 *****************************************************************************/
169 #define MEDIACODEC_ENABLE_TEXT N_("Enable hardware acceleration")
171 #define DIRECTRENDERING_TEXT "Android direct rendering"
172 #define DIRECTRENDERING_LONGTEXT \
173 "Enable Android direct rendering using opaque buffers."
175 #define MEDIACODEC_AUDIO_TEXT "Use MediaCodec for audio decoding"
176 #define MEDIACODEC_AUDIO_LONGTEXT "Still experimental."
178 #define MEDIACODEC_TUNNELEDPLAYBACK_TEXT "Use a tunneled surface for playback"
180 #define CFG_PREFIX "mediacodec-"
183 set_description("Video decoder using Android MediaCodec via NDK")
184 set_category(CAT_INPUT
)
185 set_subcategory(SUBCAT_INPUT_VCODEC
)
186 set_section(N_("Decoding"), NULL
)
187 set_capability("video decoder", 800)
188 add_bool("mediacodec", true, MEDIACODEC_ENABLE_TEXT
, NULL
, false)
189 add_bool(CFG_PREFIX
"dr", true,
190 DIRECTRENDERING_TEXT
, DIRECTRENDERING_LONGTEXT
, true)
191 add_bool(CFG_PREFIX
"audio", false,
192 MEDIACODEC_AUDIO_TEXT
, MEDIACODEC_AUDIO_LONGTEXT
, true)
193 add_bool(CFG_PREFIX
"tunneled-playback", false,
194 MEDIACODEC_TUNNELEDPLAYBACK_TEXT
, NULL
, true)
195 set_callbacks(OpenDecoderNdk
, CloseDecoder
)
196 add_shortcut("mediacodec_ndk")
198 set_capability("audio decoder", 0)
199 set_callbacks(OpenDecoderNdk
, CloseDecoder
)
200 add_shortcut("mediacodec_ndk")
202 set_description("Video decoder using Android MediaCodec via JNI")
203 set_capability("video decoder", 0)
204 set_callbacks(OpenDecoderJni
, CloseDecoder
)
205 add_shortcut("mediacodec_jni")
207 set_capability("audio decoder", 0)
208 set_callbacks(OpenDecoderJni
, CloseDecoder
)
209 add_shortcut("mediacodec_jni")
212 static void CSDFree(decoder_t
*p_dec
)
214 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
216 for (unsigned int i
= 0; i
< p_sys
->i_csd_count
; ++i
)
217 block_Release(p_sys
->pp_csd
[i
]);
218 p_sys
->i_csd_count
= 0;
221 /* Init the p_sys->p_csd that will be sent from DecodeBlock */
222 static void CSDInit(decoder_t
*p_dec
, block_t
*p_blocks
, size_t i_count
)
224 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
225 assert(i_count
>= 0 && i_count
<= 3);
229 for (size_t i
= 0; i
< i_count
; ++i
)
231 assert(p_blocks
!= NULL
);
232 p_sys
->pp_csd
[i
] = p_blocks
;
233 p_sys
->pp_csd
[i
]->i_flags
= BLOCK_FLAG_CSD
;
234 p_blocks
= p_blocks
->p_next
;
235 p_sys
->pp_csd
[i
]->p_next
= NULL
;
238 p_sys
->i_csd_count
= i_count
;
239 p_sys
->i_csd_send
= 0;
242 static int CSDDup(decoder_t
*p_dec
, const void *p_buf
, size_t i_buf
)
244 block_t
*p_block
= block_Alloc(i_buf
);
247 memcpy(p_block
->p_buffer
, p_buf
, i_buf
);
249 CSDInit(p_dec
, p_block
, 1);
253 static void HXXXInitSize(decoder_t
*p_dec
, bool *p_size_changed
)
257 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
258 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
259 unsigned i_w
, i_h
, i_vw
, i_vh
;
260 hxxx_helper_get_current_picture_size(hh
, &i_w
, &i_h
, &i_vw
, &i_vh
);
262 *p_size_changed
= (i_w
!= p_sys
->video
.i_input_width
263 || i_h
!= p_sys
->video
.i_input_height
);
264 p_sys
->video
.i_input_width
= i_w
;
265 p_sys
->video
.i_input_height
= i_h
;
266 /* fmt_out video size will be updated by mediacodec output callback */
270 /* Fill the p_sys->p_csd struct with H264 Parameter Sets */
271 static int H264SetCSD(decoder_t
*p_dec
, bool *p_size_changed
)
273 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
274 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
275 assert(hh
->h264
.i_sps_count
> 0 || hh
->h264
.i_pps_count
> 0);
277 block_t
*p_spspps_blocks
= h264_helper_get_annexb_config(hh
);
279 if (p_spspps_blocks
!= NULL
)
280 CSDInit(p_dec
, p_spspps_blocks
, 2);
282 HXXXInitSize(p_dec
, p_size_changed
);
287 /* Fill the p_sys->p_csd struct with HEVC Parameter Sets */
288 static int HEVCSetCSD(decoder_t
*p_dec
, bool *p_size_changed
)
290 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
291 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
293 assert(hh
->hevc
.i_vps_count
> 0 || hh
->hevc
.i_sps_count
> 0 ||
294 hh
->hevc
.i_pps_count
> 0 );
296 block_t
*p_xps_blocks
= hevc_helper_get_annexb_config(hh
);
297 if (p_xps_blocks
!= NULL
)
299 block_t
*p_monolith
= block_ChainGather(p_xps_blocks
);
300 if (p_monolith
== NULL
)
302 block_ChainRelease(p_xps_blocks
);
305 CSDInit(p_dec
, p_monolith
, 1);
308 HXXXInitSize(p_dec
, p_size_changed
);
312 static int ParseVideoExtraH264(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
314 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
315 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
317 int i_ret
= hxxx_helper_set_extra(hh
, p_extra
, i_extra
);
318 if (i_ret
!= VLC_SUCCESS
)
320 assert(hh
->pf_process_block
!= NULL
);
322 if (p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
323 p_sys
->b_adaptive
= true;
325 p_sys
->pf_on_new_block
= VideoHXXX_OnNewBlock
;
327 if (hh
->h264
.i_sps_count
> 0 || hh
->h264
.i_pps_count
> 0)
328 return H264SetCSD(p_dec
, NULL
);
332 static int ParseVideoExtraHEVC(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
334 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
335 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
337 int i_ret
= hxxx_helper_set_extra(hh
, p_extra
, i_extra
);
338 if (i_ret
!= VLC_SUCCESS
)
340 assert(hh
->pf_process_block
!= NULL
);
342 if (p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
343 p_sys
->b_adaptive
= true;
345 p_sys
->pf_on_new_block
= VideoHXXX_OnNewBlock
;
347 if (hh
->hevc
.i_vps_count
> 0 || hh
->hevc
.i_sps_count
> 0 ||
348 hh
->hevc
.i_pps_count
> 0 )
349 return HEVCSetCSD(p_dec
, NULL
);
353 static int ParseVideoExtraVc1(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
355 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
361 /* Initialisation data starts with : 0x00 0x00 0x01 0x0f */
362 /* Skipping unecessary data */
363 static const uint8_t vc1_start_code
[4] = {0x00, 0x00, 0x01, 0x0f};
364 for (; offset
< i_extra
- 4 ; ++offset
)
366 if (!memcmp(&p_extra
[offset
], vc1_start_code
, 4))
370 /* Could not find the sequence header start code */
371 if (offset
>= i_extra
- 4)
374 p_sys
->pf_on_new_block
= VideoVC1_OnNewBlock
;
375 return CSDDup(p_dec
, p_extra
+ offset
, i_extra
- offset
);
378 static int ParseVideoExtraWmv3(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
380 /* WMV3 initialisation data :
383 * 4 height bytes (little endian)
384 * 4 width bytes (little endian)
390 uint8_t p_data
[36] = {
391 0x8e, 0x01, 0x00, 0xc5, /* Fixed bytes values */
392 0x04, 0x00, 0x00, 0x00, /* Same */
393 0x00, 0x00, 0x00, 0x00, /* extradata emplacement */
394 0x00, 0x00, 0x00, 0x00, /* height emplacement (little endian) */
395 0x00, 0x00, 0x00, 0x00, /* width emplacement (little endian) */
396 0x0c, 0x00, 0x00, 0x00, /* Fixed byte pattern */
397 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00
402 /* Adding extradata */
403 memcpy(&p_data
[8], p_extra
, 4);
404 /* Adding height and width, little endian */
405 SetDWLE(&(p_data
[12]), p_dec
->fmt_in
.video
.i_height
);
406 SetDWLE(&(p_data
[16]), p_dec
->fmt_in
.video
.i_width
);
408 return CSDDup(p_dec
, p_data
, sizeof(p_data
));
411 static int ParseExtra(decoder_t
*p_dec
)
413 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
414 uint8_t *p_extra
= p_dec
->fmt_in
.p_extra
;
415 int i_extra
= p_dec
->fmt_in
.i_extra
;
417 switch (p_dec
->fmt_in
.i_codec
)
420 return ParseVideoExtraH264(p_dec
, p_extra
, i_extra
);
422 return ParseVideoExtraHEVC(p_dec
, p_extra
, i_extra
);
424 return ParseVideoExtraWmv3(p_dec
, p_extra
, i_extra
);
426 return ParseVideoExtraVc1(p_dec
, p_extra
, i_extra
);
428 if (!i_extra
&& p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
429 p_sys
->b_adaptive
= true;
433 p_sys
->pf_on_new_block
= VideoMPEG2_OnNewBlock
;
436 /* Set default CSD */
437 if (p_dec
->fmt_in
.i_extra
)
438 return CSDDup(p_dec
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
443 static int UpdateVout(decoder_t
*p_dec
)
445 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
447 if ((p_dec
->fmt_in
.i_codec
== VLC_CODEC_MPGV
||
448 p_dec
->fmt_in
.i_codec
== VLC_CODEC_MP2V
) &&
449 (p_sys
->video
.i_mpeg_dar_num
* p_sys
->video
.i_mpeg_dar_den
!= 0))
451 p_dec
->fmt_out
.video
.i_sar_num
=
452 p_sys
->video
.i_mpeg_dar_num
* p_dec
->fmt_out
.video
.i_height
;
453 p_dec
->fmt_out
.video
.i_sar_den
=
454 p_sys
->video
.i_mpeg_dar_den
* p_dec
->fmt_out
.video
.i_width
;
457 /* If MediaCodec can handle the rotation, reset the orientation to
458 * Normal in order to ask the vout not to rotate. */
459 if (p_sys
->video
.i_angle
!= 0)
461 assert(p_dec
->fmt_out
.i_codec
== VLC_CODEC_ANDROID_OPAQUE
);
462 p_dec
->fmt_out
.video
.orientation
= p_dec
->fmt_in
.video
.orientation
;
463 video_format_TransformTo(&p_dec
->fmt_out
.video
, ORIENT_NORMAL
);
466 if (decoder_UpdateVideoFormat(p_dec
) != 0)
469 if (p_dec
->fmt_out
.i_codec
!= VLC_CODEC_ANDROID_OPAQUE
)
472 /* Direct rendering: get the surface attached to the VOUT */
473 picture_t
*p_dummy_hwpic
= decoder_NewPicture(p_dec
);
474 if (p_dummy_hwpic
== NULL
)
477 picture_sys_t
*p_picsys
= p_dummy_hwpic
->p_sys
;
479 assert(p_picsys
->hw
.p_surface
);
480 assert(p_picsys
->hw
.p_jsurface
);
482 p_sys
->video
.p_surface
= p_picsys
->hw
.p_surface
;
483 p_sys
->video
.p_jsurface
= p_picsys
->hw
.p_jsurface
;
484 picture_Release(p_dummy_hwpic
);
488 /*****************************************************************************
489 * StartMediaCodec: Create the mediacodec instance
490 *****************************************************************************/
491 static int StartMediaCodec(decoder_t
*p_dec
)
493 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
494 union mc_api_args args
;
496 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
498 args
.video
.i_width
= p_dec
->fmt_out
.video
.i_width
;
499 args
.video
.i_height
= p_dec
->fmt_out
.video
.i_height
;
500 args
.video
.i_angle
= p_sys
->video
.i_angle
;
502 args
.video
.p_surface
= p_sys
->video
.p_surface
;
503 args
.video
.p_jsurface
= p_sys
->video
.p_jsurface
;
504 args
.video
.b_tunneled_playback
= args
.video
.p_surface
?
505 var_InheritBool(p_dec
, CFG_PREFIX
"tunneled-playback") : false;
506 if (p_sys
->b_adaptive
)
507 msg_Dbg(p_dec
, "mediacodec configured for adaptative playback");
508 args
.video
.b_adaptive_playback
= p_sys
->b_adaptive
;
512 date_Set(&p_sys
->audio
.i_end_date
, VLC_TICK_INVALID
);
514 args
.audio
.i_sample_rate
= p_dec
->fmt_in
.audio
.i_rate
;
515 args
.audio
.i_channel_count
= p_sys
->audio
.i_channels
;
518 if (p_sys
->api
.configure_decoder(&p_sys
->api
, &args
) != 0)
523 return p_sys
->api
.start(&p_sys
->api
);
526 /*****************************************************************************
527 * StopMediaCodec: Close the mediacodec instance
528 *****************************************************************************/
529 static void StopMediaCodec(decoder_t
*p_dec
)
531 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
533 /* Remove all pictures that are currently in flight in order
534 * to prevent the vout from using destroyed output buffers. */
535 if (p_sys
->api
.b_direct_rendering
)
536 RemoveInflightPictures(p_dec
);
538 p_sys
->api
.stop(&p_sys
->api
);
541 /*****************************************************************************
542 * OpenDecoder: Create the decoder instance
543 *****************************************************************************/
544 static int OpenDecoder(vlc_object_t
*p_this
, pf_MediaCodecApi_init pf_init
)
546 decoder_t
*p_dec
= (decoder_t
*)p_this
;
548 if (!var_InheritBool(p_dec
, "mediacodec"))
551 decoder_sys_t
*p_sys
;
553 int i_profile
= p_dec
->fmt_in
.i_profile
;
554 const char *mime
= NULL
;
556 /* Video or Audio if "mediacodec-audio" bool is true */
557 if (p_dec
->fmt_in
.i_cat
!= VIDEO_ES
&& (p_dec
->fmt_in
.i_cat
!= AUDIO_ES
558 || !var_InheritBool(p_dec
, CFG_PREFIX
"audio")))
561 /* Fail if this module already failed to decode this ES */
562 if (var_Type(p_dec
, "mediacodec-failed") != 0)
565 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
567 /* Not all mediacodec versions can handle a size of 0. Hopefully, the
568 * packetizer will trigger a decoder restart when a new video size is
570 if (!p_dec
->fmt_in
.video
.i_width
|| !p_dec
->fmt_in
.video
.i_height
)
573 switch (p_dec
->fmt_in
.i_codec
) {
577 uint8_t i_hevc_profile
;
578 if (hevc_get_profile_level(&p_dec
->fmt_in
, &i_hevc_profile
, NULL
, NULL
))
579 i_profile
= i_hevc_profile
;
586 uint8_t i_h264_profile
;
587 if (h264_get_profile_level(&p_dec
->fmt_in
, &i_h264_profile
, NULL
, NULL
))
588 i_profile
= i_h264_profile
;
592 case VLC_CODEC_H263
: mime
= "video/3gpp"; break;
593 case VLC_CODEC_MP4V
: mime
= "video/mp4v-es"; break;
596 mime
= "video/mpeg2";
598 case VLC_CODEC_WMV3
: mime
= "video/x-ms-wmv"; break;
599 case VLC_CODEC_VC1
: mime
= "video/wvc1"; break;
600 case VLC_CODEC_VP8
: mime
= "video/x-vnd.on2.vp8"; break;
601 case VLC_CODEC_VP9
: mime
= "video/x-vnd.on2.vp9"; break;
606 switch (p_dec
->fmt_in
.i_codec
) {
607 case VLC_CODEC_AMR_NB
: mime
= "audio/3gpp"; break;
608 case VLC_CODEC_AMR_WB
: mime
= "audio/amr-wb"; break;
610 case VLC_CODEC_MP3
: mime
= "audio/mpeg"; break;
611 case VLC_CODEC_MP2
: mime
= "audio/mpeg-L2"; break;
612 case VLC_CODEC_MP4A
: mime
= "audio/mp4a-latm"; break;
613 case VLC_CODEC_QCELP
: mime
= "audio/qcelp"; break;
614 case VLC_CODEC_VORBIS
: mime
= "audio/vorbis"; break;
615 case VLC_CODEC_OPUS
: mime
= "audio/opus"; break;
616 case VLC_CODEC_ALAW
: mime
= "audio/g711-alaw"; break;
617 case VLC_CODEC_MULAW
: mime
= "audio/g711-mlaw"; break;
618 case VLC_CODEC_FLAC
: mime
= "audio/flac"; break;
619 case VLC_CODEC_GSM
: mime
= "audio/gsm"; break;
620 case VLC_CODEC_A52
: mime
= "audio/ac3"; break;
621 case VLC_CODEC_EAC3
: mime
= "audio/eac3"; break;
622 case VLC_CODEC_ALAC
: mime
= "audio/alac"; break;
623 case VLC_CODEC_DTS
: mime
= "audio/vnd.dts"; break;
624 /* case VLC_CODEC_: mime = "audio/mpeg-L1"; break; */
625 /* case VLC_CODEC_: mime = "audio/aac-adts"; break; */
630 msg_Dbg(p_dec
, "codec %4.4s not supported",
631 (char *)&p_dec
->fmt_in
.i_codec
);
635 /* Allocate the memory needed to store the decoder's structure */
636 if ((p_sys
= calloc(1, sizeof(*p_sys
))) == NULL
)
639 p_sys
->api
.p_obj
= p_this
;
640 p_sys
->api
.i_codec
= p_dec
->fmt_in
.i_codec
;
641 p_sys
->api
.i_cat
= p_dec
->fmt_in
.i_cat
;
642 p_sys
->api
.psz_mime
= mime
;
643 p_sys
->video
.i_mpeg_dar_num
= 0;
644 p_sys
->video
.i_mpeg_dar_den
= 0;
646 if (pf_init(&p_sys
->api
) != 0)
651 if (p_sys
->api
.prepare(&p_sys
->api
, i_profile
) != 0)
653 /* If the device can't handle video/wvc1,
654 * it can probably handle video/x-ms-wmv */
655 if (!strcmp(mime
, "video/wvc1") && p_dec
->fmt_in
.i_codec
== VLC_CODEC_VC1
)
657 p_sys
->api
.psz_mime
= "video/x-ms-wmv";
658 if (p_sys
->api
.prepare(&p_sys
->api
, i_profile
) != 0)
660 p_sys
->api
.clean(&p_sys
->api
);
662 return (VLC_EGENERIC
);
667 p_sys
->api
.clean(&p_sys
->api
);
673 p_dec
->p_sys
= p_sys
;
675 vlc_mutex_init(&p_sys
->lock
);
676 vlc_cond_init(&p_sys
->cond
);
677 vlc_cond_init(&p_sys
->dec_cond
);
679 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
681 switch (p_dec
->fmt_in
.i_codec
)
685 hxxx_helper_init(&p_sys
->video
.hh
, VLC_OBJECT(p_dec
),
686 p_dec
->fmt_in
.i_codec
, false);
689 p_sys
->pf_on_new_block
= Video_OnNewBlock
;
690 p_sys
->pf_on_flush
= Video_OnFlush
;
691 p_sys
->pf_process_output
= Video_ProcessOutput
;
693 p_sys
->video
.timestamp_fifo
= timestamp_FifoNew(32);
694 if (!p_sys
->video
.timestamp_fifo
)
697 TAB_INIT(p_sys
->video
.i_inflight_pictures
,
698 p_sys
->video
.pp_inflight_pictures
);
700 if (var_InheritBool(p_dec
, CFG_PREFIX
"dr"))
702 /* Direct rendering: Request a valid OPAQUE Vout in order to get
703 * the surface attached to it */
704 p_dec
->fmt_out
.i_codec
= VLC_CODEC_ANDROID_OPAQUE
;
706 if (p_sys
->api
.b_support_rotation
)
708 switch (p_dec
->fmt_out
.video
.orientation
)
710 case ORIENT_ROTATED_90
:
711 p_sys
->video
.i_angle
= 90;
713 case ORIENT_ROTATED_180
:
714 p_sys
->video
.i_angle
= 180;
716 case ORIENT_ROTATED_270
:
717 p_sys
->video
.i_angle
= 270;
720 p_sys
->video
.i_angle
= 0;
725 p_sys
->video
.i_angle
= 0;
727 p_dec
->fmt_out
.video
= p_dec
->fmt_in
.video
;
728 if (p_dec
->fmt_out
.video
.i_sar_num
* p_dec
->fmt_out
.video
.i_sar_den
== 0)
730 p_dec
->fmt_out
.video
.i_sar_num
= 1;
731 p_dec
->fmt_out
.video
.i_sar_den
= 1;
734 p_sys
->video
.i_input_width
=
735 p_dec
->fmt_out
.video
.i_visible_width
= p_dec
->fmt_out
.video
.i_width
;
736 p_sys
->video
.i_input_height
=
737 p_dec
->fmt_out
.video
.i_visible_height
= p_dec
->fmt_out
.video
.i_height
;
739 if (UpdateVout(p_dec
) != VLC_SUCCESS
)
741 msg_Err(p_dec
, "Opaque Vout request failed");
748 p_sys
->pf_on_new_block
= Audio_OnNewBlock
;
749 p_sys
->pf_on_flush
= Audio_OnFlush
;
750 p_sys
->pf_process_output
= Audio_ProcessOutput
;
751 p_sys
->audio
.i_channels
= p_dec
->fmt_in
.audio
.i_channels
;
753 if ((p_sys
->api
.i_quirks
& MC_API_AUDIO_QUIRKS_NEED_CHANNELS
)
754 && !p_sys
->audio
.i_channels
)
756 msg_Warn(p_dec
, "codec need a valid channel count");
760 p_dec
->fmt_out
.audio
= p_dec
->fmt_in
.audio
;
763 /* Try first to configure CSD */
764 if (ParseExtra(p_dec
) != VLC_SUCCESS
)
767 if ((p_sys
->api
.i_quirks
& MC_API_QUIRKS_NEED_CSD
) && !p_sys
->i_csd_count
768 && !p_sys
->b_adaptive
)
770 switch (p_dec
->fmt_in
.i_codec
)
774 break; /* CSDs will come from hxxx_helper */
776 msg_Warn(p_dec
, "Not CSD found for %4.4s",
777 (const char *) &p_dec
->fmt_in
.i_codec
);
782 i_ret
= StartMediaCodec(p_dec
);
783 if (i_ret
!= VLC_SUCCESS
)
785 msg_Err(p_dec
, "StartMediaCodec failed");
789 if (vlc_clone(&p_sys
->out_thread
, OutThread
, p_dec
,
790 VLC_THREAD_PRIORITY_LOW
))
792 msg_Err(p_dec
, "vlc_clone failed");
793 vlc_mutex_unlock(&p_sys
->lock
);
797 p_dec
->pf_decode
= DecodeBlock
;
798 p_dec
->pf_flush
= DecodeFlush
;
807 static int OpenDecoderNdk(vlc_object_t
*p_this
)
809 return OpenDecoder(p_this
, MediaCodecNdk_Init
);
812 static int OpenDecoderJni(vlc_object_t
*p_this
)
814 return OpenDecoder(p_this
, MediaCodecJni_Init
);
817 static void AbortDecoderLocked(decoder_t
*p_dec
)
819 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
821 if (!p_sys
->b_aborted
)
823 p_sys
->b_aborted
= true;
824 vlc_cancel(p_sys
->out_thread
);
828 static void CleanDecoder(decoder_t
*p_dec
)
830 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
832 vlc_mutex_destroy(&p_sys
->lock
);
833 vlc_cond_destroy(&p_sys
->cond
);
834 vlc_cond_destroy(&p_sys
->dec_cond
);
836 StopMediaCodec(p_dec
);
839 p_sys
->api
.clean(&p_sys
->api
);
841 if (p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
843 if (p_dec
->fmt_in
.i_codec
== VLC_CODEC_H264
844 || p_dec
->fmt_in
.i_codec
== VLC_CODEC_HEVC
)
845 hxxx_helper_clean(&p_sys
->video
.hh
);
847 if (p_sys
->video
.timestamp_fifo
)
848 timestamp_FifoRelease(p_sys
->video
.timestamp_fifo
);
853 /*****************************************************************************
854 * CloseDecoder: Close the decoder instance
855 *****************************************************************************/
856 static void CloseDecoder(vlc_object_t
*p_this
)
858 decoder_t
*p_dec
= (decoder_t
*)p_this
;
859 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
861 vlc_mutex_lock(&p_sys
->lock
);
862 /* Unblock output thread waiting in dequeue_out */
863 DecodeFlushLocked(p_dec
);
864 /* Cancel the output thread */
865 AbortDecoderLocked(p_dec
);
866 vlc_mutex_unlock(&p_sys
->lock
);
868 vlc_join(p_sys
->out_thread
, NULL
);
873 /*****************************************************************************
875 *****************************************************************************/
876 static void ReleasePicture(decoder_t
*p_dec
, unsigned i_index
, bool b_render
)
878 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
880 p_sys
->api
.release_out(&p_sys
->api
, i_index
, b_render
);
883 static void ReleasePictureTs(decoder_t
*p_dec
, unsigned i_index
, vlc_tick_t i_ts
)
885 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
886 assert(p_sys
->api
.release_out_ts
);
888 p_sys
->api
.release_out_ts(&p_sys
->api
, i_index
, i_ts
* INT64_C(1000));
891 static void InvalidateAllPictures(decoder_t
*p_dec
)
893 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
895 for (unsigned int i
= 0; i
< p_sys
->video
.i_inflight_pictures
; ++i
)
896 AndroidOpaquePicture_Release(p_sys
->video
.pp_inflight_pictures
[i
],
900 static int InsertInflightPicture(decoder_t
*p_dec
, picture_sys_t
*p_picsys
)
902 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
904 if (!p_picsys
->hw
.p_dec
)
906 p_picsys
->hw
.p_dec
= p_dec
;
907 p_picsys
->hw
.pf_release
= ReleasePicture
;
908 if (p_sys
->api
.release_out_ts
)
909 p_picsys
->hw
.pf_release_ts
= ReleasePictureTs
;
910 TAB_APPEND_CAST((picture_sys_t
**),
911 p_sys
->video
.i_inflight_pictures
,
912 p_sys
->video
.pp_inflight_pictures
,
914 } /* else already attached */
918 static void RemoveInflightPictures(decoder_t
*p_dec
)
920 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
922 for (unsigned int i
= 0; i
< p_sys
->video
.i_inflight_pictures
; ++i
)
923 AndroidOpaquePicture_DetachDecoder(p_sys
->video
.pp_inflight_pictures
[i
]);
924 TAB_CLEAN(p_sys
->video
.i_inflight_pictures
,
925 p_sys
->video
.pp_inflight_pictures
);
928 static int Video_ProcessOutput(decoder_t
*p_dec
, mc_api_out
*p_out
,
929 picture_t
**pp_out_pic
, block_t
**pp_out_block
)
931 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
935 if (p_out
->type
== MC_OUT_TYPE_BUF
)
937 picture_t
*p_pic
= NULL
;
939 /* If the oldest input block had no PTS, the timestamp of
940 * the frame returned by MediaCodec might be wrong so we
941 * overwrite it with the corresponding dts. Call FifoGet
942 * first in order to avoid a gap if buffers are released
943 * due to an invalid format or a preroll */
944 int64_t forced_ts
= timestamp_FifoGet(p_sys
->video
.timestamp_fifo
);
946 if (!p_sys
->b_has_format
) {
947 msg_Warn(p_dec
, "Buffers returned before output format is set, dropping frame");
948 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
951 if (p_out
->buf
.i_ts
<= p_sys
->i_preroll_end
)
952 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
954 if (!p_sys
->api
.b_direct_rendering
&& p_out
->buf
.p_ptr
== NULL
)
956 /* This can happen when receiving an EOS buffer */
957 msg_Warn(p_dec
, "Invalid buffer, dropping frame");
958 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
961 p_pic
= decoder_NewPicture(p_dec
);
963 msg_Warn(p_dec
, "NewPicture failed");
964 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
967 if (forced_ts
== VLC_TICK_INVALID
)
968 p_pic
->date
= p_out
->buf
.i_ts
;
970 p_pic
->date
= forced_ts
;
971 p_pic
->b_progressive
= true;
973 if (p_sys
->api
.b_direct_rendering
)
975 picture_sys_t
*p_picsys
= p_pic
->p_sys
;
976 p_picsys
->hw
.i_index
= p_out
->buf
.i_index
;
977 InsertInflightPicture(p_dec
, p_pic
->p_sys
);
979 unsigned int chroma_div
;
980 GetVlcChromaSizes(p_dec
->fmt_out
.i_codec
,
981 p_dec
->fmt_out
.video
.i_width
,
982 p_dec
->fmt_out
.video
.i_height
,
983 NULL
, NULL
, &chroma_div
);
984 CopyOmxPicture(p_sys
->video
.i_pixel_format
, p_pic
,
985 p_sys
->video
.i_slice_height
, p_sys
->video
.i_stride
,
986 (uint8_t *)p_out
->buf
.p_ptr
, chroma_div
, NULL
);
988 if (p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false))
990 picture_Release(p_pic
);
994 assert(!(*pp_out_pic
));
998 assert(p_out
->type
== MC_OUT_TYPE_CONF
);
999 p_sys
->video
.i_pixel_format
= p_out
->conf
.video
.pixel_format
;
1001 const char *name
= "unknown";
1002 if (!p_sys
->api
.b_direct_rendering
1003 && !GetVlcChromaFormat(p_sys
->video
.i_pixel_format
,
1004 &p_dec
->fmt_out
.i_codec
, &name
))
1006 msg_Err(p_dec
, "color-format not recognized");
1010 msg_Err(p_dec
, "output: %d %s, %dx%d stride %d %d, crop %d %d %d %d",
1011 p_sys
->video
.i_pixel_format
, name
,
1012 p_out
->conf
.video
.width
, p_out
->conf
.video
.height
,
1013 p_out
->conf
.video
.stride
, p_out
->conf
.video
.slice_height
,
1014 p_out
->conf
.video
.crop_left
, p_out
->conf
.video
.crop_top
,
1015 p_out
->conf
.video
.crop_right
, p_out
->conf
.video
.crop_bottom
);
1017 int i_width
= p_out
->conf
.video
.crop_right
+ 1
1018 - p_out
->conf
.video
.crop_left
;
1019 int i_height
= p_out
->conf
.video
.crop_bottom
+ 1
1020 - p_out
->conf
.video
.crop_top
;
1021 if (i_width
<= 1 || i_height
<= 1)
1023 i_width
= p_out
->conf
.video
.width
;
1024 i_height
= p_out
->conf
.video
.height
;
1027 p_dec
->fmt_out
.video
.i_visible_width
=
1028 p_dec
->fmt_out
.video
.i_width
= i_width
;
1029 p_dec
->fmt_out
.video
.i_visible_height
=
1030 p_dec
->fmt_out
.video
.i_height
= i_height
;
1032 p_sys
->video
.i_stride
= p_out
->conf
.video
.stride
;
1033 p_sys
->video
.i_slice_height
= p_out
->conf
.video
.slice_height
;
1034 if (p_sys
->video
.i_stride
<= 0)
1035 p_sys
->video
.i_stride
= p_out
->conf
.video
.width
;
1036 if (p_sys
->video
.i_slice_height
<= 0)
1037 p_sys
->video
.i_slice_height
= p_out
->conf
.video
.height
;
1039 if (p_sys
->video
.i_pixel_format
== OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
)
1040 p_sys
->video
.i_slice_height
-= p_out
->conf
.video
.crop_top
/2;
1041 if ((p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_IGNORE_PADDING
))
1043 p_sys
->video
.i_slice_height
= 0;
1044 p_sys
->video
.i_stride
= p_dec
->fmt_out
.video
.i_width
;
1047 if (UpdateVout(p_dec
) != VLC_SUCCESS
)
1049 msg_Err(p_dec
, "UpdateVout failed");
1053 p_sys
->b_has_format
= true;
1058 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
1059 static uint32_t pi_audio_order_src
[] =
1061 AOUT_CHAN_LEFT
, AOUT_CHAN_RIGHT
, AOUT_CHAN_CENTER
, AOUT_CHAN_LFE
,
1062 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
, AOUT_CHAN_REARCENTER
,
1063 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
,
1066 static int Audio_ProcessOutput(decoder_t
*p_dec
, mc_api_out
*p_out
,
1067 picture_t
**pp_out_pic
, block_t
**pp_out_block
)
1069 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1071 assert(pp_out_block
);
1073 if (p_out
->type
== MC_OUT_TYPE_BUF
)
1075 block_t
*p_block
= NULL
;
1076 if (p_out
->buf
.p_ptr
== NULL
)
1078 /* This can happen when receiving an EOS buffer */
1079 msg_Warn(p_dec
, "Invalid buffer, dropping frame");
1080 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1083 if (!p_sys
->b_has_format
) {
1084 msg_Warn(p_dec
, "Buffers returned before output format is set, dropping frame");
1085 return p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false);
1088 p_block
= block_Alloc(p_out
->buf
.i_size
);
1091 p_block
->i_nb_samples
= p_out
->buf
.i_size
1092 / p_dec
->fmt_out
.audio
.i_bytes_per_frame
;
1094 if (p_sys
->audio
.b_extract
)
1096 aout_ChannelExtract(p_block
->p_buffer
,
1097 p_dec
->fmt_out
.audio
.i_channels
,
1098 p_out
->buf
.p_ptr
, p_sys
->audio
.i_channels
,
1099 p_block
->i_nb_samples
, p_sys
->audio
.pi_extraction
,
1100 p_dec
->fmt_out
.audio
.i_bitspersample
);
1103 memcpy(p_block
->p_buffer
, p_out
->buf
.p_ptr
, p_out
->buf
.i_size
);
1105 if (p_out
->buf
.i_ts
!= 0
1106 && p_out
->buf
.i_ts
!= date_Get(&p_sys
->audio
.i_end_date
))
1107 date_Set(&p_sys
->audio
.i_end_date
, p_out
->buf
.i_ts
);
1109 p_block
->i_pts
= date_Get(&p_sys
->audio
.i_end_date
);
1110 p_block
->i_length
= date_Increment(&p_sys
->audio
.i_end_date
,
1111 p_block
->i_nb_samples
)
1114 if (p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false))
1116 block_Release(p_block
);
1119 *pp_out_block
= p_block
;
1122 uint32_t i_layout_dst
;
1125 assert(p_out
->type
== MC_OUT_TYPE_CONF
);
1127 if (p_out
->conf
.audio
.channel_count
<= 0
1128 || p_out
->conf
.audio
.channel_count
> 8
1129 || p_out
->conf
.audio
.sample_rate
<= 0)
1131 msg_Warn(p_dec
, "invalid audio properties channels count %d, sample rate %d",
1132 p_out
->conf
.audio
.channel_count
,
1133 p_out
->conf
.audio
.sample_rate
);
1137 msg_Err(p_dec
, "output: channel_count: %d, channel_mask: 0x%X, rate: %d",
1138 p_out
->conf
.audio
.channel_count
, p_out
->conf
.audio
.channel_mask
,
1139 p_out
->conf
.audio
.sample_rate
);
1141 p_dec
->fmt_out
.i_codec
= VLC_CODEC_S16N
;
1142 p_dec
->fmt_out
.audio
.i_format
= p_dec
->fmt_out
.i_codec
;
1144 p_dec
->fmt_out
.audio
.i_rate
= p_out
->conf
.audio
.sample_rate
;
1145 date_Init(&p_sys
->audio
.i_end_date
, p_out
->conf
.audio
.sample_rate
, 1);
1147 p_sys
->audio
.i_channels
= p_out
->conf
.audio
.channel_count
;
1148 p_sys
->audio
.b_extract
=
1149 aout_CheckChannelExtraction(p_sys
->audio
.pi_extraction
,
1150 &i_layout_dst
, &i_channels_dst
,
1151 NULL
, pi_audio_order_src
,
1152 p_sys
->audio
.i_channels
);
1154 if (p_sys
->audio
.b_extract
)
1155 msg_Warn(p_dec
, "need channel extraction: %d -> %d",
1156 p_sys
->audio
.i_channels
, i_channels_dst
);
1158 p_dec
->fmt_out
.audio
.i_physical_channels
= i_layout_dst
;
1159 aout_FormatPrepare(&p_dec
->fmt_out
.audio
);
1161 if (decoder_UpdateAudioFormat(p_dec
))
1164 p_sys
->b_has_format
= true;
1169 static void DecodeFlushLocked(decoder_t
*p_dec
)
1171 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1172 bool b_had_input
= p_sys
->b_input_dequeued
;
1174 p_sys
->b_input_dequeued
= false;
1175 p_sys
->b_flush_out
= true;
1176 p_sys
->i_preroll_end
= 0;
1177 p_sys
->b_output_ready
= false;
1178 /* Resend CODEC_CONFIG buffer after a flush */
1179 p_sys
->i_csd_send
= 0;
1181 p_sys
->pf_on_flush(p_dec
);
1183 if (b_had_input
&& p_sys
->api
.flush(&p_sys
->api
) != VLC_SUCCESS
)
1185 AbortDecoderLocked(p_dec
);
1189 vlc_cond_broadcast(&p_sys
->cond
);
1191 while (!p_sys
->b_aborted
&& p_sys
->b_flush_out
)
1192 vlc_cond_wait(&p_sys
->dec_cond
, &p_sys
->lock
);
1195 static void DecodeFlush(decoder_t
*p_dec
)
1197 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1199 vlc_mutex_lock(&p_sys
->lock
);
1200 DecodeFlushLocked(p_dec
);
1201 vlc_mutex_unlock(&p_sys
->lock
);
1204 static void *OutThread(void *data
)
1206 decoder_t
*p_dec
= data
;
1207 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1209 vlc_mutex_lock(&p_sys
->lock
);
1210 mutex_cleanup_push(&p_sys
->lock
);
1215 /* Wait for output ready */
1216 while (!p_sys
->b_flush_out
&& !p_sys
->b_output_ready
)
1217 vlc_cond_wait(&p_sys
->cond
, &p_sys
->lock
);
1219 if (p_sys
->b_flush_out
)
1221 /* Acknowledge flushed state */
1222 p_sys
->b_flush_out
= false;
1223 vlc_cond_broadcast(&p_sys
->dec_cond
);
1227 int canc
= vlc_savecancel();
1229 vlc_mutex_unlock(&p_sys
->lock
);
1231 /* Wait for an output buffer. This function returns when a new output
1232 * is available or if output is flushed. */
1233 i_index
= p_sys
->api
.dequeue_out(&p_sys
->api
, -1);
1235 vlc_mutex_lock(&p_sys
->lock
);
1237 /* Ignore dequeue_out errors caused by flush */
1238 if (p_sys
->b_flush_out
)
1240 /* If i_index >= 0, Release it. There is no way to know if i_index
1241 * is owned by us, so don't check the error. */
1243 p_sys
->api
.release_out(&p_sys
->api
, i_index
, false);
1245 /* Parse output format/buffers even when we are flushing */
1246 if (i_index
!= MC_API_INFO_OUTPUT_FORMAT_CHANGED
1247 && i_index
!= MC_API_INFO_OUTPUT_BUFFERS_CHANGED
)
1249 vlc_restorecancel(canc
);
1254 /* Process output returned by dequeue_out */
1255 if (i_index
>= 0 || i_index
== MC_API_INFO_OUTPUT_FORMAT_CHANGED
1256 || i_index
== MC_API_INFO_OUTPUT_BUFFERS_CHANGED
)
1258 struct mc_api_out out
;
1259 int i_ret
= p_sys
->api
.get_out(&p_sys
->api
, i_index
, &out
);
1263 picture_t
*p_pic
= NULL
;
1264 block_t
*p_block
= NULL
;
1266 if (p_sys
->pf_process_output(p_dec
, &out
, &p_pic
,
1267 &p_block
) == -1 && !out
.b_eos
)
1269 msg_Err(p_dec
, "pf_process_output failed");
1270 vlc_restorecancel(canc
);
1274 decoder_QueueVideo(p_dec
, p_pic
);
1276 decoder_QueueAudio(p_dec
, p_block
);
1280 msg_Warn(p_dec
, "EOS received");
1281 p_sys
->b_drained
= true;
1282 vlc_cond_signal(&p_sys
->dec_cond
);
1284 } else if (i_ret
!= 0)
1286 msg_Err(p_dec
, "get_out failed");
1287 vlc_restorecancel(canc
);
1293 vlc_restorecancel(canc
);
1296 vlc_restorecancel(canc
);
1298 msg_Warn(p_dec
, "OutThread stopped");
1300 /* Signal DecoderFlush that the output thread aborted */
1301 p_sys
->b_aborted
= true;
1302 vlc_cond_signal(&p_sys
->dec_cond
);
1305 vlc_mutex_unlock(&p_sys
->lock
);
1310 static block_t
*GetNextBlock(decoder_sys_t
*p_sys
, block_t
*p_block
)
1312 if (p_sys
->i_csd_send
< p_sys
->i_csd_count
)
1313 return p_sys
->pp_csd
[p_sys
->i_csd_send
++];
1318 static int QueueBlockLocked(decoder_t
*p_dec
, block_t
*p_in_block
,
1321 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1322 block_t
*p_block
= NULL
;
1323 bool b_dequeue_timeout
= false;
1325 assert(p_sys
->api
.b_started
);
1327 if ((p_sys
->api
.i_quirks
& MC_API_QUIRKS_NEED_CSD
) && !p_sys
->i_csd_count
1328 && !p_sys
->b_adaptive
)
1329 return VLC_EGENERIC
; /* Wait for CSDs */
1331 /* Queue CSD blocks and input blocks */
1332 while (b_drain
|| (p_block
= GetNextBlock(p_sys
, p_in_block
)))
1336 vlc_mutex_unlock(&p_sys
->lock
);
1337 /* Wait for an input buffer. This function returns when a new input
1338 * buffer is available or after 2secs of timeout. */
1339 i_index
= p_sys
->api
.dequeue_in(&p_sys
->api
,
1340 p_sys
->api
.b_direct_rendering
?
1341 INT64_C(2000000) : -1);
1342 vlc_mutex_lock(&p_sys
->lock
);
1344 if (p_sys
->b_aborted
)
1345 return VLC_EGENERIC
;
1347 bool b_config
= false;
1348 vlc_tick_t i_ts
= 0;
1349 p_sys
->b_input_dequeued
= true;
1350 const void *p_buf
= NULL
;
1355 assert(b_drain
|| p_block
!= NULL
);
1356 if (p_block
!= NULL
)
1358 b_config
= (p_block
->i_flags
& BLOCK_FLAG_CSD
);
1361 i_ts
= p_block
->i_pts
;
1362 if (!i_ts
&& p_block
->i_dts
)
1363 i_ts
= p_block
->i_dts
;
1365 p_buf
= p_block
->p_buffer
;
1366 i_size
= p_block
->i_buffer
;
1369 if (p_sys
->api
.queue_in(&p_sys
->api
, i_index
, p_buf
, i_size
,
1370 i_ts
, b_config
) == 0)
1372 if (!b_config
&& p_block
!= NULL
)
1374 if (p_block
->i_flags
& BLOCK_FLAG_PREROLL
)
1375 p_sys
->i_preroll_end
= i_ts
;
1377 /* One input buffer is queued, signal OutThread that will
1378 * fetch output buffers */
1379 p_sys
->b_output_ready
= true;
1380 vlc_cond_broadcast(&p_sys
->cond
);
1382 assert(p_block
== p_in_block
),
1385 b_dequeue_timeout
= false;
1390 msg_Err(p_dec
, "queue_in failed");
1394 else if (i_index
== MC_API_INFO_TRYAGAIN
)
1396 /* HACK: When direct rendering is enabled, there is a possible
1397 * deadlock between the Decoder and the Vout. It happens when the
1398 * Vout is paused and when the Decoder is flushing. In that case,
1399 * the Vout won't release any output buffers, therefore MediaCodec
1400 * won't dequeue any input buffers. To work around this issue,
1401 * release all output buffers if DecodeBlock is waiting more than
1402 * 2secs for a new input buffer. */
1403 if (!b_dequeue_timeout
)
1405 msg_Warn(p_dec
, "Decoder stuck: invalidate all buffers");
1406 InvalidateAllPictures(p_dec
);
1407 b_dequeue_timeout
= true;
1412 msg_Err(p_dec
, "dequeue_in timeout: no input available for 2secs");
1418 msg_Err(p_dec
, "dequeue_in failed");
1425 msg_Warn(p_dec
, "EOS sent, waiting for OutThread");
1427 /* Wait for the OutThread to stop (and process all remaining output
1428 * frames. Use a timeout here since we can't know if all decoders will
1429 * behave correctly. */
1430 vlc_tick_t deadline
= vlc_tick_now() + INT64_C(3000000);
1431 while (!p_sys
->b_aborted
&& !p_sys
->b_drained
1432 && vlc_cond_timedwait(&p_sys
->dec_cond
, &p_sys
->lock
, deadline
) == 0);
1434 if (!p_sys
->b_drained
)
1436 msg_Err(p_dec
, "OutThread timed out");
1437 AbortDecoderLocked(p_dec
);
1439 p_sys
->b_drained
= false;
1445 AbortDecoderLocked(p_dec
);
1446 return VLC_EGENERIC
;
1449 static int DecodeBlock(decoder_t
*p_dec
, block_t
*p_in_block
)
1451 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1454 vlc_mutex_lock(&p_sys
->lock
);
1456 if (p_sys
->b_aborted
)
1458 if (p_sys
->b_has_format
)
1464 if (p_in_block
== NULL
)
1466 /* No input block, decoder is draining */
1467 msg_Err(p_dec
, "Decoder is draining");
1469 if (p_sys
->b_output_ready
)
1470 QueueBlockLocked(p_dec
, NULL
, true);
1474 if (p_in_block
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
))
1476 if (p_sys
->b_output_ready
)
1477 QueueBlockLocked(p_dec
, NULL
, true);
1478 DecodeFlushLocked(p_dec
);
1479 if (p_sys
->b_aborted
)
1481 if (p_in_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
1485 if (p_in_block
->i_flags
& BLOCK_FLAG_INTERLACED_MASK
1486 && !(p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_SUPPORT_INTERLACED
))
1488 /* Before Android 21 and depending on the vendor, MediaCodec can
1489 * crash or be in an inconsistent state when decoding interlaced
1490 * videos. See OMXCodec_GetQuirks() for a white list of decoders
1491 * that supported interlaced videos before Android 21. */
1492 msg_Warn(p_dec
, "codec doesn't support interlaced videos");
1496 /* Parse input block */
1497 if ((i_ret
= p_sys
->pf_on_new_block(p_dec
, &p_in_block
)) != 1)
1501 AbortDecoderLocked(p_dec
);
1502 msg_Err(p_dec
, "pf_on_new_block failed");
1506 if (p_sys
->i_decode_flags
& (DECODE_FLAG_DRAIN
|DECODE_FLAG_RESTART
))
1508 msg_Warn(p_dec
, "Draining from DecodeBlock");
1509 const bool b_restart
= p_sys
->i_decode_flags
& DECODE_FLAG_RESTART
;
1510 p_sys
->i_decode_flags
= 0;
1512 /* Drain and flush before restart to unblock OutThread */
1513 if (p_sys
->b_output_ready
)
1514 QueueBlockLocked(p_dec
, NULL
, true);
1515 DecodeFlushLocked(p_dec
);
1516 if (p_sys
->b_aborted
)
1521 StopMediaCodec(p_dec
);
1523 int i_ret
= StartMediaCodec(p_dec
);
1527 msg_Warn(p_dec
, "Restarted from DecodeBlock");
1532 msg_Err(p_dec
, "StartMediaCodec failed");
1533 AbortDecoderLocked(p_dec
);
1539 /* Abort if MediaCodec is not yet started */
1540 if (p_sys
->api
.b_started
)
1541 QueueBlockLocked(p_dec
, p_in_block
, false);
1545 block_Release(p_in_block
);
1546 /* Too late to reload here, we already modified/released the input block,
1547 * do it next time. */
1548 int ret
= p_sys
->b_aborted
&& p_sys
->b_has_format
? VLCDEC_ECRITICAL
1550 vlc_mutex_unlock(&p_sys
->lock
);
1554 vlc_mutex_unlock(&p_sys
->lock
);
1555 /* Add an empty variable so that mediacodec won't be loaded again
1557 var_Create(p_dec
, "mediacodec-failed", VLC_VAR_VOID
);
1558 return VLCDEC_RELOAD
;
1561 static int Video_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1563 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1564 block_t
*p_block
= *pp_block
;
1566 timestamp_FifoPut(p_sys
->video
.timestamp_fifo
,
1567 p_block
->i_pts
? VLC_TICK_INVALID
: p_block
->i_dts
);
1572 static int VideoHXXX_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1574 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1575 struct hxxx_helper
*hh
= &p_sys
->video
.hh
;
1576 bool b_config_changed
= false;
1577 bool *p_config_changed
= p_sys
->b_adaptive
? NULL
: &b_config_changed
;
1579 *pp_block
= hh
->pf_process_block(hh
, *pp_block
, p_config_changed
);
1582 if (b_config_changed
)
1584 bool b_size_changed
;
1586 switch (p_dec
->fmt_in
.i_codec
)
1588 case VLC_CODEC_H264
:
1589 if (hh
->h264
.i_sps_count
> 0 || hh
->h264
.i_pps_count
> 0)
1590 i_ret
= H264SetCSD(p_dec
, &b_size_changed
);
1592 i_ret
= VLC_EGENERIC
;
1594 case VLC_CODEC_HEVC
:
1595 if (hh
->hevc
.i_vps_count
> 0 || hh
->hevc
.i_sps_count
> 0 ||
1596 hh
->hevc
.i_pps_count
> 0 )
1597 i_ret
= HEVCSetCSD(p_dec
, &b_size_changed
);
1599 i_ret
= VLC_EGENERIC
;
1602 if (i_ret
!= VLC_SUCCESS
)
1604 if (b_size_changed
|| !p_sys
->api
.b_started
)
1606 if (p_sys
->api
.b_started
)
1607 msg_Err(p_dec
, "SPS/PPS changed during playback and "
1608 "video size are different. Restart it !");
1609 p_sys
->i_decode_flags
|= DECODE_FLAG_RESTART
;
1612 msg_Err(p_dec
, "SPS/PPS changed during playback. Drain it");
1613 p_sys
->i_decode_flags
|= DECODE_FLAG_DRAIN
;
1617 return Video_OnNewBlock(p_dec
, pp_block
);
1620 static int VideoMPEG2_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1622 if (pp_block
== NULL
|| (*pp_block
)->i_buffer
<= 7)
1625 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1626 const int startcode
= (*pp_block
)->p_buffer
[3];
1628 /* DAR aspect ratio from the DVD MPEG2 standard */
1629 static const int mpeg2_aspect
[16][2] =
1631 {0,0}, /* reserved */
1632 {0,0}, /* DAR = 0:0 will result in SAR = 1:1 */
1633 {4,3}, {16,9}, {221,100},
1635 {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
1639 if (startcode
== 0xB3 /* SEQUENCE_HEADER_STARTCODE */)
1641 int mpeg_dar_code
= (*pp_block
)->p_buffer
[7] >> 4;
1643 if (mpeg_dar_code
>= 16)
1646 p_sys
->video
.i_mpeg_dar_num
= mpeg2_aspect
[mpeg_dar_code
][0];
1647 p_sys
->video
.i_mpeg_dar_den
= mpeg2_aspect
[mpeg_dar_code
][1];
1653 static int VideoVC1_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1655 block_t
*p_block
= *pp_block
;
1657 /* Adding frame start code */
1658 p_block
= *pp_block
= block_Realloc(p_block
, 4, p_block
->i_buffer
);
1659 if (p_block
== NULL
)
1661 p_block
->p_buffer
[0] = 0x00;
1662 p_block
->p_buffer
[1] = 0x00;
1663 p_block
->p_buffer
[2] = 0x01;
1664 p_block
->p_buffer
[3] = 0x0d;
1666 return Video_OnNewBlock(p_dec
, pp_block
);
1669 static void Video_OnFlush(decoder_t
*p_dec
)
1671 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1673 timestamp_FifoEmpty(p_sys
->video
.timestamp_fifo
);
1674 /* Invalidate all pictures that are currently in flight
1675 * since flushing make all previous indices returned by
1676 * MediaCodec invalid. */
1677 if (p_sys
->api
.b_direct_rendering
)
1678 InvalidateAllPictures(p_dec
);
1681 static int Audio_OnNewBlock(decoder_t
*p_dec
, block_t
**pp_block
)
1683 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1684 block_t
*p_block
= *pp_block
;
1686 /* We've just started the stream, wait for the first PTS. */
1687 if (date_Get(&p_sys
->audio
.i_end_date
) == VLC_TICK_INVALID
)
1689 if (p_block
->i_pts
== VLC_TICK_INVALID
)
1691 date_Set(&p_sys
->audio
.i_end_date
, p_block
->i_pts
);
1697 static void Audio_OnFlush(decoder_t
*p_dec
)
1699 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1701 date_Set(&p_sys
->audio
.i_end_date
, VLC_TICK_INVALID
);