From dddb84897f75560d01792fe9a51d432b3f99a020 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Tue, 13 Feb 2018 13:50:08 -0900 Subject: [PATCH] msdk: adds util functions to handle GstContext To share GstMsdkContext with each msdk element, it will be using GstContext. Most common code is from gstreamer-vaapi. https://bugzilla.gnome.org/show_bug.cgi?id=790752 --- sys/msdk/Makefile.am | 2 + sys/msdk/gstmsdkcontextutil.c | 234 ++++++++++++++++++++++++++++++++++ sys/msdk/gstmsdkcontextutil.h | 57 +++++++++ sys/msdk/meson.build | 1 + 4 files changed, 294 insertions(+) create mode 100644 sys/msdk/gstmsdkcontextutil.c create mode 100644 sys/msdk/gstmsdkcontextutil.h diff --git a/sys/msdk/Makefile.am b/sys/msdk/Makefile.am index f0b22b2a27..bdfae2b442 100644 --- a/sys/msdk/Makefile.am +++ b/sys/msdk/Makefile.am @@ -2,6 +2,7 @@ plugin_LTLIBRARIES = libgstmsdk.la libgstmsdk_la_SOURCES = \ gstmsdkcontext.c \ + gstmsdkcontextutil.c \ gstmsdksystemmemory.c \ gstmsdkvideomemory.c \ gstmsdkbufferpool.c \ @@ -25,6 +26,7 @@ nodist_EXTRA_libgstmsdk_la_SOURCES = not_present.cxx noinst_HEADERS = \ msdk.h \ gstmsdkcontext.h \ + gstmsdkcontextutil.h \ gstmsdksystemmemory.h \ gstmsdkvideomemory.h \ gstmsdkbufferpool.h \ diff --git a/sys/msdk/gstmsdkcontextutil.c b/sys/msdk/gstmsdkcontextutil.c new file mode 100644 index 0000000000..a3e803df11 --- /dev/null +++ b/sys/msdk/gstmsdkcontextutil.c @@ -0,0 +1,234 @@ +/* GStreamer Intel MSDK plugin + * Copyright (c) 2018, Intel Corporation + * Copyright (c) 2018, Igalia S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGDECE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gstmsdkcontextutil.h" + +GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT); + +static void +_init_context_debug (void) +{ +#ifndef GST_DISABLE_GST_DEBUG + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT"); + g_once_init_leave (&_init, 1); + } +#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); +} + +gboolean +gst_msdk_context_prepare (GstElement * element, GstMsdkContext ** context_ptr) +{ + 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, + *context_ptr); + return TRUE; + } + + _gst_context_query (element, GST_MSDK_CONTEXT_TYPE_NAME); + + if (*context_ptr) + GST_LOG_OBJECT (element, "found a context %" GST_PTR_FORMAT, *context_ptr); + + return *context_ptr != NULL; +} + +gboolean +gst_msdk_context_get_context (GstContext * context, + GstMsdkContext ** msdk_context) +{ + const GstStructure *structure; + const gchar *type; + + g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE); + + type = gst_context_get_context_type (context); + + if (!g_strcmp0 (type, GST_MSDK_CONTEXT_TYPE_NAME)) { + structure = gst_context_get_structure (context); + return gst_structure_get (structure, GST_MSDK_CONTEXT_TYPE_NAME, + GST_TYPE_MSDK_CONTEXT, msdk_context, NULL); + } + + return FALSE; +} + +static void +gst_msdk_context_propagate (GstElement * element, GstMsdkContext * msdk_context) +{ + GstContext *context; + GstStructure *structure; + GstMessage *msg; + + context = gst_context_new (GST_MSDK_CONTEXT_TYPE_NAME, FALSE); + + structure = gst_context_writable_structure (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)) { + GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element, "No bus attached"); + } +} + +gboolean +gst_msdk_context_ensure_context (GstElement * element, gboolean hardware) +{ + GstMsdkContext *msdk_context; + + msdk_context = gst_msdk_context_new (hardware); + if (!msdk_context) { + GST_ERROR_OBJECT (element, "Context creation failed"); + return FALSE; + } + + GST_INFO_OBJECT (element, "New MSDK Context %p", msdk_context); + + gst_msdk_context_propagate (element, msdk_context); + gst_object_unref (msdk_context); + + return TRUE; +} diff --git a/sys/msdk/gstmsdkcontextutil.h b/sys/msdk/gstmsdkcontextutil.h new file mode 100644 index 0000000000..93071b16f4 --- /dev/null +++ b/sys/msdk/gstmsdkcontextutil.h @@ -0,0 +1,57 @@ +/* GStreamer Intel MSDK plugin + * Copyright (c) 2018, Intel Corporation + * Copyright (c) 2018, Igalia S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGDECE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GST_MSDK_CONTEXT_UTIL_H +#define GST_MSDK_CONTEXT_UTIL_H + +#include "msdk.h" +#include "gstmsdkcontext.h" +#ifndef _WIN32 +#include +#endif + +#define GST_MSDK_CONTEXT_TYPE_NAME "gst.msdk.Context" + +G_BEGIN_DECLS + +gboolean +gst_msdk_context_prepare (GstElement * element, GstMsdkContext ** context_ptr); + +gboolean +gst_msdk_context_get_context (GstContext * context, GstMsdkContext ** msdk_context); + +gboolean +gst_msdk_context_ensure_context (GstElement * element, gboolean hardware); + +G_END_DECLS + +#endif /* GST_MSDK_CONTEXT_UTIL_H */ diff --git a/sys/msdk/meson.build b/sys/msdk/meson.build index e689cc2df8..2d491436b5 100644 --- a/sys/msdk/meson.build +++ b/sys/msdk/meson.build @@ -1,6 +1,7 @@ msdk_sources = [ 'gstmsdk.c', 'gstmsdkcontext.c', + 'gstmsdkcontextutil.c', 'gstmsdksystemmemory.c', 'gstmsdkvideomemory.c', 'gstmsdkbufferpool.c',