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_memory.h>
39 #include <vlc_timestamp_helper.h>
40 #include <vlc_threads.h>
43 #include "mediacodec.h"
44 #include "../codec/hxxx_helper.h"
46 #include <OMX_Component.h>
47 #include "omxil_utils.h"
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)
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
**);
61 * Callback called when decoder is flushing.
63 typedef void (*dec_on_flush_cb
)(decoder_t
*);
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
**,
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
];
85 int64_t i_preroll_end
;
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
;
94 vlc_thread_t out_thread
;
95 /* Cond used to signal the output thread */
97 /* Cond used to signal the decoder thread */
99 /* Set to true by pf_flush to signal the output thread to flush */
101 /* If true, the output thread will start to dequeue output pictures */
103 /* If true, the first input block was successfully dequeued */
104 bool b_input_dequeued
;
114 void *p_surface
, *p_jsurface
;
116 unsigned i_input_width
, i_input_height
;
117 unsigned int i_stride
, i_slice_height
;
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
;
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 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
**,
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
**,
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 /*****************************************************************************
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-"
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")
194 set_capability("audio decoder", 0)
195 set_callbacks(OpenDecoderNdk
, CloseDecoder
)
196 add_shortcut("mediacodec_ndk")
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")
203 set_capability("audio decoder", 0)
204 set_callbacks(OpenDecoderJni
, CloseDecoder
)
205 add_shortcut("mediacodec_jni")
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);
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
);
243 memcpy(p_block
->p_buffer
, p_buf
, i_buf
);
245 CSDInit(p_dec
, p_block
, 1);
249 static void HXXXInitSize(decoder_t
*p_dec
, bool *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
);
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
);
301 CSDInit(p_dec
, p_monolith
, 1);
304 HXXXInitSize(p_dec
, p_size_changed
);
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
)
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
);
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
)
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
);
349 static int ParseVideoExtraVc1(decoder_t
*p_dec
, uint8_t *p_extra
, int i_extra
)
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))
365 /* Could not find the sequence header start code */
366 if (offset
>= i_extra
- 4)
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 :
378 * 4 height bytes (little endian)
379 * 4 width bytes (little endian)
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
)
415 return ParseVideoExtraH264(p_dec
, p_extra
, i_extra
);
417 return ParseVideoExtraHEVC(p_dec
, p_extra
, i_extra
);
419 return ParseVideoExtraWmv3(p_dec
, p_extra
, i_extra
);
421 return ParseVideoExtraVc1(p_dec
, p_extra
, i_extra
);
423 if (!i_extra
&& p_sys
->api
.i_quirks
& MC_API_VIDEO_QUIRKS_ADAPTIVE
)
424 p_sys
->b_adaptive
= true;
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
);
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)
451 if (p_dec
->fmt_out
.i_codec
!= VLC_CODEC_ANDROID_OPAQUE
)
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
)
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
);
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
;
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
;
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")))
533 /* Fail if this module already failed to decode this ES */
534 if (var_Type(p_dec
, "mediacodec-failed") != 0)
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
542 if (!p_dec
->fmt_in
.video
.i_width
|| !p_dec
->fmt_in
.video
.i_height
)
545 switch (p_dec
->fmt_in
.i_codec
) {
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
;
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
;
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;
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;
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; */
604 msg_Dbg(p_dec
, "codec %4.4s not supported",
605 (char *)&p_dec
->fmt_in
.i_codec
);
609 /* Allocate the memory needed to store the decoder's structure */
610 if ((p_sys
= calloc(1, sizeof(*p_sys
))) == NULL
)
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)
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
);
634 return (VLC_EGENERIC
);
639 p_sys
->api
.clean(&p_sys
->api
);
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
)
657 hxxx_helper_init(&p_sys
->video
.hh
, VLC_OBJECT(p_dec
),
658 p_dec
->fmt_in
.i_codec
, false);
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
)
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;
685 case ORIENT_ROTATED_180
:
686 p_sys
->video
.i_angle
= 180;
688 case ORIENT_ROTATED_270
:
689 p_sys
->video
.i_angle
= 270;
692 p_sys
->video
.i_angle
= 0;
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");
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");
726 p_dec
->fmt_out
.audio
= p_dec
->fmt_in
.audio
;
729 /* Try first to configure CSD */
730 if (ParseExtra(p_dec
) != VLC_SUCCESS
)
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
)
740 break; /* CSDs will come from hxxx_helper */
742 msg_Warn(p_dec
, "Not CSD found for %4.4s",
743 (const char *) &p_dec
->fmt_in
.i_codec
);
748 i_ret
= StartMediaCodec(p_dec
);
749 if (i_ret
!= VLC_SUCCESS
)
751 msg_Err(p_dec
, "StartMediaCodec failed");
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
);
763 p_dec
->pf_decode
= DecodeBlock
;
764 p_dec
->pf_flush
= DecodeFlush
;
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
);
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
);
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
);
839 /*****************************************************************************
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
],
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
,
880 } /* else already attached */
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
;
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
);
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
;
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
);
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
);
959 assert(!(*pp_out_pic
));
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");
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");
1018 p_sys
->b_has_format
= true;
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
;
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
);
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
);
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
)
1079 if (p_sys
->api
.release_out(&p_sys
->api
, p_out
->buf
.i_index
, false))
1081 block_Release(p_block
);
1084 *pp_out_block
= p_block
;
1087 uint32_t i_layout_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
);
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
))
1129 p_sys
->b_has_format
= true;
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
);
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
);
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
);
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. */
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
);
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
);
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
);
1239 decoder_QueueVideo(p_dec
, p_pic
);
1241 decoder_QueueAudio(p_dec
, p_block
);
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
);
1258 vlc_restorecancel(canc
);
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
);
1270 vlc_mutex_unlock(&p_sys
->lock
);
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
++];
1283 static int QueueBlockLocked(decoder_t
*p_dec
, block_t
*p_in_block
,
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
)))
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;
1314 p_sys
->b_input_dequeued
= true;
1315 const void *p_buf
= NULL
;
1320 assert(b_drain
|| p_block
!= NULL
);
1321 if (p_block
!= NULL
)
1323 b_config
= (p_block
->i_flags
& BLOCK_FLAG_CSD
);
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
),
1350 b_dequeue_timeout
= false;
1355 msg_Err(p_dec
, "queue_in failed");
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;
1377 msg_Err(p_dec
, "dequeue_in timeout: no input available for 2secs");
1383 msg_Err(p_dec
, "dequeue_in failed");
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;
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
;
1419 vlc_mutex_lock(&p_sys
->lock
);
1421 if (p_sys
->b_aborted
)
1423 if (p_sys
->b_has_format
)
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);
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
)
1446 if (p_in_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
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");
1461 /* Parse input block */
1462 if ((i_ret
= p_sys
->pf_on_new_block(p_dec
, &p_in_block
)) != 1)
1466 AbortDecoderLocked(p_dec
);
1467 msg_Err(p_dec
, "pf_on_new_block failed");
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
)
1486 StopMediaCodec(p_dec
);
1488 int i_ret
= StartMediaCodec(p_dec
);
1492 msg_Warn(p_dec
, "Restarted from DecodeBlock");
1497 msg_Err(p_dec
, "StartMediaCodec failed");
1498 AbortDecoderLocked(p_dec
);
1504 /* Abort if MediaCodec is not yet started */
1505 if (p_sys
->api
.b_started
)
1506 QueueBlockLocked(p_dec
, p_in_block
, false);
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
1515 vlc_mutex_unlock(&p_sys
->lock
);
1519 vlc_mutex_unlock(&p_sys
->lock
);
1520 /* Add an empty variable so that mediacodec won't be loaded again
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
);
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
);
1547 if (b_config_changed
)
1549 bool b_size_changed
;
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
);
1557 i_ret
= VLC_EGENERIC
;
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
);
1564 i_ret
= VLC_EGENERIC
;
1567 if (i_ret
!= VLC_SUCCESS
)
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
;
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
)
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
)
1623 date_Set(&p_sys
->audio
.i_end_date
, p_block
->i_pts
);
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
);