From 556a254e59ebadb5b7230cd99b1574f6c433197f Mon Sep 17 00:00:00 2001 From: He Junyan Date: Thu, 4 Apr 2024 21:25:51 +0800 Subject: [PATCH] va: baseenc: Add a preferred_output_delay field for GPU parallel processing The encoder can specify the a preferred_output_delay value to get better throughput performance. The higher delay may get better HW performance, but it may increases the encoder and pipeline latency. When the output queue length is smaller than preferred_output_delay, the encoder will not block to waiting for the encoding output. It will continue to prepare and send more commands to GPU, which may improve the encoder throughput performance. Part-of: --- .../gst-plugins-bad/sys/va/gstvabaseenc.c | 71 ++++++++++++++++--- .../gst-plugins-bad/sys/va/gstvabaseenc.h | 1 + 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c index 32a29b36f3..936a69b9b0 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c @@ -32,6 +32,8 @@ #define GST_CAT_DEFAULT gst_va_base_enc_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); +#define GST_FLOW_OUTPUT_NOT_READY GST_FLOW_CUSTOM_SUCCESS_2 + struct _GstVaBaseEncPrivate { GstVideoInfo sinkpad_info; @@ -73,6 +75,7 @@ gst_va_base_enc_reset_state_default (GstVaBaseEnc * base) base->profile = VAProfileNone; base->rt_format = 0; base->codedbuf_size = 0; + base->preferred_output_delay = 0; g_atomic_int_set (&base->reconf, FALSE); } @@ -505,6 +508,33 @@ _push_out_one_buffer (GstVaBaseEnc * base) return ret; } +static GstFlowReturn +_try_to_push_out_one_buffer (GstVaBaseEnc * base) +{ + GstVideoCodecFrame *frame_out; + GstVaEncFrame *frame_enc; + VASurfaceID surface; + gboolean ready; + + frame_out = g_queue_peek_head (&base->output_list); + if (frame_out == NULL) + return GST_FLOW_OUTPUT_NOT_READY; + + frame_enc = gst_va_get_enc_frame (frame_out); + + surface = gst_va_encode_picture_get_reconstruct_surface (frame_enc->picture); + + ready = va_check_surface_has_status (base->display, surface, VASurfaceReady); + + GST_LOG_OBJECT (base, "Output of system_frame_number %d is %s", + frame_out->system_frame_number, ready ? "ready" : "not ready"); + + if (!ready) + return GST_FLOW_OUTPUT_NOT_READY; + + return _push_out_one_buffer (base); +} + static GstFlowReturn gst_va_base_enc_drain (GstVideoEncoder * venc) { @@ -655,20 +685,41 @@ gst_va_base_enc_handle_frame (GstVideoEncoder * venc, /* pass it to reorder list and we should not use it again. */ frame = NULL; - while (frame_encode) { - ret = base_class->encode_frame (base, frame_encode, FALSE); - if (ret != GST_FLOW_OK) - goto error_encode; + if (frame_encode) { + while (frame_encode) { + ret = base_class->encode_frame (base, frame_encode, FALSE); + if (ret != GST_FLOW_OK) + goto error_encode; - while (ret == GST_FLOW_OK && g_queue_get_length (&base->output_list) > 0) - ret = _push_out_one_buffer (base); + while (ret == GST_FLOW_OK && g_queue_get_length (&base->output_list) > + base->preferred_output_delay) + ret = _push_out_one_buffer (base); + if (ret != GST_FLOW_OK) + goto error_push_buffer; + + /* Try to push out all ready frames. */ + do { + ret = _try_to_push_out_one_buffer (base); + } while (ret == GST_FLOW_OK); + if (ret == GST_FLOW_OUTPUT_NOT_READY) + ret = GST_FLOW_OK; + if (ret != GST_FLOW_OK) + goto error_push_buffer; + + frame_encode = NULL; + if (!base_class->reorder_frame (base, NULL, FALSE, &frame_encode)) + goto error_reorder; + } + } else { + /* Try to push out all ready frames. */ + do { + ret = _try_to_push_out_one_buffer (base); + } while (ret == GST_FLOW_OK); + if (ret == GST_FLOW_OUTPUT_NOT_READY) + ret = GST_FLOW_OK; if (ret != GST_FLOW_OK) goto error_push_buffer; - - frame_encode = NULL; - if (!base_class->reorder_frame (base, NULL, FALSE, &frame_encode)) - goto error_reorder; } return ret; diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h index fde2479836..1cd2af19ef 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h @@ -67,6 +67,7 @@ struct _GstVaBaseEnc GQueue ref_list; GQueue output_list; GstVecDeque *dts_queue; + guint preferred_output_delay; GstVideoCodecState *input_state; union {