mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
vtdec: add support for outputing vulkan images
This commit is contained in:
parent
52ff97d085
commit
526afac736
10 changed files with 867 additions and 26 deletions
|
@ -369,6 +369,7 @@ if ['darwin', 'ios'].contains(host_system)
|
|||
# cdata.set('HAVE_VIDEOTOOLBOX_10_9_6', 1)
|
||||
# endif
|
||||
endif
|
||||
have_objcpp = add_languages('objcpp', required : false)
|
||||
|
||||
have_orcc = false
|
||||
orcc_args = []
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
#include "iosurfaceglmemory.h"
|
||||
#endif
|
||||
#include "videotexturecache-gl.h"
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
#include "videotexturecache-vulkan.h"
|
||||
#if !HAVE_IOS
|
||||
#include "iosurfacevulkanmemory.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const GstMetaInfo *gst_core_video_meta_get_info (void);
|
||||
|
||||
|
@ -123,6 +129,13 @@ _create_glmem (GstAppleCoreVideoPixelBuffer * gpixbuf,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
/* in videotexturecache-vulkan.m to avoid objc-ism from Metal being included
|
||||
* in a non-objc file */
|
||||
extern GstMemory *_create_vulkan_memory (GstAppleCoreVideoPixelBuffer * gpixbuf,
|
||||
GstVideoInfo * info, guint plane, gsize size, GstVideoTextureCache * cache);
|
||||
#endif
|
||||
|
||||
void
|
||||
gst_core_video_wrap_pixel_buffer (GstBuffer * buf,
|
||||
GstVideoInfo * info,
|
||||
|
@ -136,6 +149,9 @@ gst_core_video_wrap_pixel_buffer (GstBuffer * buf,
|
|||
GstAppleCoreVideoPixelBuffer *gpixbuf;
|
||||
GstMemory *mem = NULL;
|
||||
gboolean do_gl = GST_IS_VIDEO_TEXTURE_CACHE_GL (cache);
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
gboolean do_vulkan = GST_IS_VIDEO_TEXTURE_CACHE_VULKAN (cache);
|
||||
#endif
|
||||
|
||||
gpixbuf = gst_apple_core_video_pixel_buffer_new (pixel_buf);
|
||||
|
||||
|
@ -158,6 +174,10 @@ gst_core_video_wrap_pixel_buffer (GstBuffer * buf,
|
|||
|
||||
if (do_gl)
|
||||
mem = _create_glmem (gpixbuf, info, i, size, cache);
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
else if (do_vulkan)
|
||||
mem = _create_vulkan_memory (gpixbuf, info, i, size, cache);
|
||||
#endif
|
||||
else
|
||||
mem =
|
||||
GST_MEMORY_CAST (gst_apple_core_video_memory_new_wrapped (gpixbuf,
|
||||
|
@ -172,6 +192,10 @@ gst_core_video_wrap_pixel_buffer (GstBuffer * buf,
|
|||
|
||||
if (do_gl)
|
||||
mem = _create_glmem (gpixbuf, info, 0, size, cache);
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
else if (do_vulkan)
|
||||
mem = _create_vulkan_memory (gpixbuf, info, 0, size, cache);
|
||||
#endif
|
||||
else
|
||||
mem =
|
||||
GST_MEMORY_CAST (gst_apple_core_video_memory_new_wrapped (gpixbuf, 0,
|
||||
|
|
241
sys/applemedia/iosurfacevulkanmemory.c
Normal file
241
sys/applemedia/iosurfacevulkanmemory.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* 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 "iosurfacevulkanmemory.h"
|
||||
#include "metal-helpers.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_IO_SURFACE_VULKAN_MEMORY);
|
||||
#define GST_CAT_DEFAULT GST_CAT_IO_SURFACE_VULKAN_MEMORY
|
||||
|
||||
G_DEFINE_TYPE (GstIOSurfaceVulkanMemoryAllocator,
|
||||
gst_io_surface_vulkan_memory_allocator,
|
||||
GST_TYPE_VULKAN_IMAGE_MEMORY_ALLOCATOR);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstIOSurfaceVulkanMemory *memory;
|
||||
IOSurfaceRef surface;
|
||||
} ContextThreadData;
|
||||
|
||||
static GstAllocator *_io_surface_vulkan_memory_allocator;
|
||||
|
||||
static void
|
||||
_mem_free (GstAllocator * allocator, GstMemory * mem)
|
||||
{
|
||||
gst_io_surface_vulkan_memory_set_surface ((GstIOSurfaceVulkanMemory *) mem,
|
||||
NULL);
|
||||
|
||||
GST_ALLOCATOR_CLASS
|
||||
(gst_io_surface_vulkan_memory_allocator_parent_class)->free (allocator,
|
||||
mem);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_io_surface_vulkan_memory_allocator_map (GstMemory * bmem,
|
||||
GstMapInfo * info, gsize size)
|
||||
{
|
||||
GstIOSurfaceVulkanMemory *mem = (GstIOSurfaceVulkanMemory *) bmem;
|
||||
|
||||
GST_LOG ("mapping surface %p flags %d", mem->surface, info->flags);
|
||||
|
||||
if (!(info->flags & GST_MAP_WRITE)) {
|
||||
IOSurfaceLock (mem->surface, kIOSurfaceLockReadOnly, NULL);
|
||||
return IOSurfaceGetBaseAddressOfPlane (mem->surface, mem->plane);
|
||||
} else {
|
||||
GST_ERROR ("couldn't map IOSurface %p flags %d", mem->surface, info->flags);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_io_surface_vulkan_memory_allocator_unmap (GstMemory * bmem, GstMapInfo * info)
|
||||
{
|
||||
GstIOSurfaceVulkanMemory *mem = (GstIOSurfaceVulkanMemory *) bmem;
|
||||
|
||||
GST_LOG ("unmapping surface %p flags %d", mem->surface, info->flags);
|
||||
|
||||
IOSurfaceUnlock (mem->surface, kIOSurfaceLockReadOnly, NULL);
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
_mem_alloc (GstAllocator * allocator, gsize size, GstAllocationParams * params)
|
||||
{
|
||||
g_warning
|
||||
("use gst_io_surface_vulkan_memory_wrapped () to allocate from this "
|
||||
"IOSurface allocator");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_io_surface_vulkan_memory_allocator_class_init
|
||||
(GstIOSurfaceVulkanMemoryAllocatorClass * klass)
|
||||
{
|
||||
GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
|
||||
|
||||
allocator_class->alloc = _mem_alloc;
|
||||
allocator_class->free = _mem_free;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_io_surface_vulkan_memory_allocator_init (GstIOSurfaceVulkanMemoryAllocator *
|
||||
allocator)
|
||||
{
|
||||
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
|
||||
|
||||
alloc->mem_type = GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_NAME;
|
||||
GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
|
||||
|
||||
alloc->mem_map_full = _io_surface_vulkan_memory_allocator_map;
|
||||
alloc->mem_unmap_full = _io_surface_vulkan_memory_allocator_unmap;
|
||||
}
|
||||
|
||||
void
|
||||
gst_io_surface_vulkan_memory_init (void)
|
||||
{
|
||||
static volatile gsize _init = 0;
|
||||
|
||||
if (g_once_init_enter (&_init)) {
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_IO_SURFACE_VULKAN_MEMORY,
|
||||
"iosurfacevulkan", 0, "IOSurface Vulkan Buffer");
|
||||
|
||||
_io_surface_vulkan_memory_allocator =
|
||||
g_object_new (GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR, NULL);
|
||||
gst_object_ref_sink (_io_surface_vulkan_memory_allocator);
|
||||
|
||||
gst_allocator_register (GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_NAME,
|
||||
gst_object_ref (_io_surface_vulkan_memory_allocator));
|
||||
g_once_init_leave (&_init, 1);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_is_io_surface_vulkan_memory (GstMemory * mem)
|
||||
{
|
||||
return mem != NULL && mem->allocator != NULL &&
|
||||
g_type_is_a (G_OBJECT_TYPE (mem->allocator),
|
||||
GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR);
|
||||
}
|
||||
|
||||
static GstIOSurfaceVulkanMemory *
|
||||
_io_surface_vulkan_memory_new (GstVulkanDevice * device, IOSurfaceRef surface,
|
||||
unsigned int /* MTLPixelFormat */ fmt, GstVideoInfo * info, guint plane,
|
||||
gpointer user_data, GDestroyNotify notify)
|
||||
{
|
||||
GstIOSurfaceVulkanMemory *mem;
|
||||
GstAllocationParams params = { 0, };
|
||||
VkImageCreateInfo image_info;
|
||||
VkPhysicalDevice gpu;
|
||||
VkImageUsageFlags usage;
|
||||
VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
VkFormat vk_format;
|
||||
VkImage image;
|
||||
GError *error = NULL;
|
||||
VkResult err;
|
||||
|
||||
mem = g_new0 (GstIOSurfaceVulkanMemory, 1);
|
||||
|
||||
vk_format = metal_format_to_vulkan (fmt);
|
||||
/* FIXME: choose from outside */
|
||||
usage =
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
image_info = (VkImageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = vk_format,
|
||||
/* MoltenVK double checks these against the IOSurface in vkUseIOSurface()
|
||||
* and will fail if they do not match */
|
||||
.extent = (VkExtent3D) { GST_VIDEO_INFO_COMP_WIDTH (info, plane), GST_VIDEO_INFO_COMP_HEIGHT (info, plane), 1 },
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = tiling,
|
||||
.usage = usage,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = NULL,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
gpu = gst_vulkan_device_get_physical_device (device);
|
||||
|
||||
err = vkCreateImage (device->device, &image_info, NULL, &image);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkCreateImage") < 0)
|
||||
goto vk_error;
|
||||
|
||||
vkGetImageMemoryRequirements (device->device, image,
|
||||
&mem->vulkan_mem.requirements);
|
||||
|
||||
gst_vulkan_image_memory_init (&mem->vulkan_mem,
|
||||
_io_surface_vulkan_memory_allocator, NULL, device, usage, ¶ms,
|
||||
mem->vulkan_mem.requirements.size, user_data, notify);
|
||||
mem->vulkan_mem.create_info = image_info;
|
||||
mem->vulkan_mem.image = image;
|
||||
mem->vulkan_mem.barrier.image_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
err =
|
||||
vkGetPhysicalDeviceImageFormatProperties (gpu, vk_format,
|
||||
VK_IMAGE_TYPE_2D, tiling, usage, 0, &mem->vulkan_mem.format_properties);
|
||||
if (gst_vulkan_error_to_g_error (err, &error,
|
||||
"vkGetPhysicalDeviceImageFormatProperties") < 0)
|
||||
goto vk_error;
|
||||
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);
|
||||
|
||||
mem->surface = NULL;
|
||||
mem->plane = plane;
|
||||
gst_io_surface_vulkan_memory_set_surface (mem, surface);
|
||||
|
||||
return mem;
|
||||
|
||||
vk_error:
|
||||
{
|
||||
GST_CAT_ERROR (GST_CAT_IO_SURFACE_VULKAN_MEMORY,
|
||||
"Failed to allocate image memory %s", error->message);
|
||||
g_clear_error (&error);
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
{
|
||||
if (mem)
|
||||
gst_memory_unref ((GstMemory *) mem);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GstIOSurfaceVulkanMemory *
|
||||
gst_io_surface_vulkan_memory_wrapped (GstVulkanDevice * device,
|
||||
IOSurfaceRef surface, unsigned int /* MTLPixelFormat */ fmt,
|
||||
GstVideoInfo * info, guint plane, gpointer user_data, GDestroyNotify notify)
|
||||
{
|
||||
return _io_surface_vulkan_memory_new (device, surface, fmt, info, plane,
|
||||
user_data, notify);
|
||||
}
|
77
sys/applemedia/iosurfacevulkanmemory.h
Normal file
77
sys/applemedia/iosurfacevulkanmemory.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* 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_IO_SURFACE_VULKAN_MEMORY_H_
|
||||
#define _GST_IO_SURFACE_VULKAN_MEMORY_H_
|
||||
|
||||
#include <IOSurface/IOSurfaceRef.h>
|
||||
#include <IOSurface/IOSurfaceObjc.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/gstallocator.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR (gst_io_surface_vulkan_memory_allocator_get_type())
|
||||
GType gst_io_surface_vulkan_memory_allocator_get_type(void);
|
||||
|
||||
#define GST_IS_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR))
|
||||
#define GST_IS_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR))
|
||||
#define GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR, GstIOSurfaceVulkanMemoryAllocatorClass))
|
||||
#define GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR, GstIOSurfaceVulkanMemoryAllocator))
|
||||
#define GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR, GstIOSurfaceVulkanMemoryAllocatorClass))
|
||||
#define GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_CAST(obj) ((GstIOSurfaceVulkanMemoryAllocator *)(obj))
|
||||
|
||||
typedef struct _GstIOSurfaceVulkanMemory
|
||||
{
|
||||
GstVulkanImageMemory vulkan_mem;
|
||||
IOSurfaceRef surface;
|
||||
guint plane;
|
||||
} GstIOSurfaceVulkanMemory;
|
||||
|
||||
#define GST_IO_SURFACE_VULKAN_MEMORY_ALLOCATOR_NAME "IOSurfaceVulkanMemory"
|
||||
|
||||
void gst_io_surface_vulkan_memory_init (void);
|
||||
|
||||
GstIOSurfaceVulkanMemory *
|
||||
gst_io_surface_vulkan_memory_wrapped (GstVulkanDevice * device,
|
||||
IOSurfaceRef surface,
|
||||
unsigned int fmt, /* MTLPixelFormat */
|
||||
GstVideoInfo * info,
|
||||
guint plane,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
gboolean gst_is_io_surface_vulkan_memory (GstMemory * mem);
|
||||
|
||||
typedef struct _GstIOSurfaceVulkanMemoryAllocator
|
||||
{
|
||||
GstVulkanMemoryAllocator allocator;
|
||||
} GstIOSurfaceVulkanMemoryAllocator;
|
||||
|
||||
typedef struct _GstIOSurfaceVulkanMemoryAllocatorClass
|
||||
{
|
||||
GstVulkanMemoryAllocatorClass parent_class;
|
||||
} GstIOSurfaceVulkanMemoryAllocatorClass;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GST_IO_SURFACE_MEMORY_H_ */
|
|
@ -68,12 +68,12 @@ if host_system == 'ios'
|
|||
applemedia_objc_args += ['-fobjc-abi-version=2', '-fobjc-legacy-dispatch']
|
||||
|
||||
ios_media_dep = dependency('appleframeworks', modules : ['Foundation', 'AssetsLibrary'], required : applemedia_option)
|
||||
applemedia_frameworks += [ios_media_dep]
|
||||
iosurface_dep = dependency('IOSurface', required : applemedia_option)
|
||||
applemedia_frameworks += [ios_media_dep, iosurface_dep]
|
||||
else
|
||||
applemedia_sources += [
|
||||
'iosurfaceglmemory.c'
|
||||
]
|
||||
applemedia_objc_args += ['-mmacosx-version-min=10.8']
|
||||
cocoa_dep = dependency('Cocoa', required : applemedia_option)
|
||||
iosurface_dep = dependency('IOSurface', required : applemedia_option)
|
||||
applemedia_opengl_dep = dependency('appleframeworks', modules : ['OpenGL'], required : applemedia_option)
|
||||
|
@ -87,11 +87,25 @@ foreach framework : applemedia_frameworks
|
|||
endif
|
||||
endforeach
|
||||
|
||||
if gstvulkan_dep.found() and have_objcpp
|
||||
moltenvk_dep = cc.find_library('MoltenVK', required : false)
|
||||
metal_dep = dependency('appleframeworks', modules : ['Metal'], required : false)
|
||||
if metal_dep.found() and moltenvk_dep.found() and cc.has_header ('MoltenVK/vk_mvk_moltenvk.h')
|
||||
applemedia_frameworks += [moltenvk_dep, gstvulkan_dep, metal_dep]
|
||||
applemedia_sources += [
|
||||
'videotexturecache-vulkan.mm',
|
||||
'iosurfacevulkanmemory.c',
|
||||
]
|
||||
applemedia_args += ['-DAPPLEMEDIA_MOLTENVK']
|
||||
endif
|
||||
endif
|
||||
|
||||
if applemedia_found_deps
|
||||
gstapplemedia = library('gstapplemedia',
|
||||
applemedia_sources,
|
||||
c_args : gst_plugins_bad_args + applemedia_args,
|
||||
objc_args : gst_plugins_bad_args + applemedia_args + applemedia_objc_args,
|
||||
objcpp_args : gst_plugins_bad_args + applemedia_args + applemedia_objc_args,
|
||||
link_args : noseh_link_args,
|
||||
include_directories : [configinc, libsinc],
|
||||
dependencies : [gstvideo_dep, gstaudio_dep, gstpbutils_dep, gst_dep, gstbase_dep, gstgl_dep] + applemedia_frameworks,
|
||||
|
|
44
sys/applemedia/metal-helpers.h
Normal file
44
sys/applemedia/metal-helpers.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* 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 _APPLEMEDIA_METAL_HELPERS_H_
|
||||
#define _APPLEMEDIA_METAL_HELPERS_H_
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "corevideomemory.h"
|
||||
#include "videotexturecache.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
VkFormat metal_format_to_vulkan (unsigned int fmt);
|
||||
unsigned int video_info_to_metal_format (GstVideoInfo * info,
|
||||
guint plane);
|
||||
|
||||
GstMemory * _create_vulkan_memory (GstAppleCoreVideoPixelBuffer * gpixbuf,
|
||||
GstVideoInfo * info,
|
||||
guint plane,
|
||||
gsize size,
|
||||
GstVideoTextureCache * cache);
|
||||
|
||||
void gst_io_surface_vulkan_memory_set_surface (GstIOSurfaceVulkanMemory * memory,
|
||||
IOSurfaceRef surface);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* _APPLEMEDIA_METAL_HELPERS_H_ */
|
52
sys/applemedia/videotexturecache-vulkan.h
Normal file
52
sys/applemedia/videotexturecache-vulkan.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* 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_CORE_VIDEO_TEXTURE_CACHE_VULKAN_H__
|
||||
#define __GST_CORE_VIDEO_TEXTURE_CACHE_VULKAN_H__
|
||||
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
#include "videotexturecache.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN (gst_video_texture_cache_vulkan_get_type())
|
||||
#define GST_VIDEO_TEXTURE_CACHE_VULKAN(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN, GstVideoTextureCacheVulkan))
|
||||
#define GST_VIDEO_TEXTURE_CACHE_VULKAN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN, GstVideoTextureCacheVulkanClass))
|
||||
#define GST_IS_VIDEO_TEXTURE_CACHE_VULKAN(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN))
|
||||
#define GST_IS_VIDEO_TEXTURE_CACHE_VULKAN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN))
|
||||
#define GST_VIDEO_TEXTURE_CACHE_VULKAN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN, GstVideoTextureCacheVulkanClass))
|
||||
GType gst_video_texture_cache_vulkan_get_type (void);
|
||||
|
||||
typedef struct _GstVideoTextureCacheVulkan
|
||||
{
|
||||
GstVideoTextureCache parent;
|
||||
|
||||
GstVulkanDevice *device;
|
||||
} GstVideoTextureCacheVulkan;
|
||||
|
||||
typedef struct _GstVideoTextureCacheVulkanClass
|
||||
{
|
||||
GstVideoTextureCacheClass parent_class;
|
||||
} GstVideoTextureCacheVulkanClass;
|
||||
|
||||
GstVideoTextureCache * gst_video_texture_cache_vulkan_new (GstVulkanDevice * device);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_CORE_VIDEO_TEXTURE_CACHE_H__ */
|
301
sys/applemedia/videotexturecache-vulkan.mm
Normal file
301
sys/applemedia/videotexturecache-vulkan.mm
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* 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 <Metal/Metal.h>
|
||||
|
||||
#if !HAVE_IOS
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
#include "iosurfacevulkanmemory.h"
|
||||
|
||||
/* silence macor redefinition warnings */
|
||||
#undef VK_USE_PLATFORM_MACOS_MVK
|
||||
#undef VK_USE_PLATFORM_IOS_MVK
|
||||
#include <MoltenVK/vk_mvk_moltenvk.h>
|
||||
#include <MoltenVK/mvk_datatypes.h>
|
||||
/* silence macro redefinition warnings */
|
||||
#undef VK_USE_PLATFORM_MACOS_MVK
|
||||
#undef VK_USE_PLATFORM_IOS_MVK
|
||||
|
||||
#include "coremediabuffer.h"
|
||||
#include "corevideobuffer.h"
|
||||
#include "vtutil.h"
|
||||
|
||||
#include "videotexturecache-vulkan.h"
|
||||
#include "metal-helpers.h"
|
||||
|
||||
typedef struct _GstVideoTextureCacheVulkanPrivate
|
||||
{
|
||||
GstBufferPool *pool;
|
||||
} GstVideoTextureCacheVulkanPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GstVideoTextureCacheVulkan, gst_video_texture_cache_vulkan, GST_TYPE_VIDEO_TEXTURE_CACHE);
|
||||
|
||||
#define GET_PRIV(instance) \
|
||||
G_TYPE_INSTANCE_GET_PRIVATE (instance, GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN, GstVideoTextureCacheVulkanPrivate)
|
||||
|
||||
typedef struct _IOSTextureWrapper
|
||||
{
|
||||
CVMetalTextureCacheRef cache;
|
||||
CVMetalTextureRef texture;
|
||||
} IOSTextureWrapper;
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DEVICE,
|
||||
};
|
||||
|
||||
static GstMemory * gst_video_texture_cache_vulkan_create_memory (GstVideoTextureCache * cache,
|
||||
GstAppleCoreVideoPixelBuffer *gpixbuf, guint plane, gsize size);
|
||||
|
||||
GstVideoTextureCache *
|
||||
gst_video_texture_cache_vulkan_new (GstVulkanDevice * device)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), NULL);
|
||||
|
||||
return (GstVideoTextureCache *) g_object_new (GST_TYPE_VIDEO_TEXTURE_CACHE_VULKAN,
|
||||
"device", device, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_texture_cache_vulkan_finalize (GObject * object)
|
||||
{
|
||||
GstVideoTextureCacheVulkan *cache_vulkan = GST_VIDEO_TEXTURE_CACHE_VULKAN (object);
|
||||
|
||||
#if 0
|
||||
gst_buffer_pool_set_active (cache->pool, FALSE);
|
||||
gst_object_unref (cache->pool);
|
||||
#endif
|
||||
gst_object_unref (cache_vulkan->device);
|
||||
|
||||
G_OBJECT_CLASS (gst_video_texture_cache_vulkan_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_texture_cache_vulkan_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstVideoTextureCacheVulkan *cache_vulkan = GST_VIDEO_TEXTURE_CACHE_VULKAN (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DEVICE:
|
||||
cache_vulkan->device = (GstVulkanDevice *) g_value_dup_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_texture_cache_vulkan_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstVideoTextureCacheVulkan *cache_vulkan = GST_VIDEO_TEXTURE_CACHE_VULKAN (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, cache_vulkan->device);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_texture_cache_vulkan_constructed (GObject * object)
|
||||
{
|
||||
GstVideoTextureCacheVulkan *cache_vulkan = GST_VIDEO_TEXTURE_CACHE_VULKAN (object);
|
||||
|
||||
g_return_if_fail (GST_IS_VULKAN_DEVICE (cache_vulkan->device));
|
||||
|
||||
gst_io_surface_vulkan_memory_init ();
|
||||
#if 0
|
||||
cache->pool = GST_BUFFER_POOL (gst_vulkan_buffer_pool_new (ctx));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_texture_cache_vulkan_init (GstVideoTextureCacheVulkan * cache_vulkan)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_texture_cache_vulkan_class_init (GstVideoTextureCacheVulkanClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstVideoTextureCacheClass *cache_class = (GstVideoTextureCacheClass *) klass;
|
||||
|
||||
gobject_class->set_property = gst_video_texture_cache_vulkan_set_property;
|
||||
gobject_class->get_property = gst_video_texture_cache_vulkan_get_property;
|
||||
gobject_class->constructed = gst_video_texture_cache_vulkan_constructed;
|
||||
gobject_class->finalize = gst_video_texture_cache_vulkan_finalize;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_DEVICE,
|
||||
g_param_spec_object ("device", "device",
|
||||
"Associated Vulkan device", GST_TYPE_VULKAN_DEVICE,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
cache_class->create_memory = gst_video_texture_cache_vulkan_create_memory;
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
gst_video_texture_cache_vulkan_create_memory (GstVideoTextureCache * cache,
|
||||
GstAppleCoreVideoPixelBuffer *gpixbuf, guint plane, gsize size)
|
||||
{
|
||||
return (GstMemory *) gpixbuf;
|
||||
}
|
||||
|
||||
VkFormat
|
||||
metal_format_to_vulkan (unsigned int fmt)
|
||||
{
|
||||
MTLPixelFormat mtl_fmt = (MTLPixelFormat) fmt;
|
||||
|
||||
switch (mtl_fmt) {
|
||||
case MTLPixelFormatRGBA8Unorm:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case MTLPixelFormatRG8Unorm:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case MTLPixelFormatR8Unorm:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
video_info_to_metal_format (GstVideoInfo * info, guint plane)
|
||||
{
|
||||
switch (GST_VIDEO_INFO_FORMAT (info)) {
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
return (unsigned int) MTLPixelFormatRGBA8Unorm;
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
if (plane == 0)
|
||||
return (unsigned int) MTLPixelFormatR8Unorm;
|
||||
else
|
||||
return (unsigned int) MTLPixelFormatRG8Unorm;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
GstMemory *
|
||||
_create_vulkan_memory (GstAppleCoreVideoPixelBuffer * gpixbuf,
|
||||
GstVideoInfo * info, guint plane, gsize size, GstVideoTextureCache * cache)
|
||||
{
|
||||
GstIOSurfaceVulkanMemory *mem;
|
||||
CVPixelBufferRef pixel_buf = gpixbuf->buf;
|
||||
IOSurfaceRef surface = CVPixelBufferGetIOSurface (pixel_buf);
|
||||
GstVideoTextureCacheVulkan *cache_vulkan =
|
||||
GST_VIDEO_TEXTURE_CACHE_VULKAN (cache);
|
||||
MTLPixelFormat fmt = video_info_to_metal_format (info, plane);
|
||||
|
||||
CFRetain (pixel_buf);
|
||||
mem = gst_io_surface_vulkan_memory_wrapped (cache_vulkan->device,
|
||||
surface, fmt, info, plane, pixel_buf, (GDestroyNotify) CFRelease);
|
||||
|
||||
if (!mem)
|
||||
return NULL;
|
||||
|
||||
return GST_MEMORY_CAST (mem);
|
||||
}
|
||||
|
||||
typedef struct _IOSurfaceTextureWrapper
|
||||
{
|
||||
CVPixelBufferRef pixbuf;
|
||||
gpointer texture; /* id<MTLTexture> */
|
||||
} IOSurfaceTextureWrapper;
|
||||
|
||||
static void
|
||||
free_texture_wrapper (IOSurfaceTextureWrapper * wrapper)
|
||||
{
|
||||
CFRelease (wrapper->pixbuf);
|
||||
id<MTLTexture> tex = (__bridge_transfer id<MTLTexture>) wrapper->texture;
|
||||
(void) tex;
|
||||
g_free (wrapper);
|
||||
}
|
||||
|
||||
static MTLTextureDescriptor *
|
||||
gst_new_mtl_tex_descripter_from_memory (GstIOSurfaceVulkanMemory * memory)
|
||||
{
|
||||
GstVulkanImageMemory *vk_mem = (GstVulkanImageMemory *) memory;
|
||||
MTLTextureDescriptor* tex_desc = [MTLTextureDescriptor new];
|
||||
tex_desc.pixelFormat = mvkMTLPixelFormatFromVkFormat (vk_mem->create_info.format);
|
||||
tex_desc.textureType = mvkMTLTextureTypeFromVkImageType (vk_mem->create_info.imageType, 0, false);
|
||||
tex_desc.width = vk_mem->create_info.extent.width;
|
||||
tex_desc.height = vk_mem->create_info.extent.height;
|
||||
tex_desc.depth = vk_mem->create_info.extent.depth;
|
||||
tex_desc.mipmapLevelCount = vk_mem->create_info.mipLevels;
|
||||
tex_desc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(vk_mem->create_info.samples);
|
||||
tex_desc.arrayLength = vk_mem->create_info.arrayLayers;
|
||||
tex_desc.usage = MTLTextureUsageShaderRead | MTLTextureUsagePixelFormatView;//mvkMTLTextureUsageFromVkImageUsageFlags(vk_mem->create_info.usage);
|
||||
tex_desc.storageMode = MTLStorageModePrivate;//MTLStorageModeManaged; /* IOSurface == shared/managed */
|
||||
tex_desc.cpuCacheMode = MTLCPUCacheModeDefaultCache;//mvkMTLCPUCacheModeFromVkMemoryPropertyFlags(vk_mem->vk_mem->properties);
|
||||
|
||||
return tex_desc;
|
||||
}
|
||||
|
||||
void
|
||||
gst_io_surface_vulkan_memory_set_surface (GstIOSurfaceVulkanMemory * memory,
|
||||
IOSurfaceRef surface)
|
||||
{
|
||||
GstVulkanImageMemory *vk_mem = (GstVulkanImageMemory *) memory;
|
||||
|
||||
if (memory->surface) {
|
||||
IOSurfaceDecrementUseCount (memory->surface);
|
||||
} else {
|
||||
g_assert (vk_mem->notify == (GDestroyNotify) CFRelease);
|
||||
g_assert (vk_mem->user_data != NULL);
|
||||
}
|
||||
|
||||
memory->surface = surface;
|
||||
if (surface) {
|
||||
id<MTLDevice> mtl_dev = nil;
|
||||
id<MTLTexture> texture = nil;
|
||||
VkPhysicalDevice gpu;
|
||||
|
||||
IOSurfaceIncrementUseCount (surface);
|
||||
|
||||
gpu = gst_vulkan_device_get_physical_device (vk_mem->device);
|
||||
vkGetMTLDeviceMVK (gpu, &mtl_dev);
|
||||
|
||||
/* We cannot use vkUseIOSurfaceMVK() for multi-planer as MoltenVK does not
|
||||
* support them. */
|
||||
|
||||
MTLTextureDescriptor *tex_desc = gst_new_mtl_tex_descripter_from_memory (memory);
|
||||
texture = [mtl_dev newTextureWithDescriptor:tex_desc iosurface:surface plane:memory->plane];
|
||||
|
||||
IOSurfaceTextureWrapper *texture_data = g_new0 (IOSurfaceTextureWrapper, 1);
|
||||
texture_data->pixbuf = (CVPixelBufferRef) vk_mem->user_data;
|
||||
texture_data->texture = (__bridge_retained gpointer) texture;
|
||||
|
||||
VkResult err = vkSetMTLTextureMVK (memory->vulkan_mem.image, texture);
|
||||
GST_DEBUG ("bound texture %p to image %p: 0x%x", texture, memory->vulkan_mem.image,
|
||||
err);
|
||||
|
||||
vk_mem->user_data = texture_data;
|
||||
vk_mem->notify = (GDestroyNotify) free_texture_wrapper;
|
||||
}
|
||||
}
|
|
@ -45,6 +45,9 @@
|
|||
#include "corevideobuffer.h"
|
||||
#include "coremediabuffer.h"
|
||||
#include "videotexturecache-gl.h"
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
#include "videotexturecache-vulkan.h"
|
||||
#endif
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_vtdec_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_vtdec_debug_category
|
||||
|
@ -111,11 +114,21 @@ const CFStringRef
|
|||
CFSTR ("RequireHardwareAcceleratedVideoDecoder");
|
||||
#endif
|
||||
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
#define VIDEO_SRC_CAPS \
|
||||
GST_VIDEO_CAPS_MAKE("NV12") ";" \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES(GST_CAPS_FEATURE_MEMORY_GL_MEMORY,\
|
||||
"NV12") ", " \
|
||||
"texture-target = (string) rectangle;"
|
||||
"texture-target = (string) rectangle ; " \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES(GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE,\
|
||||
"NV12")
|
||||
#else
|
||||
#define VIDEO_SRC_CAPS \
|
||||
GST_VIDEO_CAPS_MAKE("NV12") ";" \
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES(GST_CAPS_FEATURE_MEMORY_GL_MEMORY,\
|
||||
"NV12") ", " \
|
||||
"texture-target = (string) rectangle "
|
||||
#endif
|
||||
|
||||
G_DEFINE_TYPE (GstVtdec, gst_vtdec, GST_TYPE_VIDEO_DECODER);
|
||||
|
||||
|
@ -210,20 +223,22 @@ gst_vtdec_stop (GstVideoDecoder * decoder)
|
|||
CFRelease (vtdec->format_description);
|
||||
vtdec->format_description = NULL;
|
||||
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
gst_clear_object (&vtdec->device);
|
||||
gst_clear_object (&vtdec->instance);
|
||||
#endif
|
||||
|
||||
GST_DEBUG_OBJECT (vtdec, "stop");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_texture_cache (GstVtdec * vtdec, GstGLContext * context)
|
||||
setup_texture_cache (GstVtdec * vtdec)
|
||||
{
|
||||
GstVideoCodecState *output_state;
|
||||
|
||||
g_return_if_fail (vtdec->texture_cache == NULL);
|
||||
|
||||
output_state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (vtdec));
|
||||
vtdec->texture_cache = gst_video_texture_cache_gl_new (context);
|
||||
gst_video_texture_cache_set_format (vtdec->texture_cache,
|
||||
GST_VIDEO_FORMAT_NV12, output_state->caps);
|
||||
gst_video_codec_state_unref (output_state);
|
||||
|
@ -240,7 +255,10 @@ gst_vtdec_negotiate (GstVideoDecoder * decoder)
|
|||
GstVtdec *vtdec;
|
||||
OSStatus err = noErr;
|
||||
GstCapsFeatures *features = NULL;
|
||||
gboolean output_textures;
|
||||
gboolean output_textures = FALSE;
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
gboolean output_vulkan = FALSE;
|
||||
#endif
|
||||
|
||||
vtdec = GST_VTDEC (decoder);
|
||||
if (vtdec->session)
|
||||
|
@ -296,6 +314,12 @@ gst_vtdec_negotiate (GstVideoDecoder * decoder)
|
|||
GST_GL_TEXTURE_TARGET_2D_STR,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
output_vulkan =
|
||||
gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE);
|
||||
#endif
|
||||
}
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
@ -323,12 +347,20 @@ gst_vtdec_negotiate (GstVideoDecoder * decoder)
|
|||
}
|
||||
}
|
||||
|
||||
if (vtdec->texture_cache != NULL && !output_textures) {
|
||||
if (vtdec->texture_cache != NULL
|
||||
&& ((GST_IS_VIDEO_TEXTURE_CACHE_GL (vtdec->texture_cache)
|
||||
&& !output_textures)
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
|| (GST_IS_VIDEO_TEXTURE_CACHE_VULKAN (vtdec->texture_cache)
|
||||
&& !output_vulkan)
|
||||
#endif
|
||||
)) {
|
||||
g_object_unref (vtdec->texture_cache);
|
||||
vtdec->texture_cache = NULL;
|
||||
}
|
||||
|
||||
if (err == noErr && output_textures) {
|
||||
if (err == noErr) {
|
||||
if (output_textures) {
|
||||
GstVideoTextureCacheGL *cache_gl = NULL;
|
||||
|
||||
if (vtdec->texture_cache)
|
||||
|
@ -341,15 +373,57 @@ gst_vtdec_negotiate (GstVideoDecoder * decoder)
|
|||
vtdec->ctxh = gst_gl_context_helper_new (GST_ELEMENT (vtdec));
|
||||
gst_gl_context_helper_ensure_context (vtdec->ctxh);
|
||||
|
||||
GST_INFO_OBJECT (vtdec, "pushing textures, context %p old context %p",
|
||||
GST_INFO_OBJECT (vtdec, "pushing GL textures, context %p old context %p",
|
||||
vtdec->ctxh->context, cache_gl ? cache_gl->ctx : NULL);
|
||||
|
||||
if (cache_gl && cache_gl->ctx != vtdec->ctxh->context) {
|
||||
g_object_unref (vtdec->texture_cache);
|
||||
vtdec->texture_cache = NULL;
|
||||
}
|
||||
if (!vtdec->texture_cache)
|
||||
setup_texture_cache (vtdec, vtdec->ctxh->context);
|
||||
if (!vtdec->texture_cache) {
|
||||
vtdec->texture_cache =
|
||||
gst_video_texture_cache_gl_new (vtdec->ctxh->context);
|
||||
setup_texture_cache (vtdec);
|
||||
}
|
||||
}
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
if (output_vulkan) {
|
||||
GstVideoTextureCacheVulkan *cache_vulkan = NULL;
|
||||
|
||||
if (vtdec->texture_cache)
|
||||
cache_vulkan = GST_VIDEO_TEXTURE_CACHE_VULKAN (vtdec->texture_cache);
|
||||
|
||||
gst_vulkan_ensure_element_data (GST_ELEMENT (vtdec), NULL,
|
||||
&vtdec->instance);
|
||||
|
||||
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (vtdec),
|
||||
&vtdec->device)) {
|
||||
GError *error = NULL;
|
||||
GST_DEBUG_OBJECT (vtdec, "No device retrieved from peer elements");
|
||||
if (!(vtdec->device =
|
||||
gst_vulkan_instance_create_device (vtdec->instance, &error))) {
|
||||
GST_ELEMENT_ERROR (vtdec, RESOURCE, NOT_FOUND,
|
||||
("Failed to create vulkan device"), ("%s", error->message));
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (vtdec, "pushing vulkan images, device %" GST_PTR_FORMAT
|
||||
" old device %" GST_PTR_FORMAT, vtdec->device,
|
||||
cache_vulkan ? cache_vulkan->device : NULL);
|
||||
|
||||
if (cache_vulkan && cache_vulkan->device != vtdec->device) {
|
||||
g_object_unref (vtdec->texture_cache);
|
||||
vtdec->texture_cache = NULL;
|
||||
}
|
||||
if (!vtdec->texture_cache) {
|
||||
vtdec->texture_cache =
|
||||
gst_video_texture_cache_vulkan_new (vtdec->device);
|
||||
setup_texture_cache (vtdec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (prevcaps)
|
||||
|
@ -1043,6 +1117,11 @@ gst_vtdec_set_context (GstElement * element, GstContext * context)
|
|||
vtdec->ctxh = gst_gl_context_helper_new (element);
|
||||
gst_gl_handle_set_context (element, context,
|
||||
&vtdec->ctxh->display, &vtdec->ctxh->other_context);
|
||||
|
||||
#if defined (APPLEMEDIA_MOLTENVK)
|
||||
gst_vulkan_handle_set_context (element, context, NULL, &vtdec->instance);
|
||||
#endif
|
||||
|
||||
GST_ELEMENT_CLASS (gst_vtdec_parent_class)->set_context (element, context);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <VideoToolbox/VideoToolbox.h>
|
||||
#include "videotexturecache.h"
|
||||
#include "glcontexthelper.h"
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -51,6 +54,11 @@ struct _GstVtdec
|
|||
GstVideoTextureCache *texture_cache;
|
||||
GstGLContextHelper *ctxh;
|
||||
|
||||
#if defined(APPLEMEDIA_MOLTENVK)
|
||||
GstVulkanInstance *instance;
|
||||
GstVulkanDevice *device;
|
||||
#endif
|
||||
|
||||
gboolean require_hardware;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue