From 85664b5af620680cd38d22aebb935f9290635323 Mon Sep 17 00:00:00 2001 From: He Junyan Date: Tue, 17 Aug 2021 21:51:58 +0800 Subject: [PATCH] MSDK: Improve the GstContext setting logic. We now can use the gst va lib's display to create our MSDK context, and use its helper functions to simplify our code. The improved logic is like this: 1. Every MSDK element should use gst_msdk_context_find() to find a MSDK context from neighbour. If valid, reuse it. 2. Use gst_msdk_ensure_new_context(). It will first query neighbours about the GstVaDisplay, if found(e.g. some VA element is connected), use gst_msdk_context_from_external_display() to create a MSDK context. 3. Then, creating the MSDK context from scratch. It creates both the display and MSDK context. Part-of: --- .../gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c | 204 ++++++++++----------- .../gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h | 6 +- subprojects/gst-plugins-bad/sys/msdk/gstmsdkdec.c | 10 +- subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c | 10 +- subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpp.c | 10 +- 5 files changed, 123 insertions(+), 117 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c index 0cd24eb..4ec9faa 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c @@ -31,6 +31,8 @@ */ #include "gstmsdkcontextutil.h" +#include +#include GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT); @@ -47,113 +49,15 @@ _init_context_debug (void) #endif } -static gboolean -context_pad_query (const GValue * item, GValue * value, gpointer user_data) -{ - GstPad *const pad = g_value_get_object (item); - GstQuery *const query = user_data; - - if (gst_pad_peer_query (pad, query)) { - g_value_set_boolean (value, TRUE); - return FALSE; - } - - GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, pad, "context pad peer query failed"); - return TRUE; -} - -static gboolean -_gst_context_run_query (GstElement * element, GstQuery * query, - GstPadDirection direction) -{ - GstIteratorFoldFunction const func = context_pad_query; - GstIterator *it; - GValue res = { 0 }; - - g_value_init (&res, G_TYPE_BOOLEAN); - g_value_set_boolean (&res, FALSE); - - /* Ask neighbour */ - if (direction == GST_PAD_SRC) - it = gst_element_iterate_src_pads (element); - else - it = gst_element_iterate_sink_pads (element); - - while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC) - gst_iterator_resync (it); - gst_iterator_free (it); - - return g_value_get_boolean (&res); -} - -static gboolean -_gst_context_get_from_query (GstElement * element, GstQuery * query, - GstPadDirection direction) -{ - GstContext *ctxt; - - if (!_gst_context_run_query (element, query, direction)) - return FALSE; - - gst_query_parse_context (query, &ctxt); - if (!ctxt) - return FALSE; - - GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, - "found context (%" GST_PTR_FORMAT ") in %s query", ctxt, - direction == GST_PAD_SRC ? "downstream" : "upstream"); - - gst_element_set_context (element, ctxt); - return TRUE; -} - -static void -_gst_context_query (GstElement * element, const gchar * context_type) -{ - GstQuery *query; - GstMessage *msg; - - /* 2) Query downstream with GST_QUERY_CONTEXT for the context and - check if downstream already has a context of the specific - type */ - - /* 3) Query upstream with GST_QUERY_CONTEXT for the context and - check if upstream already has a context of the specific - type */ - query = gst_query_new_context (context_type); - if (_gst_context_get_from_query (element, query, GST_PAD_SRC)) - goto found; - if (_gst_context_get_from_query (element, query, GST_PAD_SINK)) - goto found; - - /* 4) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with - the required context types and afterwards check if an - usable context was set now as in 1). The message could - be handled by the parent bins of the element and the - application. */ - GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, - "posting `need-context' message"); - - msg = gst_message_new_need_context (GST_OBJECT_CAST (element), context_type); - if (!gst_element_post_message (element, msg)) - GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "No bus attached"); - - /* Whomever responds to the need-context message performs a - GstElement::set_context() with the required context in which the - element is required to update the display_ptr */ - -found: - gst_query_unref (query); -} - +/* Find whether the other elements already have a msdk context. */ gboolean gst_msdk_context_find (GstElement * element, GstMsdkContext ** context_ptr) { + _init_context_debug (); + g_return_val_if_fail (element != NULL, FALSE); g_return_val_if_fail (context_ptr != NULL, FALSE); - _init_context_debug (); - /* 1) Check if the element already has a context of the specific type. */ if (*context_ptr) { GST_LOG_OBJECT (element, "already have a context %" GST_PTR_FORMAT, @@ -162,10 +66,12 @@ gst_msdk_context_find (GstElement * element, GstMsdkContext ** context_ptr) } /* This may indirectly set *context_ptr, see function body */ - _gst_context_query (element, GST_MSDK_CONTEXT_TYPE_NAME); + gst_va_context_query (element, GST_MSDK_CONTEXT_TYPE_NAME); - if (*context_ptr) + if (*context_ptr) { GST_LOG_OBJECT (element, "found a context %" GST_PTR_FORMAT, *context_ptr); + return TRUE; + } return *context_ptr != NULL; } @@ -177,6 +83,8 @@ gst_msdk_context_get_context (GstContext * context, const GstStructure *structure; const gchar *type; + _init_context_debug (); + g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE); type = gst_context_get_context_type (context); @@ -203,34 +111,110 @@ gst_msdk_context_propagate (GstElement * element, GstMsdkContext * msdk_context) gst_structure_set (structure, GST_MSDK_CONTEXT_TYPE_NAME, GST_TYPE_MSDK_CONTEXT, msdk_context, NULL); - gst_element_set_context (element, context); - GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "posting `have-context' message with MSDK context %" GST_PTR_FORMAT, msdk_context); msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context); - if (!gst_element_post_message (element, msg)) { + if (!gst_element_post_message (element, msg)) GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "No bus attached"); - } } +/* When we can not find a suitable context from others, we ensure to create + a new context. */ gboolean -gst_msdk_context_ensure_context (GstElement * element, gboolean hardware, - GstMsdkContextJobType job) +gst_msdk_ensure_new_context (GstElement * element, gboolean hardware, + GstMsdkContextJobType job, GstMsdkContext ** context_ptr) { GstMsdkContext *msdk_context; + gboolean propagate_display = FALSE; + gboolean ret = FALSE; + + g_return_val_if_fail (element, FALSE); + g_return_val_if_fail (context_ptr, FALSE); + _init_context_debug (); + + /* 1) Already have. */ + if (g_atomic_pointer_get (context_ptr)) + return TRUE; + +#ifndef _WIN32 + /* 2) Query the neighbour the VA display. If already a valid VA display, + using it by gst_msdk_context_from_external_display() in set_context(). */ + gst_va_context_query (element, GST_VA_DISPLAY_HANDLE_CONTEXT_TYPE_STR); + msdk_context = g_atomic_pointer_get (context_ptr); + if (msdk_context) { + gst_object_ref (msdk_context); + propagate_display = FALSE; + ret = TRUE; + goto done; + } +#endif + + /* 3) Create a MSDK context from scratch. */ msdk_context = gst_msdk_context_new (hardware, job); if (!msdk_context) { GST_ERROR_OBJECT (element, "Context creation failed"); return FALSE; } + propagate_display = TRUE; + ret = TRUE; GST_INFO_OBJECT (element, "New MSDK Context %p", msdk_context); + gst_object_replace ((GstObject **) context_ptr, (GstObject *) msdk_context); + +done: + if (propagate_display) { +#ifndef _WIN32 + GstVaDisplay *display = + (GstVaDisplay *) gst_msdk_context_get_display (msdk_context); + gst_va_element_propagate_display_context (element, display); + gst_clear_object (&display); +#endif + } + gst_msdk_context_propagate (element, msdk_context); gst_object_unref (msdk_context); - return TRUE; + return ret; +} + +gboolean +gst_msdk_context_from_external_display (GstContext * context, gboolean hardware, + GstMsdkContextJobType job_type, GstMsdkContext ** msdk_context) +{ +#ifndef _WIN32 + GstObject *va_display = NULL; + const gchar *type; + const GstStructure *s; + GstMsdkContext *ctx = NULL; + + _init_context_debug (); + + type = gst_context_get_context_type (context); + if (g_strcmp0 (type, GST_VA_DISPLAY_HANDLE_CONTEXT_TYPE_STR)) + return FALSE; + + s = gst_context_get_structure (context); + if (gst_structure_get (s, "gst-display", GST_TYPE_OBJECT, &va_display, NULL)) { + if (GST_IS_VA_DISPLAY (va_display)) { + /* TODO: Need to check whether the display is the DEV we want. */ + ctx = + gst_msdk_context_new_with_va_display (va_display, hardware, job_type); + if (ctx) + *msdk_context = ctx; + } + + /* let's try other fields */ + gst_clear_object (&va_display); + } + + if (ctx) + return TRUE; + +#endif + + return FALSE; } diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h index 4792006..58ea749 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h @@ -47,10 +47,14 @@ gboolean gst_msdk_context_find (GstElement * element, GstMsdkContext ** context_ptr); gboolean +gst_msdk_ensure_new_context (GstElement * element, gboolean hardware, GstMsdkContextJobType job, GstMsdkContext ** context_ptr); + +gboolean gst_msdk_context_get_context (GstContext * context, GstMsdkContext ** msdk_context); gboolean -gst_msdk_context_ensure_context (GstElement * element, gboolean hardware, GstMsdkContextJobType job); +gst_msdk_context_from_external_display (GstContext * context, gboolean hardware, + GstMsdkContextJobType job_type, GstMsdkContext ** msdk_context); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkdec.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkdec.c index b31258e..4ea8222 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkdec.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkdec.c @@ -312,6 +312,12 @@ gst_msdkdec_set_context (GstElement * element, GstContext * context) gst_object_replace ((GstObject **) & thiz->context, (GstObject *) msdk_context); gst_object_unref (msdk_context); + } else if (gst_msdk_context_from_external_display (context, + thiz->hardware, 0 /* GST_MSDK_JOB_DECODER will be set later */ , + &msdk_context)) { + gst_object_replace ((GstObject **) & thiz->context, + (GstObject *) msdk_context); + gst_object_unref (msdk_context); } GST_ELEMENT_CLASS (parent_class)->set_context (element, context); @@ -829,8 +835,8 @@ gst_msdkdec_start (GstVideoDecoder * decoder) GstMsdkDec *thiz = GST_MSDKDEC (decoder); if (!gst_msdkdec_context_prepare (thiz)) { - if (!gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz), - thiz->hardware, GST_MSDK_JOB_DECODER)) + if (!gst_msdk_ensure_new_context (GST_ELEMENT_CAST (thiz), + thiz->hardware, GST_MSDK_JOB_DECODER, &thiz->context)) return FALSE; GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT, thiz->context); diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c index b58f2d3..d7546a4 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkenc.c @@ -138,6 +138,12 @@ gst_msdkenc_set_context (GstElement * element, GstContext * context) gst_object_replace ((GstObject **) & thiz->context, (GstObject *) msdk_context); gst_object_unref (msdk_context); + } else if (gst_msdk_context_from_external_display (context, + thiz->hardware, 0 /* GST_MSDK_JOB_ENCODER will be set later */ , + &msdk_context)) { + gst_object_replace ((GstObject **) & thiz->context, + (GstObject *) msdk_context); + gst_object_unref (msdk_context); } GST_ELEMENT_CLASS (parent_class)->set_context (element, context); @@ -1887,8 +1893,8 @@ gst_msdkenc_start (GstVideoEncoder * encoder) GstMsdkEnc *thiz = GST_MSDKENC (encoder); if (!gst_msdkenc_context_prepare (thiz)) { - if (!gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz), - thiz->hardware, GST_MSDK_JOB_ENCODER)) + if (!gst_msdk_ensure_new_context (GST_ELEMENT_CAST (thiz), + thiz->hardware, GST_MSDK_JOB_ENCODER, &thiz->context)) return FALSE; GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT, thiz->context); diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpp.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpp.c index 50687e2..8f1e5e4 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpp.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpp.c @@ -339,8 +339,8 @@ ensure_context (GstBaseTransform * trans) GstMsdkVPP *thiz = GST_MSDKVPP (trans); if (!gst_msdkvpp_context_prepare (thiz)) { - if (!gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz), - thiz->hardware, GST_MSDK_JOB_VPP)) + if (!gst_msdk_ensure_new_context (GST_ELEMENT_CAST (thiz), + thiz->hardware, GST_MSDK_JOB_VPP, &thiz->context)) return FALSE; GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT, thiz->context); @@ -1648,6 +1648,12 @@ gst_msdkvpp_set_context (GstElement * element, GstContext * context) gst_object_replace ((GstObject **) & thiz->context, (GstObject *) msdk_context); gst_object_unref (msdk_context); + } else if (gst_msdk_context_from_external_display (context, + thiz->hardware, 0 /* GST_MSDK_JOB_VPP will be set later */ , + &msdk_context)) { + gst_object_replace ((GstObject **) & thiz->context, + (GstObject *) msdk_context); + gst_object_unref (msdk_context); } GST_ELEMENT_CLASS (parent_class)->set_context (element, context); -- 2.7.4