diff --git a/ext/vulkan/Makefile.am b/ext/vulkan/Makefile.am index 2b28b3db03..d99eaa5fe9 100644 --- a/ext/vulkan/Makefile.am +++ b/ext/vulkan/Makefile.am @@ -16,6 +16,7 @@ libgstvulkan_la_SOURCES = \ vkqueue.c \ vksink.c \ vkswapper.c \ + vkupload.c \ vkutils.c \ vkwindow.c @@ -32,6 +33,7 @@ noinst_HEADERS = \ vkqueue.h \ vksink.h \ vkswapper.h \ + vkupload.h \ vkutils.h \ vkutils_private.h \ vkwindow.h diff --git a/ext/vulkan/gstvulkan.c b/ext/vulkan/gstvulkan.c index 1fcc77be9c..7158895a2c 100644 --- a/ext/vulkan/gstvulkan.c +++ b/ext/vulkan/gstvulkan.c @@ -29,6 +29,7 @@ #endif #include "vksink.h" +#include "vkupload.h" #if GST_VULKAN_HAVE_WINDOW_X11 #include @@ -37,7 +38,6 @@ #define GST_CAT_DEFAULT gst_gl_gstgl_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); -/* Register filters that make up the gstgl plugin */ static gboolean plugin_init (GstPlugin * plugin) { @@ -53,6 +53,11 @@ plugin_init (GstPlugin * plugin) return FALSE; } + if (!gst_element_register (plugin, "vulkanupload", + GST_RANK_NONE, GST_TYPE_VULKAN_UPLOAD)) { + return FALSE; + } + return TRUE; } diff --git a/ext/vulkan/vksink.c b/ext/vulkan/vksink.c index 8afd9c563c..f3eff34f2c 100644 --- a/ext/vulkan/vksink.c +++ b/ext/vulkan/vksink.c @@ -68,7 +68,9 @@ static GstStaticPadTemplate gst_vulkan_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGBA"))); + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES + (GST_CAPS_FEATURE_MEMORY_VULKAN_BUFFER, + GST_VULKAN_SWAPPER_VIDEO_FORMATS))); enum { diff --git a/ext/vulkan/vkswapper.c b/ext/vulkan/vkswapper.c index 49dde09f18..c2e74acfff 100644 --- a/ext/vulkan/vkswapper.c +++ b/ext/vulkan/vkswapper.c @@ -181,8 +181,8 @@ _vulkan_swapper_retrieve_surface_properties (GstVulkanSwapper * swapper, supports_present = gst_vulkan_window_get_presentation_support (swapper->window, swapper->device, i); - if ((swapper->device->queue_family_props[i]. - queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { + if ((swapper->device-> + queue_family_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { if (supports_present) { /* found one that supports both */ graphics_queue = present_queue = i; @@ -360,6 +360,8 @@ gst_vulkan_swapper_get_supported_caps (GstVulkanSwapper * swapper, return NULL; caps = gst_caps_new_empty_simple ("video/x-raw"); + gst_caps_set_features (caps, 0, + gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VULKAN_BUFFER)); s = gst_caps_get_structure (caps, 0); { @@ -568,8 +570,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps, n_images_wanted = swapper->surf_props.maxImageCount; } - if (swapper-> - surf_props.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { + if (swapper->surf_props. + supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = swapper->surf_props.currentTransform; @@ -609,8 +611,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps, "Incorrect usage flags available for the swap images"); return FALSE; } - if ((swapper->surf_props. - supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + if ((swapper-> + surf_props.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) { usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } else { @@ -742,11 +744,8 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx, { GstVulkanBufferMemory *buf_mem; GstVulkanImageMemory *swap_mem; - GstMapInfo buf_map_info; - GstVideoFrame vframe; VkCommandBuffer cmd; VkResult err; - gsize size; g_return_val_if_fail (swap_idx < swapper->n_swap_chain_images, FALSE); swap_mem = swapper->swap_chain_images[swap_idx]; @@ -756,35 +755,7 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx, if (!gst_vulkan_device_create_cmd_buffer (swapper->device, &cmd, error)) return FALSE; - if (!gst_video_frame_map (&vframe, &swapper->v_info, buffer, GST_MAP_READ)) { - g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_MEMORY_MAP_FAILED, - "Failed to map buffer"); - return FALSE; - } - - size = - GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, - 0) * GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0); - buf_mem = (GstVulkanBufferMemory *) - gst_vulkan_buffer_memory_alloc_bind (swapper->device, - swap_mem->create_info.format, size, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - - if (!buf_mem) { - g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_MEMORY_MAP_FAILED, - "Failed to create staging memory"); - gst_video_frame_unmap (&vframe); - return FALSE; - } - - if (!gst_memory_map ((GstMemory *) buf_mem, &buf_map_info, GST_MAP_WRITE)) { - g_set_error (error, GST_VULKAN_ERROR, VK_ERROR_MEMORY_MAP_FAILED, - "Failed to map swap image"); - gst_video_frame_unmap (&vframe); - gst_memory_unref ((GstMemory *) buf_mem); - return FALSE; - } + buf_mem = (GstVulkanBufferMemory *) gst_buffer_peek_memory (buffer, 0); { VkCommandBufferInheritanceInfo buf_inh = { 0, }; @@ -809,11 +780,6 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx, return FALSE; } - g_assert (buf_map_info.size >= size); - memcpy (buf_map_info.data, vframe.data[0], size); - gst_memory_unmap ((GstMemory *) buf_mem, &buf_map_info); - gst_video_frame_unmap (&vframe); - if (!_swapper_set_image_layout_with_cmd (swapper, cmd, swap_mem, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, error)) { return FALSE; @@ -823,8 +789,8 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx, VkBufferImageCopy region = { 0, }; guint32 dst_width = gst_vulkan_image_memory_get_width (swap_mem); guint32 dst_height = gst_vulkan_image_memory_get_height (swap_mem); - guint src_width = GST_VIDEO_FRAME_WIDTH (&vframe); - guint src_height = GST_VIDEO_FRAME_HEIGHT (&vframe); + guint src_width = GST_VIDEO_INFO_WIDTH (&swapper->v_info); + guint src_height = GST_VIDEO_INFO_HEIGHT (&swapper->v_info); guint x, y; if (src_width != dst_width || src_height != dst_height) { @@ -855,8 +821,7 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx, return FALSE; cmd_data->cmd = cmd; - cmd_data->notify = (GDestroyNotify) gst_memory_unref; - cmd_data->data = buf_mem; + cmd_data->notify = NULL; if (!_new_fence (swapper->device, &cmd_data->fence, error)) { return FALSE; @@ -990,8 +955,21 @@ gboolean gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper, GstBuffer * buffer, GError ** error) { + GstMemory *mem; gboolean ret; + mem = gst_buffer_peek_memory (buffer, 0); + if (!mem) { + g_set_error_literal (error, GST_VULKAN_ERROR, VK_ERROR_FORMAT_NOT_SUPPORTED, + "Buffer has no memory"); + return FALSE; + } + if (!gst_is_vulkan_buffer_memory (mem)) { + g_set_error_literal (error, GST_VULKAN_ERROR, VK_ERROR_FORMAT_NOT_SUPPORTED, + "Incorrect memory type"); + return FALSE; + } + RENDER_LOCK (swapper); ret = _render_buffer_unlocked (swapper, buffer, error); RENDER_UNLOCK (swapper); diff --git a/ext/vulkan/vkswapper.h b/ext/vulkan/vkswapper.h index 1ffb493637..0486036259 100644 --- a/ext/vulkan/vkswapper.h +++ b/ext/vulkan/vkswapper.h @@ -35,6 +35,8 @@ G_BEGIN_DECLS #define GST_VULKAN_SWAPPER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VULKAN_SWAPPER, GstVulkanSwapperClass)) GType gst_vulkan_swapper_get_type (void); +#define GST_VULKAN_SWAPPER_VIDEO_FORMATS " { RGBA, BGRA, RGB, BGR } " + struct _GstVulkanSwapper { GstObject parent; diff --git a/ext/vulkan/vkupload.c b/ext/vulkan/vkupload.c new file mode 100644 index 0000000000..1070db02a6 --- /dev/null +++ b/ext/vulkan/vkupload.c @@ -0,0 +1,436 @@ +/* + * GStreamer + * Copyright (C) 2016 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. + */ + +/** + * SECTION:element-vulkanupload + * + * vulkanupload uploads data into Vulkan memory objects. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "vkupload.h" + +GST_DEBUG_CATEGORY (gst_debug_vulkan_upload); +#define GST_CAT_DEFAULT gst_debug_vulkan_upload + +static void gst_vulkan_upload_finalize (GObject * object); +static void gst_vulkan_upload_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * param_spec); +static void gst_vulkan_upload_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * param_spec); + +static gboolean gst_vulkan_upload_query (GstBaseTransform * bt, + GstPadDirection direction, GstQuery * query); +static void gst_vulkan_upload_set_context (GstElement * element, + GstContext * context); +static GstStateChangeReturn gst_vulkan_upload_change_state (GstElement * + element, GstStateChange transition); + +static gboolean gst_vulkan_upload_set_caps (GstBaseTransform * bt, + GstCaps * in_caps, GstCaps * out_caps); +static GstCaps *gst_vulkan_upload_transform_caps (GstBaseTransform * bt, + GstPadDirection direction, GstCaps * caps, GstCaps * filter); +static GstFlowReturn gst_vulkan_upload_transform (GstBaseTransform * bt, + GstBuffer * inbuf, GstBuffer * outbuf); +static GstFlowReturn gst_vulkan_upload_prepare_output_buffer (GstBaseTransform * + bt, GstBuffer * inbuf, GstBuffer ** outbuf); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw")); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw(memory:" + GST_VULKAN_BUFFER_MEMORY_ALLOCATOR_NAME ") ; " "video/x-raw")); + +enum +{ + PROP_0, +}; + +enum +{ + SIGNAL_0, + LAST_SIGNAL +}; + +/* static guint gst_vulkan_upload_signals[LAST_SIGNAL] = { 0 }; */ + +#define gst_vulkan_upload_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstVulkanUpload, gst_vulkan_upload, + GST_TYPE_BASE_TRANSFORM, GST_DEBUG_CATEGORY_INIT (gst_debug_vulkan_upload, + "vulkanupload", 0, "Vulkan Uploader")); + +static void +gst_vulkan_upload_class_init (GstVulkanUploadClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseTransformClass *gstbasetransform_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasetransform_class = (GstBaseTransformClass *) klass; + + gobject_class->set_property = gst_vulkan_upload_set_property; + gobject_class->get_property = gst_vulkan_upload_get_property; + + gst_element_class_set_metadata (gstelement_class, "Vulkan Uploader", + "Filter/Video", "A Vulkan data uploader", + "Matthew Waters "); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_template)); + + gobject_class->finalize = gst_vulkan_upload_finalize; + + gstelement_class->change_state = gst_vulkan_upload_change_state; + gstelement_class->set_context = gst_vulkan_upload_set_context; + gstbasetransform_class->query = GST_DEBUG_FUNCPTR (gst_vulkan_upload_query); + gstbasetransform_class->set_caps = gst_vulkan_upload_set_caps; + gstbasetransform_class->transform_caps = gst_vulkan_upload_transform_caps; + gstbasetransform_class->transform = gst_vulkan_upload_transform; + gstbasetransform_class->prepare_output_buffer = + gst_vulkan_upload_prepare_output_buffer; +} + +static void +gst_vulkan_upload_init (GstVulkanUpload * vk_upload) +{ +} + +static void +gst_vulkan_upload_finalize (GObject * object) +{ +// GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (object); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_vulkan_upload_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ +// GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vulkan_upload_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ +// GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_vulkan_upload_query (GstBaseTransform * bt, GstPadDirection direction, + GstQuery * query) +{ + GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (bt); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONTEXT:{ + res = gst_vulkan_handle_context_query (GST_ELEMENT (vk_upload), query, + &vk_upload->display, &vk_upload->instance, &vk_upload->device); + + if (res) + return res; + break; + } + default: + break; + } + + return GST_BASE_TRANSFORM_CLASS (parent_class)->query (bt, direction, query); +} + +static void +gst_vulkan_upload_set_context (GstElement * element, GstContext * context) +{ + GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (element); + + gst_vulkan_handle_set_context (element, context, &vk_upload->display, + &vk_upload->instance); + + GST_ELEMENT_CLASS (parent_class)->set_context (element, context); +} + +static gboolean +_find_vulkan_device (GstVulkanUpload * upload) +{ + /* Requires the instance to exist */ + GstQuery *query; + GstContext *context; + const GstStructure *s; + + if (upload->device) + return TRUE; + + query = gst_query_new_context ("gst.vulkan.device"); + if (!upload->device + && gst_vulkan_run_query (GST_ELEMENT (upload), query, GST_PAD_SRC)) { + gst_query_parse_context (query, &context); + if (context) { + s = gst_context_get_structure (context); + gst_structure_get (s, "device", GST_TYPE_VULKAN_DEVICE, &upload->device, + NULL); + } + } + if (!upload->device + && gst_vulkan_run_query (GST_ELEMENT (upload), query, GST_PAD_SINK)) { + gst_query_parse_context (query, &context); + if (context) { + s = gst_context_get_structure (context); + gst_structure_get (s, "device", GST_TYPE_VULKAN_DEVICE, &upload->device, + NULL); + } + } + + GST_DEBUG_OBJECT (upload, "found device %p", upload->device); + + gst_query_unref (query); + + if (upload->device) + return TRUE; + + return FALSE; +} + +static GstStateChangeReturn +gst_vulkan_upload_change_state (GstElement * element, GstStateChange transition) +{ + GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (element); + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + GST_DEBUG ("changing state: %s => %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!gst_vulkan_ensure_element_data (element, &vk_upload->display, + &vk_upload->instance)) { + GST_ELEMENT_ERROR (vk_upload, RESOURCE, NOT_FOUND, + ("Failed to retreive vulkan instance/display"), (NULL)); + return GST_STATE_CHANGE_FAILURE; + } + if (!_find_vulkan_device (vk_upload)) { + GST_ELEMENT_ERROR (vk_upload, RESOURCE, NOT_FOUND, + ("Failed to retreive vulkan device"), (NULL)); + return GST_STATE_CHANGE_FAILURE; + } + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (vk_upload->display) + gst_object_unref (vk_upload->display); + vk_upload->display = NULL; + if (vk_upload->device) + gst_object_unref (vk_upload->device); + vk_upload->device = NULL; + if (vk_upload->instance) + gst_object_unref (vk_upload->instance); + vk_upload->instance = NULL; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +static GstCaps * +gst_vulkan_upload_transform_caps (GstBaseTransform * bt, + GstPadDirection direction, GstCaps * caps, GstCaps * filter) +{ +// GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (bt); + GstCaps *tmp = NULL; + GstCaps *result = NULL; + + tmp = gst_caps_copy (caps); + + if (direction == GST_PAD_SINK) { + gst_caps_set_features (tmp, 0, + gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VULKAN_BUFFER)); + } else { + gst_caps_set_features (tmp, 0, + gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)); + } + + if (filter) { + GST_DEBUG_OBJECT (bt, "intersecting with filter caps %" GST_PTR_FORMAT, + filter); + + result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (tmp); + } else { + result = tmp; + } + + GST_DEBUG_OBJECT (bt, "returning caps: %" GST_PTR_FORMAT, result); + + return result; +} + +static gboolean +gst_vulkan_upload_set_caps (GstBaseTransform * bt, GstCaps * in_caps, + GstCaps * out_caps) +{ + GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (bt); + guint out_width, out_height; + guint i; + + if (!gst_video_info_from_caps (&vk_upload->in_info, in_caps)) + return FALSE; + + if (!gst_video_info_from_caps (&vk_upload->out_info, out_caps)) + return FALSE; + + out_width = GST_VIDEO_INFO_WIDTH (&vk_upload->out_info); + out_height = GST_VIDEO_INFO_HEIGHT (&vk_upload->out_info); + + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&vk_upload->out_info); i++) { + GstVideoFormat v_format = GST_VIDEO_INFO_FORMAT (&vk_upload->out_info); + GstVulkanImageMemory *img_mem; + VkFormat vk_format; + + vk_format = gst_vulkan_format_from_video_format (v_format, i); + + img_mem = (GstVulkanImageMemory *) + gst_vulkan_image_memory_alloc (vk_upload->device, vk_format, out_width, + out_height, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vk_upload->alloc_sizes[i] = img_mem->requirements.size; + + gst_memory_unref (GST_MEMORY_CAST (img_mem)); + } + + GST_DEBUG_OBJECT (bt, + "set caps in: %" GST_PTR_FORMAT " out: %" GST_PTR_FORMAT, in_caps, + out_caps); + + return TRUE; +} + +static GstFlowReturn +gst_vulkan_upload_prepare_output_buffer (GstBaseTransform * bt, + GstBuffer * inbuf, GstBuffer ** outbuf) +{ + GstVulkanUpload *vk_upload = GST_VULKAN_UPLOAD (bt); + GstBaseTransformClass *bclass; + GstVideoFrame v_frame; + guint i; + + bclass = GST_BASE_TRANSFORM_GET_CLASS (bt); + + if (!gst_video_frame_map (&v_frame, &vk_upload->in_info, inbuf, GST_MAP_READ)) { + GST_ELEMENT_ERROR (bt, RESOURCE, NOT_FOUND, + ("%s", "Failed to map input buffer"), NULL); + return GST_FLOW_ERROR; + } + + *outbuf = gst_buffer_new (); + + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&vk_upload->out_info); i++) { + GstVideoFormat v_format = GST_VIDEO_INFO_FORMAT (&vk_upload->out_info); + GstMapInfo map_info; + VkFormat vk_format; + gsize plane_size; + GstMemory *mem; + + vk_format = gst_vulkan_format_from_video_format (v_format, i); + + mem = gst_vulkan_buffer_memory_alloc_bind (vk_upload->device, + vk_format, vk_upload->alloc_sizes[i], + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + + if (!gst_memory_map (GST_MEMORY_CAST (mem), &map_info, GST_MAP_WRITE)) { + GST_ELEMENT_ERROR (bt, RESOURCE, NOT_FOUND, + ("%s", "Failed to map output memory"), NULL); + gst_buffer_unref (*outbuf); + *outbuf = NULL; + return GST_FLOW_ERROR; + } + + plane_size = + GST_VIDEO_INFO_PLANE_STRIDE (&vk_upload->out_info, + i) * GST_VIDEO_INFO_COMP_HEIGHT (&vk_upload->out_info, i); + g_assert (plane_size < map_info.size); + memcpy (map_info.data, v_frame.data[i], plane_size); + + gst_memory_unmap (GST_MEMORY_CAST (mem), &map_info); + + gst_buffer_append_memory (*outbuf, mem); + } + + gst_video_frame_unmap (&v_frame); + + bclass->copy_metadata (bt, inbuf, *outbuf); + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_vulkan_upload_transform (GstBaseTransform * bt, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + return GST_FLOW_OK; +} diff --git a/ext/vulkan/vkupload.h b/ext/vulkan/vkupload.h new file mode 100644 index 0000000000..02b8a22195 --- /dev/null +++ b/ext/vulkan/vkupload.h @@ -0,0 +1,63 @@ +/* + * GStreamer + * Copyright (C) 2016 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 _VK_UPLOAD_H_ +#define _VK_UPLOAD_H_ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VULKAN_UPLOAD (gst_vulkan_upload_get_type()) +#define GST_VULKAN_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VULKAN_UPLOAD,GstVulkanUpload)) +#define GST_VULKAN_UPLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VULKAN_UPLOAD,GstVulkanUploadClass)) +#define GST_IS_VULKAN_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VULKAN_UPLOAD)) +#define GST_IS_VULKAN_UPLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VULKAN_UPLOAD)) + +typedef struct _GstVulkanUpload GstVulkanUpload; +typedef struct _GstVulkanUploadClass GstVulkanUploadClass; + +struct _GstVulkanUpload +{ + GstBaseTransform parent; + + GstVulkanInstance *instance; + GstVulkanDevice *device; + + GstVulkanDisplay *display; + + GstVideoInfo in_info; + GstVideoInfo out_info; + + gsize alloc_sizes[GST_VIDEO_MAX_PLANES]; +}; + +struct _GstVulkanUploadClass +{ + GstBaseTransformClass video_sink_class; +}; + +GType gst_vulkan_upload_get_type(void); + +G_END_DECLS + +#endif