mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-05-11 13:02:52 +00:00
Compare commits
18 commits
3acfe6eb86
...
06a92667ac
Author | SHA1 | Date | |
---|---|---|---|
06a92667ac | |||
d7eeb62f38 | |||
753aeccde7 | |||
7074849c5c | |||
f0ef33d018 | |||
1f8accbc8d | |||
7f47dba299 | |||
1f080391ed | |||
18c32272bd | |||
668b395a38 | |||
547e2899d1 | |||
7eb08feeee | |||
8737b9ca84 | |||
ff7b41ac86 | |||
be7ba5ac51 | |||
4ac46ce82b | |||
47ff3ea50a | |||
b5a7d0ae48 |
|
@ -1314,21 +1314,6 @@ need to use this function.</doc>
|
|||
<record name="VulkanCommandPoolPrivate" c:type="GstVulkanCommandPoolPrivate" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<record name="VulkanDecoder" c:type="GstVulkanDecoder" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<record name="VulkanDecoderClass" c:type="GstVulkanDecoderClass" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<union name="VulkanDecoderParameters" c:type="GstVulkanDecoderParameters">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</union>
|
||||
<record name="VulkanDecoderPicture" c:type="GstVulkanDecoderPicture" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<record name="VulkanDecoderPrivate" c:type="GstVulkanDecoderPrivate" disguised="1">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/vulkan_fwd.h"/>
|
||||
</record>
|
||||
<class name="VulkanDescriptorCache" c:symbol-prefix="vulkan_descriptor_cache" c:type="GstVulkanDescriptorCache" version="1.18" parent="VulkanHandlePool" glib:type-name="GstVulkanDescriptorCache" glib:get-type="gst_vulkan_descriptor_cache_get_type" glib:type-struct="VulkanDescriptorCacheClass">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkdescriptorcache.h"/>
|
||||
<constructor name="new" c:identifier="gst_vulkan_descriptor_cache_new" version="1.18">
|
||||
|
@ -5178,24 +5163,6 @@ surrounding elements of @element.</doc>
|
|||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="create_decoder" c:identifier="gst_vulkan_queue_create_decoder" version="1.24" introspectable="0">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">Creates a #GstVulkanDecoder object if @codec decoding is supported by @queue</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.h"/>
|
||||
<return-value transfer-ownership="full" nullable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">the #GstVulkanDecoder object</doc>
|
||||
<type name="VulkanDecoder" c:type="GstVulkanDecoder*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="queue" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">a #GstVulkanQueue</doc>
|
||||
<type name="VulkanQueue" c:type="GstVulkanQueue*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="codec" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.c">the VkVideoCodecOperationFlagBitsKHR to decode</doc>
|
||||
<type name="guint" c:type="guint"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="get_device" c:identifier="gst_vulkan_queue_get_device" version="1.18">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkqueue.h"/>
|
||||
<return-value transfer-ownership="full" nullable="1">
|
||||
|
|
|
@ -19449,23 +19449,6 @@
|
|||
"GstVulkanCommandPool.pool",
|
||||
"GstVulkanCommandPool.queue",
|
||||
"GstVulkanCommandPoolClass.parent_class",
|
||||
"GstVulkanDecoder",
|
||||
"GstVulkanDecoder.codec",
|
||||
"GstVulkanDecoder.dedicated_dpb",
|
||||
"GstVulkanDecoder.input_buffer",
|
||||
"GstVulkanDecoder.layered_buffer",
|
||||
"GstVulkanDecoder.layered_dpb",
|
||||
"GstVulkanDecoder.parent",
|
||||
"GstVulkanDecoder.profile",
|
||||
"GstVulkanDecoder.queue",
|
||||
"GstVulkanDecoderClass.parent",
|
||||
"GstVulkanDecoderPicture",
|
||||
"GstVulkanDecoderPicture.dpb",
|
||||
"GstVulkanDecoderPicture.img_view_out",
|
||||
"GstVulkanDecoderPicture.img_view_ref",
|
||||
"GstVulkanDecoderPicture.out",
|
||||
"GstVulkanDecoderPicture.refs",
|
||||
"GstVulkanDecoderPicture.slice_offs",
|
||||
"GstVulkanDescriptorCache",
|
||||
"GstVulkanDescriptorCache.parent",
|
||||
"GstVulkanDescriptorCache.pool",
|
||||
|
@ -44795,22 +44778,6 @@
|
|||
"gst_vulkan_command_pool_lock",
|
||||
"gst_vulkan_command_pool_unlock",
|
||||
"gst_vulkan_create_shader",
|
||||
"gst_vulkan_decoder_append_slice",
|
||||
"gst_vulkan_decoder_caps",
|
||||
"gst_vulkan_decoder_create_dpb_pool",
|
||||
"gst_vulkan_decoder_decode",
|
||||
"gst_vulkan_decoder_flush",
|
||||
"gst_vulkan_decoder_is_started",
|
||||
"gst_vulkan_decoder_out_format",
|
||||
"gst_vulkan_decoder_picture_create_view",
|
||||
"gst_vulkan_decoder_picture_init",
|
||||
"gst_vulkan_decoder_picture_release",
|
||||
"gst_vulkan_decoder_profile_caps",
|
||||
"gst_vulkan_decoder_start",
|
||||
"gst_vulkan_decoder_stop",
|
||||
"gst_vulkan_decoder_update_video_session_parameters",
|
||||
"gst_vulkan_decoder_update_ycbcr_sampler",
|
||||
"gst_vulkan_decoder_wait",
|
||||
"gst_vulkan_descriptor_cache_acquire",
|
||||
"gst_vulkan_descriptor_cache_new",
|
||||
"gst_vulkan_descriptor_pool_create",
|
||||
|
@ -44965,7 +44932,6 @@
|
|||
"gst_vulkan_physical_device_type_to_string",
|
||||
"gst_vulkan_present_mode_to_string",
|
||||
"gst_vulkan_queue_create_command_pool",
|
||||
"gst_vulkan_queue_create_decoder",
|
||||
"gst_vulkan_queue_flags_to_string",
|
||||
"gst_vulkan_queue_get_device",
|
||||
"gst_vulkan_queue_handle_context_query",
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <gst/video/video.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
|
||||
#include "gst/vulkan/gstvkdecoder-private.h"
|
||||
#include "gstvulkanelements.h"
|
||||
|
||||
typedef struct _GstVulkanH264Decoder GstVulkanH264Decoder;
|
||||
|
@ -161,7 +162,7 @@ gst_vulkan_h264_decoder_open (GstVideoDecoder * decoder)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
self->decoder = gst_vulkan_queue_create_decoder (self->decode_queue,
|
||||
self->decoder = gst_vulkan_decoder_new_from_queue (self->decode_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
|
||||
if (!self->decoder) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
#include "gst/vulkan/gstvkdecoder-private.h"
|
||||
|
||||
#include "gstvulkanelements.h"
|
||||
|
||||
|
@ -219,7 +220,7 @@ gst_vulkan_h265_decoder_open (GstVideoDecoder * decoder)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
self->decoder = gst_vulkan_queue_create_decoder (self->decode_queue,
|
||||
self->decoder = gst_vulkan_decoder_new_from_queue (self->decode_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
|
||||
if (!self->decoder) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
|
|
|
@ -203,10 +203,10 @@ gst_d3d11_device_enable_d3d11_debug (void)
|
|||
/* If all below libraries are unavailable, d3d11 device would fail with
|
||||
* D3D11_CREATE_DEVICE_DEBUG flag */
|
||||
static const gchar *sdk_dll_names[] = {
|
||||
"d3d11sdklayers.dll",
|
||||
"d3d11_1sdklayers.dll",
|
||||
"d3d11_2sdklayers.dll",
|
||||
"d3d11_3sdklayers.dll",
|
||||
"d3d11_2sdklayers.dll",
|
||||
"d3d11_1sdklayers.dll",
|
||||
"d3d11sdklayers.dll",
|
||||
};
|
||||
|
||||
GST_D3D11_CALL_ONCE_BEGIN {
|
||||
|
@ -289,6 +289,78 @@ gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static ID3D11Debug *g_debug_device = nullptr;
|
||||
static ID3D11InfoQueue *g_debug_info_queue = nullptr;
|
||||
static std::recursive_mutex g_sdk_debug_lock;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static void
|
||||
gst_d3d11_device_sdk_debug_init (ID3D11Debug * dbg, ID3D11InfoQueue * queue)
|
||||
{
|
||||
std::lock_guard < std::recursive_mutex > lk (g_sdk_debug_lock);
|
||||
if (g_debug_device)
|
||||
return;
|
||||
|
||||
g_debug_device = dbg;
|
||||
g_debug_device->AddRef ();
|
||||
|
||||
g_debug_info_queue = queue;
|
||||
g_debug_info_queue->AddRef ();
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d11_device_sdk_debug_deinit (gpointer user_data)
|
||||
{
|
||||
std::lock_guard < std::recursive_mutex > lk (g_sdk_debug_lock);
|
||||
if (!g_debug_device)
|
||||
return;
|
||||
|
||||
GST_CAT_INFO (gst_d3d11_debug_layer_debug, "Begin live object report");
|
||||
auto hr = g_debug_device->ReportLiveDeviceObjects ((D3D11_RLDO_FLAGS)
|
||||
GST_D3D11_RLDO_FLAGS);
|
||||
|
||||
if (SUCCEEDED (hr)) {
|
||||
UINT64 num_msg = g_debug_info_queue->GetNumStoredMessages ();
|
||||
for (UINT64 i = 0; num_msg; i++) {
|
||||
GstDebugLevel level;
|
||||
SIZE_T msg_len;
|
||||
|
||||
hr = g_debug_info_queue->GetMessage (i, nullptr, &msg_len);
|
||||
if (FAILED (hr))
|
||||
break;
|
||||
|
||||
if (msg_len == 0)
|
||||
continue;
|
||||
|
||||
auto msg = (D3D11_MESSAGE *) g_malloc0 (msg_len);
|
||||
hr = g_debug_info_queue->GetMessage (i, msg, &msg_len);
|
||||
if (FAILED (hr)) {
|
||||
g_free (msg);
|
||||
break;
|
||||
}
|
||||
|
||||
level = d3d11_message_severity_to_gst (msg->Severity);
|
||||
if (msg->Category == D3D11_MESSAGE_CATEGORY_STATE_CREATION &&
|
||||
level > GST_LEVEL_ERROR) {
|
||||
level = GST_LEVEL_INFO;
|
||||
}
|
||||
|
||||
gst_debug_log (gst_d3d11_debug_layer_debug, level, __FILE__, GST_FUNCTION,
|
||||
__LINE__, nullptr, "D3D11InfoQueue: Severity (%d), %s",
|
||||
msg->Severity, msg->pDescription);
|
||||
g_free (msg);
|
||||
}
|
||||
}
|
||||
|
||||
g_debug_info_queue->ClearStoredMessages ();
|
||||
|
||||
GST_CAT_INFO (gst_d3d11_debug_layer_debug, "End live object report");
|
||||
|
||||
GST_D3D11_CLEAR_COM (g_debug_info_queue);
|
||||
GST_D3D11_CLEAR_COM (g_debug_device);
|
||||
}
|
||||
#else
|
||||
void
|
||||
gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
|
||||
|
@ -456,6 +528,10 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
|
|||
pspec_removed_reason);
|
||||
|
||||
gst_d3d11_memory_init_once ();
|
||||
|
||||
#if HAVE_D3D11SDKLAYERS_H
|
||||
gst_deinit_register_notify (gst_d3d11_device_sdk_debug_deinit, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -994,6 +1070,7 @@ gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
|
|||
GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
|
||||
"ID3D11InfoQueue interface available");
|
||||
priv->d3d11_info_queue = info_queue;
|
||||
gst_d3d11_device_sdk_debug_init (debug, info_queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1327,7 +1327,7 @@ static inline gboolean
|
|||
_is_old_mesa (GstVaAllocator * va_allocator)
|
||||
{
|
||||
return GST_VA_DISPLAY_IS_IMPLEMENTATION (va_allocator->display, MESA_GALLIUM)
|
||||
&& !gst_va_display_check_version (va_allocator->display, 23, 2);
|
||||
&& !gst_va_display_check_version (va_allocator->display, 23, 3);
|
||||
}
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
|
@ -1376,13 +1376,15 @@ _update_image_info (GstVaAllocator * va_allocator,
|
|||
}
|
||||
va_allocator->use_derived = FALSE;
|
||||
#else
|
||||
/* XXX: Derived in Mesa <23.3 can't use derived images for P010 format
|
||||
/* XXX: Derived in radeonsi Mesa <23.3 can't use derived images for several
|
||||
* cases
|
||||
* https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24381
|
||||
* https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26174
|
||||
*/
|
||||
if (va_allocator->img_format == GST_VIDEO_FORMAT_P010_10LE
|
||||
&& _is_old_mesa (va_allocator)) {
|
||||
if (_is_old_mesa (va_allocator)) {
|
||||
if (feat_use_derived != GST_VA_FEATURE_DISABLED) {
|
||||
GST_INFO_OBJECT (va_allocator, "Disable image derive on old Mesa.");
|
||||
GST_INFO_OBJECT (va_allocator,
|
||||
"Disable image derive on old Mesa (< 23.3).");
|
||||
feat_use_derived = GST_VA_FEATURE_DISABLED;
|
||||
}
|
||||
va_allocator->use_derived = FALSE;
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
#endif
|
||||
|
||||
#include "gstvavideoformat.h"
|
||||
#ifndef G_OS_WIN32
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#define GST_CAT_DEFAULT gst_va_display_debug
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_va_display_debug);
|
||||
|
@ -38,73 +35,62 @@ static struct FormatMap
|
|||
GstVideoFormat format;
|
||||
guint va_rtformat;
|
||||
VAImageFormat va_format;
|
||||
/* The drm fourcc may have different definition from VA */
|
||||
guint drm_fourcc;
|
||||
} format_map[] = {
|
||||
#ifndef G_OS_WIN32
|
||||
#define F(format, drm, fourcc, rtformat, order, bpp, depth, r, g, b, a) { \
|
||||
#define F(format, fourcc, rtformat, order, bpp, depth, r, g, b, a) { \
|
||||
G_PASTE (GST_VIDEO_FORMAT_, format), \
|
||||
G_PASTE (VA_RT_FORMAT_, rtformat), \
|
||||
{ VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), \
|
||||
bpp, depth, r, g, b, a }, G_PASTE (DRM_FORMAT_, drm) }
|
||||
#else
|
||||
#define F(format, drm, fourcc, rtformat, order, bpp, depth, r, g, b, a) { \
|
||||
G_PASTE (GST_VIDEO_FORMAT_, format), \
|
||||
G_PASTE (VA_RT_FORMAT_, rtformat), \
|
||||
{ VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), \
|
||||
bpp, depth, r, g, b, a }, 0 /* DRM_FORMAT_INVALID */ }
|
||||
#endif
|
||||
#define G(format, drm, fourcc, rtformat, order, bpp) \
|
||||
F (format, drm, fourcc, rtformat, order, bpp, 0, 0, 0 ,0, 0)
|
||||
G (NV12, NV12, ('N', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
G (NV21, NV21, ('N', 'V', '2', '1'), YUV420, NSB, 21),
|
||||
G (VUYA, AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
F (RGBA, RGBA8888, ('R', 'G', 'B', 'A'), RGB32, LSB, 32, 32, 0x000000ff,
|
||||
bpp, depth, r, g, b, a } }
|
||||
#define G(format, fourcc, rtformat, order, bpp) \
|
||||
F (format, fourcc, rtformat, order, bpp, 0, 0, 0 ,0, 0)
|
||||
G (NV12, ('N', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
G (NV21, ('N', 'V', '2', '1'), YUV420, NSB, 21),
|
||||
G (VUYA, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
F (RGBA, ('R', 'G', 'B', 'A'), RGB32, LSB, 32, 32, 0x000000ff,
|
||||
0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
F (RGBx, RGBX8888, ('R', 'G', 'B', 'X'), RGB32, LSB, 32, 24, 0x000000ff,
|
||||
F (RGBx, ('R', 'G', 'B', 'X'), RGB32, LSB, 32, 24, 0x000000ff,
|
||||
0x0000ff00, 0x00ff0000, 0x00000000),
|
||||
F (BGRA, BGRA8888, ('B', 'G', 'R', 'A'), RGB32, LSB, 32, 32, 0x00ff0000,
|
||||
F (BGRA, ('B', 'G', 'R', 'A'), RGB32, LSB, 32, 32, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff, 0xff000000),
|
||||
F (ARGB, ARGB8888, ('A', 'R', 'G', 'B'), RGB32, LSB, 32, 32, 0x0000ff00,
|
||||
F (ARGB, ('A', 'R', 'G', 'B'), RGB32, LSB, 32, 32, 0x0000ff00,
|
||||
0x00ff0000, 0xff000000, 0x000000ff),
|
||||
F (xRGB, XRGB8888, ('X', 'R', 'G', 'B'), RGB32, LSB, 32, 24, 0x0000ff00,
|
||||
F (xRGB, ('X', 'R', 'G', 'B'), RGB32, LSB, 32, 24, 0x0000ff00,
|
||||
0x00ff0000, 0xff000000, 0x00000000),
|
||||
F (ABGR, ABGR8888, ('A', 'B', 'G', 'R'), RGB32, LSB, 32, 32, 0xff000000,
|
||||
F (ABGR, ('A', 'B', 'G', 'R'), RGB32, LSB, 32, 32, 0xff000000,
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
F (xBGR, XBGR8888, ('X', 'B', 'G', 'R'), RGB32, LSB, 32, 24, 0xff000000,
|
||||
F (xBGR, ('X', 'B', 'G', 'R'), RGB32, LSB, 32, 24, 0xff000000,
|
||||
0x00ff0000, 0x0000ff00, 0x00000000),
|
||||
F (BGRx, BGRX8888, ('B', 'G', 'R', 'X'), RGB32, LSB, 32, 24, 0x00ff0000,
|
||||
F (BGRx, ('B', 'G', 'R', 'X'), RGB32, LSB, 32, 24, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff, 0x00000000),
|
||||
G (UYVY, UYVY, ('U', 'Y', 'V', 'Y'), YUV422, NSB, 16),
|
||||
G (YUY2, YUYV, ('Y', 'U', 'Y', '2'), YUV422, NSB, 16),
|
||||
G (AYUV, AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
G (UYVY, ('U', 'Y', 'V', 'Y'), YUV422, NSB, 16),
|
||||
G (YUY2, ('Y', 'U', 'Y', '2'), YUV422, NSB, 16),
|
||||
G (AYUV, ('A', 'Y', 'U', 'V'), YUV444, LSB, 32),
|
||||
/* F (????, NV11), */
|
||||
G (YV12, YVU420, ('Y', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
G (YV12, ('Y', 'V', '1', '2'), YUV420, NSB, 12),
|
||||
/* F (????, P208), */
|
||||
G (I420, YUV420, ('I', '4', '2', '0'), YUV420, NSB, 12),
|
||||
G (I420, ('I', '4', '2', '0'), YUV420, NSB, 12),
|
||||
/* F (????, YV24), */
|
||||
/* F (????, YV32), */
|
||||
/* F (????, Y800), */
|
||||
/* F (????, IMC3), */
|
||||
/* F (????, 411P), */
|
||||
/* F (????, 411R), */
|
||||
G (Y42B, YUV422, ('4', '2', '2', 'H'), YUV422, LSB, 16),
|
||||
G (Y42B, ('4', '2', '2', 'H'), YUV422, LSB, 16),
|
||||
/* F (????, 422V), */
|
||||
/* F (????, 444P), */
|
||||
/* No RGBP support in drm fourcc */
|
||||
G (RGBP, INVALID, ('R', 'G', 'B', 'P'), RGBP, LSB, 8),
|
||||
G (RGBP, ('R', 'G', 'B', 'P'), RGBP, LSB, 8),
|
||||
/* F (????, BGRP), */
|
||||
/* F (????, RGB565), */
|
||||
/* F (????, BGR565), */
|
||||
G (Y210, Y210, ('Y', '2', '1', '0'), YUV422_10, NSB, 32),
|
||||
G (Y210, ('Y', '2', '1', '0'), YUV422_10, NSB, 32),
|
||||
/* F (????, Y216), */
|
||||
G (Y410, Y410, ('Y', '4', '1', '0'), YUV444_10, NSB, 32),
|
||||
G (Y212_LE, Y212, ('Y', '2', '1', '2'), YUV422_12, NSB, 32),
|
||||
G (Y412_LE, Y412, ('Y', '4', '1', '2'), YUV444_12, NSB, 32),
|
||||
G (Y410, ('Y', '4', '1', '0'), YUV444_10, NSB, 32),
|
||||
G (Y212_LE, ('Y', '2', '1', '2'), YUV422_12, NSB, 32),
|
||||
G (Y412_LE, ('Y', '4', '1', '2'), YUV444_12, NSB, 32),
|
||||
/* F (????, Y416), */
|
||||
/* F (????, YV16), */
|
||||
G (P010_10LE, P010, ('P', '0', '1', '0'), YUV420_10, NSB, 24),
|
||||
G (P012_LE, P012, ('P', '0', '1', '2'), YUV420_12, NSB, 24),
|
||||
G (P010_10LE, ('P', '0', '1', '0'), YUV420_10, NSB, 24),
|
||||
G (P012_LE, ('P', '0', '1', '2'), YUV420_12, NSB, 24),
|
||||
/* F (P016_LE, P016, ????), */
|
||||
/* F (????, I010), */
|
||||
/* F (????, IYUV), */
|
||||
|
@ -112,20 +98,19 @@ static struct FormatMap
|
|||
/* F (????, A2B10G10R10), */
|
||||
/* F (????, X2R10G10B10), */
|
||||
/* F (????, X2B10G10R10), */
|
||||
/* No GRAY8 support in drm fourcc */
|
||||
G (GRAY8, INVALID, ('Y', '8', '0', '0'), YUV400, NSB, 8),
|
||||
G (Y444, YUV444, ('4', '4', '4', 'P'), YUV444, NSB, 24),
|
||||
G (GRAY8, ('Y', '8', '0', '0'), YUV400, NSB, 8),
|
||||
G (Y444, ('4', '4', '4', 'P'), YUV444, NSB, 24),
|
||||
/* F (????, Y16), */
|
||||
/* G (VYUY, VYUY, YUV422), */
|
||||
/* G (YVYU, YVYU, YUV422), */
|
||||
/* F (ARGB64, ARGB64, ????), */
|
||||
/* F (????, ABGR64), */
|
||||
F (RGB16, RGB565, ('R', 'G', '1', '6'), RGB16, NSB, 16, 16, 0x0000f800,
|
||||
F (RGB16, ('R', 'G', '1', '6'), RGB16, NSB, 16, 16, 0x0000f800,
|
||||
0x000007e0, 0x0000001f, 0x00000000),
|
||||
F (RGB, RGB888, ('R', 'G', '2', '4'), RGB32, NSB, 32, 24, 0x00ff0000,
|
||||
F (RGB, ('R', 'G', '2', '4'), RGB32, NSB, 32, 24, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff, 0x00000000),
|
||||
F (BGR10A2_LE, ARGB2101010, ('A', 'R', '3', '0'), RGB32, LSB, 32, 30,
|
||||
0x3ff00000, 0x000ffc00, 0x000003ff, 0x30000000),
|
||||
F (BGR10A2_LE, ('A', 'R', '3', '0'), RGB32, LSB, 32, 30, 0x3ff00000,
|
||||
0x000ffc00, 0x000003ff, 0x30000000),
|
||||
#undef F
|
||||
#undef G
|
||||
};
|
||||
|
@ -133,54 +118,47 @@ static struct FormatMap
|
|||
static const struct RBG32FormatMap
|
||||
{
|
||||
GstVideoFormat format;
|
||||
guint drm_fourcc;
|
||||
VAImageFormat va_format[2];
|
||||
} rgb32_format_map[] = {
|
||||
#define F(fourcc, order, bpp, depth, r, g, b, a) \
|
||||
{ VA_FOURCC fourcc, G_PASTE (G_PASTE (VA_, order), _FIRST), bpp, depth, r, g, b, a }
|
||||
#define A(fourcc, order, r, g, b, a) F (fourcc, order, 32, 32, r, g, b, a)
|
||||
#define X(fourcc, order, r, g, b) F (fourcc, order, 32, 24, r, g, b, 0x0)
|
||||
#ifndef G_OS_WIN32
|
||||
#define D(format, drm_fourcc) G_PASTE (GST_VIDEO_FORMAT_, format), G_PASTE (DRM_FORMAT_, drm_fourcc)
|
||||
#else
|
||||
#define D(format, drm_fourcc) G_PASTE (GST_VIDEO_FORMAT_, format), 0 /* DRM_FORMAT_INVALID */
|
||||
#endif
|
||||
{ D (ARGB, BGRA8888), {
|
||||
{ GST_VIDEO_FORMAT_ARGB, {
|
||||
A (('B', 'G', 'R', 'A'), LSB, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff),
|
||||
A (('A', 'R', 'G', 'B'), MSB, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
|
||||
} },
|
||||
{ D (RGBA, ABGR8888), {
|
||||
{ GST_VIDEO_FORMAT_RGBA, {
|
||||
A (('A', 'B', 'G', 'R'), LSB, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
A (('R', 'G', 'B', 'A'), MSB, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
} },
|
||||
{ D (ABGR, RGBA8888), {
|
||||
{ GST_VIDEO_FORMAT_ABGR, {
|
||||
A (('R', 'G', 'B', 'A'), LSB, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
A (('A', 'B', 'G', 'R'), MSB, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
} },
|
||||
{ D (BGRA, ARGB8888), {
|
||||
{ GST_VIDEO_FORMAT_BGRA, {
|
||||
A (('A', 'R', 'G', 'B'), LSB, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
|
||||
A (('B', 'G', 'R', 'A'), MSB, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff),
|
||||
} },
|
||||
{ D (xRGB, BGRX8888), {
|
||||
{ GST_VIDEO_FORMAT_xRGB, {
|
||||
X (('B', 'G', 'R', 'X'), LSB, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
X (('X', 'R', 'G', 'B'), MSB, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
} },
|
||||
{ D (RGBx, XBGR8888), {
|
||||
{ GST_VIDEO_FORMAT_RGBx, {
|
||||
X (('X', 'B', 'G', 'R'), LSB, 0x000000ff, 0x0000ff00, 0x00ff0000),
|
||||
X (('R', 'G', 'B', 'X'), MSB, 0xff000000, 0x00ff0000, 0x0000ff00),
|
||||
} },
|
||||
{ D (xBGR, RGBX8888), {
|
||||
{ GST_VIDEO_FORMAT_xBGR, {
|
||||
X (('R', 'G', 'B', 'X'), LSB, 0xff000000, 0x00ff0000, 0x0000ff00),
|
||||
X (('X', 'B', 'G', 'R'), MSB, 0x000000ff, 0x0000ff00, 0x00ff0000),
|
||||
} },
|
||||
{ D (BGRx, XRGB8888), {
|
||||
{ GST_VIDEO_FORMAT_BGRx, {
|
||||
X (('X', 'R', 'G', 'B'), LSB, 0x00ff0000, 0x0000ff00, 0x000000ff),
|
||||
X (('B', 'G', 'R', 'X'), MSB, 0x0000ff00, 0x00ff0000, 0xff000000),
|
||||
} },
|
||||
#undef X
|
||||
#undef A
|
||||
#undef F
|
||||
#undef D
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -201,9 +179,11 @@ static const struct FormatMap *
|
|||
get_format_map_from_drm_fourcc (guint drm_fourcc)
|
||||
{
|
||||
int i;
|
||||
GstVideoFormat format;
|
||||
|
||||
format = gst_video_dma_drm_fourcc_to_format (drm_fourcc);
|
||||
for (i = 0; i < G_N_ELEMENTS (format_map); i++) {
|
||||
if (format_map[i].drm_fourcc == drm_fourcc)
|
||||
if (format_map[i].format == format)
|
||||
return &format_map[i];
|
||||
}
|
||||
|
||||
|
@ -263,6 +243,20 @@ get_format_map_from_va_image_format (const VAImageFormat * va_format)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX: there are two potentially different fourcc: the VA and the DRM.
|
||||
*
|
||||
* Normally they should be the same, but there are a couple formats where VA's
|
||||
* fourcc is different from the DRM's fourcc. One example is
|
||||
* GST_VIDEO_FORMAT_I420, where VA's fourcc is ('I', '4', '2', '0') while DRM's
|
||||
* is ('Y', 'U', '1', '2').
|
||||
*
|
||||
* That's the reason there are two functions:
|
||||
* gst_va_video_format_from_va_fourcc() and
|
||||
* gst_va_video_format_from_drm_fourcc() They should be used depending where the
|
||||
* value is going to be used: for VA concerns the first should be used, for
|
||||
* DMABuf exportation, the last.
|
||||
*/
|
||||
GstVideoFormat
|
||||
gst_va_video_format_from_va_fourcc (guint fourcc)
|
||||
{
|
||||
|
@ -292,7 +286,7 @@ gst_va_drm_fourcc_from_video_format (GstVideoFormat format)
|
|||
{
|
||||
const struct FormatMap *map = get_format_map_from_video_format (format);
|
||||
|
||||
return map ? map->drm_fourcc : 0;
|
||||
return map ? gst_video_dma_drm_fourcc_from_format (format) : 0;
|
||||
}
|
||||
|
||||
guint
|
||||
|
@ -406,15 +400,13 @@ gst_va_dma_drm_info_to_video_info (const GstVideoInfoDmaDrm * drm_info,
|
|||
}
|
||||
|
||||
static GstVideoFormat
|
||||
find_gst_video_format_in_rgb32_map (VAImageFormat * image_format,
|
||||
guint * drm_fourcc)
|
||||
find_gst_video_format_in_rgb32_map (VAImageFormat * image_format)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (rgb32_format_map); i++) {
|
||||
for (j = 0; j < G_N_ELEMENTS (rgb32_format_map[i].va_format); j++) {
|
||||
if (va_format_is_same (&rgb32_format_map[i].va_format[j], image_format)) {
|
||||
*drm_fourcc = rgb32_format_map[i].drm_fourcc;
|
||||
return rgb32_format_map[i].format;
|
||||
}
|
||||
}
|
||||
|
@ -436,14 +428,13 @@ fix_map (gpointer data)
|
|||
GstVideoFormat format;
|
||||
VAImageFormat *image_format;
|
||||
struct FormatMap *map;
|
||||
guint drm_fourcc = 0;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < args->len; i++) {
|
||||
image_format = &args->image_formats[i];
|
||||
if (!va_format_is_rgb (image_format))
|
||||
continue;
|
||||
format = find_gst_video_format_in_rgb32_map (image_format, &drm_fourcc);
|
||||
format = find_gst_video_format_in_rgb32_map (image_format);
|
||||
if (format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||
continue;
|
||||
map = get_format_map_from_video_format (format);
|
||||
|
@ -453,14 +444,11 @@ fix_map (gpointer data)
|
|||
continue;
|
||||
|
||||
map->va_format = *image_format;
|
||||
map->drm_fourcc = drm_fourcc;
|
||||
|
||||
GST_INFO ("GST_VIDEO_FORMAT_%s => { fourcc %" GST_FOURCC_FORMAT ", "
|
||||
"drm fourcc %" GST_FOURCC_FORMAT ", %s, bpp %d, depth %d, "
|
||||
"R %#010x, G %#010x, B %#010x, A %#010x }",
|
||||
gst_video_format_to_string (map->format),
|
||||
GST_INFO ("GST_VIDEO_FORMAT_%s => { fourcc %"
|
||||
GST_FOURCC_FORMAT ", %s, bpp %d, depth %d, R %#010x, G %#010x, "
|
||||
"B %#010x, A %#010x }", gst_video_format_to_string (map->format),
|
||||
GST_FOURCC_ARGS (map->va_format.fourcc),
|
||||
GST_FOURCC_ARGS (map->drm_fourcc),
|
||||
(map->va_format.byte_order == 1) ? "LSB" : "MSB",
|
||||
map->va_format.bits_per_pixel, map->va_format.depth,
|
||||
map->va_format.red_mask, map->va_format.green_mask,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstvkdecoder.h"
|
||||
#include "gstvkdecoder-private.h"
|
||||
|
||||
#include "gstvkoperation.h"
|
||||
#include "gstvkphysicaldevice-private.h"
|
||||
|
@ -39,6 +39,7 @@
|
|||
* Since: 1.24
|
||||
*/
|
||||
|
||||
typedef struct _GstVulkanDecoderPrivate GstVulkanDecoderPrivate;
|
||||
struct _GstVulkanDecoderPrivate
|
||||
{
|
||||
GstVulkanHandle *empty_params;
|
||||
|
@ -1309,3 +1310,72 @@ gst_vulkan_decoder_wait (GstVulkanDecoder * self)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_decoder_new_from_queue:
|
||||
* @queue: a #GstVulkanQueue
|
||||
* @codec: (type guint): the VkVideoCodecOperationFlagBitsKHR to decode
|
||||
*
|
||||
* Creates a #GstVulkanDecoder object if @codec decoding is supported by @queue
|
||||
*
|
||||
* Returns: (transfer full) (nullable): the #GstVulkanDecoder object
|
||||
*/
|
||||
GstVulkanDecoder *
|
||||
gst_vulkan_decoder_new_from_queue (GstVulkanQueue * queue, guint codec)
|
||||
{
|
||||
GstVulkanPhysicalDevice *device;
|
||||
GstVulkanDecoder *decoder;
|
||||
guint flags, expected_flag, supported_video_ops;
|
||||
const char *extension;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VULKAN_QUEUE (queue), NULL);
|
||||
|
||||
device = queue->device->physical_device;
|
||||
expected_flag = VK_QUEUE_VIDEO_DECODE_BIT_KHR;
|
||||
flags = device->queue_family_props[queue->family].queueFlags;
|
||||
supported_video_ops = device->queue_family_ops[queue->family].video;
|
||||
|
||||
if (device->properties.apiVersion < VK_MAKE_VERSION (1, 3, 238)) {
|
||||
GST_WARNING_OBJECT (queue,
|
||||
"Driver API version [%d.%d.%d] doesn't support Video extensions",
|
||||
VK_VERSION_MAJOR (device->properties.apiVersion),
|
||||
VK_VERSION_MINOR (device->properties.apiVersion),
|
||||
VK_VERSION_PATCH (device->properties.apiVersion));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (codec) {
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME;
|
||||
break;
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (queue, "Unsupported codec %u", codec);
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & expected_flag) != expected_flag) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support decoding");
|
||||
return NULL;
|
||||
}
|
||||
if ((supported_video_ops & codec) != codec) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support codec %u decoding",
|
||||
codec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device, extension)))
|
||||
return NULL;
|
||||
|
||||
decoder = g_object_new (GST_TYPE_VULKAN_DECODER, NULL);
|
||||
gst_object_ref_sink (decoder);
|
||||
decoder->queue = gst_object_ref (queue);
|
||||
decoder->codec = codec;
|
||||
|
||||
return decoder;
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <gst/vulkan/gstvkqueue.h>
|
||||
#include <gst/vulkan/gstvkvideoutils.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -34,6 +33,11 @@ G_BEGIN_DECLS
|
|||
GST_VULKAN_API
|
||||
GType gst_vulkan_decoder_get_type (void);
|
||||
|
||||
typedef struct _GstVulkanDecoder GstVulkanDecoder;
|
||||
typedef struct _GstVulkanDecoderClass GstVulkanDecoderClass;
|
||||
typedef struct _GstVulkanDecoderPicture GstVulkanDecoderPicture;
|
||||
typedef union _GstVulkanDecoderParameters GstVulkanDecoderParameters;
|
||||
|
||||
/**
|
||||
* GstVulkanDecoderPicture:
|
||||
* @out: output buffer
|
||||
|
@ -132,6 +136,9 @@ union _GstVulkanDecoderParameters
|
|||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstVulkanDecoder, gst_object_unref)
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanDecoder * gst_vulkan_decoder_new_from_queue (GstVulkanQueue * queue,
|
||||
guint codec);
|
||||
GST_VULKAN_API
|
||||
gboolean gst_vulkan_decoder_start (GstVulkanDecoder * self,
|
||||
GstVulkanVideoProfile * profile,
|
|
@ -23,6 +23,9 @@
|
|||
#endif
|
||||
|
||||
#include "gstvkqueue.h"
|
||||
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
|
||||
#include "gstvkdecoder-private.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:vkqueue
|
||||
|
@ -154,81 +157,6 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_queue_create_decoder:
|
||||
* @queue: a #GstVulkanQueue
|
||||
* @codec: (type guint): the VkVideoCodecOperationFlagBitsKHR to decode
|
||||
*
|
||||
* Creates a #GstVulkanDecoder object if @codec decoding is supported by @queue
|
||||
*
|
||||
* Returns: (transfer full) (nullable): the #GstVulkanDecoder object
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
GstVulkanDecoder *
|
||||
gst_vulkan_queue_create_decoder (GstVulkanQueue * queue, guint codec)
|
||||
{
|
||||
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
|
||||
GstVulkanPhysicalDevice *device;
|
||||
GstVulkanDecoder *decoder;
|
||||
guint flags, expected_flag, supported_video_ops;
|
||||
const char *extension;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VULKAN_QUEUE (queue), NULL);
|
||||
|
||||
device = queue->device->physical_device;
|
||||
expected_flag = VK_QUEUE_VIDEO_DECODE_BIT_KHR;
|
||||
flags = device->queue_family_props[queue->family].queueFlags;
|
||||
supported_video_ops = device->queue_family_ops[queue->family].video;
|
||||
|
||||
if (device->properties.apiVersion < VK_MAKE_VERSION (1, 3, 238)) {
|
||||
GST_WARNING_OBJECT (queue,
|
||||
"Driver API version [%d.%d.%d] doesn't support Video extensions",
|
||||
VK_VERSION_MAJOR (device->properties.apiVersion),
|
||||
VK_VERSION_MINOR (device->properties.apiVersion),
|
||||
VK_VERSION_PATCH (device->properties.apiVersion));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (codec) {
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME;
|
||||
break;
|
||||
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
|
||||
extension = VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (queue, "Unsupported codec %u", codec);
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & expected_flag) != expected_flag) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support decoding");
|
||||
return NULL;
|
||||
}
|
||||
if ((supported_video_ops & codec) != codec) {
|
||||
GST_WARNING_OBJECT (queue, "Queue doesn't support codec %u decoding",
|
||||
codec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device,
|
||||
VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME)
|
||||
&& gst_vulkan_device_is_extension_enabled (queue->device, extension)))
|
||||
return NULL;
|
||||
|
||||
decoder = g_object_new (GST_TYPE_VULKAN_DECODER, NULL);
|
||||
gst_object_ref_sink (decoder);
|
||||
decoder->queue = gst_object_ref (queue);
|
||||
decoder->codec = codec;
|
||||
|
||||
return decoder;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_context_set_vulkan_queue:
|
||||
* @context: a #GstContext
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
|
||||
#include <gst/vulkan/gstvkdevice.h>
|
||||
#include <gst/vulkan/gstvkcommandpool.h>
|
||||
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
|
||||
#include <gst/vulkan/gstvkdecoder.h>
|
||||
#endif
|
||||
|
||||
#define GST_TYPE_VULKAN_QUEUE (gst_vulkan_queue_get_type())
|
||||
#define GST_VULKAN_QUEUE(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VULKAN_QUEUE, GstVulkanQueue))
|
||||
|
@ -83,15 +80,12 @@ struct _GstVulkanQueueClass
|
|||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstVulkanQueue, gst_object_unref)
|
||||
|
||||
GST_VULKAN_API
|
||||
GST_VULKAN_API
|
||||
GstVulkanDevice * gst_vulkan_queue_get_device (GstVulkanQueue * queue);
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanCommandPool * gst_vulkan_queue_create_command_pool (GstVulkanQueue * queue,
|
||||
GError ** error);
|
||||
GST_VULKAN_API
|
||||
GstVulkanDecoder * gst_vulkan_queue_create_decoder (GstVulkanQueue * queue,
|
||||
guint codec);
|
||||
|
||||
GST_VULKAN_API
|
||||
void gst_vulkan_queue_submit_lock (GstVulkanQueue * queue);
|
||||
|
|
|
@ -333,12 +333,9 @@ static StdVideoH265PictureParameterSet h265_pps;
|
|||
endif
|
||||
if have_vk_video
|
||||
vulkan_conf.set('GST_VULKAN_HAVE_VIDEO_EXTENSIONS', 1)
|
||||
vulkan_priv_sources += files('gstvkvideo-private.c')
|
||||
vulkan_sources += files(
|
||||
'gstvkdecoder.c',
|
||||
)
|
||||
vulkan_headers += files(
|
||||
'gstvkdecoder.h'
|
||||
vulkan_priv_sources += files(
|
||||
'gstvkvideo-private.c',
|
||||
'gstvkdecoder-private.c',
|
||||
)
|
||||
elif get_option('vulkan-video').enabled()
|
||||
error('Vulkan Video extensions headers not found')
|
||||
|
@ -501,4 +498,3 @@ if enabled_vulkan_winsys.contains('wayland')
|
|||
sources : vulkan_wayland_gir)
|
||||
meson.override_dependency('gstreamer-vulkan-wayland-1.0', gstvulkanwayland_dep)
|
||||
endif
|
||||
|
||||
|
|
|
@ -119,12 +119,6 @@ typedef struct _GstVulkanOperation GstVulkanOperation;
|
|||
typedef struct _GstVulkanOperationClass GstVulkanOperationClass;
|
||||
typedef struct _GstVulkanOperationPrivate GstVulkanOperationPrivate;
|
||||
|
||||
typedef struct _GstVulkanDecoder GstVulkanDecoder;
|
||||
typedef struct _GstVulkanDecoderClass GstVulkanDecoderClass;
|
||||
typedef struct _GstVulkanDecoderPrivate GstVulkanDecoderPrivate;
|
||||
typedef union _GstVulkanDecoderParameters GstVulkanDecoderParameters;
|
||||
typedef struct _GstVulkanDecoderPicture GstVulkanDecoderPicture;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_VULKAN_FWD_H__ */
|
||||
|
|
|
@ -196,6 +196,9 @@ gst_wl_window_finalize (GObject * gobject)
|
|||
gst_wl_display_callback_destroy (priv->display, &priv->frame_callback);
|
||||
gst_wl_display_callback_destroy (priv->display, &priv->commit_callback);
|
||||
|
||||
if (priv->staged_buffer)
|
||||
gst_wl_buffer_unref_buffer (priv->staged_buffer);
|
||||
|
||||
g_cond_clear (&priv->configure_cond);
|
||||
g_mutex_clear (&priv->configure_mutex);
|
||||
g_mutex_clear (&priv->window_lock);
|
||||
|
|
|
@ -428,12 +428,22 @@ send_command_to_all (GstUnixFdSink * self, CommandType type, GUnixFDList * fds,
|
|||
}
|
||||
|
||||
static GstClockTime
|
||||
calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
||||
GstClockTime latency, GstClockTimeDiff clock_diff)
|
||||
to_monotonic (GstClockTime timestamp, const GstSegment * segment,
|
||||
GstClockTime base_time, GstClockTime latency, GstClockTimeDiff clock_diff)
|
||||
{
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
/* Convert running time to pipeline clock time */
|
||||
timestamp += base_time;
|
||||
gint res =
|
||||
gst_segment_to_running_time_full (segment, GST_FORMAT_TIME, timestamp,
|
||||
×tamp);
|
||||
if (res == 0)
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
else if (res > 0)
|
||||
timestamp += base_time;
|
||||
else if (base_time > timestamp)
|
||||
timestamp = base_time - timestamp;
|
||||
else
|
||||
timestamp = 0;
|
||||
if (GST_CLOCK_TIME_IS_VALID (latency))
|
||||
timestamp += latency;
|
||||
/* Convert to system monotonic clock time */
|
||||
|
@ -485,11 +495,11 @@ gst_unix_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
* id so we know which buffer to unref. */
|
||||
new_buffer->id = (guint64) buffer;
|
||||
new_buffer->pts =
|
||||
calculate_timestamp (GST_BUFFER_PTS (buffer), base_time, latency,
|
||||
clock_diff);
|
||||
to_monotonic (GST_BUFFER_PTS (buffer),
|
||||
&GST_BASE_SINK_CAST (self)->segment, base_time, latency, clock_diff);
|
||||
new_buffer->dts =
|
||||
calculate_timestamp (GST_BUFFER_DTS (buffer), base_time, latency,
|
||||
clock_diff);
|
||||
to_monotonic (GST_BUFFER_DTS (buffer),
|
||||
&GST_BASE_SINK_CAST (self)->segment, base_time, latency, clock_diff);
|
||||
new_buffer->duration = GST_BUFFER_DURATION (buffer);
|
||||
new_buffer->offset = GST_BUFFER_OFFSET (buffer);
|
||||
new_buffer->offset_end = GST_BUFFER_OFFSET_END (buffer);
|
||||
|
@ -498,6 +508,15 @@ gst_unix_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
new_buffer->n_memory = n_memory;
|
||||
new_buffer->n_meta = n_meta;
|
||||
|
||||
if ((GST_BUFFER_PTS_IS_VALID (buffer)
|
||||
&& !GST_CLOCK_TIME_IS_VALID (new_buffer->pts))
|
||||
|| (GST_BUFFER_DTS_IS_VALID (buffer)
|
||||
&& !GST_CLOCK_TIME_IS_VALID (new_buffer->dts))) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Could not convert buffer timestamp to running time");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
gboolean dmabuf_count = 0;
|
||||
GUnixFDList *fds = g_unix_fd_list_new ();
|
||||
for (int i = 0; i < n_memory; i++) {
|
||||
|
|
|
@ -89,31 +89,34 @@ typedef struct
|
|||
guint n_memory;
|
||||
} BufferContext;
|
||||
|
||||
static void
|
||||
release_buffer (GstUnixFdSrc * self, guint64 id)
|
||||
{
|
||||
/* Notify that we are not using this buffer anymore */
|
||||
ReleaseBufferPayload payload = { id };
|
||||
GError *error = NULL;
|
||||
if (!gst_unix_fd_send_command (self->socket, COMMAND_TYPE_RELEASE_BUFFER,
|
||||
NULL, (guint8 *) & payload, sizeof (payload), &error)) {
|
||||
GST_WARNING_OBJECT (self, "Failed to send release-buffer command: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
memory_weak_ref_cb (GstUnixFdSrc * self, GstMemory * mem)
|
||||
{
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
BufferContext *ctx = g_hash_table_lookup (self->memories, mem);
|
||||
if (ctx == NULL)
|
||||
goto out;
|
||||
|
||||
if (--ctx->n_memory == 0) {
|
||||
/* Notify that we are not using this buffer anymore */
|
||||
ReleaseBufferPayload payload = { ctx->id };
|
||||
GError *error = NULL;
|
||||
if (!gst_unix_fd_send_command (self->socket, COMMAND_TYPE_RELEASE_BUFFER,
|
||||
NULL, (guint8 *) & payload, sizeof (payload), &error)) {
|
||||
GST_WARNING_OBJECT (self, "Failed to send release-buffer command: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
if (ctx != NULL) {
|
||||
if (--ctx->n_memory == 0) {
|
||||
release_buffer (self, ctx->id);
|
||||
g_free (ctx);
|
||||
}
|
||||
g_free (ctx);
|
||||
g_hash_table_remove (self->memories, mem);
|
||||
}
|
||||
|
||||
g_hash_table_remove (self->memories, mem);
|
||||
|
||||
out:
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
}
|
||||
|
||||
|
@ -279,7 +282,7 @@ gst_unix_fd_src_unlock_stop (GstBaseSrc * bsrc)
|
|||
}
|
||||
|
||||
static GstClockTime
|
||||
calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
||||
from_monotonic (GstClockTime timestamp, GstClockTime base_time,
|
||||
GstClockTimeDiff clock_diff)
|
||||
{
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||
|
@ -295,6 +298,14 @@ calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
|||
return timestamp;
|
||||
}
|
||||
|
||||
static void
|
||||
close_and_free_fds (gint * fds, gint fds_len)
|
||||
{
|
||||
for (int i = 0; i < fds_len; i++)
|
||||
g_close (fds[i], NULL);
|
||||
g_free (fds);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_unix_fd_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
|
||||
{
|
||||
|
@ -335,33 +346,26 @@ again:
|
|||
goto on_error;
|
||||
}
|
||||
|
||||
if (fds == NULL) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Received new buffer command without file descriptors");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
if (g_unix_fd_list_get_length (fds) != new_buffer->n_memory) {
|
||||
gint fds_arr_len = 0;
|
||||
gint *fds_arr =
|
||||
(fds != NULL) ? g_unix_fd_list_steal_fds (fds, &fds_arr_len) : NULL;
|
||||
if (fds_arr_len != new_buffer->n_memory) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Received new buffer command with %d file descriptors instead of "
|
||||
"%d", g_unix_fd_list_get_length (fds), new_buffer->n_memory);
|
||||
"%d", fds_arr_len, new_buffer->n_memory);
|
||||
ret = GST_FLOW_ERROR;
|
||||
close_and_free_fds (fds_arr, fds_arr_len);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (new_buffer->type >= MEMORY_TYPE_LAST) {
|
||||
GST_ERROR_OBJECT (self, "Unknown buffer type %d", new_buffer->type);
|
||||
ret = GST_FLOW_ERROR;
|
||||
close_and_free_fds (fds_arr, fds_arr_len);
|
||||
goto on_error;
|
||||
}
|
||||
GstAllocator *allocator = self->allocators[new_buffer->type];
|
||||
|
||||
gint *fds_arr = g_unix_fd_list_steal_fds (fds, NULL);
|
||||
|
||||
BufferContext *ctx = g_new0 (BufferContext, 1);
|
||||
ctx->id = new_buffer->id;
|
||||
ctx->n_memory = new_buffer->n_memory;
|
||||
|
||||
*outbuf = gst_buffer_new ();
|
||||
|
||||
GstClockTime base_time =
|
||||
|
@ -373,9 +377,9 @@ again:
|
|||
}
|
||||
|
||||
GST_BUFFER_PTS (*outbuf) =
|
||||
calculate_timestamp (new_buffer->pts, base_time, clock_diff);
|
||||
from_monotonic (new_buffer->pts, base_time, clock_diff);
|
||||
GST_BUFFER_DTS (*outbuf) =
|
||||
calculate_timestamp (new_buffer->dts, base_time, clock_diff);
|
||||
from_monotonic (new_buffer->dts, base_time, clock_diff);
|
||||
GST_BUFFER_DURATION (*outbuf) = new_buffer->duration;
|
||||
GST_BUFFER_OFFSET (*outbuf) = new_buffer->offset;
|
||||
GST_BUFFER_OFFSET_END (*outbuf) = new_buffer->offset_end;
|
||||
|
@ -388,24 +392,35 @@ again:
|
|||
if (consumed == 0) {
|
||||
GST_ERROR_OBJECT (self, "Malformed meta serialization");
|
||||
ret = GST_FLOW_ERROR;
|
||||
close_and_free_fds (fds_arr, fds_arr_len);
|
||||
gst_clear_buffer (outbuf);
|
||||
goto on_error;
|
||||
}
|
||||
payload_off += consumed;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
for (int i = 0; i < new_buffer->n_memory; i++) {
|
||||
GstMemory *mem = gst_fd_allocator_alloc (allocator, fds_arr[i],
|
||||
new_buffer->memories[i].size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (mem, new_buffer->memories[i].offset,
|
||||
new_buffer->memories[i].size);
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);
|
||||
if (new_buffer->n_memory > 0) {
|
||||
BufferContext *ctx = g_new0 (BufferContext, 1);
|
||||
ctx->id = new_buffer->id;
|
||||
ctx->n_memory = new_buffer->n_memory;
|
||||
for (int i = 0; i < new_buffer->n_memory; i++) {
|
||||
GstMemory *mem = gst_fd_allocator_alloc (allocator, fds_arr[i],
|
||||
new_buffer->memories[i].size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (mem, new_buffer->memories[i].offset,
|
||||
new_buffer->memories[i].size);
|
||||
GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_READONLY);
|
||||
|
||||
g_hash_table_insert (self->memories, mem, ctx);
|
||||
gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (mem),
|
||||
(GstMiniObjectNotify) memory_weak_ref_cb, self);
|
||||
g_hash_table_insert (self->memories, mem, ctx);
|
||||
gst_mini_object_weak_ref (GST_MINI_OBJECT_CAST (mem),
|
||||
(GstMiniObjectNotify) memory_weak_ref_cb, self);
|
||||
|
||||
gst_buffer_append_memory (*outbuf, mem);
|
||||
gst_buffer_append_memory (*outbuf, mem);
|
||||
}
|
||||
} else {
|
||||
/* This buffer has no memories, we can release it immediately otherwise
|
||||
* it gets leaked. */
|
||||
release_buffer (self, new_buffer->id);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -777,11 +777,13 @@ gst_d3d12_screen_capture_src_decide_allocation (GstBaseSrc * bsrc,
|
|||
if (!params) {
|
||||
params = gst_d3d12_allocation_params_new (self->device, &vinfo,
|
||||
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
|
||||
D3D12_HEAP_FLAG_NONE);
|
||||
D3D12_HEAP_FLAG_SHARED);
|
||||
} else {
|
||||
gst_d3d12_allocation_params_set_resource_flags (params, resource_flags);
|
||||
gst_d3d12_allocation_params_unset_resource_flags (params,
|
||||
D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);
|
||||
gst_d3d12_allocation_params_set_heap_flags (params,
|
||||
D3D12_HEAP_FLAG_SHARED);
|
||||
}
|
||||
|
||||
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
|
||||
|
@ -815,7 +817,7 @@ gst_d3d12_screen_capture_src_decide_allocation (GstBaseSrc * bsrc,
|
|||
|
||||
auto params = gst_d3d12_allocation_params_new (self->device, &vinfo,
|
||||
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
|
||||
D3D12_HEAP_FLAG_NONE);
|
||||
D3D12_HEAP_FLAG_SHARED);
|
||||
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
|
||||
gst_d3d12_allocation_params_free (params);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/app/app.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
static void
|
||||
|
@ -134,6 +135,92 @@ GST_START_TEST (test_unixfd_videotestsrc)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_unixfd_segment)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
/* Ensure we don't have socket from previous failed test */
|
||||
gchar *socket_path =
|
||||
g_strdup_printf ("%s/unixfd-test-socket", g_get_user_runtime_dir ());
|
||||
if (g_file_test (socket_path, G_FILE_TEST_EXISTS)) {
|
||||
g_unlink (socket_path);
|
||||
}
|
||||
|
||||
GstCaps *caps = gst_caps_new_empty_simple ("video/x-raw");
|
||||
|
||||
/* Setup service */
|
||||
gchar *pipeline_str =
|
||||
g_strdup_printf
|
||||
("appsrc name=src format=time handle-segment-change=true ! unixfdsink socket-path=%s sync=false async=false",
|
||||
socket_path);
|
||||
GstElement *pipeline_service = gst_parse_launch (pipeline_str, &error);
|
||||
g_assert_no_error (error);
|
||||
fail_unless (gst_element_set_state (pipeline_service,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||
GstElement *appsrc = gst_bin_get_by_name (GST_BIN (pipeline_service), "src");
|
||||
gst_object_unref (appsrc);
|
||||
g_free (pipeline_str);
|
||||
|
||||
/* Setup client */
|
||||
pipeline_str =
|
||||
g_strdup_printf
|
||||
("unixfdsrc socket-path=%s ! appsink name=sink sync=false async=false",
|
||||
socket_path);
|
||||
GstElement *pipeline_client = gst_parse_launch (pipeline_str, &error);
|
||||
g_assert_no_error (error);
|
||||
fail_unless (gst_element_set_state (pipeline_client,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||
GstElement *appsink = gst_bin_get_by_name (GST_BIN (pipeline_client), "sink");
|
||||
gst_object_unref (appsink);
|
||||
g_free (pipeline_str);
|
||||
|
||||
/* Send a buffer with PTS=30s */
|
||||
GstSegment segment;
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
GstBuffer *buf = gst_buffer_new ();
|
||||
GST_BUFFER_PTS (buf) = 30 * GST_SECOND;
|
||||
GstSample *sample = gst_sample_new (buf, caps, &segment, NULL);
|
||||
gst_app_src_push_sample (GST_APP_SRC (appsrc), sample);
|
||||
gst_sample_unref (sample);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
/* Wait for it */
|
||||
sample = gst_app_sink_pull_sample (GST_APP_SINK (appsink));
|
||||
buf = gst_sample_get_buffer (sample);
|
||||
GstClockTime first_pts = GST_BUFFER_PTS (buf);
|
||||
gst_sample_unref (sample);
|
||||
|
||||
/* Send a buffer with PTS=1s but with 30s offset in the segment */
|
||||
segment.base = 30 * GST_SECOND;
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_PTS (buf) = 1 * GST_SECOND;
|
||||
sample = gst_sample_new (buf, caps, &segment, NULL);
|
||||
gst_app_src_push_sample (GST_APP_SRC (appsrc), sample);
|
||||
gst_sample_unref (sample);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
/* Wait for it */
|
||||
sample = gst_app_sink_pull_sample (GST_APP_SINK (appsink));
|
||||
buf = gst_sample_get_buffer (sample);
|
||||
GstClockTime second_pts = GST_BUFFER_PTS (buf);
|
||||
gst_sample_unref (sample);
|
||||
|
||||
/* They should be 1s appart */
|
||||
fail_unless_equals_uint64 (second_pts - first_pts, GST_SECOND);
|
||||
|
||||
/* Teardown */
|
||||
fail_unless (gst_element_set_state (pipeline_client,
|
||||
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||
fail_unless (gst_element_set_state (pipeline_service,
|
||||
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||
gst_object_unref (pipeline_service);
|
||||
gst_object_unref (pipeline_client);
|
||||
g_free (socket_path);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
unixfd_suite (void)
|
||||
{
|
||||
|
@ -142,6 +229,7 @@ unixfd_suite (void)
|
|||
|
||||
suite_add_tcase (s, tc);
|
||||
tcase_add_test (tc, test_unixfd_videotestsrc);
|
||||
tcase_add_test (tc, test_unixfd_segment);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
|
||||
#include "gst/vulkan/gstvkdecoder-private.h"
|
||||
|
||||
static GstVulkanInstance *instance;
|
||||
static GstVulkanDevice *device;
|
||||
static GstVulkanQueue *video_queue = NULL;
|
||||
|
@ -327,7 +329,7 @@ GST_START_TEST (test_h264_decoder)
|
|||
return;
|
||||
}
|
||||
|
||||
dec = gst_vulkan_queue_create_decoder (video_queue,
|
||||
dec = gst_vulkan_decoder_new_from_queue (video_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
|
||||
if (!dec) {
|
||||
GST_WARNING ("Unable to create a vulkan decoder");
|
||||
|
@ -495,7 +497,7 @@ GST_START_TEST (test_h265_decoder)
|
|||
return;
|
||||
}
|
||||
|
||||
dec = gst_vulkan_queue_create_decoder (video_queue,
|
||||
dec = gst_vulkan_decoder_new_from_queue (video_queue,
|
||||
VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
|
||||
if (!dec) {
|
||||
GST_WARNING ("Unable to create a vulkan decoder");
|
||||
|
|
|
@ -65,6 +65,25 @@ typedef struct _GstExifWriter GstExifWriter;
|
|||
typedef struct _GstExifReader GstExifReader;
|
||||
typedef struct _GstExifTagData GstExifTagData;
|
||||
|
||||
#define GST_CAT_DEFAULT gst_exif_tag_ensure_debug_category()
|
||||
|
||||
static GstDebugCategory *
|
||||
gst_exif_tag_ensure_debug_category (void)
|
||||
{
|
||||
static gsize cat_gonce = 0;
|
||||
|
||||
if (g_once_init_enter (&cat_gonce)) {
|
||||
GstDebugCategory *cat = NULL;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (cat, "exif-tags", 0, "EXIF tag parsing");
|
||||
|
||||
g_once_init_leave (&cat_gonce, (gsize) cat);
|
||||
}
|
||||
|
||||
return (GstDebugCategory *) cat_gonce;
|
||||
}
|
||||
|
||||
|
||||
typedef void (*GstExifSerializationFunc) (GstExifWriter * writer,
|
||||
const GstTagList * taglist, const GstExifTagMatch * exiftag);
|
||||
|
||||
|
|
|
@ -2614,25 +2614,38 @@ reconfigure_output (GstPlayBin3 * playbin)
|
|||
GST_DEBUG_OBJECT (playbin, "Stream type '%s' is now requested",
|
||||
gst_stream_type_get_name (combine->stream_type));
|
||||
|
||||
g_assert (combine->sinkpad == NULL);
|
||||
if (combine->sinkpad) {
|
||||
/* This was previously an assert but is now just a WARNING
|
||||
*
|
||||
* This *theoretically* should never happen, but there is the
|
||||
* possibility where there was a failure within (uri)decodebin3 where
|
||||
* the collection was posted (by demuxer for ex) but the decoding failed
|
||||
* (no decoder, bad stream, etc...).
|
||||
*
|
||||
* in that case, we could have a combiner already prepared for that type
|
||||
* but never got activated.
|
||||
**/
|
||||
GST_WARNING_OBJECT (playbin, "Combiner already configured");
|
||||
} else {
|
||||
|
||||
/* Request playsink sink pad */
|
||||
combine->sinkpad =
|
||||
gst_play_sink_request_pad (playbin->playsink,
|
||||
gst_play_sink_type_from_stream_type (combine->stream_type));
|
||||
gst_object_ref (combine->sinkpad);
|
||||
/* Create combiner if needed and link it */
|
||||
create_combiner (playbin, combine);
|
||||
if (combine->combiner) {
|
||||
res = gst_pad_link (combine->srcpad, combine->sinkpad);
|
||||
GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
|
||||
gst_stream_type_get_name (combine->stream_type), res);
|
||||
if (res != GST_PAD_LINK_OK) {
|
||||
GST_ELEMENT_ERROR (playbin, CORE, PAD,
|
||||
("Internal playbin error."),
|
||||
("Failed to link combiner to sink. Error %d", res));
|
||||
}
|
||||
|
||||
/* Request playsink sink pad */
|
||||
combine->sinkpad =
|
||||
gst_play_sink_request_pad (playbin->playsink,
|
||||
gst_play_sink_type_from_stream_type (combine->stream_type));
|
||||
gst_object_ref (combine->sinkpad);
|
||||
/* Create combiner if needed and link it */
|
||||
create_combiner (playbin, combine);
|
||||
if (combine->combiner) {
|
||||
res = gst_pad_link (combine->srcpad, combine->sinkpad);
|
||||
GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
|
||||
gst_stream_type_get_name (combine->stream_type), res);
|
||||
if (res != GST_PAD_LINK_OK) {
|
||||
GST_ELEMENT_ERROR (playbin, CORE, PAD,
|
||||
("Internal playbin error."),
|
||||
("Failed to link combiner to sink. Error %d", res));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1202,7 +1202,7 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
|
|||
/* now owned by the loop */
|
||||
g_main_context_unref (ctx);
|
||||
|
||||
src->session->thread = g_thread_try_new ("souphttpsrc-thread",
|
||||
src->session->thread = g_thread_try_new ("souphttpsrc",
|
||||
thread_func, src, NULL);
|
||||
|
||||
if (!src->session->thread) {
|
||||
|
|
|
@ -45,35 +45,53 @@ pylib_loc = get_option('libpython-dir')
|
|||
fsmod = import('fs')
|
||||
pylib_prefix = 'lib'
|
||||
pylib_suffix = 'so'
|
||||
pylib_ver = python_dep.version()
|
||||
pylib_locs = []
|
||||
if host_system == 'windows'
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
pylib_prefix = ''
|
||||
endif
|
||||
pylib_suffix = 'dll'
|
||||
pylib_ver = pylib_ver.replace('.', '')
|
||||
elif host_system == 'darwin'
|
||||
pylib_suffix = 'dylib'
|
||||
endif
|
||||
pylib_fnames = []
|
||||
# Library name with soversion, non-devel package
|
||||
pylib_fnames += python.get_variable('INSTSONAME', [])
|
||||
if python.has_variable('INSTSONAME')
|
||||
# For example, libpython3.12.so.1.0 (Linux), libpython3.11.dll.a (MSYS2), etc.
|
||||
pylib_fnames += python.get_variable('INSTSONAME')
|
||||
endif
|
||||
# Library name without soversion, devel package, framework, etc.
|
||||
pylib_fnames += python.get_variable('LDLIBRARY', [])
|
||||
if python.has_variable('LDLIBRARY')
|
||||
# For example, libpython3.12.so (Linux), libpython3.11.dll.a (MSYS2), etc.
|
||||
pylib_fnames += python.get_variable('LDLIBRARY')
|
||||
endif
|
||||
# Manually construct name as a fallback
|
||||
pylib_fnames += [
|
||||
pylib_prefix + 'python' + python_dep.version() + python_abi_flags + '.' + pylib_suffix
|
||||
pylib_prefix + 'python' + pylib_ver + python_abi_flags + '.' + pylib_suffix
|
||||
]
|
||||
if pylib_loc != ''
|
||||
pylib_locs = [pylib_loc]
|
||||
else
|
||||
pylib_locs = [
|
||||
python.get_variable('LIBDIR', ''),
|
||||
python.get_variable('LIBPL', ''),
|
||||
]
|
||||
if python.has_variable('LIBDIR')
|
||||
pylib_locs += python.get_variable('LIBDIR')
|
||||
endif
|
||||
if python.has_variable('LIBPL')
|
||||
pylib_locs += python.get_variable('LIBPL')
|
||||
endif
|
||||
# On Windows, python312.dll is in the rootdir where Python is installed,
|
||||
# which is configured as the "prefix" in sysconfig.
|
||||
if host_system == 'windows'
|
||||
pylib_locs += python.get_variable('prefix')
|
||||
endif
|
||||
endif
|
||||
pylib_fname = ''
|
||||
foreach loc: pylib_locs
|
||||
foreach fname: pylib_fnames
|
||||
if fsmod.exists(loc / fname)
|
||||
fpath = loc / fname
|
||||
debug(f'Looking for Python library at: @fpath@')
|
||||
if fsmod.exists(fpath)
|
||||
pylib_fname = fname
|
||||
message(f'PY_LIB_FNAME = @fname@ (@loc@)')
|
||||
break
|
||||
|
@ -81,12 +99,7 @@ foreach loc: pylib_locs
|
|||
endforeach
|
||||
endforeach
|
||||
if pylib_fname == ''
|
||||
error_msg = 'Could not find python library to load'
|
||||
if python_opt.enabled()
|
||||
error(error_msg)
|
||||
else
|
||||
message(error_msg)
|
||||
endif
|
||||
message('Could not find python library to load, will try loading at runtime')
|
||||
endif
|
||||
|
||||
pygi_override_dir = get_option('pygi-overrides-dir')
|
||||
|
|
|
@ -172,6 +172,23 @@ static gboolean parse_goption_arg (const gchar * s_opt,
|
|||
|
||||
GSList *_priv_gst_preload_plugins = NULL;
|
||||
|
||||
/* deinit callbacks */
|
||||
static GList *_gst_deinit_notifies = NULL;
|
||||
|
||||
typedef struct _GstDeinitNotify
|
||||
{
|
||||
GstDeinitNotifyFunc func;
|
||||
gpointer user_data;
|
||||
} GstDeinitNotify;
|
||||
|
||||
static void
|
||||
gst_deinit_notify_free (GstDeinitNotify * cb)
|
||||
{
|
||||
if (cb->func)
|
||||
cb->func (cb->user_data);
|
||||
g_free (cb);
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_VERSION = 1,
|
||||
|
@ -1092,6 +1109,10 @@ gst_deinit (void)
|
|||
}
|
||||
|
||||
GST_INFO ("deinitializing GStreamer");
|
||||
|
||||
g_list_free_full (_gst_deinit_notifies,
|
||||
(GDestroyNotify) gst_deinit_notify_free);
|
||||
|
||||
g_thread_pool_set_max_unused_threads (0);
|
||||
bin_class = (GstBinClass *) g_type_class_peek (gst_bin_get_type ());
|
||||
if (bin_class && bin_class->pool != NULL) {
|
||||
|
@ -1326,3 +1347,40 @@ gst_segtrap_set_enabled (gboolean enabled)
|
|||
{
|
||||
_gst_disable_segtrap = !enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_deinit_register_notify:
|
||||
* @func: (scope async): a #GstDeinitNotifyFunc
|
||||
* @user_data: (nullable): private user data
|
||||
*
|
||||
* Registers a callback notified when gst_deinit() is called.
|
||||
* This could be useful for a GStreamer library where the library holds
|
||||
* persistent resources but prefers the resources to be released
|
||||
* when gst_deinit() is called, so that any expected resource leaks
|
||||
* (either GStreamer object or native handle/memory) can be addressed.
|
||||
*
|
||||
* Applications or GStreamer components can register callbacks
|
||||
* before GStreamer is initialized, but installing notify after gst_deinit()
|
||||
* is not allowed.
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
void
|
||||
gst_deinit_register_notify (GstDeinitNotifyFunc func, gpointer user_data)
|
||||
{
|
||||
GstDeinitNotify *cb;
|
||||
|
||||
g_rec_mutex_lock (&init_lock);
|
||||
if (gst_deinitialized) {
|
||||
g_warning ("GStreamer was deinitialized already.");
|
||||
g_rec_mutex_unlock (&init_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
cb = g_new0 (GstDeinitNotify, 1);
|
||||
cb->func = func;
|
||||
cb->user_data = user_data;
|
||||
|
||||
_gst_deinit_notifies = g_list_prepend (_gst_deinit_notifies, cb);
|
||||
g_rec_mutex_unlock (&init_lock);
|
||||
}
|
||||
|
|
|
@ -144,6 +144,18 @@ gboolean gst_update_registry (void);
|
|||
GST_API
|
||||
const gchar * gst_get_main_executable_path (void);
|
||||
|
||||
/**
|
||||
* GstDeinitNotifyFunc:
|
||||
* @user_data: User data registered along with this function via gst_deinit_register_notify()
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
typedef void (*GstDeinitNotifyFunc) (gpointer user_data);
|
||||
|
||||
GST_API
|
||||
void gst_deinit_register_notify (GstDeinitNotifyFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_H__ */
|
||||
|
|
49
subprojects/gstreamer/tests/check/gst/gstdeinit2.c
Normal file
49
subprojects/gstreamer/tests/check/gst/gstdeinit2.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2024 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>
|
||||
|
||||
static void
|
||||
deinit_cb (guint * cb_count)
|
||||
{
|
||||
*cb_count += 1;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
guint cb_count = 0;
|
||||
|
||||
/* Installing callback before gst_init() is allowed */
|
||||
gst_deinit_register_notify ((GstDeinitNotifyFunc) deinit_cb, &cb_count);
|
||||
|
||||
gst_init (NULL, NULL);
|
||||
|
||||
/* Install callback again */
|
||||
gst_deinit_register_notify ((GstDeinitNotifyFunc) deinit_cb, &cb_count);
|
||||
|
||||
gst_deinit ();
|
||||
|
||||
g_assert (cb_count == 2);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -16,6 +16,7 @@ core_tests = [
|
|||
[ 'gst/gstcapsfeatures.c' ],
|
||||
[ 'gst/gstdatetime.c' ],
|
||||
[ 'gst/gstdeinit.c' ],
|
||||
[ 'gst/gstdeinit2.c' ],
|
||||
[ 'gst/gstdevice.c' ],
|
||||
[ 'gst/gstelement.c', not gst_registry or not gst_parse],
|
||||
[ 'gst/gstelementfactory.c', not gst_registry ],
|
||||
|
|
Loading…
Reference in a new issue