mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
234 lines
5.8 KiB
C
234 lines
5.8 KiB
C
|
/*
|
||
|
* GStreamer
|
||
|
* Copyright (C) 2023 Seungha Yang <seungha@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 <gst/gst.h>
|
||
|
#include <gst/check/gstcheck.h>
|
||
|
#include <gst/d3d11/gstd3d11.h>
|
||
|
#include <gst/video/video.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
static GstD3D11Device *device = NULL;
|
||
|
static GQuark memory_tester_quark;
|
||
|
|
||
|
static void
|
||
|
setup_func (void)
|
||
|
{
|
||
|
device = gst_d3d11_device_new (0, D3D11_CREATE_DEVICE_BGRA_SUPPORT);
|
||
|
fail_unless (GST_IS_D3D11_DEVICE (device));
|
||
|
|
||
|
memory_tester_quark = g_quark_from_static_string ("gst-d3d11-memory-tester");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
teardown_func (void)
|
||
|
{
|
||
|
gst_object_unref (device);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
allocator_finalize_cb (gboolean * alloc_finalized)
|
||
|
{
|
||
|
*alloc_finalized = TRUE;
|
||
|
}
|
||
|
|
||
|
GST_START_TEST (test_free_active_allocator)
|
||
|
{
|
||
|
GstD3D11PoolAllocator *alloc;
|
||
|
GstMemory *mem = NULL;
|
||
|
gboolean ret;
|
||
|
GstFlowReturn flow_ret;
|
||
|
gboolean alloc_finalized = FALSE;
|
||
|
D3D11_TEXTURE2D_DESC desc;
|
||
|
|
||
|
memset (&desc, 0, sizeof (desc));
|
||
|
|
||
|
desc.Width = 16;
|
||
|
desc.Height = 16;
|
||
|
desc.MipLevels = 1;
|
||
|
desc.ArraySize = 1;
|
||
|
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||
|
desc.SampleDesc.Count = 1;
|
||
|
desc.SampleDesc.Quality = 0;
|
||
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
||
|
|
||
|
alloc = gst_d3d11_pool_allocator_new (device, &desc);
|
||
|
fail_unless (alloc);
|
||
|
|
||
|
g_object_set_qdata_full (G_OBJECT (alloc), memory_tester_quark,
|
||
|
&alloc_finalized, (GDestroyNotify) allocator_finalize_cb);
|
||
|
|
||
|
/* inactive pool should return flusing */
|
||
|
flow_ret = gst_d3d11_pool_allocator_acquire_memory (alloc, &mem);
|
||
|
fail_unless (flow_ret == GST_FLOW_FLUSHING);
|
||
|
fail_if (mem);
|
||
|
|
||
|
ret = gst_d3d11_allocator_set_active (GST_D3D11_ALLOCATOR (alloc), TRUE);
|
||
|
fail_unless (ret);
|
||
|
|
||
|
flow_ret = gst_d3d11_pool_allocator_acquire_memory (alloc, &mem);
|
||
|
fail_unless (flow_ret == GST_FLOW_OK);
|
||
|
fail_unless (mem);
|
||
|
|
||
|
gst_object_unref (alloc);
|
||
|
/* Only memory should hold refcount at this moment */
|
||
|
fail_unless (G_OBJECT (alloc)->ref_count == 1);
|
||
|
fail_if (alloc_finalized);
|
||
|
|
||
|
/* allocator should be finalized as well */
|
||
|
gst_memory_unref (mem);
|
||
|
fail_unless (alloc_finalized);
|
||
|
}
|
||
|
|
||
|
GST_END_TEST;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
GMutex lock;
|
||
|
GCond cond;
|
||
|
gboolean blocked;
|
||
|
GstBufferPool *pool;
|
||
|
} UnblockTestData;
|
||
|
|
||
|
static gpointer
|
||
|
alloc_thread (UnblockTestData * data)
|
||
|
{
|
||
|
GstBuffer *buffers[2];
|
||
|
GstBuffer *flush_buf = NULL;
|
||
|
GstFlowReturn ret;
|
||
|
|
||
|
g_mutex_lock (&data->lock);
|
||
|
ret = gst_buffer_pool_acquire_buffer (data->pool, &buffers[0], NULL);
|
||
|
fail_unless (ret == GST_FLOW_OK);
|
||
|
|
||
|
ret = gst_buffer_pool_acquire_buffer (data->pool, &buffers[1], NULL);
|
||
|
fail_unless (ret == GST_FLOW_OK);
|
||
|
|
||
|
/* below call will be blocked by buffer pool */
|
||
|
data->blocked = TRUE;
|
||
|
g_cond_signal (&data->cond);
|
||
|
g_mutex_unlock (&data->lock);
|
||
|
|
||
|
ret = gst_buffer_pool_acquire_buffer (data->pool, &flush_buf, NULL);
|
||
|
fail_unless (ret == GST_FLOW_FLUSHING);
|
||
|
|
||
|
gst_buffer_unref (buffers[0]);
|
||
|
gst_buffer_unref (buffers[1]);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
GST_START_TEST (test_unblock_on_stop)
|
||
|
{
|
||
|
GstStructure *config;
|
||
|
GstVideoInfo info;
|
||
|
GstCaps *caps;
|
||
|
GstD3D11AllocationParams *params;
|
||
|
UnblockTestData data;
|
||
|
GThread *thread;
|
||
|
|
||
|
data.blocked = FALSE;
|
||
|
g_mutex_init (&data.lock);
|
||
|
g_cond_init (&data.cond);
|
||
|
|
||
|
gst_video_info_set_format (&info, GST_VIDEO_FORMAT_NV12, 16, 16);
|
||
|
caps = gst_video_info_to_caps (&info);
|
||
|
fail_unless (caps);
|
||
|
|
||
|
data.pool = gst_d3d11_buffer_pool_new (device);
|
||
|
fail_unless (data.pool);
|
||
|
|
||
|
config = gst_buffer_pool_get_config (data.pool);
|
||
|
fail_unless (config);
|
||
|
|
||
|
params = gst_d3d11_allocation_params_new (device,
|
||
|
&info, GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY, 0, 0);
|
||
|
fail_unless (params);
|
||
|
|
||
|
params->desc[0].ArraySize = 2;
|
||
|
|
||
|
gst_buffer_pool_config_set_d3d11_allocation_params (config, params);
|
||
|
gst_d3d11_allocation_params_free (params);
|
||
|
gst_buffer_pool_config_set_params (config, caps, info.size, 0, 2);
|
||
|
gst_caps_unref (caps);
|
||
|
|
||
|
fail_unless (gst_buffer_pool_set_config (data.pool, config));
|
||
|
fail_unless (gst_buffer_pool_set_active (data.pool, TRUE));
|
||
|
|
||
|
thread = g_thread_new (NULL, (GThreadFunc) alloc_thread, &data);
|
||
|
|
||
|
g_mutex_lock (&data.lock);
|
||
|
while (!data.blocked)
|
||
|
g_cond_wait (&data.cond, &data.lock);
|
||
|
g_mutex_unlock (&data.lock);
|
||
|
|
||
|
/* Wait 1 second for the alloc thread to be actually blocked */
|
||
|
Sleep (1000);
|
||
|
|
||
|
fail_unless (gst_buffer_pool_set_active (data.pool, FALSE));
|
||
|
g_thread_join (thread);
|
||
|
|
||
|
gst_object_unref (data.pool);
|
||
|
g_mutex_clear (&data.lock);
|
||
|
g_cond_clear (&data.cond);
|
||
|
}
|
||
|
|
||
|
GST_END_TEST;
|
||
|
|
||
|
static gboolean
|
||
|
check_d3d11_device (void)
|
||
|
{
|
||
|
GstD3D11Device *device;
|
||
|
|
||
|
device = gst_d3d11_device_new (0, D3D11_CREATE_DEVICE_BGRA_SUPPORT);
|
||
|
if (device) {
|
||
|
gst_object_unref (device);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static Suite *
|
||
|
d3d11memory_suite (void)
|
||
|
{
|
||
|
Suite *s;
|
||
|
TCase *tc_chain;
|
||
|
|
||
|
s = suite_create ("d3d11memory");
|
||
|
tc_chain = tcase_create ("general");
|
||
|
|
||
|
suite_add_tcase (s, tc_chain);
|
||
|
tcase_add_checked_fixture (tc_chain, setup_func, teardown_func);
|
||
|
|
||
|
if (!check_d3d11_device ())
|
||
|
return s;
|
||
|
|
||
|
tcase_add_test (tc_chain, test_free_active_allocator);
|
||
|
tcase_add_test (tc_chain, test_unblock_on_stop);
|
||
|
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
GST_CHECK_MAIN (d3d11memory);
|