From 855463c007719d8a9cddfa757a00ae5428b3dbde Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 11 Jan 2015 16:40:27 +0100 Subject: [PATCH] avcodec/h264: Keep a reference to the last picture for EC This and the next commit improve error concealment for green-block-artifacts-from-canon-100-hs.MOV Signed-off-by: Michael Niedermayer --- libavcodec/h264.c | 5 +++++ libavcodec/h264.h | 1 + libavcodec/h264_refs.c | 4 ++++ libavcodec/h264_slice.c | 8 +++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index f40449eb0a..b27e747d0b 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -1838,6 +1838,8 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data, * packets do not get used. */ h->data_partitioning = 0; + ff_h264_unref_picture(h, &h->last_pic_for_ec); + /* end of stream, output what is still in the buffers */ if (buf_size == 0) { out: @@ -1930,6 +1932,8 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data, assert(pict->buf[0] || !*got_frame); + ff_h264_unref_picture(h, &h->last_pic_for_ec); + return get_consumed_bytes(buf_index, buf_size); } @@ -1954,6 +1958,7 @@ static av_cold int h264_decode_end(AVCodecContext *avctx) ff_h264_free_context(h); ff_h264_unref_picture(h, &h->cur_pic); + ff_h264_unref_picture(h, &h->last_pic_for_ec); return 0; } diff --git a/libavcodec/h264.h b/libavcodec/h264.h index 74c1bbf79f..2d8e1375a2 100644 --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -352,6 +352,7 @@ typedef struct H264Context { H264Picture *DPB; H264Picture *cur_pic_ptr; H264Picture cur_pic; + H264Picture last_pic_for_ec; int pixel_shift; ///< 0 for 8-bit H264, 1 for high-bit-depth H264 int chroma_qp[2]; // QPc diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index 12da9210be..78c283c7a0 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -493,6 +493,10 @@ void ff_h264_remove_all_refs(H264Context *h) } assert(h->long_ref_count == 0); + ff_h264_unref_picture(h, &h->last_pic_for_ec); + if (h->short_ref_count) + ff_h264_ref_picture(h, &h->last_pic_for_ec, h->short_ref[0]); + for (i = 0; i < h->short_ref_count; i++) { unreference_pic(h, h->short_ref[i], 0); h->short_ref[i] = NULL; diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index e689044323..ae50b9a2fe 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -542,6 +542,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, memset(&h->mb_luma_dc, 0, sizeof(h->mb_luma_dc)); memset(&h->mb_padding, 0, sizeof(h->mb_padding)); memset(&h->cur_pic, 0, sizeof(h->cur_pic)); + memset(&h->last_pic_for_ec, 0, sizeof(h->last_pic_for_ec)); h->avctx = dst; h->DPB = NULL; @@ -1959,7 +1960,12 @@ int ff_h264_decode_slice_header(H264Context *h, H264Context *h0) (h->ref_list[j][i].reference & 3); } - if (h->ref_count[0]) ff_h264_set_erpic(&h->er.last_pic, &h->ref_list[0][0]); + if (h->ref_count[0]) { + ff_h264_set_erpic(&h->er.last_pic, &h->ref_list[0][0]); + } else if (h->last_pic_for_ec.f.buf[0]) { + ff_h264_set_erpic(&h->er.last_pic, &h->last_pic_for_ec); + } + if (h->ref_count[1]) ff_h264_set_erpic(&h->er.next_pic, &h->ref_list[1][0]); h->er.ref_count = h->ref_count[0];