Add "-skip_frame invalid" option to allow user to request decoder to skip invalid nalus before an IRAP.
This would benefit decoding pipeline of bitstreams who didn't start from an IRAP frame. NULL pointer pointing to missing reference may lead to unexpected hang issues[1] in sub-level like hardware decoding. Fixing the hang in driver is the first correct thing. Besides, adding a check in nalu parsing and skip frames until we got the first IRAP would be another good choice to be more robust for error tolerance. Also this needs worker thread to update the skip_frames field in time. [1] https://github.com/intel/media-driver/issues/992 Signed-off-by: Linjie Fu <linjie.justin...@gmail.com> --- Request for comments: The purpose is to allow decoder to skip frames until an IRAP has arrived, however not sure whether we already had this in ffmpeg, hence submit a patch and request for comments. Skip logic identical for AVDISCARD_NONKEY in decode_nal_unit(). libavcodec/avcodec.h | 1 + libavcodec/hevcdec.c | 5 ++++- libavcodec/options_table.h | 1 + libavcodec/pthread_frame.c | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c91b2fd169..376d7f4d6d 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -233,6 +233,7 @@ enum AVDiscard{ AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames AVDISCARD_NONINTRA= 24, ///< discard all non intra frames AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_INVALID = 33, ///< discard invalid packets like NALs before IRAP AVDISCARD_ALL = 48, ///< discard all }; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index b77df8d89f..78658fd537 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -539,8 +539,11 @@ static int hls_slice_header(HEVCContext *s) ff_hevc_clear_refs(s); } sh->no_output_of_prior_pics_flag = 0; - if (IS_IRAP(s)) + if (IS_IRAP(s)) { sh->no_output_of_prior_pics_flag = get_bits1(gb); + if (s->avctx->skip_frame == AVDISCARD_INVALID) + s->avctx->skip_frame = AVDISCARD_DEFAULT; + } sh->pps_id = get_ue_golomb_long(gb); if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) { diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 1d0db1b5a4..d52bce5908 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -310,6 +310,7 @@ static const AVOption avcodec_options[] = { {"bidir" , "discard all bidirectional frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"nokey" , "discard all frames except keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"nointra" , "discard all frames except I frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONINTRA}, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"invalid" , "discard NALUs before IRAP", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_INVALID }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"all" , "discard all frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, V|D, "avdiscard"}, {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E}, #if FF_API_PRIVATE_OPT diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 3255aa9337..302e6149ac 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -259,6 +259,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->has_b_frames = src->has_b_frames; dst->idct_algo = src->idct_algo; + dst->skip_frame = src->skip_frame; dst->bits_per_coded_sample = src->bits_per_coded_sample; dst->sample_aspect_ratio = src->sample_aspect_ratio; -- 2.28.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".