gstreamer/subprojects/gst-plugins-bad/tests/check/libs/vkimagebufferpool.c
2023-06-22 04:42:58 +00:00

244 lines
6.9 KiB
C

/* GStreamer
*
* Copyright (C) 2023 Igalia, S.L.
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/check/gstcheck.h>
#include <gst/vulkan/vulkan.h>
static GstVulkanInstance *instance;
static GstVulkanDevice *device;
static GstVulkanQueue *queue = NULL;
static gboolean
_choose_queue (GstVulkanDevice * device, GstVulkanQueue * _queue, gpointer data)
{
guint flags =
device->physical_device->queue_family_props[_queue->family].queueFlags;
guint expected_flags = VK_QUEUE_COMPUTE_BIT;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
if (data)
expected_flags = VK_QUEUE_VIDEO_DECODE_BIT_KHR;
#endif
if ((flags & expected_flags) != 0) {
gst_object_replace ((GstObject **) & queue, GST_OBJECT_CAST (_queue));
return FALSE;
}
return TRUE;
}
static void
setup (void)
{
instance = gst_vulkan_instance_new ();
fail_unless (gst_vulkan_instance_open (instance, NULL));
device = gst_vulkan_device_new_with_index (instance, 0);
fail_unless (gst_vulkan_device_open (device, NULL));
gst_vulkan_device_foreach_queue (device, _choose_queue, NULL);
fail_unless (GST_IS_VULKAN_QUEUE (queue));
}
static void
teardown (void)
{
gst_clear_object (&queue);
gst_object_unref (device);
gst_object_unref (instance);
}
static GstBufferPool *
create_buffer_pool (const char *format, VkImageUsageFlags usage,
GstCaps * dec_caps)
{
GstCaps *caps;
GstBufferPool *pool;
GstStructure *config;
caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, format,
"width", G_TYPE_INT, 1024, "height", G_TYPE_INT, 780, NULL);
gst_caps_set_features_simple (caps,
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE, NULL));
pool = gst_vulkan_image_buffer_pool_new (device);
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, caps, 1024, 1, 0);
gst_caps_unref (caps);
gst_vulkan_image_buffer_pool_config_set_allocation_params (config,
usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (dec_caps)
gst_vulkan_image_buffer_pool_config_set_decode_caps (config, dec_caps);
fail_unless (gst_buffer_pool_set_config (pool, config));
gst_buffer_pool_set_active (pool, TRUE);
return pool;
}
GST_START_TEST (test_image)
{
GstBufferPool *pool;
GstFlowReturn ret;
GstBuffer *buffer = NULL;
pool = create_buffer_pool ("NV12", 0, NULL);
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
fail_unless (ret == GST_FLOW_OK);
gst_buffer_unref (buffer);
gst_buffer_pool_set_active (pool, FALSE);
gst_object_unref (pool);
}
GST_END_TEST;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
GST_START_TEST (test_vulkan_profiles)
{
GstCaps *caps;
/* *INDENT-OFF* */
GstVulkanVideoProfile profile2 = { { 0, }, }, profile = {
.profile = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,
.pNext = &profile.codec,
.videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR,
.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR,
.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR,
.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR,
},
.codec.h265 = {
.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR,
.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN_10,
}
};
/* *INDENT-ON* */
caps = gst_vulkan_video_profile_to_caps (&profile);
fail_unless (caps);
fail_unless (gst_vulkan_video_profile_from_caps (&profile2, caps));
gst_caps_unref (caps);
fail_unless (profile2.profile.sType
== VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR);
fail_unless (profile2.profile.videoCodecOperation
== profile.profile.videoCodecOperation);
fail_unless (profile2.codec.h265.stdProfileIdc
== profile.codec.h265.stdProfileIdc);
}
GST_END_TEST;
GST_START_TEST (test_decoding_image)
{
GstBufferPool *pool;
GstCaps *dec_caps;
GstBuffer *buffer = NULL;
GstFlowReturn ret;
/* *INDENT-OFF* */
GstVulkanVideoProfile profile = {
.profile = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,
.pNext = &profile.codec,
.videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,
.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR,
.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,
.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,
},
.codec.h264 = {
.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR,
.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN,
.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR,
}
};
/* *INDENT-ON* */
/* force to use a queue with decoding support */
if (queue && (device->physical_device->queue_family_ops[queue->family].video
& VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) == 0)
gst_clear_object (&queue);
if (!queue) {
gst_vulkan_device_foreach_queue (device, _choose_queue,
GUINT_TO_POINTER (1));
}
if (!queue)
return;
if ((device->physical_device->queue_family_ops[queue->family].video
& VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) == 0)
return;
dec_caps = gst_vulkan_video_profile_to_caps (&profile);
fail_unless (dec_caps);
pool = create_buffer_pool ("NV12", VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR,
dec_caps);
gst_caps_unref (dec_caps);
ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
fail_unless (ret == GST_FLOW_OK);
gst_buffer_unref (buffer);
gst_buffer_pool_set_active (pool, FALSE);
gst_object_unref (pool);
}
GST_END_TEST;
#endif
static Suite *
vkimagebufferpool_suite (void)
{
Suite *s = suite_create ("vkimagebufferpool");
TCase *tc_basic = tcase_create ("general");
gboolean have_instance;
suite_add_tcase (s, tc_basic);
tcase_add_checked_fixture (tc_basic, setup, teardown);
/* FIXME: CI doesn't have a software vulkan renderer (and none exists currently) */
instance = gst_vulkan_instance_new ();
have_instance = gst_vulkan_instance_open (instance, NULL);
gst_object_unref (instance);
if (have_instance) {
tcase_add_test (tc_basic, test_image);
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
tcase_add_test (tc_basic, test_decoding_image);
tcase_add_test (tc_basic, test_vulkan_profiles);
#endif
}
return s;
}
GST_CHECK_MAIN (vkimagebufferpool);