From d77fe9495a91d4c319d5f537909f29ef76c01220 Mon Sep 17 00:00:00 2001
From: "F. Duncanh" <fduncanh@gmail.com>
Date: Sun, 13 Nov 2022 19:19:41 -0500
Subject: [PATCH] v4l2videodec: Fixes three H.264/HEVC ITU conformance tests

Postpone the cleanup of any consecutive sequence of lost frames
which starts at frame 0, until frame 100 is dequeued from driver.

This allows fluster tests JVT/CVWP2_TOSHIBA_E, JVC/CVWP3_TOSHIBA_E
and HEVC/POC_A_Bossen_3 that sends out-of-order frames to successfully
complete  (e.g., test of Amphion vpu driver).

Fixes #1569

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3398>
---
 .../sys/v4l2/gstv4l2videodec.c                | 60 +++++++++----------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c
index 9f6fa7bbee..2a110e5e4a 100644
--- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c
+++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c
@@ -675,11 +675,9 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
   GstVideoCodecFrame *frame;
   GstBuffer *buffer = NULL;
   GstFlowReturn ret;
-  gint capture_configuration_change;
 
   GST_VIDEO_DECODER_STREAM_LOCK (decoder);
-  if ((capture_configuration_change =
-          g_atomic_int_get (&self->capture_configuration_change))) {
+  if (g_atomic_int_get (&self->capture_configuration_change)) {
     gst_v4l2_object_stop (self->v4l2capture);
     ret = gst_v4l2_video_dec_setup_capture (decoder);
     if (ret != GST_FLOW_OK) {
@@ -761,36 +759,38 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
     while ((oldest_frame = gst_video_decoder_get_oldest_frame (decoder)) &&
         check_system_frame_number_too_old (frame->system_frame_number,
             oldest_frame->system_frame_number)) {
-      gst_video_decoder_drop_frame (decoder, oldest_frame);
-      oldest_frame = NULL;
-
-      if (!warned) {
-        g_warning ("%s: Too old frames, bug in decoder -- please file a bug",
-            GST_ELEMENT_NAME (decoder));
-        warned = TRUE;
-      }
-    }
-
-    /* If the initial frame triggered a Caps renegotiation, but with no actual change in 
-     * resolution, already-correctly-decoded frames may incorrectly be dropped by the driver.
-     * This has been observed to occur in at least one driver.  These frames will never dequeue.
-     * As a workaround, drop all pending frames older than the current frame now. */
-    if (capture_configuration_change && oldest_frame
-        && oldest_frame->system_frame_number == 0
-        && frame->system_frame_number) {
-      gint counter = 0;
-      while (oldest_frame) {
-        counter++;
+      if (oldest_frame->system_frame_number > 0) {
         gst_video_decoder_drop_frame (decoder, oldest_frame);
-        oldest_frame = gst_video_decoder_get_oldest_frame (decoder);
-        if (oldest_frame->system_frame_number == frame->system_frame_number) {
-          gst_video_codec_frame_unref (oldest_frame);
-          oldest_frame = NULL;
+        oldest_frame = NULL;
+
+        if (!warned) {
+          g_warning ("%s: Too old frames, bug in decoder -- please file a bug",
+              GST_ELEMENT_NAME (decoder));
+          warned = TRUE;
         }
+      } else {
+        /* special treatment when oldest_frame->system_frame_number = 0:
+         * if a consecutive sequence 0, 1, 2,..., n < frame->system_frame_number
+         * is pending, drop them all at this time. (This has been seen to occur
+         * as a driver bug when the initial frame triggered a Caps re-negotiation,
+         * and the driver dropped these frames) */
+        guint32 counter = 0;
+        while (oldest_frame) {
+          gst_video_decoder_drop_frame (decoder, oldest_frame);
+          counter++;
+          oldest_frame = gst_video_decoder_get_oldest_frame (decoder);
+          if (oldest_frame &&
+              (oldest_frame->system_frame_number > counter ||
+                  oldest_frame->system_frame_number >=
+                  frame->system_frame_number)) {
+            gst_video_codec_frame_unref (oldest_frame);
+            oldest_frame = NULL;
+          }
+        }
+        g_warning
+            ("%s: %i initial frames were not dequeued: bug in decoder -- please file a bug",
+            GST_ELEMENT_NAME (decoder), counter);
       }
-      g_warning
-          ("%s: %i initial frames before frame %u were not dequeued: bug in decoder -- please file a bug",
-          GST_ELEMENT_NAME (decoder), counter, frame->system_frame_number);
     }
     if (oldest_frame)
       gst_video_codec_frame_unref (oldest_frame);