From 2dd3ce721a318ed3fafc6599cdd95d5e19ba1258 Mon Sep 17 00:00:00 2001 From: He Junyan Date: Fri, 3 May 2024 12:08:19 +0800 Subject: [PATCH] vah265enc: Use a FIFO queue to generate DTS The base parse will infer the DTS by itself, so we need to make DTS offset before PTS in order to avoid DTS bigger than PTS. We now use a FIFO queue to store all PTS and assign it to DTS by an offset. Part-of: --- .../gst-plugins-bad/sys/va/gstvah265enc.c | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvah265enc.c b/subprojects/gst-plugins-bad/sys/va/gstvah265enc.c index 75673414b6..e5f510eb6b 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvah265enc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvah265enc.c @@ -333,7 +333,6 @@ struct _GstVaH265Enc guint cpb_length_bits; } rc; - GstClockTime last_dts; GstH265VPS vps_hdr; GstH265SPS sps_hdr; }; @@ -350,7 +349,6 @@ struct _GstVaH265EncFrame gint poc; gboolean last_frame; - gboolean reorder; }; /** @@ -452,7 +450,6 @@ gst_va_h265_enc_frame_new (void) frame = g_new (GstVaH265EncFrame, 1); frame->last_frame = FALSE; frame->picture = NULL; - frame->reorder = FALSE; return frame; } @@ -2193,9 +2190,6 @@ again: /* it will unref at pop_frame */ f = g_queue_pop_nth (&base->reorder_list, index); g_assert (f == b_frame); - - if (index > 0) - _enc_frame (f)->reorder = TRUE; } else { b_frame = NULL; } @@ -2224,9 +2218,6 @@ _h265_pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame) vaframe = _enc_frame (frame); if (vaframe->type != GST_H265_B_SLICE) { frame = g_queue_pop_tail (&base->reorder_list); - if (!g_queue_is_empty (&base->reorder_list)) - vaframe->reorder = TRUE; - goto get_one; } @@ -2542,7 +2533,6 @@ gst_va_h265_enc_reset_state (GstVaBaseEnc * base) self->rc.target_bitrate_bits = 0; self->rc.cpb_length_bits = 0; - self->last_dts = GST_CLOCK_TIME_NONE; memset (&self->vps_hdr, 0, sizeof (GstH265VPS)); memset (&self->sps_hdr, 0, sizeof (GstH265SPS)); } @@ -4614,15 +4604,28 @@ gst_va_h265_enc_flush (GstVideoEncoder * venc) return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc); } +static gboolean +gst_va_h265_enc_start (GstVideoEncoder * venc) +{ + /* Set the minimum pts to some huge value (1000 hours). This keeps + * the dts at the start of the stream from needing to be negative. */ + gst_video_encoder_set_min_pts (venc, GST_SECOND * 60 * 60 * 1000); + + return GST_VIDEO_ENCODER_CLASS (parent_class)->start (venc); +} + static gboolean gst_va_h265_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame) { + GstVaH265Enc *self = GST_VA_H265_ENC (base); GstVaH265EncFrame *frame_in; frame_in = gst_va_h265_enc_frame_new (); gst_video_codec_frame_set_user_data (frame, frame_in, gst_va_h265_enc_frame_free); + gst_va_base_enc_push_dts (base, frame, self->gop.num_reorder_frames); + return TRUE; } @@ -4630,27 +4633,19 @@ static gboolean gst_va_h265_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame, gboolean * complete) { - GstVaH265Enc *self = GST_VA_H265_ENC (base); GstVaH265EncFrame *frame_enc; GstBuffer *buf; frame_enc = _enc_frame (frame); - if (frame_enc->reorder) { - if (!GST_CLOCK_TIME_IS_VALID (self->last_dts)) { - GST_WARNING_OBJECT (base, "Reorder frame poc: %d, system frame " - "number: %d without previous valid DTS.", frame_enc->poc, - frame->system_frame_number); - frame->dts = frame->pts; - } else { - GST_LOG_OBJECT (base, "Set reorder frame poc: %d, system frame " - "number: %d with DTS: %" GST_TIME_FORMAT, frame_enc->poc, - frame->system_frame_number, GST_TIME_ARGS (self->last_dts)); - frame->dts = self->last_dts; - } - } else { + frame->dts = gst_va_base_enc_pop_dts (base); + if (!GST_CLOCK_TIME_IS_VALID (frame->dts)) { + GST_DEBUG_OBJECT (base, "Pop invalid DTS."); + } else if (GST_CLOCK_TIME_IS_VALID (frame->pts) && frame->dts > frame->pts) { + GST_WARNING_OBJECT (base, "Pop DTS: %" GST_TIME_FORMAT " > PTS: %" + GST_TIME_FORMAT, GST_TIME_ARGS (frame->dts), + GST_TIME_ARGS (frame->pts)); frame->dts = frame->pts; - self->last_dts = frame->dts; } buf = gst_va_base_enc_create_output_buffer (base, @@ -5008,6 +5003,7 @@ gst_va_h265_enc_class_init (gpointer g_klass, gpointer class_data) object_class->get_property = gst_va_h265_enc_get_property; venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h265_enc_flush); + venc_class->start = GST_DEBUG_FUNCPTR (gst_va_h265_enc_start); va_enc_class->reset_state = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reset_state); va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reconfig);