From 23f0272092f6528a268abe7e6a7fd8764553048f Mon Sep 17 00:00:00 2001
From: Kieran Kunhya <kierank@obe.tv>
Date: Thu, 16 Jul 2020 20:29:24 +0100
Subject: [PATCH] [RFC] libavcodec/hevc_refs: Clear DPB of old frames

During glitching or looping streams, old frames remain in the DPB.
The decoder incorrectly thinks that the DPB contains the right number of buffered frames to output and reordering breaks badly
---
 libavcodec/hevc_refs.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c
index 4f6d985..a8e0028 100644
--- a/libavcodec/hevc_refs.c
+++ b/libavcodec/hevc_refs.c
@@ -277,6 +277,10 @@ static int init_slice_rpl(HEVCContext *s)
     int ctb_addr_ts  = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_segment_addr];
     int i;
 
+    if(frame && !frame->rpl_buf) {
+        return AVERROR_INVALIDDATA;
+    }
+
     if (s->slice_idx >= frame->rpl_buf->size / sizeof(RefPicListTab))
         return AVERROR_INVALIDDATA;
 
@@ -462,6 +466,21 @@ int ff_hevc_frame_rps(HEVCContext *s)
         mark_ref(frame, 0);
     }
 
+    /* Clear the DPB of any junk frames */
+    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
+        HEVCFrame *frame = &s->DPB[i];
+        if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) &&
+            frame->sequence == s->seq_output) {
+            if (frame->frame->buf[0] && ((frame->poc > s->poc + FF_ARRAY_ELEMS(s->DPB)) || (frame->poc < s->poc - FF_ARRAY_ELEMS(s->DPB))))
+            {
+                if(frame->poc == s->poc)
+                    continue;
+
+                ff_hevc_unref_frame(s, frame, ~0);
+            }
+        }
+    }
+
     for (i = 0; i < NB_RPS_TYPE; i++)
         rps[i].nb_refs = 0;
 
-- 
1.9.1

