plugins: add compat layer for GstVideoContext.
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Wed, 22 May 2013 16:07:52 +0000 (12:07 -0400)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 27 Sep 2013 12:16:52 +0000 (14:16 +0200)
Add thin compatibility layer for the deprecated GstVideoContext API.
For GStreamer API >= 1.2, this involves the following two functions:
- gst_vaapi_video_context_prepare(): queries if a context is already
  set in the pipeline ;
- gst_vaapi_video_context_propagate(): propagates the newly-created
  context to the rest of the pipeline.

https://bugzilla.gnome.org/show_bug.cgi?id=703235

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
gst/vaapi/Makefile.am
gst/vaapi/gstvaapipluginutil.c
gst/vaapi/gstvaapivideocontext.c [new file with mode: 0644]
gst/vaapi/gstvaapivideocontext.h [new file with mode: 0644]

index f6fc130..e9fba8c 100644 (file)
@@ -36,6 +36,7 @@ libgstvaapi_source_c = \
        gstvaapisink.c          \
        gstvaapiuploader.c      \
        gstvaapivideobuffer.c   \
+       gstvaapivideocontext.c  \
        gstvaapivideometa.c     \
        $(NULL)
 
@@ -45,6 +46,7 @@ libgstvaapi_source_h = \
        gstvaapisink.h          \
        gstvaapiuploader.h      \
        gstvaapivideobuffer.h   \
+       gstvaapivideocontext.h  \
        gstvaapivideometa.h     \
        $(NULL)
 
index 75210d5..43b1fc5 100644 (file)
@@ -22,9 +22,7 @@
  */
 
 #include "gst/vaapi/sysdeps.h"
-#if !GST_CHECK_VERSION(1,1,0)
-#include <gst/video/videocontext.h>
-#endif
+#include "gstvaapivideocontext.h"
 #if USE_DRM
 # include <gst/vaapi/gstvaapidisplay_drm.h>
 #endif
@@ -119,11 +117,9 @@ gst_vaapi_ensure_display(
 )
 {
     GstVaapiDisplay *display;
-#if !GST_CHECK_VERSION(1,1,0)
     GstVideoContext *context;
 
     g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
-#endif
     g_return_val_if_fail(display_ptr != NULL, FALSE);
 
     /* Already exist ? */
@@ -131,12 +127,10 @@ gst_vaapi_ensure_display(
     if (display)
         return TRUE;
 
-#if !GST_CHECK_VERSION(1,1,0)
     context = GST_VIDEO_CONTEXT(element);
     g_return_val_if_fail(context != NULL, FALSE);
 
-    gst_video_context_prepare(context, display_types);
-#endif
+    gst_vaapi_video_context_prepare(context, display_types);
 
     /* Neighbour found and it updated the display */
     if (*display_ptr)
@@ -147,6 +141,8 @@ gst_vaapi_ensure_display(
 
     if (display_ptr)
         *display_ptr = display;
+
+    gst_vaapi_video_context_propagate(context, display);
     return display != NULL;
 }
 
diff --git a/gst/vaapi/gstvaapivideocontext.c b/gst/vaapi/gstvaapivideocontext.c
new file mode 100644 (file)
index 0000000..1331d4b
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ *  gstvaapivideocontext.c - GStreamer/VA video context
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2013 Intel Corporation
+ *  Copyright (C) 2013 Igalia
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "gst/vaapi/sysdeps.h"
+#include "gstvaapivideocontext.h"
+
+#if GST_CHECK_VERSION(1,1,0)
+
+GST_DEBUG_CATEGORY_STATIC(GST_CAT_CONTEXT);
+
+#define GST_VAAPI_TYPE_DISPLAY \
+    gst_vaapi_display_get_type()
+
+GType
+gst_vaapi_display_get_type(void) G_GNUC_CONST;
+
+G_DEFINE_BOXED_TYPE(GstVaapiDisplay, gst_vaapi_display,
+    (GBoxedCopyFunc)gst_vaapi_display_ref,
+    (GBoxedFreeFunc)gst_vaapi_display_unref)
+
+GstContext *
+gst_vaapi_video_context_new_with_display(GstVaapiDisplay *display,
+    gboolean persistent)
+{
+    GstContext *context;
+    GstStructure *structure;
+
+    context = gst_context_new(GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME, persistent);
+    structure = gst_context_writable_structure(context);
+    gst_structure_set(structure, "display", GST_VAAPI_TYPE_DISPLAY,
+        display, NULL);
+    return context;
+}
+
+gboolean
+gst_vaapi_video_context_get_display(GstContext *context,
+    GstVaapiDisplay **display_ptr)
+{
+    const GstStructure *structure;
+
+    g_return_val_if_fail(GST_IS_CONTEXT(context), FALSE);
+    g_return_val_if_fail(g_strcmp0(gst_context_get_context_type(context),
+                  GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME) == 0, FALSE);
+
+    structure = gst_context_get_structure(context);
+    return gst_structure_get(structure, "display", GST_VAAPI_TYPE_DISPLAY,
+        display_ptr, NULL);
+}
+
+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
+run_context_query(GstElement *element, GstQuery *query)
+{
+    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 downstream neighbour */
+    it = gst_element_iterate_src_pads(element);
+    while (gst_iterator_fold(it, func, &res, query) == GST_ITERATOR_RESYNC)
+        gst_iterator_resync(it);
+    gst_iterator_free(it);
+
+    /* Ignore upstream neighbours */
+    return g_value_get_boolean(&res);
+}
+
+void
+gst_vaapi_video_context_prepare(GstElement *element, const gchar **types)
+{
+    GstContext *context;
+    GstQuery *query;
+
+    if (!GST_CAT_CONTEXT)
+        GST_DEBUG_CATEGORY_GET(GST_CAT_CONTEXT, "GST_CONTEXT");
+
+    /* (2) Query downstream with GST_QUERY_CONTEXT for the context and
+       check if downstream already has a context of the specified type */
+    context = NULL;
+    query = gst_query_new_context(GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME);
+    if (run_context_query(element, query)) {
+        gst_query_parse_context(query, &context);
+        GST_CAT_INFO_OBJECT(GST_CAT_CONTEXT, element,
+            "found context (%p) in query", context);
+        gst_element_set_context(element, context);
+    }
+    else {
+        /* (3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
+           the required context types and afterwards check if a usable
+           context was set now as in (1). The message could be handled
+           by the parent bins of the element and the application */
+        GstMessage *msg;
+
+        GST_CAT_INFO_OBJECT(GST_CAT_CONTEXT, element,
+            "posting `need-context' message");
+        msg = gst_message_new_need_context(GST_OBJECT_CAST(element),
+            GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME);
+        gst_element_post_message(element, msg);
+    }
+    gst_query_unref(query);
+}
+
+/* (4) Create context by itself and post a GST_MESSAGE_HAVE_CONTEXT
+   message and send a GST_EVENT_CONTEXT event downstream, thus
+   containing the complete context information at this time */
+void
+gst_vaapi_video_context_propagate(GstElement *element, GstVaapiDisplay *display)
+{
+    GstContext *context;
+    GstMessage *msg;
+
+    if (!display) {
+        GST_ERROR_OBJECT(element, "failed to get VA-API display connection");
+        return;
+    }
+
+    context = gst_vaapi_video_context_new_with_display(display, FALSE);
+
+    GST_CAT_INFO_OBJECT(GST_CAT_CONTEXT, element,
+        "posting `have-context' (%p) message with display (%p)",
+        context, display);
+    msg = gst_message_new_have_context(GST_OBJECT_CAST(element), context);
+    gst_element_post_message(GST_ELEMENT_CAST(element), msg);
+}
+
+#endif
diff --git a/gst/vaapi/gstvaapivideocontext.h b/gst/vaapi/gstvaapivideocontext.h
new file mode 100644 (file)
index 0000000..3ef5849
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  gstvaapivideocontext.h - GStreamer/VA video context
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *  Copyright (C) 2011-2013 Intel Corporation
+ *  Copyright (C) 2013 Igalia
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_VIDEO_CONTEXT_H
+#define GST_VAAPI_VIDEO_CONTEXT_H
+
+#include <gst/vaapi/gstvaapidisplay.h>
+
+#if GST_CHECK_VERSION(1,1,0)
+
+#define GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME "gst.vaapi.Display"
+
+/* Fake GstVideoContext symbols */
+#define GST_VIDEO_CONTEXT(obj)          (GST_ELEMENT(obj))
+#define GST_IS_VIDEO_CONTEXT(obj)       (GST_IS_ELEMENT(obj))
+#define GstVideoContext                 GstElement
+#define gst_video_context_prepare       gst_vaapi_video_context_prepare
+
+G_GNUC_INTERNAL
+GstContext *
+gst_vaapi_video_context_new_with_display(GstVaapiDisplay *display,
+    gboolean persistent);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_video_context_get_display(GstContext *context,
+    GstVaapiDisplay **display_ptr);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_video_context_prepare(GstElement *element, const gchar **types);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_video_context_propagate(GstElement *element,
+    GstVaapiDisplay *display);
+
+#else
+#include <gst/video/videocontext.h>
+
+static inline void
+gst_vaapi_video_context_prepare(GstVideoContext *context, const gchar **types)
+{
+    gst_video_context_prepare(context, types);
+}
+
+static inline void
+gst_vaapi_video_context_propagate(GstVideoContext *context,
+    GstVaapiDisplay *display)
+{
+}
+
+#endif
+
+#endif /* GST_VAAPI_VIDEO_CONTEXT_H */