[PATCH 10/18] avcodec/h264_slice: do not reclaim the picture awaiting output

Dom Cobley via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <[email protected]>
h264_select_output_frame() clears DELAYED_PIC_REF on the picture it selects, so
from then until the caller hands it over at the end of the packet a non-reference
picture has reference == 0 and nothing stops release_unused_pictures() from
reclaiming it. No further picture starts in that window today, but one does as
soon as a second picture of the same access unit starts, as an MVC dependent
view does, so guard against it.

The pointer must then be cleared once the picture has been handed over. It is
otherwise still set when release_unused_pictures() runs at the top of the next
frame_start(), and the guard keeps a picture that was already output occupying
its DPB slot for another access unit. That is observable: it changes which
buffer the next allocation reuses, and so changes the concealed output of a
stream damaged enough to be relying on it.

Signed-off-by: Dom Cobley <[email protected]>
---
 libavcodec/h264_slice.c | 1 +
 libavcodec/h264dec.c    | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 33cb20f922..d1838f814b 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -122,6 +122,7 @@ static void release_unused_pictures(H264Context *h, int remove_current)
     /* release non reference frames */
     for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
         if (h->DPB[i].f->buf[0] && !h->DPB[i].reference &&
+            &h->DPB[i] != h->next_output_pic &&
             (remove_current || &h->DPB[i] != h->cur_pic_ptr)) {
             ff_h264_unref_picture(&h->DPB[i]);
         }
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 17baef28d2..9f424aaf06 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -1147,6 +1147,11 @@ static int h264_decode_packet(AVCodecContext *avctx, AVPacket *avpkt)
             if (ret < 0)
                 return ret;
         }
+
+        /* Handed over; the hold release_unused_pictures() keeps on it must end
+         * here, or the next packet's frame_start() sees a stale pointer and
+         * leaves the picture occupying a DPB slot for another access unit. */
+        h->next_output_pic = NULL;
     }
 
     ff_h264_unref_picture(&h->last_pic_for_ec);
-- 
2.53.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.