[PATCH 02/18] avcodec/h264dec: do not await a field that was never decoded
Dom Cobley via ffmpeg-devel <[email protected]>
| Newsgroups | gmane.comp.video.ffmpeg.devel |
|---|---|
| Message-ID | <[email protected]> |
The frame num gap concealment awaits the previous short term reference before copying it into the dummy picture it just allocated, both fields of it when that picture is field coded. Nothing guarantees either field was ever decoded. A field pair whose second field never arrived reports only the field it has, and the end of decode_nal_units() reports one field of ::cur_pic_ptr and none at all of a picture that is not a reference. Corrupt input reaches both, and the wait is then for a field that no thread will ever produce -- often the awaiting thread's own, so it deadlocks against itself. A decoder that hangs on damaged input is worse than one that conceals it badly. ::reference collects the field bits as ff_h264_execute_ref_pic_marking() marks each field, so requiring a whole frame there admits exactly the pictures whose every field has been decoded and reported. Anything else falls through to the colour fill below, which is what the concealment does already when there is no previous picture to copy from. Found by fuzzing 00004.MTS with the noise bitstream filter under frame threading; it reproduces on an unmodified tree, without any multiview involvement, and roughly five times more often once a view is selected with -map 0:v:0:view:1. Signed-off-by: Dom Cobley <[email protected]> --- libavcodec/h264_slice.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index a042616f7b..c96d99d242 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1551,7 +1551,15 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, -1 }; - if (prev && + /* Only conceal from a picture that is certain to be reported. + * ::reference collects the field bits as each field is marked, so + * anything short of a whole frame is either a field pair whose + * second field never arrived or a picture that is no reference at + * all -- and the end of decode_nal_units() reports neither. Corrupt + * input reaches both, and awaiting one waits for a field that will + * never be decoded. Fall through to the colour fill instead. + * Masked, as ::reference also carries DELAYED_PIC_REF. */ + if (prev && (prev->reference & PICT_FRAME) == PICT_FRAME && h->short_ref[0]->f->width == prev->f->width && h->short_ref[0]->f->height == prev->f->height && h->short_ref[0]->f->format == prev->f->format) { -- 2.53.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]