diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c index f1f06e391c..7393455a78 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c @@ -2291,7 +2291,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) @@ -2314,35 +2314,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; - 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_frames_delay = max_dpb_size + priv->preferred_output_delay; - GST_LOG_OBJECT (self, - "latency min %" G_GUINT64_FORMAT " max %" G_GUINT64_FORMAT, min, max); + min = gst_util_uint64_scale_int (frames_delay * GST_SECOND, fps_d, fps_n); + max = gst_util_uint64_scale_int (max_frames_delay * GST_SECOND, fps_d, fps_n); + + 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); } @@ -2358,6 +2350,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; @@ -2422,15 +2416,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) @@ -2456,14 +2457,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; } diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.c index 0962d4cdf1..bc304cb783 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.c +++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.c @@ -280,6 +280,22 @@ gst_h264_dpb_set_max_num_reorder_frames (GstH264Dpb * dpb, dpb->max_num_reorder_frames = max_num_reorder_frames; } +/** + * 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 diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.h b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.h index 62a3f3a097..73547066d8 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264picture.h @@ -249,6 +249,9 @@ GST_CODECS_API 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);