h264decoder: Fix for latency report
authorSeungha Yang <seungha@centricular.com>
Thu, 6 Apr 2023 11:48:17 +0000 (20:48 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 10 Apr 2023 17:05:53 +0000 (17:05 +0000)
The minimum latency answered by an element should be the maximum
latency from the element's perspective. Also consider max_reorder_frames
update as a sequence change

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4383>

subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.c
subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.h

index ec414d0..a72d516 100644 (file)
@@ -2293,7 +2293,7 @@ gst_h264_decoder_set_latency (GstH264Decoder * self, const GstH264SPS * sps,
   GstStructure *structure;
   gint fps_d = 1, fps_n = 0;
   GstH264DpbBumpMode bump_level;
-  guint32 frames_delay;
+  guint32 frames_delay, max_frames_delay;
 
   caps = gst_pad_get_current_caps (GST_VIDEO_DECODER_SRC_PAD (self));
   if (!caps && self->input_state)
@@ -2316,35 +2316,27 @@ gst_h264_decoder_set_latency (GstH264Decoder * self, const GstH264SPS * sps,
     fps_d = 1;
   }
 
+  frames_delay = max_dpb_size;
+
   bump_level = get_bump_level (self);
-  frames_delay = 0;
-  switch (bump_level) {
-    case GST_H264_DPB_BUMP_NORMAL_LATENCY:
-      /* We always wait the DPB full before bumping. */
-      frames_delay = max_dpb_size;
-      break;
-    case GST_H264_DPB_BUMP_LOW_LATENCY:
-      /* We bump the IDR if the second frame is not a minus POC. */
-      frames_delay = 1;
-      break;
-    case GST_H264_DPB_BUMP_VERY_LOW_LATENCY:
-      /* We bump the IDR immediately. */
-      frames_delay = 0;
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
+  if (bump_level != GST_H264_DPB_BUMP_NORMAL_LATENCY) {
+    guint32 max_reorder_frames =
+        gst_h264_dpb_get_max_num_reorder_frames (priv->dpb);
+    frames_delay = MIN (max_dpb_size, max_reorder_frames);
   }
 
   /* Consider output delay wanted by subclass */
   frames_delay += priv->preferred_output_delay;
 
+  max_frames_delay = max_dpb_size + priv->preferred_output_delay;
+
   min = gst_util_uint64_scale_int (frames_delay * GST_SECOND, fps_d, fps_n);
-  max = gst_util_uint64_scale_int ((max_dpb_size + priv->preferred_output_delay)
-      * GST_SECOND, fps_d, fps_n);
+  max = gst_util_uint64_scale_int (max_frames_delay * GST_SECOND, fps_d, fps_n);
 
-  GST_LOG_OBJECT (self,
-      "latency min %" G_GUINT64_FORMAT " max %" G_GUINT64_FORMAT, min, max);
+  GST_DEBUG_OBJECT (self,
+      "latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
+      ", frames-delay %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max),
+      frames_delay);
 
   gst_video_decoder_set_latency (GST_VIDEO_DECODER (self), min, max);
 }
@@ -2360,6 +2352,8 @@ gst_h264_decoder_process_sps (GstH264Decoder * self, GstH264SPS * sps)
   gint max_dpb_frames;
   gint max_dpb_size;
   gint prev_max_dpb_size;
+  gint max_reorder_frames;
+  gint prev_max_reorder_frames;
   gboolean prev_interlaced;
   gboolean interlaced;
   GstFlowReturn ret = GST_FLOW_OK;
@@ -2424,15 +2418,22 @@ gst_h264_decoder_process_sps (GstH264Decoder * self, GstH264SPS * sps)
 
   prev_max_dpb_size = gst_h264_dpb_get_max_num_frames (priv->dpb);
   prev_interlaced = gst_h264_dpb_get_interlaced (priv->dpb);
+
+  prev_max_reorder_frames = gst_h264_dpb_get_max_num_reorder_frames (priv->dpb);
+  max_reorder_frames =
+      gst_h264_decoder_get_max_num_reorder_frames (self, sps, max_dpb_size);
+
   if (priv->width != sps->width || priv->height != sps->height ||
-      prev_max_dpb_size != max_dpb_size || prev_interlaced != interlaced) {
+      prev_max_dpb_size != max_dpb_size || prev_interlaced != interlaced ||
+      prev_max_reorder_frames != max_reorder_frames) {
     GstH264DecoderClass *klass = GST_H264_DECODER_GET_CLASS (self);
 
     GST_DEBUG_OBJECT (self,
         "SPS updated, resolution: %dx%d -> %dx%d, dpb size: %d -> %d, "
-        "interlaced %d -> %d",
+        "interlaced %d -> %d, max_reorder_frames: %d -> %d",
         priv->width, priv->height, sps->width, sps->height,
-        prev_max_dpb_size, max_dpb_size, prev_interlaced, interlaced);
+        prev_max_dpb_size, max_dpb_size, prev_interlaced, interlaced,
+        prev_max_reorder_frames, max_reorder_frames);
 
     ret = gst_h264_decoder_drain (GST_VIDEO_DECODER (self));
     if (ret != GST_FLOW_OK)
@@ -2458,14 +2459,12 @@ gst_h264_decoder_process_sps (GstH264Decoder * self, GstH264SPS * sps)
     priv->width = sps->width;
     priv->height = sps->height;
 
-    gst_h264_decoder_set_latency (self, sps, max_dpb_size);
     gst_h264_dpb_set_max_num_frames (priv->dpb, max_dpb_size);
     gst_h264_dpb_set_interlaced (priv->dpb, interlaced);
+    gst_h264_dpb_set_max_num_reorder_frames (priv->dpb, max_reorder_frames);
+    gst_h264_decoder_set_latency (self, sps, max_dpb_size);
   }
 
-  gst_h264_dpb_set_max_num_reorder_frames (priv->dpb,
-      gst_h264_decoder_get_max_num_reorder_frames (self, sps, max_dpb_size));
-
   return GST_FLOW_OK;
 }
 
index 7b100a7..02f328b 100644 (file)
@@ -264,6 +264,22 @@ gst_h264_dpb_set_max_num_reorder_frames (GstH264Dpb * dpb,
 }
 
 /**
+ * gst_h264_dpb_get_max_num_reorder_frames:
+ * @dpb: a #GstH264Dpb
+ *
+ * Returns: Maximum number of reorder frames
+ *
+ * Since: 1.22.2
+ */
+guint32
+gst_h264_dpb_get_max_num_reorder_frames (GstH264Dpb * dpb)
+{
+  g_return_val_if_fail (dpb != NULL, GST_H264_DPB_MAX_SIZE);
+
+  return dpb->max_num_reorder_frames;
+}
+
+/**
  * gst_h264_dpb_add:
  * @dpb: a #GstH264Dpb
  * @picture: (transfer full): a #GstH264Picture
index 19f865d..4734d6b 100644 (file)
@@ -250,6 +250,9 @@ void gst_h264_dpb_set_max_num_reorder_frames (GstH264Dpb * dpb,
                                               guint32 max_num_reorder_frames);
 
 GST_CODECS_API
+guint32 gst_h264_dpb_get_max_num_reorder_frames (GstH264Dpb * dpb);
+
+GST_CODECS_API
 gboolean gst_h264_dpb_get_interlaced  (GstH264Dpb * dpb);
 
 GST_CODECS_API