mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
h264decoder: Update latency dynamically
The actual number of reorder frames is unknown unless frame reordering is disabled (e.g., POC type 2 or constrained-* profiles). Also derived maximum DPB size or max_num_reorder_frames in VUI is not the upper bound of output delay. Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2702 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5326>
This commit is contained in:
parent
bd25c2738e
commit
48a0c01570
2 changed files with 55 additions and 8 deletions
|
@ -153,6 +153,12 @@ struct _GstH264DecoderPrivate
|
|||
|
||||
/* Return value from output_picture() */
|
||||
GstFlowReturn last_flow;
|
||||
|
||||
/* Latency report params */
|
||||
guint32 max_reorder_count;
|
||||
guint32 last_reorder_frame_number;
|
||||
gint fps_n;
|
||||
gint fps_d;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -405,6 +411,17 @@ gst_h264_decoder_finalize (GObject * object)
|
|||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h264_decoder_reset_latency_infos (GstH264Decoder * self)
|
||||
{
|
||||
GstH264DecoderPrivate *priv = self->priv;
|
||||
|
||||
priv->max_reorder_count = 0;
|
||||
priv->last_reorder_frame_number = 0;
|
||||
priv->fps_n = 25;
|
||||
priv->fps_d = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h264_decoder_reset (GstH264Decoder * self)
|
||||
{
|
||||
|
@ -420,6 +437,8 @@ gst_h264_decoder_reset (GstH264Decoder * self)
|
|||
priv->height = 0;
|
||||
priv->nal_length_size = 4;
|
||||
priv->last_flow = GST_FLOW_OK;
|
||||
|
||||
gst_h264_decoder_reset_latency_infos (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1290,6 +1309,9 @@ gst_h264_decoder_parse_slice (GstH264Decoder * self, GstH264NalUnit * nalu)
|
|||
gst_h264_picture_unref (picture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->last_reorder_frame_number++;
|
||||
picture->reorder_frame_number = priv->last_reorder_frame_number;
|
||||
}
|
||||
|
||||
/* This allows accessing the frame from the picture. */
|
||||
|
@ -1797,6 +1819,28 @@ gst_h264_decoder_do_output_picture (GstH264Decoder * self,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (priv->last_reorder_frame_number > picture->reorder_frame_number) {
|
||||
guint64 diff = priv->last_reorder_frame_number -
|
||||
picture->reorder_frame_number;
|
||||
guint64 total_delay = diff + priv->preferred_output_delay;
|
||||
if (diff > priv->max_reorder_count && total_delay < G_MAXUINT32) {
|
||||
GstClockTime latency;
|
||||
|
||||
priv->max_reorder_count = (guint32) diff;
|
||||
latency = gst_util_uint64_scale_int (GST_SECOND * total_delay,
|
||||
priv->fps_d, priv->fps_n);
|
||||
|
||||
if (latency != G_MAXUINT64) {
|
||||
GST_DEBUG_OBJECT (self, "Updating latency to %" GST_TIME_FORMAT
|
||||
", reorder count: %" G_GUINT64_FORMAT ", output-delay: %u",
|
||||
GST_TIME_ARGS (latency), diff, priv->preferred_output_delay);
|
||||
|
||||
gst_video_decoder_set_latency (GST_VIDEO_DECODER (self),
|
||||
latency, latency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||
GST_CODEC_PICTURE_FRAME_NUMBER (picture));
|
||||
|
||||
|
@ -2309,16 +2353,14 @@ gst_h264_decoder_set_latency (GstH264Decoder * self, const GstH264SPS * sps,
|
|||
|
||||
bump_level = get_bump_level (self);
|
||||
if (bump_level != GST_H264_DPB_BUMP_NORMAL_LATENCY) {
|
||||
if (sps->pic_order_cnt_type == 2) {
|
||||
/* POC type 2 has does not allow frame reordering */
|
||||
GST_DEBUG_OBJECT (self, "Actual latency will be updated later");
|
||||
frames_delay = 0;
|
||||
} else {
|
||||
guint32 max_reorder_frames =
|
||||
gst_h264_dpb_get_max_num_reorder_frames (priv->dpb);
|
||||
frames_delay = MIN (max_dpb_size, max_reorder_frames);
|
||||
}
|
||||
}
|
||||
|
||||
priv->max_reorder_count = frames_delay;
|
||||
priv->fps_n = fps_n;
|
||||
priv->fps_d = fps_d;
|
||||
|
||||
/* Consider output delay wanted by subclass */
|
||||
frames_delay += priv->preferred_output_delay;
|
||||
|
||||
|
@ -2433,6 +2475,8 @@ gst_h264_decoder_process_sps (GstH264Decoder * self, GstH264SPS * sps)
|
|||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
||||
gst_h264_decoder_reset_latency_infos (self);
|
||||
|
||||
g_assert (klass->new_sequence);
|
||||
|
||||
if (klass->get_preferred_output_delay) {
|
||||
|
|
|
@ -153,6 +153,9 @@ struct _GstH264Picture
|
|||
|
||||
GstH264DecRefPicMarking dec_ref_pic_marking;
|
||||
|
||||
/* Set by decoder to trace the number of delayed output pictures */
|
||||
guint32 reorder_frame_number;
|
||||
|
||||
/* For interlaced decoding */
|
||||
gboolean second_field;
|
||||
GstH264Picture * other_field;
|
||||
|
|
Loading…
Reference in a new issue