From: Víctor Manuel Jáquez Leal Date: Thu, 20 Oct 2022 09:13:19 +0000 (+0200) Subject: vabaseenc: Enable encoder reconfiguration. X-Git-Tag: 1.22.0~521 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bd3c50e50ff530e17d10a9ef96c53529fe965d19;p=platform%2Fupstream%2Fgstreamer.git vabaseenc: Enable encoder reconfiguration. Adds an internal function reset() which drains the internal queues and calls the reconfig() vmethod. This reset() method is called inconditionally at set_format() and in handle_frame() if the instance's reconf flag is enabled. Part-of: --- diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c index 625b965..ba7003d 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c +++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c @@ -68,6 +68,7 @@ gst_va_base_enc_reset_state_default (GstVaBaseEnc * base) base->profile = VAProfileNone; base->rt_format = 0; base->codedbuf_size = 0; + g_atomic_int_set (&base->reconf, FALSE); } static void @@ -508,6 +509,112 @@ _push_out_one_buffer (GstVaBaseEnc * base) } static GstFlowReturn +gst_va_base_enc_drain (GstVideoEncoder * venc) +{ + GstVaBaseEnc *base = GST_VA_BASE_ENC (venc); + GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base); + GstFlowReturn ret = GST_FLOW_OK; + GstVideoCodecFrame *frame_enc = NULL; + gboolean is_last = FALSE; + + GST_DEBUG_OBJECT (base, "Encoder is draining"); + + /* Kickout all cached frames */ + if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) { + ret = GST_FLOW_ERROR; + goto error_and_purge_all; + } + + while (frame_enc) { + is_last = FALSE; + + if (g_queue_is_empty (&base->reorder_list)) + is_last = TRUE; + + ret = base_class->encode_frame (base, frame_enc, is_last); + if (ret != GST_FLOW_OK) + goto error_and_purge_all; + + frame_enc = NULL; + + ret = _push_out_one_buffer (base); + if (ret != GST_FLOW_OK) + goto error_and_purge_all; + + if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) { + ret = GST_FLOW_ERROR; + goto error_and_purge_all; + } + } + + g_assert (g_queue_is_empty (&base->reorder_list)); + + /* Output all frames. */ + while (!g_queue_is_empty (&base->output_list)) { + ret = _push_out_one_buffer (base); + if (ret != GST_FLOW_OK) + goto error_and_purge_all; + } + + /* Also clear the reference list. */ + g_queue_clear_full (&base->ref_list, + (GDestroyNotify) gst_video_codec_frame_unref); + + return GST_FLOW_OK; + +error_and_purge_all: + if (frame_enc) { + gst_clear_buffer (&frame_enc->output_buffer); + gst_video_encoder_finish_frame (venc, frame_enc); + } + + if (!g_queue_is_empty (&base->output_list)) { + GST_WARNING_OBJECT (base, "Still %d frame in the output list" + " after drain", g_queue_get_length (&base->output_list)); + while (!g_queue_is_empty (&base->output_list)) { + frame_enc = g_queue_pop_head (&base->output_list); + gst_video_codec_frame_unref (frame_enc); + gst_clear_buffer (&frame_enc->output_buffer); + gst_video_encoder_finish_frame (venc, frame_enc); + } + } + + if (!g_queue_is_empty (&base->reorder_list)) { + GST_WARNING_OBJECT (base, "Still %d frame in the reorder list" + " after drain", g_queue_get_length (&base->reorder_list)); + while (!g_queue_is_empty (&base->reorder_list)) { + frame_enc = g_queue_pop_head (&base->reorder_list); + gst_video_codec_frame_unref (frame_enc); + gst_clear_buffer (&frame_enc->output_buffer); + gst_video_encoder_finish_frame (venc, frame_enc); + } + } + + /* Also clear the reference list. */ + g_queue_clear_full (&base->ref_list, + (GDestroyNotify) gst_video_codec_frame_unref); + + return ret; +} + +static gboolean +gst_va_base_enc_reset (GstVaBaseEnc * base) +{ + GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base); + + GST_DEBUG_OBJECT (base, "Reconfiguration"); + if (gst_va_base_enc_drain (GST_VIDEO_ENCODER (base)) != GST_FLOW_OK) + return FALSE; + + if (!base_class->reconfig (base)) { + GST_ERROR_OBJECT (base, "Error at reconfiguration error"); + return FALSE; + } + + return TRUE; +} + +static GstFlowReturn gst_va_base_enc_handle_frame (GstVideoEncoder * venc, GstVideoCodecFrame * frame) { @@ -523,6 +630,11 @@ gst_va_base_enc_handle_frame (GstVideoEncoder * venc, GST_TIME_ARGS (GST_BUFFER_DTS (frame->input_buffer)), GST_TIME_ARGS (GST_BUFFER_PTS (frame->input_buffer))); + if (g_atomic_int_compare_and_exchange (&base->reconf, TRUE, FALSE)) { + if (!gst_va_base_enc_reset (base)) + return GST_FLOW_ERROR; + } + ret = gst_va_base_enc_import_input_buffer (base, frame->input_buffer, &in_buf); if (ret != GST_FLOW_OK) @@ -600,95 +712,6 @@ error_push_buffer: } static GstFlowReturn -gst_va_base_enc_drain (GstVideoEncoder * venc) -{ - GstVaBaseEnc *base = GST_VA_BASE_ENC (venc); - GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base); - GstFlowReturn ret = GST_FLOW_OK; - GstVideoCodecFrame *frame_enc = NULL; - gboolean is_last = FALSE; - - GST_DEBUG_OBJECT (base, "Encoder is draining"); - - /* Kickout all cached frames */ - if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) { - ret = GST_FLOW_ERROR; - goto error_and_purge_all; - } - - while (frame_enc) { - is_last = FALSE; - - if (g_queue_is_empty (&base->reorder_list)) - is_last = TRUE; - - ret = base_class->encode_frame (base, frame_enc, is_last); - if (ret != GST_FLOW_OK) - goto error_and_purge_all; - - frame_enc = NULL; - - ret = _push_out_one_buffer (base); - if (ret != GST_FLOW_OK) - goto error_and_purge_all; - - if (!base_class->reorder_frame (base, NULL, TRUE, &frame_enc)) { - ret = GST_FLOW_ERROR; - goto error_and_purge_all; - } - } - - g_assert (g_queue_is_empty (&base->reorder_list)); - - /* Output all frames. */ - while (!g_queue_is_empty (&base->output_list)) { - ret = _push_out_one_buffer (base); - if (ret != GST_FLOW_OK) - goto error_and_purge_all; - } - - /* Also clear the reference list. */ - g_queue_clear_full (&base->ref_list, - (GDestroyNotify) gst_video_codec_frame_unref); - - return GST_FLOW_OK; - -error_and_purge_all: - if (frame_enc) { - gst_clear_buffer (&frame_enc->output_buffer); - gst_video_encoder_finish_frame (venc, frame_enc); - } - - if (!g_queue_is_empty (&base->output_list)) { - GST_WARNING_OBJECT (base, "Still %d frame in the output list" - " after drain", g_queue_get_length (&base->output_list)); - while (!g_queue_is_empty (&base->output_list)) { - frame_enc = g_queue_pop_head (&base->output_list); - gst_video_codec_frame_unref (frame_enc); - gst_clear_buffer (&frame_enc->output_buffer); - gst_video_encoder_finish_frame (venc, frame_enc); - } - } - - if (!g_queue_is_empty (&base->reorder_list)) { - GST_WARNING_OBJECT (base, "Still %d frame in the reorder list" - " after drain", g_queue_get_length (&base->reorder_list)); - while (!g_queue_is_empty (&base->reorder_list)) { - frame_enc = g_queue_pop_head (&base->reorder_list); - gst_video_codec_frame_unref (frame_enc); - gst_clear_buffer (&frame_enc->output_buffer); - gst_video_encoder_finish_frame (venc, frame_enc); - } - } - - /* Also clear the reference list. */ - g_queue_clear_full (&base->ref_list, - (GDestroyNotify) gst_video_codec_frame_unref); - - return ret; -} - -static GstFlowReturn gst_va_base_enc_finish (GstVideoEncoder * venc) { return gst_va_base_enc_drain (venc); @@ -698,7 +721,6 @@ static gboolean gst_va_base_enc_set_format (GstVideoEncoder * venc, GstVideoCodecState * state) { GstVaBaseEnc *base = GST_VA_BASE_ENC (venc); - GstVaBaseEncClass *base_class = GST_VA_BASE_ENC_GET_CLASS (base); g_return_val_if_fail (state->caps != NULL, FALSE); @@ -706,18 +728,8 @@ gst_va_base_enc_set_format (GstVideoEncoder * venc, GstVideoCodecState * state) gst_video_codec_state_unref (base->input_state); base->input_state = gst_video_codec_state_ref (state); - if (gst_va_base_enc_drain (venc) != GST_FLOW_OK) - return FALSE; - - if (!gst_va_encoder_close (base->encoder)) { - GST_ERROR_OBJECT (base, "Failed to close the VA encoder"); - return FALSE; - } - - if (!base_class->reconfig (base)) { - GST_ERROR_OBJECT (base, "Reconfig the encoder error"); + if (!gst_va_base_enc_reset (base)) return FALSE; - } /* Sub class should open the encoder if reconfig succeeds. */ return gst_va_encoder_is_open (base->encoder); diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h index 20b858d..2db7c76 100644 --- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h +++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h @@ -46,6 +46,8 @@ struct _GstVaBaseEnc GstVaDisplay *display; GstVaEncoder *encoder; + gboolean reconf; + VAProfile profile; gint width; gint height;