diff mbox series

[FFmpeg-devel,PATCHv2,RFC] libavcodec/hevc_refs: Clear DPB of old frames

Message ID CAK+ULv6jWgsHjNr9DrF24CwFadSzWhu1KXDurEix=hJ0y997UQ@mail.gmail.com
State New
Headers show
Series [FFmpeg-devel,PATCHv2,RFC] libavcodec/hevc_refs: Clear DPB of old frames | expand

Checks

Context Check Description
andriy/default pending
andriy/configure warning Failed to apply patch

Commit Message

Kieran Kunhya Sept. 14, 2020, 4:37 p.m. UTC
From 21bf6e5eac61d34f270534dd5a2a7229967c1ee9 Mon Sep 17 00:00:00 2001
From: Kieran Kunhya <kierank@obe.tv>
Date: Thu, 16 Jul 2020 20:29:24 +0100
Subject: [PATCHv2] [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(+)


--
1.9.1

Comments

Kieran Kunhya Sept. 15, 2020, 2:38 a.m. UTC | #1
On Mon, 14 Sep 2020 at 17:37, Kieran Kunhya <kierank@obe.tv> wrote:

> From 21bf6e5eac61d34f270534dd5a2a7229967c1ee9 Mon Sep 17 00:00:00 2001
> From: Kieran Kunhya <kierank@obe.tv>
> Date: Thu, 16 Jul 2020 20:29:24 +0100
> Subject: [PATCHv2] [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
>

It seems there are also legal streams that have jumps in POC.
So I am really not sure how one distinguishes between a glitch or stream
loop which requires cleaning out the DPB vs a genuine stream.

Kieran
diff mbox series

Patch

diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c
index 4f6d985..6af0f6e 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) {
+            int dpb_size = FF_ARRAY_ELEMS(s->DPB);
+            if (frame->frame->buf[0] && ((frame->poc > s->poc +
dpb_size) || (frame->poc < s->poc - dpb_size))) {
+                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;