diff --git a/gst-libs/gst/vulkan/android/gstvkdisplay_android.c b/gst-libs/gst/vulkan/android/gstvkdisplay_android.c new file mode 100644 index 0000000000..5a4156d7d9 --- /dev/null +++ b/gst-libs/gst/vulkan/android/gstvkdisplay_android.c @@ -0,0 +1,86 @@ +/* + * GStreamer + * Copyright (C) 2019 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstvkdisplay_android.h" + +#define GST_CAT_DEFAULT gst_vulkan_display_debug +GST_DEBUG_CATEGORY_STATIC (gst_vulkan_display_debug); + +G_DEFINE_TYPE (GstVulkanDisplayAndroid, gst_vulkan_display_android, + GST_TYPE_VULKAN_DISPLAY); + +static void gst_vulkan_display_android_finalize (GObject * object); +static gpointer gst_vulkan_display_android_get_handle (GstVulkanDisplay * + display); + +static void +gst_vulkan_display_android_class_init (GstVulkanDisplayAndroidClass * klass) +{ + GST_VULKAN_DISPLAY_CLASS (klass)->get_handle = + GST_DEBUG_FUNCPTR (gst_vulkan_display_android_get_handle); + + G_OBJECT_CLASS (klass)->finalize = gst_vulkan_display_android_finalize; +} + +static void +gst_vulkan_display_android_init (GstVulkanDisplayAndroid * display_android) +{ + GstVulkanDisplay *display = (GstVulkanDisplay *) display_android; + + display->type = GST_VULKAN_DISPLAY_TYPE_ANDROID; +} + +static void +gst_vulkan_display_android_finalize (GObject * object) +{ + G_OBJECT_CLASS (gst_vulkan_display_android_parent_class)->finalize (object); +} + +/** + * gst_vulkan_display_android_new: + * + * Create a new #GstVulkanDisplayAndroid. + * + * Returns: (transfer full): a new #GstVulkanDisplayAndroid or %NULL + */ +GstVulkanDisplayAndroid * +gst_vulkan_display_android_new (void) +{ + GstVulkanDisplayAndroid *ret; + + GST_DEBUG_CATEGORY_GET (gst_vulkan_display_debug, "vulkandisplay"); + + ret = g_object_new (GST_TYPE_VULKAN_DISPLAY_ANDROID, NULL); + gst_object_ref_sink (ret); + + return ret; +} + +static gpointer +gst_vulkan_display_android_get_handle (GstVulkanDisplay * display) +{ + return NULL; +} diff --git a/gst-libs/gst/vulkan/android/gstvkdisplay_android.h b/gst-libs/gst/vulkan/android/gstvkdisplay_android.h new file mode 100644 index 0000000000..674e0f91a0 --- /dev/null +++ b/gst-libs/gst/vulkan/android/gstvkdisplay_android.h @@ -0,0 +1,63 @@ +/* + * GStreamer + * Copyright (C) 2019 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_VULKAN_DISPLAY_ANDROID_H__ +#define __GST_VULKAN_DISPLAY_ANDROID_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +GType gst_vulkan_display_android_get_type (void); + +#define GST_TYPE_VULKAN_DISPLAY_ANDROID (gst_vulkan_display_android_get_type()) +#define GST_VULKAN_DISPLAY_ANDROID(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VULKAN_DISPLAY_ANDROID,GstVulkanDisplayAndroid)) +#define GST_VULKAN_DISPLAY_ANDROID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_VULKAN_DISPLAY_ANDROID,GstVulkanDisplayAndroidClass)) +#define GST_IS_VULKAN_DISPLAY_ANDROID(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VULKAN_DISPLAY_ANDROID)) +#define GST_IS_VULKAN_DISPLAY_ANDROID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VULKAN_DISPLAY_ANDROID)) +#define GST_VULKAN_DISPLAY_ANDROID_CAST(obj) ((GstVulkanDisplayAndroid*)(obj)) + +typedef struct _GstVulkanDisplayAndroid GstVulkanDisplayAndroid; +typedef struct _GstVulkanDisplayAndroidClass GstVulkanDisplayAndroidClass; + +/** + * GstVulkanDisplayAndroid: + * + * the contents of a #GstVulkanDisplayAndroid are private and should only be accessed + * through the provided API + */ +struct _GstVulkanDisplayAndroid +{ + GstVulkanDisplay parent; +}; + +struct _GstVulkanDisplayAndroidClass +{ + GstVulkanDisplayClass object_class; +}; + +GstVulkanDisplayAndroid * gst_vulkan_display_android_new (void); + +G_END_DECLS + +#endif /* __GST_VULKAN_DISPLAY_ANDROID_H__ */ diff --git a/gst-libs/gst/vulkan/android/gstvkwindow_android.c b/gst-libs/gst/vulkan/android/gstvkwindow_android.c new file mode 100644 index 0000000000..c1bd866acd --- /dev/null +++ b/gst-libs/gst/vulkan/android/gstvkwindow_android.c @@ -0,0 +1,218 @@ +/* + * GStreamer + * Copyright (C) 2019 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include "gstvkwindow_android.h" +#include "gstvkdisplay_android.h" + +#define GET_PRIV(o) gst_vulkan_window_android_get_instance_private (o) + +#define GST_CAT_DEFAULT gst_vulkan_window_android_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +static void +_init_debug (void) +{ + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "vulkanwindowandroid", 0, + "Vulkan Android Window"); + g_once_init_leave (&_init, 1); + } +} + +enum +{ + PROP_0, +}; + +struct _GstVulkanWindowAndroidPrivate +{ + struct ANativeWindow *internal_window; + gint window_width, window_height; + + gint preferred_width; + gint preferred_height; +}; + +#define gst_vulkan_window_android_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstVulkanWindowAndroid, gst_vulkan_window_android, + GST_TYPE_VULKAN_WINDOW, + G_ADD_PRIVATE (GstVulkanWindowAndroid) _init_debug ()); + +static VkSurfaceKHR gst_vulkan_window_android_get_surface (GstVulkanWindow * + window, GError ** error); +static gboolean +gst_vulkan_window_android_get_presentation_support (GstVulkanWindow * window, + GstVulkanDevice * device, guint32 queue_family_idx); +static gboolean gst_vulkan_window_android_open (GstVulkanWindow * window, + GError ** error); +static void gst_vulkan_window_android_close (GstVulkanWindow * window); +static void gst_vulkan_window_android_set_window_handle (GstVulkanWindow * + window, guintptr window_handle); + +static void +gst_vulkan_window_android_class_init (GstVulkanWindowAndroidClass * klass) +{ + GstVulkanWindowClass *window_class = (GstVulkanWindowClass *) klass; + + window_class->open = GST_DEBUG_FUNCPTR (gst_vulkan_window_android_open); + window_class->close = GST_DEBUG_FUNCPTR (gst_vulkan_window_android_close); + window_class->get_surface = gst_vulkan_window_android_get_surface; + window_class->get_presentation_support = + gst_vulkan_window_android_get_presentation_support; + window_class->set_window_handle = gst_vulkan_window_android_set_window_handle; +} + +static void +gst_vulkan_window_android_init (GstVulkanWindowAndroid * window) +{ + GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window); + + priv->preferred_width = 320; + priv->preferred_height = 240; +} + +/* Must be called in the gl thread */ +GstVulkanWindowAndroid * +gst_vulkan_window_android_new (GstVulkanDisplay * display) +{ + GstVulkanWindowAndroid *window; + + _init_debug (); + + if ((gst_vulkan_display_get_handle_type (display) & + GST_VULKAN_DISPLAY_TYPE_ANDROID) + == GST_VULKAN_DISPLAY_TYPE_NONE) { + GST_INFO ("Wrong display type %u for this window type %u", display->type, + GST_VULKAN_DISPLAY_TYPE_ANDROID); + return NULL; + } + + window = g_object_new (GST_TYPE_VULKAN_WINDOW_ANDROID, NULL); + gst_object_ref_sink (window); + + return window; +} + +gboolean +gst_vulkan_window_android_create_window (GstVulkanWindowAndroid * + window_android) +{ + GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window_android); + + if (!priv->internal_window) { + GST_WARNING_OBJECT (window_android, "No ANativeWindow provided"); + return FALSE; + } + + return TRUE; +} + +static VkSurfaceKHR +gst_vulkan_window_android_get_surface (GstVulkanWindow * window, + GError ** error) +{ + GstVulkanWindowAndroid *window_android = GST_VULKAN_WINDOW_ANDROID (window); + GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window_android); + VkAndroidSurfaceCreateInfoKHR info = { 0, }; + VkSurfaceKHR ret; + VkResult err; + + if (!priv->internal_window) { + g_set_error_literal (error, GST_VULKAN_ERROR, + VK_ERROR_INITIALIZATION_FAILED, + "No layer to retrieve surface for. Has create_window() been called?"); + return 0; + } + + info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + info.pNext = NULL; + info.flags = 0; + info.window = priv->internal_window; + + if (!window_android->CreateAndroidSurface) + window_android->CreateAndroidSurface = + gst_vulkan_instance_get_proc_address (window->display->instance, + "vkCreateAndroidSurfaceKHR"); + if (!window_android->CreateAndroidSurface) { + g_set_error_literal (error, GST_VULKAN_ERROR, VK_ERROR_FEATURE_NOT_PRESENT, + "Could not retrieve \"vkCreateAndroidSurfaceKHR\" function pointer"); + return 0; + } + + err = + window_android->CreateAndroidSurface (window->display->instance->instance, + &info, NULL, &ret); + if (gst_vulkan_error_to_g_error (err, error, "vkCreateAndroidSurfaceKHR") < 0) + return 0; + + return ret; +} + +static gboolean +gst_vulkan_window_android_get_presentation_support (GstVulkanWindow * window, + GstVulkanDevice * device, guint32 queue_family_idx) +{ + return TRUE; +} + +static gboolean +gst_vulkan_window_android_open (GstVulkanWindow * window, GError ** error) +{ + GstVulkanWindowAndroid *window_android = GST_VULKAN_WINDOW_ANDROID (window); + + if (!GST_VULKAN_WINDOW_CLASS (parent_class)->open (window, error)) + return FALSE; + + return gst_vulkan_window_android_create_window (window_android); +} + +static void +gst_vulkan_window_android_close (GstVulkanWindow * window) +{ + GST_VULKAN_WINDOW_CLASS (parent_class)->close (window); +} + +static void +gst_vulkan_window_android_set_window_handle (GstVulkanWindow * window, + guintptr window_handle) +{ + GstVulkanWindowAndroid *window_android = GST_VULKAN_WINDOW_ANDROID (window); + GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window_android); + struct ANativeWindow *native_window = (struct ANativeWindow *) window_handle; + + g_return_if_fail (native_window != NULL); + + if (priv->internal_window && priv->internal_window != native_window) { + GST_FIXME_OBJECT (window_android, "View changes are not implemented"); + return; + } + + priv->internal_window = native_window; +} diff --git a/gst-libs/gst/vulkan/android/gstvkwindow_android.h b/gst-libs/gst/vulkan/android/gstvkwindow_android.h new file mode 100644 index 0000000000..8b44991cd5 --- /dev/null +++ b/gst-libs/gst/vulkan/android/gstvkwindow_android.h @@ -0,0 +1,79 @@ +/* + * GStreamer + * Copyright (C) 2019 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_VULKAN_WINDOW_ANDROID_H__ +#define __GST_VULKAN_WINDOW_ANDROID_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VULKAN_WINDOW_ANDROID (gst_vulkan_window_android_get_type()) +#define GST_VULKAN_WINDOW_ANDROID(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VULKAN_WINDOW_ANDROID, GstVulkanWindowAndroid)) +#define GST_VULKAN_WINDOW_ANDROID_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_TYPE_VULKAN_WINDOW_ANDROID, GstVulkanWindowAndroidClass)) +#define GST_IS_VULKAN_WINDOW_ANDROID(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_VULKAN_WINDOW_ANDROID)) +#define GST_IS_VULKAN_WINDOW_ANDROID_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_VULKAN_WINDOW_ANDROID)) +#define GST_VULKAN_WINDOW_ANDROID_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VULKAN_WINDOW_ANDROID, GstVulkanWindowAndroidClass)) + +typedef struct _GstVulkanWindowAndroid GstVulkanWindowAndroid; +typedef struct _GstVulkanWindowAndroidPrivate GstVulkanWindowAndroidPrivate; +typedef struct _GstVulkanWindowAndroidClass GstVulkanWindowAndroidClass; + +/** + * GstVulkanWindowAndroid: + * + * Opaque #GstVulkanWindowAndroid object + */ +struct _GstVulkanWindowAndroid +{ + /*< private >*/ + GstVulkanWindow parent; + + gint visible :1; + + PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurface; + + /*< private >*/ + gpointer _reserved[GST_PADDING]; +}; + +/** + * GstVulkanWindowAndroidClass: + * + * Opaque #GstVulkanWindowAndroidClass object + */ +struct _GstVulkanWindowAndroidClass { + /*< private >*/ + GstVulkanWindowClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING_LARGE]; +}; + +GType gst_vulkan_window_android_get_type (void); + +GstVulkanWindowAndroid * gst_vulkan_window_android_new (GstVulkanDisplay * display); + +gboolean gst_vulkan_window_android_create_window (GstVulkanWindowAndroid * window_android); + +G_END_DECLS + +#endif /* __GST_VULKAN_WINDOW_ANDROID_H__ */ diff --git a/gst-libs/gst/vulkan/gstvkconfig.h.meson b/gst-libs/gst/vulkan/gstvkconfig.h.meson index 527f3b15a8..638543edbc 100644 --- a/gst-libs/gst/vulkan/gstvkconfig.h.meson +++ b/gst-libs/gst/vulkan/gstvkconfig.h.meson @@ -15,6 +15,7 @@ G_BEGIN_DECLS #mesondefine GST_VULKAN_HAVE_WINDOW_COCOA #mesondefine GST_VULKAN_HAVE_WINDOW_IOS #mesondefine GST_VULKAN_HAVE_WINDOW_WIN32 +#mesondefine GST_VULKAN_HAVE_WINDOW_ANDROID G_END_DECLS diff --git a/gst-libs/gst/vulkan/gstvkdisplay.c b/gst-libs/gst/vulkan/gstvkdisplay.c index 94a5826215..6f48eb4b78 100644 --- a/gst-libs/gst/vulkan/gstvkdisplay.c +++ b/gst-libs/gst/vulkan/gstvkdisplay.c @@ -39,6 +39,9 @@ #if GST_VULKAN_HAVE_WINDOW_WIN32 #include "win32/gstvkwindow_win32.h" #endif +#if GST_VULKAN_HAVE_WINDOW_ANDROID +#include "android/gstvkdisplay_android.h" +#endif /** * SECTION:vkdisplay @@ -236,6 +239,11 @@ gst_vulkan_display_new_with_type (GstVulkanInstance * instance, display = GST_VULKAN_DISPLAY (gst_vulkan_display_ios_new ()); } #endif +#if GST_VULKAN_HAVE_WINDOW_ANDROID + if (!display && type & GST_VULKAN_DISPLAY_TYPE_ANDROID) { + display = GST_VULKAN_DISPLAY (gst_vulkan_display_android_new ()); + } +#endif if (display) display->instance = gst_object_ref (instance); @@ -522,6 +530,16 @@ gst_vulkan_display_choose_type (GstVulkanInstance * instance) first_supported = GST_VULKAN_DISPLAY_TYPE_WIN32; #endif +#if GST_VULKAN_HAVE_WINDOW_ANDROID + /* CHOOSE_WINSYS macro doesn't work with "ANDROID" */ + if (!type && g_strcmp0 (window_str, "android") == 0) { + type = GST_VULKAN_DISPLAY_TYPE_ANDROID; + } + + if (!first_supported) + first_supported = GST_VULKAN_DISPLAY_TYPE_ANDROID; +#endif + /* if there are no winsys enabled at build time, we get a 'unused but set' * warning. Remove that. */ (void) window_str; @@ -571,6 +589,10 @@ gst_vulkan_display_type_to_extension_string (GstVulkanDisplayType type) if (type & GST_VULKAN_DISPLAY_TYPE_WIN32) return VK_KHR_WIN32_SURFACE_EXTENSION_NAME; #endif +#if GST_VULKAN_HAVE_WINDOW_ANDROID + if (type & GST_VULKAN_DISPLAY_TYPE_ANDROID) + return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; +#endif return NULL; } diff --git a/gst-libs/gst/vulkan/gstvkdisplay.h b/gst-libs/gst/vulkan/gstvkdisplay.h index 35f66532ed..2a17ebaf84 100644 --- a/gst-libs/gst/vulkan/gstvkdisplay.h +++ b/gst-libs/gst/vulkan/gstvkdisplay.h @@ -61,6 +61,7 @@ typedef enum GST_VULKAN_DISPLAY_TYPE_COCOA = (1 << 2), GST_VULKAN_DISPLAY_TYPE_IOS = (1 << 3), GST_VULKAN_DISPLAY_TYPE_WIN32 = (1 << 4), + GST_VULKAN_DISPLAY_TYPE_ANDROID = (1 << 5), GST_VULKAN_DISPLAY_TYPE_ANY = G_MAXUINT32 } GstVulkanDisplayType; diff --git a/gst-libs/gst/vulkan/gstvkwindow.c b/gst-libs/gst/vulkan/gstvkwindow.c index e39bcd30e5..d99e071fe3 100644 --- a/gst-libs/gst/vulkan/gstvkwindow.c +++ b/gst-libs/gst/vulkan/gstvkwindow.c @@ -52,6 +52,9 @@ #if GST_VULKAN_HAVE_WINDOW_WIN32 #include "win32/gstvkwindow_win32.h" #endif +#if GST_VULKAN_HAVE_WINDOW_ANDROID +#include "android/gstvkwindow_android.h" +#endif #define GST_CAT_DEFAULT gst_vulkan_window_debug GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); @@ -250,6 +253,10 @@ gst_vulkan_window_new (GstVulkanDisplay * display) #if GST_VULKAN_HAVE_WINDOW_WIN32 if (!window && (!user_choice || g_strstr_len (user_choice, 5, "win32"))) window = GST_VULKAN_WINDOW (gst_vulkan_window_win32_new (display)); +#endif +#if GST_VULKAN_HAVE_WINDOW_ANDROID + if (!window && (!user_choice || g_strstr_len (user_choice, 7, "android"))) + window = GST_VULKAN_WINDOW (gst_vulkan_window_android_new (display)); #endif if (!window) { /* subclass returned a NULL window */ diff --git a/gst-libs/gst/vulkan/meson.build b/gst-libs/gst/vulkan/meson.build index ca6809db42..ccd2052b47 100644 --- a/gst-libs/gst/vulkan/meson.build +++ b/gst-libs/gst/vulkan/meson.build @@ -82,6 +82,7 @@ vulkan_conf_options = [ 'GST_VULKAN_HAVE_WINDOW_COCOA', 'GST_VULKAN_HAVE_WINDOW_IOS', 'GST_VULKAN_HAVE_WINDOW_WIN32', + 'GST_VULKAN_HAVE_WINDOW_ANDROID', ] foreach option : vulkan_conf_options @@ -218,6 +219,17 @@ if host_system == 'windows' endif endif +if host_system == 'android' + if cc.has_header('vulkan/vulkan_android.h', dependencies : vulkan_dep) + vulkan_sources += [ + 'android/gstvkdisplay_android.c', + 'android/gstvkwindow_android.c', + ] + vulkan_windowing = true + vulkan_conf.set10('GST_VULKAN_HAVE_WINDOW_ANDROID', 1) + endif +endif + if not vulkan_windowing warning('No Windowing system found. vulkansink will not work') endif