*/
#include "gstmsdkcontextutil.h"
+#include <gst/va/gstvadisplay.h>
+#include <gst/va/gstvautils.h>
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
#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,
}
/* 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;
}
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);
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;
}