diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.c index 0cd24eb4ba..4ec9faa81b 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 4792006dae..58ea749427 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcontextutil.h @@ -46,11 +46,15 @@ G_BEGIN_DECLS 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 b31258e65b..4ea82229fd 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 b58f2d340f..d7546a4727 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 50687e2f3a..8f1e5e4576 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);