mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 01:31:03 +00:00
d3d12: Add H.264 decoder
Adding Direct3D12 h264 decoder Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4161>
This commit is contained in:
parent
2c058b3b99
commit
734dd50879
20 changed files with 5618 additions and 0 deletions
|
@ -6,6 +6,7 @@ subprojects/gst-plugins-bad/gst-libs/gst/va
|
|||
subprojects/gst-plugins-bad/gst-libs/gst/winrt
|
||||
subprojects/gst-plugins-bad/sys/amfcodec
|
||||
subprojects/gst-plugins-bad/sys/d3d11
|
||||
subprojects/gst-plugins-bad/sys/d3d12
|
||||
subprojects/gst-plugins-bad/sys/dwrite
|
||||
subprojects/gst-plugins-bad/sys/mediafoundation
|
||||
subprojects/gst-plugins-bad/sys/nvcodec
|
||||
|
|
|
@ -100,6 +100,7 @@ option('curl-ssh2', type : 'feature', value : 'auto', description : 'cURL networ
|
|||
option('d3dvideosink', type : 'feature', value : 'auto', description : 'Direct3D video sink plugin')
|
||||
option('d3d11', type : 'feature', value : 'auto', description : 'Direct3D11 plugin')
|
||||
option('d3d11-wgc', type : 'feature', value : 'auto', description : 'Windows Graphics Capture API support in d3d11 plugin')
|
||||
option('d3d12', type : 'feature', value : 'auto', description : 'Direct3D12 plugin')
|
||||
option('dash', type : 'feature', value : 'auto', description : 'DASH demuxer plugin')
|
||||
option('dc1394', type : 'feature', value : 'auto', description : 'libdc1394 IIDC camera source plugin')
|
||||
option('decklink', type : 'feature', value : 'auto', description : 'DeckLink audio/video source/sink plugin')
|
||||
|
|
55
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12_fwd.h
Normal file
55
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12_fwd.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#ifndef INITGUID
|
||||
#include <initguid.h>
|
||||
#endif
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <d3d12video.h>
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstD3D12Device GstD3D12Device;
|
||||
typedef struct _GstD3D12DeviceClass GstD3D12DeviceClass;
|
||||
typedef struct _GstD3D12DevicePrivate GstD3D12DevicePrivate;
|
||||
|
||||
typedef struct _GstD3D12Fence GstD3D12Fence;
|
||||
typedef struct _GstD3D12FencePrivate GstD3D12FencePrivate;
|
||||
|
||||
typedef struct _GstD3D12Memory GstD3D12Memory;
|
||||
typedef struct _GstD3D12MemoryPrivate GstD3D12MemoryPrivate;
|
||||
|
||||
typedef struct _GstD3D12Allocator GstD3D12Allocator;
|
||||
typedef struct _GstD3D12AllocatorClass GstD3D12AllocatorClass;
|
||||
typedef struct _GstD3D12AllocatorPrivate GstD3D12AllocatorPrivate;
|
||||
|
||||
typedef struct _GstD3D12PoolAllocator GstD3D12PoolAllocator;
|
||||
typedef struct _GstD3D12PoolAllocatorClass GstD3D12PoolAllocatorClass;
|
||||
typedef struct _GstD3D12PoolAllocatorPrivate GstD3D12PoolAllocatorPrivate;
|
||||
|
||||
typedef struct _GstD3D12Format GstD3D12Format;
|
||||
|
||||
G_END_DECLS
|
||||
|
1637
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp
Normal file
1637
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp
Normal file
File diff suppressed because it is too large
Load diff
167
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.h
Normal file
167
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/codecs/gstcodecpicture.h>
|
||||
#include <gst/dxva/gstdxva.h>
|
||||
#include "gstd3d12_fwd.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_D3D12_DECODER (gst_d3d12_decoder_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstD3D12Decoder,
|
||||
gst_d3d12_decoder, GST, D3D12_DECODER, GstObject);
|
||||
|
||||
typedef struct _GstD3D12DecoderClassData GstD3D12DecoderClassData;
|
||||
|
||||
struct GstD3D12DecoderSubClassData
|
||||
{
|
||||
GstDxvaCodec codec;
|
||||
gint64 adapter_luid;
|
||||
guint device_id;
|
||||
guint vendor_id;
|
||||
};
|
||||
|
||||
#define GST_D3D12_DECODER_DEFINE_TYPE(ModuleObjName,module_obj_name,MODULE,OBJ_NAME,ParentName) \
|
||||
static GstElementClass *parent_class = NULL; \
|
||||
typedef struct _##ModuleObjName { \
|
||||
ParentName parent; \
|
||||
GstD3D12Device *device; \
|
||||
GstD3D12Decoder *decoder; \
|
||||
} ModuleObjName;\
|
||||
typedef struct _##ModuleObjName##Class { \
|
||||
ParentName##Class parent_class; \
|
||||
GstD3D12DecoderSubClassData class_data; \
|
||||
} ModuleObjName##Class; \
|
||||
static inline ModuleObjName * MODULE##_##OBJ_NAME (gpointer ptr) { \
|
||||
return (ModuleObjName *) (ptr); \
|
||||
} \
|
||||
static inline ModuleObjName##Class * MODULE##_##OBJ_NAME##_GET_CLASS (gpointer ptr) { \
|
||||
return G_TYPE_INSTANCE_GET_CLASS ((ptr),G_TYPE_FROM_INSTANCE(ptr),ModuleObjName##Class); \
|
||||
} \
|
||||
static void module_obj_name##_get_property (GObject * object, \
|
||||
guint prop_id, GValue * value, GParamSpec * pspec); \
|
||||
static void module_obj_name##_set_context (GstElement * element, \
|
||||
GstContext * context); \
|
||||
static gboolean module_obj_name##_open (GstVideoDecoder * decoder); \
|
||||
static gboolean module_obj_name##_close (GstVideoDecoder * decoder); \
|
||||
static gboolean module_obj_name##_negotiate (GstVideoDecoder * decoder); \
|
||||
static gboolean module_obj_name##_decide_allocation (GstVideoDecoder * decoder, \
|
||||
GstQuery * query); \
|
||||
static gboolean module_obj_name##_sink_query (GstVideoDecoder * decoder, \
|
||||
GstQuery * query); \
|
||||
static gboolean module_obj_name##_src_query (GstVideoDecoder * decoder, \
|
||||
GstQuery * query); \
|
||||
static GstFlowReturn module_obj_name##_configure (ParentName * decoder, \
|
||||
GstVideoCodecState * input_state, const GstVideoInfo * info, \
|
||||
gint crop_x, gint crop_y, \
|
||||
gint coded_width, gint coded_height, gint max_dpb_size); \
|
||||
static GstFlowReturn module_obj_name##_new_picture (ParentName * decoder, \
|
||||
GstCodecPicture * picture); \
|
||||
static guint8 module_obj_name##_get_picture_id (ParentName * decoder, \
|
||||
GstCodecPicture * picture); \
|
||||
static GstFlowReturn module_obj_name##_start_picture (ParentName * decoder, \
|
||||
GstCodecPicture * picture, guint8 * picture_id); \
|
||||
static GstFlowReturn module_obj_name##_end_picture (ParentName * decoder, \
|
||||
GstCodecPicture * picture, GPtrArray * ref_pics, \
|
||||
const GstDxvaDecodingArgs * args); \
|
||||
static GstFlowReturn module_obj_name##_output_picture (ParentName * decoder, \
|
||||
GstVideoCodecFrame * frame, GstCodecPicture * picture, \
|
||||
GstVideoBufferFlags buffer_flags, \
|
||||
gint display_width, gint display_height);
|
||||
|
||||
#define GST_D3D12_DECODER_DEFINE_TYPE_FULL(ModuleObjName,module_obj_name,MODULE,OBJ_NAME,ParentName) \
|
||||
GST_D3D12_DECODER_DEFINE_TYPE(ModuleObjName,module_obj_name,MODULE,OBJ_NAME,ParentName); \
|
||||
static GstFlowReturn module_obj_name##_duplicate_picture (ParentName * decoder, \
|
||||
GstCodecPicture * src, GstCodecPicture * dst);
|
||||
|
||||
GstD3D12Decoder * gst_d3d12_decoder_new (GstD3D12Device * device,
|
||||
GstDxvaCodec codec);
|
||||
|
||||
GstFlowReturn gst_d3d12_decoder_configure (GstD3D12Decoder * decoder,
|
||||
GstVideoCodecState * input_state,
|
||||
const GstVideoInfo * info,
|
||||
gint crop_x,
|
||||
gint crop_y,
|
||||
gint coded_width,
|
||||
gint coded_height,
|
||||
guint dpb_size);
|
||||
|
||||
GstFlowReturn gst_d3d12_decoder_new_picture (GstD3D12Decoder * decoder,
|
||||
GstVideoDecoder * videodec,
|
||||
GstCodecPicture * picture);
|
||||
|
||||
GstFlowReturn gst_d3d12_decoder_duplicate_picture (GstD3D12Decoder * decoder,
|
||||
GstCodecPicture * src,
|
||||
GstCodecPicture * dst);
|
||||
|
||||
guint8 gst_d3d12_decoder_get_picture_id (GstD3D12Decoder * decoder,
|
||||
GstCodecPicture * picture);
|
||||
|
||||
GstFlowReturn gst_d3d12_decoder_start_picture (GstD3D12Decoder * decoder,
|
||||
GstCodecPicture * picture,
|
||||
guint8 * picture_id);
|
||||
|
||||
GstFlowReturn gst_d3d12_decoder_end_picture (GstD3D12Decoder * decoder,
|
||||
GstCodecPicture * picture,
|
||||
GPtrArray * ref_pics,
|
||||
const GstDxvaDecodingArgs * args);
|
||||
|
||||
GstFlowReturn gst_d3d12_decoder_output_picture (GstD3D12Decoder * decoder,
|
||||
GstVideoDecoder * videodec,
|
||||
GstVideoCodecFrame * frame,
|
||||
GstCodecPicture * picture,
|
||||
GstVideoBufferFlags buffer_flags,
|
||||
gint display_width,
|
||||
gint display_height);
|
||||
|
||||
gboolean gst_d3d12_decoder_negotiate (GstD3D12Decoder * decoder,
|
||||
GstVideoDecoder * videodec);
|
||||
|
||||
gboolean gst_d3d12_decoder_decide_allocation (GstD3D12Decoder * decoder,
|
||||
GstVideoDecoder * videodec,
|
||||
GstQuery * query);
|
||||
|
||||
/* Utils for element registration */
|
||||
GstD3D12DecoderClassData * gst_d3d12_decoder_check_feature_support (GstD3D12Device * device,
|
||||
ID3D12VideoDevice * video_device,
|
||||
GstDxvaCodec codec);
|
||||
|
||||
void gst_d3d12_decoder_class_data_fill_subclass_data (GstD3D12DecoderClassData * data,
|
||||
GstD3D12DecoderSubClassData * subclass_data);
|
||||
|
||||
void gst_d3d12_decoder_proxy_class_init (GstElementClass * klass,
|
||||
GstD3D12DecoderClassData * data,
|
||||
const gchar * author);
|
||||
|
||||
void gst_d3d12_decoder_proxy_get_property (GObject * object,
|
||||
guint prop_id,
|
||||
GValue * value,
|
||||
GParamSpec * pspec,
|
||||
GstD3D12DecoderSubClassData * subclass_data);
|
||||
|
||||
gboolean gst_d3d12_decoder_proxy_open (GstVideoDecoder * videodec,
|
||||
GstD3D12DecoderSubClassData * subclass_data,
|
||||
GstD3D12Device ** device,
|
||||
GstD3D12Decoder ** decoder);
|
||||
|
||||
G_END_DECLS
|
802
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.cpp
Normal file
802
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.cpp
Normal file
|
@ -0,0 +1,802 @@
|
|||
/* 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 "gstd3d12device.h"
|
||||
#include "gstd3d12utils.h"
|
||||
#include "gstd3d12format.h"
|
||||
#include <wrl.h>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
#include <d3d12sdklayers.h>
|
||||
#endif
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_d3d12_device_debug);
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_d3d12_sdk_debug);
|
||||
#define GST_CAT_DEFAULT gst_d3d12_device_debug
|
||||
|
||||
#define MAKE_FORMAT_MAP_YUV(g,d,r0,r1,r2,r3) \
|
||||
{ GST_VIDEO_FORMAT_ ##g, DXGI_FORMAT_ ##d, \
|
||||
{ DXGI_FORMAT_ ##r0, DXGI_FORMAT_ ##r1, DXGI_FORMAT_ ##r2, DXGI_FORMAT_ ##r3 }, \
|
||||
{ DXGI_FORMAT_ ##r0, DXGI_FORMAT_ ##r1, DXGI_FORMAT_ ##r2, DXGI_FORMAT_ ##r3 }, \
|
||||
(D3D12_FORMAT_SUPPORT1) (D3D12_FORMAT_SUPPORT1_TEXTURE2D | \
|
||||
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE | D3D12_FORMAT_SUPPORT1_RENDER_TARGET) }
|
||||
|
||||
#define MAKE_FORMAT_MAP_YUV_FULL(g,d,r0,r1,r2,r3,f) \
|
||||
{ GST_VIDEO_FORMAT_ ##g, DXGI_FORMAT_ ##d, \
|
||||
{ DXGI_FORMAT_ ##r0, DXGI_FORMAT_ ##r1, DXGI_FORMAT_ ##r2, DXGI_FORMAT_ ##r3 }, \
|
||||
{ DXGI_FORMAT_ ##r0, DXGI_FORMAT_ ##r1, DXGI_FORMAT_ ##r2, DXGI_FORMAT_ ##r3 }, \
|
||||
(D3D12_FORMAT_SUPPORT1) (f) }
|
||||
|
||||
#define MAKE_FORMAT_MAP_RGB(g,d) \
|
||||
{ GST_VIDEO_FORMAT_ ##g, DXGI_FORMAT_ ##d, \
|
||||
{ DXGI_FORMAT_ ##d, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, \
|
||||
{ DXGI_FORMAT_ ##d, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, \
|
||||
(D3D12_FORMAT_SUPPORT1) (D3D12_FORMAT_SUPPORT1_TEXTURE2D | \
|
||||
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE | D3D12_FORMAT_SUPPORT1_RENDER_TARGET) }
|
||||
|
||||
#define MAKE_FORMAT_MAP_RGBP(g,d,a) \
|
||||
{ GST_VIDEO_FORMAT_ ##g, DXGI_FORMAT_UNKNOWN, \
|
||||
{ DXGI_FORMAT_ ##d, DXGI_FORMAT_ ##d, DXGI_FORMAT_ ##d, DXGI_FORMAT_ ##a }, \
|
||||
{ DXGI_FORMAT_ ##d, DXGI_FORMAT_ ##d, DXGI_FORMAT_ ##d, DXGI_FORMAT_ ##a }, \
|
||||
(D3D12_FORMAT_SUPPORT1) (D3D12_FORMAT_SUPPORT1_TEXTURE2D | \
|
||||
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE | D3D12_FORMAT_SUPPORT1_RENDER_TARGET) }
|
||||
|
||||
static const GstD3D12Format _gst_d3d12_default_format_map[] = {
|
||||
MAKE_FORMAT_MAP_RGB (BGRA, B8G8R8A8_UNORM),
|
||||
MAKE_FORMAT_MAP_RGB (RGBA, R8G8B8A8_UNORM),
|
||||
MAKE_FORMAT_MAP_RGB (BGRx, B8G8R8A8_UNORM),
|
||||
MAKE_FORMAT_MAP_RGB (RGBx, R8G8B8A8_UNORM),
|
||||
MAKE_FORMAT_MAP_RGB (RGB10A2_LE, R10G10B10A2_UNORM),
|
||||
MAKE_FORMAT_MAP_RGB (RGBA64_LE, R16G16B16A16_UNORM),
|
||||
MAKE_FORMAT_MAP_YUV (AYUV, UNKNOWN, R8G8B8A8_UNORM, UNKNOWN, UNKNOWN,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (AYUV64, UNKNOWN, R16G16B16A16_UNORM, UNKNOWN, UNKNOWN,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (VUYA, AYUV, R8G8B8A8_UNORM, UNKNOWN, UNKNOWN, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (NV12, NV12, R8_UNORM, R8G8_UNORM, UNKNOWN, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (NV21, UNKNOWN, R8_UNORM, R8G8_UNORM, UNKNOWN, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (P010_10LE, P010, R16_UNORM, R16G16_UNORM, UNKNOWN,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (P012_LE, P016, R16_UNORM, R16G16_UNORM, UNKNOWN,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (P016_LE, P016, R16_UNORM, R16G16_UNORM, UNKNOWN,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (I420, UNKNOWN, R8_UNORM, R8_UNORM, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (YV12, UNKNOWN, R8_UNORM, R8_UNORM, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (I420_10LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (I420_12LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (Y42B, UNKNOWN, R8_UNORM, R8_UNORM, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (I422_10LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (I422_12LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (Y444, UNKNOWN, R8_UNORM, R8_UNORM, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (Y444_10LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (Y444_12LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
MAKE_FORMAT_MAP_YUV (Y444_16LE, UNKNOWN, R16_UNORM, R16_UNORM, R16_UNORM,
|
||||
UNKNOWN),
|
||||
/* GRAY */
|
||||
/* NOTE: To support conversion by using video processor,
|
||||
* mark DXGI_FORMAT_{R8,R16}_UNORM formats as known dxgi_format.
|
||||
* Otherwise, d3d12 elements will not try to use video processor for
|
||||
* those formats */
|
||||
MAKE_FORMAT_MAP_RGB (GRAY8, R8_UNORM),
|
||||
MAKE_FORMAT_MAP_RGB (GRAY16_LE, R16_UNORM),
|
||||
MAKE_FORMAT_MAP_YUV_FULL (Y410, Y410, R10G10B10A2_UNORM, UNKNOWN, UNKNOWN,
|
||||
UNKNOWN,
|
||||
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE),
|
||||
MAKE_FORMAT_MAP_YUV_FULL (YUY2, YUY2, R8G8B8A8_UNORM, UNKNOWN, UNKNOWN,
|
||||
UNKNOWN,
|
||||
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE),
|
||||
MAKE_FORMAT_MAP_RGBP (RGBP, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_RGBP (BGRP, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_RGBP (GBR, R8_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_RGBP (GBR_10LE, R16_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_RGBP (GBR_12LE, R16_UNORM, UNKNOWN),
|
||||
MAKE_FORMAT_MAP_RGBP (GBRA, R8_UNORM, R8_UNORM),
|
||||
MAKE_FORMAT_MAP_RGBP (GBRA_10LE, R16_UNORM, R16_UNORM),
|
||||
MAKE_FORMAT_MAP_RGBP (GBRA_12LE, R16_UNORM, R16_UNORM),
|
||||
};
|
||||
|
||||
#undef MAKE_FORMAT_MAP_YUV
|
||||
#undef MAKE_FORMAT_MAP_YUV_FULL
|
||||
#undef MAKE_FORMAT_MAP_RGB
|
||||
|
||||
#define GST_D3D12_N_FORMATS G_N_ELEMENTS(_gst_d3d12_default_format_map)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ADAPTER_INDEX,
|
||||
PROP_ADAPTER_LUID,
|
||||
PROP_DEVICE_ID,
|
||||
PROP_VENDOR_ID,
|
||||
PROP_HARDWARE,
|
||||
PROP_DESCRIPTION,
|
||||
};
|
||||
|
||||
/* d3d12 devices are singtones per adapter. Keep track of live objects and
|
||||
* reuse already created object if possible */
|
||||
/* *INDENT-OFF* */
|
||||
std::mutex device_list_lock_;
|
||||
std::vector<GstD3D12Device*> live_devices_;
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct _GstD3D12DevicePrivate
|
||||
{
|
||||
ComPtr<ID3D12Device> device;
|
||||
ComPtr<IDXGIAdapter1> adapter;
|
||||
ComPtr<IDXGIFactory2> factory;
|
||||
std::vector < GstD3D12Format> formats;
|
||||
std::mutex lock;
|
||||
std::recursive_mutex extern_lock;
|
||||
std::atomic<guint64> fence_value;
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
ComPtr<ID3D12InfoQueue> info_queue;
|
||||
#endif
|
||||
|
||||
guint adapter_index = 0;
|
||||
guint device_id = 0;
|
||||
guint vendor_id = 0;
|
||||
std::string description;
|
||||
gint64 adapter_luid = 0;
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
static gboolean
|
||||
gst_d3d12_device_enable_debug (void)
|
||||
{
|
||||
static gboolean enabled = FALSE;
|
||||
|
||||
GST_D3D12_CALL_ONCE_BEGIN {
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_device_debug,
|
||||
"d3d12device", 0, "d3d12 device object");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_sdk_debug,
|
||||
"d3d12debuglayer", 0, "d3d12 SDK layer debug");
|
||||
|
||||
/* Enables debug layer only if it's requested, otherwise
|
||||
* already configured d3d12 devices (e.g., owned by application)
|
||||
* will be invalidated by ID3D12Debug::EnableDebugLayer() */
|
||||
if (!g_getenv ("GST_ENABLE_D3D12_DEBUG"))
|
||||
return;
|
||||
|
||||
HRESULT hr;
|
||||
ComPtr < ID3D12Debug > d3d12_debug;
|
||||
hr = D3D12GetDebugInterface (IID_PPV_ARGS (&d3d12_debug));
|
||||
if (FAILED (hr))
|
||||
return;
|
||||
|
||||
d3d12_debug->EnableDebugLayer ();
|
||||
enabled = TRUE;
|
||||
|
||||
GST_INFO ("D3D12 debug layer is enabled");
|
||||
|
||||
ComPtr < ID3D12Debug5 > d3d12_debug5;
|
||||
hr = d3d12_debug.As (&d3d12_debug5);
|
||||
if (SUCCEEDED (hr))
|
||||
d3d12_debug5->SetEnableAutoName (TRUE);
|
||||
|
||||
ComPtr < ID3D12Debug1 > d3d12_debug1;
|
||||
hr = d3d12_debug.As (&d3d12_debug1);
|
||||
if (FAILED (hr))
|
||||
return;
|
||||
|
||||
d3d12_debug1->SetEnableSynchronizedCommandQueueValidation (TRUE);
|
||||
|
||||
GST_INFO ("Enabled synchronized command queue validation");
|
||||
|
||||
if (!g_getenv ("GST_ENABLE_D3D12_DEBUG_GPU_VALIDATION"))
|
||||
return;
|
||||
|
||||
d3d12_debug1->SetEnableGPUBasedValidation (TRUE);
|
||||
|
||||
GST_INFO ("Enabled GPU based validation");
|
||||
}
|
||||
GST_D3D12_CALL_ONCE_END;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define gst_d3d12_device_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstD3D12Device, gst_d3d12_device, GST_TYPE_OBJECT);
|
||||
|
||||
static void gst_d3d12_device_finalize (GObject * object);
|
||||
static void gst_d3d12_device_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_d3d12_device_setup_format_table (GstD3D12Device * self);
|
||||
|
||||
static void
|
||||
gst_d3d12_device_class_init (GstD3D12DeviceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamFlags readable_flags =
|
||||
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
gobject_class->finalize = gst_d3d12_device_finalize;
|
||||
gobject_class->get_property = gst_d3d12_device_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ADAPTER_INDEX,
|
||||
g_param_spec_uint ("adapter-index", "Adapter Index",
|
||||
"DXGI Adapter index for creating device",
|
||||
0, G_MAXUINT32, 0, readable_flags));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ADAPTER_LUID,
|
||||
g_param_spec_int64 ("adapter-luid", "Adapter LUID",
|
||||
"DXGI Adapter LUID (Locally Unique Identifier) of created device",
|
||||
0, G_MAXINT64, 0, readable_flags));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
|
||||
g_param_spec_uint ("device-id", "Device Id",
|
||||
"DXGI Device ID", 0, G_MAXUINT32, 0, readable_flags));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_VENDOR_ID,
|
||||
g_param_spec_uint ("vendor-id", "Vendor Id",
|
||||
"DXGI Vendor ID", 0, G_MAXUINT32, 0, readable_flags));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
|
||||
g_param_spec_string ("description", "Description",
|
||||
"Human readable device description", nullptr, readable_flags));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_device_init (GstD3D12Device * self)
|
||||
{
|
||||
self->priv = new GstD3D12DevicePrivate ();
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_device_finalize (GObject * object)
|
||||
{
|
||||
GstD3D12Device *self = GST_D3D12_DEVICE (object);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Finalize");
|
||||
|
||||
delete self->priv;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_device_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstD3D12Device *self = GST_D3D12_DEVICE (object);
|
||||
GstD3D12DevicePrivate *priv = self->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ADAPTER_INDEX:
|
||||
g_value_set_uint (value, priv->adapter_index);
|
||||
break;
|
||||
case PROP_ADAPTER_LUID:
|
||||
g_value_set_int64 (value, priv->adapter_luid);
|
||||
break;
|
||||
case PROP_DEVICE_ID:
|
||||
g_value_set_uint (value, priv->device_id);
|
||||
break;
|
||||
case PROP_VENDOR_ID:
|
||||
g_value_set_uint (value, priv->vendor_id);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, priv->description.c_str ());
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_format_support (GstD3D12Device * self, DXGI_FORMAT format,
|
||||
guint flags, D3D12_FEATURE_DATA_FORMAT_SUPPORT * support)
|
||||
{
|
||||
ID3D12Device *device = self->priv->device.Get ();
|
||||
HRESULT hr;
|
||||
|
||||
support->Format = format;
|
||||
hr = device->CheckFeatureSupport (D3D12_FEATURE_FORMAT_SUPPORT, support,
|
||||
sizeof (D3D12_FEATURE_DATA_FORMAT_SUPPORT));
|
||||
if (FAILED (hr)) {
|
||||
GST_INFO_OBJECT (self,
|
||||
"Failed to check feature support for DXGI format %d", format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (((guint) support->Support1 & flags) != flags) {
|
||||
GST_INFO_OBJECT (self,
|
||||
"DXGI format %d supports1 flag 0x%x, required 0x%x", format,
|
||||
support->Support1, flags);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_device_setup_format_table (GstD3D12Device * self)
|
||||
{
|
||||
GstD3D12DevicePrivate *priv = self->priv;
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (_gst_d3d12_default_format_map); i++) {
|
||||
const GstD3D12Format *iter = &_gst_d3d12_default_format_map[i];
|
||||
GstD3D12Format format;
|
||||
D3D12_FEATURE_DATA_FORMAT_SUPPORT support[GST_VIDEO_MAX_PLANES];
|
||||
|
||||
memset (support, 0, sizeof (support));
|
||||
|
||||
switch (iter->format) {
|
||||
/* RGB/GRAY */
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
case GST_VIDEO_FORMAT_BGRx:
|
||||
case GST_VIDEO_FORMAT_RGBA:
|
||||
case GST_VIDEO_FORMAT_RGBx:
|
||||
case GST_VIDEO_FORMAT_RGB10A2_LE:
|
||||
case GST_VIDEO_FORMAT_RGBA64_LE:
|
||||
case GST_VIDEO_FORMAT_GRAY8:
|
||||
case GST_VIDEO_FORMAT_GRAY16_LE:
|
||||
if (!check_format_support (self, iter->dxgi_format,
|
||||
iter->format_support1[0], &support[0])) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
/* YUV DXGI native formats */
|
||||
case GST_VIDEO_FORMAT_VUYA:
|
||||
case GST_VIDEO_FORMAT_Y410:
|
||||
case GST_VIDEO_FORMAT_NV12:
|
||||
case GST_VIDEO_FORMAT_P010_10LE:
|
||||
case GST_VIDEO_FORMAT_P012_LE:
|
||||
case GST_VIDEO_FORMAT_P016_LE:
|
||||
case GST_VIDEO_FORMAT_YUY2:
|
||||
if (!check_format_support (self, iter->dxgi_format,
|
||||
iter->format_support1[0], &support[0])) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
/* non-DXGI native formats */
|
||||
case GST_VIDEO_FORMAT_NV21:
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
case GST_VIDEO_FORMAT_YV12:
|
||||
case GST_VIDEO_FORMAT_I420_10LE:
|
||||
case GST_VIDEO_FORMAT_I420_12LE:
|
||||
case GST_VIDEO_FORMAT_Y42B:
|
||||
case GST_VIDEO_FORMAT_I422_10LE:
|
||||
case GST_VIDEO_FORMAT_I422_12LE:
|
||||
case GST_VIDEO_FORMAT_Y444:
|
||||
case GST_VIDEO_FORMAT_Y444_10LE:
|
||||
case GST_VIDEO_FORMAT_Y444_12LE:
|
||||
case GST_VIDEO_FORMAT_Y444_16LE:
|
||||
case GST_VIDEO_FORMAT_AYUV:
|
||||
case GST_VIDEO_FORMAT_AYUV64:
|
||||
/* RGB planar formats */
|
||||
case GST_VIDEO_FORMAT_RGBP:
|
||||
case GST_VIDEO_FORMAT_BGRP:
|
||||
case GST_VIDEO_FORMAT_GBR:
|
||||
case GST_VIDEO_FORMAT_GBR_10LE:
|
||||
case GST_VIDEO_FORMAT_GBR_12LE:
|
||||
case GST_VIDEO_FORMAT_GBRA:
|
||||
case GST_VIDEO_FORMAT_GBRA_10LE:
|
||||
case GST_VIDEO_FORMAT_GBRA_12LE:
|
||||
{
|
||||
bool supported = true;
|
||||
for (guint j = 0; j < GST_VIDEO_MAX_PLANES; j++) {
|
||||
if (iter->resource_format[j] == DXGI_FORMAT_UNKNOWN)
|
||||
break;
|
||||
|
||||
if (!check_format_support (self, iter->resource_format[j],
|
||||
iter->format_support1[0], &support[j])) {
|
||||
supported = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
GST_INFO_OBJECT (self, "%s is not supported",
|
||||
gst_video_format_to_string (iter->format));
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
}
|
||||
|
||||
format = *iter;
|
||||
|
||||
for (guint j = 0; j < GST_VIDEO_MAX_PLANES; j++) {
|
||||
format.format_support1[j] = support[j].Support1;
|
||||
format.format_support2[j] = support[j].Support2;
|
||||
}
|
||||
|
||||
priv->formats.push_back (format);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_device_weak_ref_notify (gpointer data, GstD3D12Device * device)
|
||||
{
|
||||
std::lock_guard < std::mutex > lk (device_list_lock_);
|
||||
auto it = std::find (live_devices_.begin (), live_devices_.end (), device);
|
||||
if (it != live_devices_.end ())
|
||||
live_devices_.erase (it);
|
||||
else
|
||||
GST_WARNING ("Could not find %p from list", device);
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_D3D12_DEVICE_CONSTRUCT_FOR_INDEX,
|
||||
GST_D3D12_DEVICE_CONSTRUCT_FOR_LUID,
|
||||
} GstD3D12DeviceConstructType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
guint index;
|
||||
gint64 luid;
|
||||
} data;
|
||||
GstD3D12DeviceConstructType type;
|
||||
} GstD3D12DeviceConstructData;
|
||||
|
||||
static HRESULT
|
||||
gst_d3d12_device_find_adapter (const GstD3D12DeviceConstructData * data,
|
||||
IDXGIFactory2 * factory, guint * index, IDXGIAdapter1 ** rst)
|
||||
{
|
||||
HRESULT hr;
|
||||
UINT factory_flags = 0;
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
if (gst_d3d12_device_enable_debug ())
|
||||
factory_flags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||
#endif
|
||||
|
||||
hr = CreateDXGIFactory2 (factory_flags, IID_PPV_ARGS (&factory));
|
||||
if (FAILED (hr)) {
|
||||
GST_WARNING ("cannot create dxgi factory, hr: 0x%x", (guint) hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
switch (data->type) {
|
||||
case GST_D3D12_DEVICE_CONSTRUCT_FOR_INDEX:{
|
||||
ComPtr < IDXGIAdapter1 > adapter;
|
||||
hr = factory->EnumAdapters1 (data->data.index, &adapter);
|
||||
if (FAILED (hr))
|
||||
return hr;
|
||||
|
||||
*index = data->data.index;
|
||||
*rst = adapter.Detach ();
|
||||
return S_OK;
|
||||
}
|
||||
case GST_D3D12_DEVICE_CONSTRUCT_FOR_LUID:
|
||||
for (UINT i = 0;; i++) {
|
||||
ComPtr < IDXGIAdapter1 > adapter;
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
|
||||
hr = factory->EnumAdapters1 (i, &adapter);
|
||||
if (FAILED (hr))
|
||||
return hr;
|
||||
|
||||
hr = adapter->GetDesc1 (&desc);
|
||||
if (FAILED (hr))
|
||||
return hr;
|
||||
|
||||
if (gst_d3d12_luid_to_int64 (&desc.AdapterLuid) != data->data.luid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*index = i;
|
||||
*rst = adapter.Detach ();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static GstD3D12Device *
|
||||
gst_d3d12_device_new_internal (const GstD3D12DeviceConstructData * data)
|
||||
{
|
||||
ComPtr < IDXGIFactory2 > factory;
|
||||
ComPtr < IDXGIAdapter1 > adapter;
|
||||
ComPtr < ID3D12Device > device;
|
||||
HRESULT hr;
|
||||
UINT factory_flags = 0;
|
||||
guint index = 0;
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
if (gst_d3d12_device_enable_debug ())
|
||||
factory_flags |= DXGI_CREATE_FACTORY_DEBUG;
|
||||
#endif
|
||||
|
||||
hr = CreateDXGIFactory2 (factory_flags, IID_PPV_ARGS (&factory));
|
||||
if (FAILED (hr)) {
|
||||
GST_WARNING ("Could create dxgi factory, hr: 0x%x", (guint) hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hr = gst_d3d12_device_find_adapter (data, factory.Get (), &index, &adapter);
|
||||
if (FAILED (hr)) {
|
||||
GST_WARNING ("Could not find adapter, hr: 0x%x", (guint) hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
hr = adapter->GetDesc1 (&desc);
|
||||
if (FAILED (hr)) {
|
||||
GST_WARNING ("Could not get adapter desc, hr: 0x%x", (guint) hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hr = D3D12CreateDevice (adapter.Get (), D3D_FEATURE_LEVEL_12_0,
|
||||
IID_PPV_ARGS (&device));
|
||||
if (FAILED (hr)) {
|
||||
GST_WARNING ("Could not create device, hr: 0x%x", (guint) hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GstD3D12Device *self = (GstD3D12Device *)
|
||||
g_object_new (GST_TYPE_D3D12_DEVICE, nullptr);
|
||||
GstD3D12DevicePrivate *priv = self->priv;
|
||||
|
||||
priv->factory = factory;
|
||||
priv->adapter = adapter;
|
||||
priv->device = device;
|
||||
priv->adapter_luid = gst_d3d12_luid_to_int64 (&desc.AdapterLuid);
|
||||
priv->vendor_id = desc.VendorId;
|
||||
priv->device_id = desc.DeviceId;
|
||||
|
||||
std::wstring_convert < std::codecvt_utf8 < wchar_t >, wchar_t >converter;
|
||||
priv->description = converter.to_bytes (desc.Description);
|
||||
|
||||
GST_INFO_OBJECT (self,
|
||||
"adapter index %d: D3D12 device vendor-id: 0x%04x, device-id: 0x%04x, "
|
||||
"Flags: 0x%x, adapter-luid: %" G_GINT64_FORMAT ", %s",
|
||||
priv->adapter_index, desc.VendorId, desc.DeviceId, desc.Flags,
|
||||
priv->adapter_luid, priv->description.c_str ());
|
||||
|
||||
gst_d3d12_device_setup_format_table (self);
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
if (gst_d3d12_device_enable_debug ()) {
|
||||
ComPtr < ID3D12InfoQueue > info_queue;
|
||||
device.As (&info_queue);
|
||||
priv->info_queue = info_queue;
|
||||
}
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GstD3D12Device *
|
||||
gst_d3d12_device_new (guint adapter_index)
|
||||
{
|
||||
GstD3D12Device *self = nullptr;
|
||||
std::lock_guard < std::mutex > lk (device_list_lock_);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
for (auto iter: live_devices_) {
|
||||
if (iter->priv->adapter_index == adapter_index) {
|
||||
self = (GstD3D12Device *) gst_object_ref (iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
|
||||
if (!self) {
|
||||
GstD3D12DeviceConstructData data;
|
||||
data.data.index = adapter_index;
|
||||
data.type = GST_D3D12_DEVICE_CONSTRUCT_FOR_INDEX;
|
||||
|
||||
self = gst_d3d12_device_new_internal (&data);
|
||||
if (!self) {
|
||||
GST_INFO ("Could not create device for index %d", adapter_index);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gst_object_ref_sink (self);
|
||||
g_object_weak_ref (G_OBJECT (self),
|
||||
(GWeakNotify) gst_d3d12_device_weak_ref_notify, nullptr);
|
||||
live_devices_.push_back (self);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GstD3D12Device *
|
||||
gst_d3d12_device_new_for_adapter_luid (gint64 adapter_luid)
|
||||
{
|
||||
GstD3D12Device *self = nullptr;
|
||||
std::lock_guard < std::mutex > lk (device_list_lock_);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
for (auto iter: live_devices_) {
|
||||
if (iter->priv->adapter_luid == adapter_luid) {
|
||||
self = (GstD3D12Device *) gst_object_ref (iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
|
||||
if (!self) {
|
||||
GstD3D12DeviceConstructData data;
|
||||
data.data.luid = adapter_luid;
|
||||
data.type = GST_D3D12_DEVICE_CONSTRUCT_FOR_LUID;
|
||||
|
||||
self = gst_d3d12_device_new_internal (&data);
|
||||
if (!self) {
|
||||
GST_INFO ("Could not create device for LUID %" G_GINT64_FORMAT,
|
||||
adapter_luid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gst_object_ref_sink (self);
|
||||
g_object_weak_ref (G_OBJECT (self),
|
||||
(GWeakNotify) gst_d3d12_device_weak_ref_notify, nullptr);
|
||||
live_devices_.push_back (self);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
ID3D12Device *
|
||||
gst_d3d12_device_get_device_handle (GstD3D12Device * device)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr);
|
||||
|
||||
return device->priv->device.Get ();
|
||||
}
|
||||
|
||||
IDXGIAdapter1 *
|
||||
gst_d3d12_device_get_adapter_handle (GstD3D12Device * device)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr);
|
||||
|
||||
return device->priv->adapter.Get ();
|
||||
}
|
||||
|
||||
IDXGIFactory2 *
|
||||
gst_d3d12_device_get_factory_handle (GstD3D12Device * device)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr);
|
||||
|
||||
return device->priv->factory.Get ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_device_get_device_format (GstD3D12Device * device,
|
||||
GstVideoFormat format, GstD3D12Format * device_format)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (device_format != nullptr, FALSE);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
for (const auto &iter : device->priv->formats) {
|
||||
if (iter.format == format) {
|
||||
*device_format = iter;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline GstDebugLevel
|
||||
d3d12_message_severity_to_gst (D3D12_MESSAGE_SEVERITY level)
|
||||
{
|
||||
switch (level) {
|
||||
case D3D12_MESSAGE_SEVERITY_CORRUPTION:
|
||||
case D3D12_MESSAGE_SEVERITY_ERROR:
|
||||
return GST_LEVEL_ERROR;
|
||||
case D3D12_MESSAGE_SEVERITY_WARNING:
|
||||
return GST_LEVEL_WARNING;
|
||||
case D3D12_MESSAGE_SEVERITY_INFO:
|
||||
return GST_LEVEL_INFO;
|
||||
case D3D12_MESSAGE_SEVERITY_MESSAGE:
|
||||
return GST_LEVEL_DEBUG;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_LEVEL_LOG;
|
||||
}
|
||||
|
||||
#ifdef HAVE_D3D12_SDKLAYERS_H
|
||||
void
|
||||
gst_d3d12_device_d3d12_debug (GstD3D12Device * device, const gchar * file,
|
||||
const gchar * function, gint line)
|
||||
{
|
||||
g_return_if_fail (GST_IS_D3D12_DEVICE (device));
|
||||
|
||||
if (!device->priv->info_queue)
|
||||
return;
|
||||
|
||||
GstD3D12DevicePrivate *priv = device->priv;
|
||||
|
||||
std::lock_guard < std::recursive_mutex > lk (priv->extern_lock);
|
||||
ID3D12InfoQueue *info_queue = priv->info_queue.Get ();
|
||||
UINT64 num_msg = info_queue->GetNumStoredMessages ();
|
||||
for (guint64 i = 0; i < num_msg; i++) {
|
||||
HRESULT hr;
|
||||
SIZE_T msg_len;
|
||||
D3D12_MESSAGE *msg;
|
||||
GstDebugLevel msg_level;
|
||||
GstDebugLevel selected_level;
|
||||
|
||||
hr = info_queue->GetMessage (i, nullptr, &msg_len);
|
||||
if (FAILED (hr) || msg_len == 0)
|
||||
continue;
|
||||
|
||||
msg = (D3D12_MESSAGE *) g_malloc0 (msg_len);
|
||||
hr = info_queue->GetMessage (i, msg, &msg_len);
|
||||
if (FAILED (hr) || msg_len == 0) {
|
||||
g_free (msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
msg_level = d3d12_message_severity_to_gst (msg->Severity);
|
||||
if (msg->Category == D3D12_MESSAGE_CATEGORY_STATE_CREATION &&
|
||||
msg_level > GST_LEVEL_ERROR) {
|
||||
/* Do not warn for live object, since there would be live object
|
||||
* when ReportLiveDeviceObjects was called */
|
||||
selected_level = GST_LEVEL_INFO;
|
||||
} else {
|
||||
selected_level = msg_level;
|
||||
}
|
||||
|
||||
gst_debug_log (gst_d3d12_sdk_debug, selected_level, file, function, line,
|
||||
G_OBJECT (device), "D3D12InfoQueue: %s", msg->pDescription);
|
||||
g_free (msg);
|
||||
}
|
||||
|
||||
info_queue->ClearStoredMessages ();
|
||||
}
|
||||
#else
|
||||
void
|
||||
gst_d3d12_device_d3d12_debug (GstD3D12Device * device, const gchar * file,
|
||||
const gchar * function, gint line)
|
||||
{
|
||||
}
|
||||
#endif
|
77
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.h
Normal file
77
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include "gstd3d12_fwd.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_D3D12_DEVICE (gst_d3d12_device_get_type())
|
||||
#define GST_D3D12_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D12_DEVICE,GstD3D12Device))
|
||||
#define GST_D3D12_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_D3D12_DEVICE,GstD3D12DeviceClass))
|
||||
#define GST_D3D12_DEVICE_GET_CLASS(obj) (GST_D3D12_DEVICE_CLASS(G_OBJECT_GET_CLASS(obj)))
|
||||
#define GST_IS_D3D12_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D12_DEVICE))
|
||||
#define GST_IS_D3D12_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D12_DEVICE))
|
||||
#define GST_D3D12_DEVICE_CAST(obj) ((GstD3D12Device*)(obj))
|
||||
|
||||
#define GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE "gst.d3d12.device.handle"
|
||||
|
||||
struct _GstD3D12Device
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
/*< private >*/
|
||||
GstD3D12DevicePrivate *priv;
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstD3D12DeviceClass
|
||||
{
|
||||
GstObjectClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GType gst_d3d12_device_get_type (void);
|
||||
|
||||
GstD3D12Device * gst_d3d12_device_new (guint adapter_index);
|
||||
|
||||
GstD3D12Device * gst_d3d12_device_new_for_adapter_luid (gint64 adapter_luid);
|
||||
|
||||
ID3D12Device * gst_d3d12_device_get_device_handle (GstD3D12Device * device);
|
||||
|
||||
IDXGIAdapter1 * gst_d3d12_device_get_adapter_handle (GstD3D12Device * device);
|
||||
|
||||
IDXGIFactory2 * gst_d3d12_device_get_factory_handle (GstD3D12Device * device);
|
||||
|
||||
gboolean gst_d3d12_device_get_device_format (GstD3D12Device * device,
|
||||
GstVideoFormat format,
|
||||
GstD3D12Format * device_format);
|
||||
|
||||
void gst_d3d12_device_d3d12_debug (GstD3D12Device * device,
|
||||
const gchar * file,
|
||||
const gchar * function,
|
||||
gint line);
|
||||
|
||||
G_END_DECLS
|
||||
|
173
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12fence.cpp
Normal file
173
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12fence.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* 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 "gstd3d12fence.h"
|
||||
#include "gstd3d12device.h"
|
||||
#include "gstd3d12utils.h"
|
||||
#include <wrl.h>
|
||||
#include <mutex>
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_d3d12_fence_debug);
|
||||
#define GST_CAT_DEFAULT gst_d3d12_fence_debug
|
||||
|
||||
GST_DEFINE_MINI_OBJECT_TYPE (GstD3D12Fence, gst_d3d12_fence);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct _GstD3D12FencePrivate
|
||||
{
|
||||
_GstD3D12FencePrivate()
|
||||
{
|
||||
event_handle = CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
|
||||
}
|
||||
|
||||
~_GstD3D12FencePrivate()
|
||||
{
|
||||
CloseHandle (event_handle);
|
||||
}
|
||||
|
||||
ComPtr<ID3D12Fence> fence;
|
||||
HANDLE event_handle;
|
||||
std::mutex lock;
|
||||
guint64 value = 0;
|
||||
gboolean can_wait = FALSE;
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static void
|
||||
gst_d3d12_fence_free (GstD3D12Fence * self)
|
||||
{
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
GST_TRACE ("Freeing fence %p", self);
|
||||
|
||||
gst_clear_object (&self->device);
|
||||
delete self->priv;
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
GstD3D12Fence *
|
||||
gst_d3d12_fence_new (GstD3D12Device * device)
|
||||
{
|
||||
GstD3D12Fence *self;
|
||||
GstD3D12FencePrivate *priv;
|
||||
ID3D12Device *device_handle;
|
||||
HRESULT hr;
|
||||
ComPtr < ID3D12Fence > fence;
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr);
|
||||
|
||||
device_handle = gst_d3d12_device_get_device_handle (device);
|
||||
hr = device_handle->CreateFence (0,
|
||||
D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS (&fence));
|
||||
if (!gst_d3d12_result (hr, device)) {
|
||||
GST_ERROR_OBJECT (device, "Failed to create fence, hr: 0x%x", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
priv = new GstD3D12FencePrivate ();
|
||||
priv->fence = fence;
|
||||
|
||||
self = g_new0 (GstD3D12Fence, 1);
|
||||
GST_TRACE_OBJECT (device, "Creating fence %p", self);
|
||||
|
||||
self->device = (GstD3D12Device *) gst_object_ref (device);
|
||||
self->priv = priv;
|
||||
|
||||
gst_mini_object_init (GST_MINI_OBJECT_CAST (self), 0, GST_TYPE_D3D12_FENCE,
|
||||
nullptr, nullptr, (GstMiniObjectFreeFunction) gst_d3d12_fence_free);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_fence_set_event_on_completion_value (GstD3D12Fence * fence,
|
||||
guint64 value)
|
||||
{
|
||||
GstD3D12FencePrivate *priv;
|
||||
HRESULT hr;
|
||||
|
||||
g_return_val_if_fail (fence != nullptr, FALSE);
|
||||
|
||||
priv = fence->priv;
|
||||
|
||||
std::lock_guard < std::mutex > lk (priv->lock);
|
||||
hr = priv->fence->SetEventOnCompletion (value, priv->event_handle);
|
||||
if (!gst_d3d12_result (hr, fence->device)) {
|
||||
GST_ERROR_OBJECT (fence->device, "Failed to set completion event");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->value = value;
|
||||
priv->can_wait = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ID3D12Fence *
|
||||
gst_d3d12_fence_get_handle (GstD3D12Fence * fence)
|
||||
{
|
||||
g_return_val_if_fail (fence != nullptr, nullptr);
|
||||
|
||||
return fence->priv->fence.Get ();
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d12_fence_wait_for (GstD3D12Fence * fence, guint timeout_ms)
|
||||
{
|
||||
g_return_if_fail (fence != nullptr);
|
||||
|
||||
GstD3D12FencePrivate *priv = fence->priv;
|
||||
|
||||
std::lock_guard < std::mutex > lk (priv->lock);
|
||||
if (!priv->can_wait)
|
||||
return;
|
||||
|
||||
GST_TRACE ("Waiting for fence to be signalled with value %" G_GUINT64_FORMAT,
|
||||
priv->value);
|
||||
WaitForSingleObjectEx (priv->event_handle, timeout_ms, FALSE);
|
||||
GST_TRACE ("Signalled with value %" G_GUINT64_FORMAT, priv->value);
|
||||
|
||||
priv->can_wait = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d12_fence_wait (GstD3D12Fence * fence)
|
||||
{
|
||||
gst_d3d12_fence_wait_for (fence, INFINITE);
|
||||
}
|
||||
|
||||
GstD3D12Fence *
|
||||
gst_d3d12_fence_ref (GstD3D12Fence * fence)
|
||||
{
|
||||
return (GstD3D12Fence *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (fence));
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d12_fence_unref (GstD3D12Fence * fence)
|
||||
{
|
||||
gst_mini_object_unref (GST_MINI_OBJECT_CAST (fence));
|
||||
}
|
60
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12fence.h
Normal file
60
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12fence.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstd3d12_fwd.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_D3D12_FENCE (gst_d3d12_fence_get_type())
|
||||
#define GST_D3D12_FENCE_CAST(f) ((GstD3D12Fence *)f)
|
||||
|
||||
struct _GstD3D12Fence
|
||||
{
|
||||
GstMiniObject parent;
|
||||
|
||||
GstD3D12Device *device;
|
||||
|
||||
/*< private >*/
|
||||
GstD3D12FencePrivate *priv;
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GType gst_d3d12_fence_get_type (void);
|
||||
|
||||
GstD3D12Fence * gst_d3d12_fence_new (GstD3D12Device * device);
|
||||
|
||||
ID3D12Fence * gst_d3d12_fence_get_handle (GstD3D12Fence * fence);
|
||||
|
||||
gboolean gst_d3d12_fence_set_event_on_completion_value (GstD3D12Fence * fence,
|
||||
guint64 value);
|
||||
|
||||
void gst_d3d12_fence_wait_for (GstD3D12Fence * fence,
|
||||
guint timeout_ms);
|
||||
|
||||
void gst_d3d12_fence_wait (GstD3D12Fence * fence);
|
||||
|
||||
GstD3D12Fence * gst_d3d12_fence_ref (GstD3D12Fence * fence);
|
||||
|
||||
void gst_d3d12_fence_unref (GstD3D12Fence * fence);
|
||||
|
||||
G_END_DECLS
|
||||
|
127
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12format.cpp
Normal file
127
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12format.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* 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 "gstd3d12format.h"
|
||||
#include "gstd3d12utils.h"
|
||||
#include "gstd3d12device.h"
|
||||
#include <string.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_d3d12_format_debug);
|
||||
#define GST_CAT_DEFAULT gst_d3d12_format_debug
|
||||
|
||||
guint
|
||||
gst_d3d12_get_format_plane_count (GstD3D12Device * device, DXGI_FORMAT format)
|
||||
{
|
||||
ID3D12Device *device_handle;
|
||||
HRESULT hr;
|
||||
D3D12_FEATURE_DATA_FORMAT_INFO format_info = { format, 0 };
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), 0);
|
||||
|
||||
device_handle = gst_d3d12_device_get_device_handle (device);
|
||||
hr = device_handle->CheckFeatureSupport (D3D12_FEATURE_FORMAT_INFO,
|
||||
&format_info, sizeof (D3D12_FEATURE_DATA_FORMAT_INFO));
|
||||
if (!gst_d3d12_result (hr, device))
|
||||
return 0;
|
||||
|
||||
return format_info.PlaneCount;
|
||||
}
|
||||
|
||||
GstVideoFormat
|
||||
gst_d3d12_dxgi_format_to_gst (DXGI_FORMAT format)
|
||||
{
|
||||
switch (format) {
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
return GST_VIDEO_FORMAT_BGRA;
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
return GST_VIDEO_FORMAT_RGBA;
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
return GST_VIDEO_FORMAT_RGB10A2_LE;
|
||||
case DXGI_FORMAT_AYUV:
|
||||
return GST_VIDEO_FORMAT_VUYA;
|
||||
case DXGI_FORMAT_YUY2:
|
||||
return GST_VIDEO_FORMAT_YUY2;
|
||||
case DXGI_FORMAT_Y210:
|
||||
return GST_VIDEO_FORMAT_Y210;
|
||||
case DXGI_FORMAT_Y410:
|
||||
return GST_VIDEO_FORMAT_Y410;
|
||||
case DXGI_FORMAT_NV12:
|
||||
return GST_VIDEO_FORMAT_NV12;
|
||||
case DXGI_FORMAT_P010:
|
||||
return GST_VIDEO_FORMAT_P010_10LE;
|
||||
case DXGI_FORMAT_P016:
|
||||
return GST_VIDEO_FORMAT_P016_LE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_VIDEO_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_dxgi_format_to_resource_formats (DXGI_FORMAT format,
|
||||
DXGI_FORMAT resource_format[GST_VIDEO_MAX_PLANES])
|
||||
{
|
||||
g_return_val_if_fail (resource_format != nullptr, FALSE);
|
||||
|
||||
for (guint i = 0; i < GST_VIDEO_MAX_PLANES; i++)
|
||||
resource_format[i] = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
switch (format) {
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
case DXGI_FORMAT_R8_UNORM:
|
||||
case DXGI_FORMAT_R8G8_UNORM:
|
||||
case DXGI_FORMAT_R16_UNORM:
|
||||
case DXGI_FORMAT_R16G16_UNORM:
|
||||
case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
||||
case DXGI_FORMAT_R8G8_B8G8_UNORM:
|
||||
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
||||
resource_format[0] = format;
|
||||
break;
|
||||
case DXGI_FORMAT_AYUV:
|
||||
case DXGI_FORMAT_YUY2:
|
||||
resource_format[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case DXGI_FORMAT_NV12:
|
||||
resource_format[0] = DXGI_FORMAT_R8_UNORM;
|
||||
resource_format[1] = DXGI_FORMAT_R8G8_UNORM;
|
||||
break;
|
||||
case DXGI_FORMAT_P010:
|
||||
case DXGI_FORMAT_P016:
|
||||
resource_format[0] = DXGI_FORMAT_R16_UNORM;
|
||||
resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
|
||||
break;
|
||||
case DXGI_FORMAT_Y210:
|
||||
resource_format[0] = DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
break;
|
||||
case DXGI_FORMAT_Y410:
|
||||
resource_format[0] = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
72
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12format.h
Normal file
72
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12format.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include "gstd3d12_fwd.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_D3D12_COMMON_FORMATS \
|
||||
"NV12, P010_10LE, P016_LE "
|
||||
|
||||
#define GST_D3D12_SINK_FORMATS \
|
||||
"{ " GST_D3D12_COMMON_FORMATS " }"
|
||||
|
||||
#define GST_D3D12_SRC_FORMATS \
|
||||
"{ " GST_D3D12_COMMON_FORMATS " }"
|
||||
|
||||
#define GST_D3D12_FORMATS_ALL \
|
||||
"{ " GST_D3D12_COMMON_FORMATS " }"
|
||||
|
||||
struct _GstD3D12Format
|
||||
{
|
||||
GstVideoFormat format;
|
||||
|
||||
/* direct mapping to dxgi format if applicable */
|
||||
DXGI_FORMAT dxgi_format;
|
||||
|
||||
/* formats for texture processing */
|
||||
DXGI_FORMAT resource_format[GST_VIDEO_MAX_PLANES];
|
||||
|
||||
/* extra format used for unordered access view (unused) */
|
||||
DXGI_FORMAT uav_format[GST_VIDEO_MAX_PLANES];
|
||||
|
||||
/* D3D12_FORMAT_SUPPORT1 flags */
|
||||
guint format_support1[GST_VIDEO_MAX_PLANES];
|
||||
|
||||
/* D3D12_FORMAT_SUPPORT2 flags (unused) */
|
||||
guint format_support2[GST_VIDEO_MAX_PLANES];
|
||||
|
||||
/*< private >*/
|
||||
guint padding[GST_PADDING_LARGE];
|
||||
};
|
||||
|
||||
guint gst_d3d12_get_format_plane_count (GstD3D12Device * device,
|
||||
DXGI_FORMAT format);
|
||||
|
||||
GstVideoFormat gst_d3d12_dxgi_format_to_gst (DXGI_FORMAT format);
|
||||
|
||||
gboolean gst_d3d12_dxgi_format_to_resource_formats (DXGI_FORMAT format,
|
||||
DXGI_FORMAT resource_format[GST_VIDEO_MAX_PLANES]);
|
||||
|
||||
G_END_DECLS
|
||||
|
327
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.cpp
Normal file
327
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.cpp
Normal file
|
@ -0,0 +1,327 @@
|
|||
/* 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 02120-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:element-d3d12h264dec
|
||||
* @title: d3d12h264dec
|
||||
*
|
||||
* A Direct3D12 based H.264 video decoder
|
||||
*
|
||||
* ## Example launch line
|
||||
* ```
|
||||
* gst-launch-1.0 filesrc location=/path/to/h264/file ! parsebin ! d3d12h264dec ! videoconvert ! autovideosink
|
||||
* ```
|
||||
*
|
||||
* Since: 1.24
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "gstd3d12h264dec.h"
|
||||
#include "gstd3d12device.h"
|
||||
#include "gstd3d12utils.h"
|
||||
#include <gst/dxva/gstdxvah264decoder.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_d3d12_h264_dec_debug);
|
||||
#define GST_CAT_DEFAULT gst_d3d12_h264_dec_debug
|
||||
|
||||
GST_D3D12_DECODER_DEFINE_TYPE_FULL (GstD3D12H264Dec, gst_d3d12_h264_dec,
|
||||
GST, D3D12_H264_DEC, GstDxvaH264Decoder);
|
||||
|
||||
static void
|
||||
gst_d3d12_h264_dec_class_init (GstD3D12H264DecClass * klass, gpointer data)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
|
||||
GstDxvaH264DecoderClass *dxva_class = GST_DXVA_H264_DECODER_CLASS (klass);
|
||||
GstD3D12DecoderClassData *cdata = (GstD3D12DecoderClassData *) data;
|
||||
|
||||
gobject_class->get_property = gst_d3d12_h264_dec_get_property;
|
||||
|
||||
element_class->set_context =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_set_context);
|
||||
|
||||
parent_class = (GstElementClass *) g_type_class_peek_parent (klass);
|
||||
gst_d3d12_decoder_class_data_fill_subclass_data (cdata, &klass->class_data);
|
||||
|
||||
gst_d3d12_decoder_proxy_class_init (element_class, cdata,
|
||||
"Seungha Yang <seungha@centricualr.com>");
|
||||
|
||||
decoder_class->open = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_open);
|
||||
decoder_class->close = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_close);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_negotiate);
|
||||
decoder_class->decide_allocation =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_decide_allocation);
|
||||
decoder_class->sink_query = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_sink_query);
|
||||
decoder_class->src_query = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_src_query);
|
||||
|
||||
dxva_class->configure = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_configure);
|
||||
dxva_class->new_picture = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_new_picture);
|
||||
dxva_class->duplicate_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_duplicate_picture);
|
||||
dxva_class->get_picture_id =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_get_picture_id);
|
||||
dxva_class->start_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_start_picture);
|
||||
dxva_class->end_picture = GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_end_picture);
|
||||
dxva_class->output_picture =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_h264_dec_output_picture);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_h264_dec_init (GstD3D12H264Dec * self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_h264_dec_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstD3D12H264DecClass *klass = GST_D3D12_H264_DEC_GET_CLASS (object);
|
||||
GstD3D12DecoderSubClassData *cdata = &klass->class_data;
|
||||
|
||||
gst_d3d12_decoder_proxy_get_property (object, prop_id, value, pspec, cdata);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d12_h264_dec_set_context (GstElement * element, GstContext * context)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (element);
|
||||
GstD3D12H264DecClass *klass = GST_D3D12_H264_DEC_GET_CLASS (self);
|
||||
GstD3D12DecoderSubClassData *cdata = &klass->class_data;
|
||||
|
||||
gst_d3d12_handle_set_context_for_adapter_luid (element,
|
||||
context, cdata->adapter_luid, &self->device);
|
||||
|
||||
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_h264_dec_open (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
GstD3D12H264DecClass *klass = GST_D3D12_H264_DEC_GET_CLASS (self);
|
||||
GstD3D12DecoderSubClassData *cdata = &klass->class_data;
|
||||
|
||||
return gst_d3d12_decoder_proxy_open (decoder, cdata, &self->device,
|
||||
&self->decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_h264_dec_close (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
gst_clear_object (&self->decoder);
|
||||
gst_clear_object (&self->device);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_h264_dec_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
if (!gst_d3d12_decoder_negotiate (self->decoder, decoder))
|
||||
return FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_h264_dec_decide_allocation (GstVideoDecoder * decoder,
|
||||
GstQuery * query)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
if (!gst_d3d12_decoder_decide_allocation (self->decoder, decoder, query)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation
|
||||
(decoder, query);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_h264_dec_sink_query (GstVideoDecoder * decoder, GstQuery * query)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CONTEXT:
|
||||
if (gst_d3d12_handle_context_query (GST_ELEMENT (decoder),
|
||||
query, self->device)) {
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->sink_query (decoder, query);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_d3d12_h264_dec_src_query (GstVideoDecoder * decoder, GstQuery * query)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CONTEXT:
|
||||
if (gst_d3d12_handle_context_query (GST_ELEMENT (decoder),
|
||||
query, self->device)) {
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d12_h264_dec_configure (GstDxvaH264Decoder * decoder,
|
||||
GstVideoCodecState * input_state, const GstVideoInfo * info,
|
||||
gint crop_x, gint crop_y, gint coded_width, gint coded_height,
|
||||
gint max_dpb_size)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_configure (self->decoder, input_state, info,
|
||||
crop_x, crop_y, coded_width, coded_height, max_dpb_size);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d12_h264_dec_new_picture (GstDxvaH264Decoder * decoder,
|
||||
GstCodecPicture * picture)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_new_picture (self->decoder,
|
||||
GST_VIDEO_DECODER (decoder), picture);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d12_h264_dec_duplicate_picture (GstDxvaH264Decoder * decoder,
|
||||
GstCodecPicture * src, GstCodecPicture * dst)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_duplicate_picture (self->decoder, src, dst);
|
||||
}
|
||||
|
||||
static guint8
|
||||
gst_d3d12_h264_dec_get_picture_id (GstDxvaH264Decoder * decoder,
|
||||
GstCodecPicture * picture)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_get_picture_id (self->decoder, picture);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d12_h264_dec_start_picture (GstDxvaH264Decoder * decoder,
|
||||
GstCodecPicture * picture, guint8 * picture_id)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_start_picture (self->decoder, picture, picture_id);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d12_h264_dec_end_picture (GstDxvaH264Decoder * decoder,
|
||||
GstCodecPicture * picture, GPtrArray * ref_pics,
|
||||
const GstDxvaDecodingArgs * args)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_end_picture (self->decoder, picture, ref_pics, args);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_d3d12_h264_dec_output_picture (GstDxvaH264Decoder * decoder,
|
||||
GstVideoCodecFrame * frame, GstCodecPicture * picture,
|
||||
GstVideoBufferFlags buffer_flags, gint display_width, gint display_height)
|
||||
{
|
||||
GstD3D12H264Dec *self = GST_D3D12_H264_DEC (decoder);
|
||||
|
||||
return gst_d3d12_decoder_output_picture (self->decoder,
|
||||
GST_VIDEO_DECODER (decoder), frame, picture,
|
||||
buffer_flags, display_width, display_height);
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d12_h264_dec_register (GstPlugin * plugin, GstD3D12Device * device,
|
||||
ID3D12VideoDevice * video_device, guint rank)
|
||||
{
|
||||
GType type;
|
||||
gchar *type_name;
|
||||
gchar *feature_name;
|
||||
guint index = 0;
|
||||
GTypeInfo type_info = {
|
||||
sizeof (GstD3D12H264DecClass),
|
||||
nullptr,
|
||||
nullptr,
|
||||
(GClassInitFunc) gst_d3d12_h264_dec_class_init,
|
||||
nullptr,
|
||||
nullptr,
|
||||
sizeof (GstD3D12H264Dec),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_d3d12_h264_dec_init,
|
||||
};
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_h264_dec_debug, "d3d12h264dec", 0,
|
||||
"d3d12h264dec");
|
||||
|
||||
type_info.class_data =
|
||||
gst_d3d12_decoder_check_feature_support (device, video_device,
|
||||
GST_DXVA_CODEC_H264);
|
||||
if (!type_info.class_data)
|
||||
return;
|
||||
|
||||
type_name = g_strdup ("GstD3D12H264Dec");
|
||||
feature_name = g_strdup ("d3d12h264dec");
|
||||
|
||||
while (g_type_from_name (type_name)) {
|
||||
index++;
|
||||
g_free (type_name);
|
||||
g_free (feature_name);
|
||||
type_name = g_strdup_printf ("GstD3D12H264Device%dDec", index);
|
||||
feature_name = g_strdup_printf ("d3d12h264device%ddec", index);
|
||||
}
|
||||
|
||||
type = g_type_register_static (GST_TYPE_DXVA_H264_DECODER,
|
||||
type_name, &type_info, (GTypeFlags) 0);
|
||||
|
||||
/* make lower rank than default device */
|
||||
if (rank > 0 && index != 0)
|
||||
rank--;
|
||||
|
||||
if (!gst_element_register (plugin, feature_name, rank, type))
|
||||
GST_WARNING ("Failed to register plugin '%s'", type_name);
|
||||
|
||||
g_free (type_name);
|
||||
g_free (feature_name);
|
||||
}
|
32
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.h
Normal file
32
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12h264dec.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gstd3d12decoder.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gst_d3d12_h264_dec_register (GstPlugin * plugin,
|
||||
GstD3D12Device * device,
|
||||
ID3D12VideoDevice * video_device,
|
||||
guint rank);
|
||||
|
||||
G_END_DECLS
|
||||
|
1068
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12memory.cpp
Normal file
1068
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12memory.cpp
Normal file
File diff suppressed because it is too large
Load diff
190
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12memory.h
Normal file
190
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12memory.h
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include "gstd3d12_fwd.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_D3D12_ALLOCATION_PARAMS (gst_d3d12_allocation_params_get_type())
|
||||
|
||||
#define GST_TYPE_D3D12_MEMORY (gst_d3d12_memory_get_type())
|
||||
#define GST_D3D12_MEMORY_CAST(obj) ((GstD3D12Memory *)obj)
|
||||
|
||||
#define GST_TYPE_D3D12_ALLOCATOR (gst_d3d12_allocator_get_type())
|
||||
#define GST_D3D12_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_D3D12_ALLOCATOR, GstD3D12Allocator))
|
||||
#define GST_D3D12_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_D3D12_ALLOCATOR, GstD3D12AllocatorClass))
|
||||
#define GST_IS_D3D12_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_D3D12_ALLOCATOR))
|
||||
#define GST_IS_D3D12_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_D3D12_ALLOCATOR))
|
||||
#define GST_D3D12_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_D3D12_ALLOCATOR, GstD3D12AllocatorClass))
|
||||
#define GST_D3D12_ALLOCATOR_CAST(obj) ((GstD3D12Allocator *)obj)
|
||||
|
||||
#define GST_TYPE_D3D12_POOL_ALLOCATOR (gst_d3d12_pool_allocator_get_type())
|
||||
#define GST_D3D12_POOL_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_D3D12_POOL_ALLOCATOR, GstD3D12PoolAllocator))
|
||||
#define GST_D3D12_POOL_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_D3D12_POOL_ALLOCATOR, GstD3D12PoolAllocatorClass))
|
||||
#define GST_IS_D3D12_POOL_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_D3D12_POOL_ALLOCATOR))
|
||||
#define GST_IS_D3D12_POOL_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_D3D12_POOL_ALLOCATOR))
|
||||
#define GST_D3D12_POOL_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_D3D12_POOL_ALLOCATOR, GstD3D12PoolAllocatorClass))
|
||||
#define GST_D3D12_POOL_ALLOCATOR_CAST(obj) ((GstD3D12PoolAllocator *)obj)
|
||||
|
||||
/**
|
||||
* GST_D3D12_MEMORY_NAME:
|
||||
*
|
||||
* The name of the Direct3D12 memory
|
||||
*/
|
||||
#define GST_D3D12_MEMORY_NAME "D3D12Memory"
|
||||
|
||||
/**
|
||||
* GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY:
|
||||
*
|
||||
* Name of the caps feature for indicating the use of #GstD3D12Memory
|
||||
*/
|
||||
#define GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY "memory:D3D12Memory"
|
||||
|
||||
/**
|
||||
* GST_MAP_D3D12:
|
||||
*
|
||||
* Flag indicating that we should map the D3D12 resource instead of to system memory.
|
||||
*/
|
||||
#define GST_MAP_D3D12 (GST_MAP_FLAG_LAST << 1)
|
||||
|
||||
struct _GstD3D12Memory
|
||||
{
|
||||
GstMemory mem;
|
||||
|
||||
/*< public >*/
|
||||
GstD3D12Device *device;
|
||||
|
||||
/*< private >*/
|
||||
GstD3D12MemoryPrivate *priv;
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GType gst_d3d12_memory_get_type (void);
|
||||
|
||||
void gst_d3d12_memory_init_once (void);
|
||||
|
||||
gboolean gst_is_d3d12_memory (GstMemory * mem);
|
||||
|
||||
ID3D12Resource * gst_d3d12_memory_get_resource_handle (GstD3D12Memory * mem);
|
||||
|
||||
gboolean gst_d3d12_memory_get_state (GstD3D12Memory * mem,
|
||||
D3D12_RESOURCE_STATES * state);
|
||||
|
||||
gboolean gst_d3d12_memory_set_state (GstD3D12Memory * mem,
|
||||
D3D12_RESOURCE_STATES state);
|
||||
|
||||
gboolean gst_d3d12_memory_get_subresource_index (GstD3D12Memory * mem,
|
||||
guint plane,
|
||||
guint * index);
|
||||
|
||||
gboolean gst_d3d12_memory_get_plane_count (GstD3D12Memory * mem,
|
||||
guint * count);
|
||||
|
||||
gboolean gst_d3d12_memory_get_plane_size (GstD3D12Memory * mem,
|
||||
guint plane,
|
||||
gint * width,
|
||||
gint * height,
|
||||
gint * stride,
|
||||
gsize * offset);
|
||||
|
||||
guint gst_d3d12_memory_get_shader_resource_view_size (GstD3D12Memory * mem);
|
||||
|
||||
gboolean gst_d3d12_memory_get_shader_resource_view (GstD3D12Memory * mem,
|
||||
guint index,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE * srv);
|
||||
|
||||
guint gst_d3d12_memory_get_render_target_view_size (GstD3D12Memory * mem);
|
||||
|
||||
gboolean gst_d3d12_memory_get_render_target_view (GstD3D12Memory * mem,
|
||||
guint index,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE * rtv);
|
||||
|
||||
struct _GstD3D12Allocator
|
||||
{
|
||||
GstAllocator allocator;
|
||||
|
||||
/*< private >*/
|
||||
GstD3D12AllocatorPrivate *priv;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstD3D12AllocatorClass
|
||||
{
|
||||
GstAllocatorClass allocator_class;
|
||||
|
||||
gboolean (*set_actvie) (GstD3D12Allocator * allocator,
|
||||
gboolean active);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||
};
|
||||
|
||||
GType gst_d3d12_allocator_get_type (void);
|
||||
|
||||
GstMemory * gst_d3d12_allocator_alloc (GstD3D12Allocator * allocator,
|
||||
GstD3D12Device * device,
|
||||
const D3D12_HEAP_PROPERTIES * heap_props,
|
||||
D3D12_HEAP_FLAGS heap_flags,
|
||||
const D3D12_RESOURCE_DESC * desc,
|
||||
D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE * optimized_clear_value);
|
||||
|
||||
gboolean gst_d3d12_allocator_set_active (GstD3D12Allocator * allocator,
|
||||
gboolean active);
|
||||
|
||||
struct _GstD3D12PoolAllocator
|
||||
{
|
||||
GstD3D12Allocator allocator;
|
||||
|
||||
/*< public >*/
|
||||
GstD3D12Device *device;
|
||||
|
||||
/*< private >*/
|
||||
GstD3D12PoolAllocatorPrivate *priv;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstD3D12PoolAllocatorClass
|
||||
{
|
||||
GstD3D12AllocatorClass allocator_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GType gst_d3d12_pool_allocator_get_type (void);
|
||||
|
||||
GstD3D12PoolAllocator * gst_d3d12_pool_allocator_new (GstD3D12Device * device,
|
||||
const D3D12_HEAP_PROPERTIES * heap_props,
|
||||
D3D12_HEAP_FLAGS heap_flags,
|
||||
const D3D12_RESOURCE_DESC * desc,
|
||||
D3D12_RESOURCE_STATES initial_state,
|
||||
const D3D12_CLEAR_VALUE * optimized_clear_value);
|
||||
|
||||
GstFlowReturn gst_d3d12_pool_allocator_acquire_memory (GstD3D12PoolAllocator * allocator,
|
||||
GstMemory ** memory);
|
||||
|
||||
G_END_DECLS
|
||||
|
442
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12utils.cpp
Normal file
442
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12utils.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
/* 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 "gstd3d12utils.h"
|
||||
#include "gstd3d12device.h"
|
||||
#include <mutex>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static std::recursive_mutex context_lock_;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_d3d12_utils_debug);
|
||||
#define GST_CAT_DEFAULT gst_d3d12_utils_debug
|
||||
|
||||
static void
|
||||
init_context_debug (void)
|
||||
{
|
||||
GST_D3D12_CALL_ONCE_BEGIN {
|
||||
GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
|
||||
} GST_D3D12_CALL_ONCE_END;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_handle_set_context (GstElement * element, GstContext * context,
|
||||
gint adapter_index, GstD3D12Device ** device)
|
||||
{
|
||||
const gchar *context_type;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
||||
g_return_val_if_fail (device != nullptr, FALSE);
|
||||
|
||||
init_context_debug ();
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
context_type = gst_context_get_context_type (context);
|
||||
if (g_strcmp0 (context_type, GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE) == 0) {
|
||||
const GstStructure *str;
|
||||
GstD3D12Device *other_device = nullptr;
|
||||
guint other_adapter = 0;
|
||||
|
||||
/* If we had device already, will not replace it */
|
||||
if (*device)
|
||||
return TRUE;
|
||||
|
||||
str = gst_context_get_structure (context);
|
||||
|
||||
if (gst_structure_get (str, "device", GST_TYPE_D3D12_DEVICE,
|
||||
&other_device, "adapter-index", G_TYPE_UINT, &other_adapter,
|
||||
nullptr)) {
|
||||
if (adapter_index == -1 || (guint) adapter_index == other_adapter) {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT,
|
||||
element, "Found D3D12 device context");
|
||||
*device = other_device;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gst_object_unref (other_device);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_handle_set_context_for_adapter_luid (GstElement * element,
|
||||
GstContext * context, gint64 adapter_luid, GstD3D12Device ** device)
|
||||
{
|
||||
const gchar *context_type;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
||||
g_return_val_if_fail (device != nullptr, FALSE);
|
||||
|
||||
init_context_debug ();
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
context_type = gst_context_get_context_type (context);
|
||||
if (g_strcmp0 (context_type, GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE) == 0) {
|
||||
const GstStructure *str;
|
||||
GstD3D12Device *other_device = nullptr;
|
||||
gint64 other_adapter = 0;
|
||||
|
||||
/* If we had device already, will not replace it */
|
||||
if (*device)
|
||||
return TRUE;
|
||||
|
||||
str = gst_context_get_structure (context);
|
||||
|
||||
if (gst_structure_get (str, "device", GST_TYPE_D3D12_DEVICE,
|
||||
&other_device, "adapter-luid", G_TYPE_INT64, &other_adapter,
|
||||
nullptr)) {
|
||||
if (adapter_luid == other_adapter) {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT,
|
||||
element, "Found D3D12 device context");
|
||||
*device = other_device;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gst_object_unref (other_device);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
context_set_d3d12_device (GstContext * context, GstD3D12Device * device)
|
||||
{
|
||||
GstStructure *s;
|
||||
guint adapter_index = 0;
|
||||
guint device_id = 0;
|
||||
guint vendor_id = 0;
|
||||
gchar *desc = nullptr;
|
||||
gint64 adapter_luid = 0;
|
||||
|
||||
g_return_if_fail (context != nullptr);
|
||||
|
||||
g_object_get (G_OBJECT (device), "adapter-index", &adapter_index,
|
||||
"device-id", &device_id, "vendor-id", &vendor_id, "description", &desc,
|
||||
"adapter-luid", &adapter_luid, nullptr);
|
||||
|
||||
GST_CAT_LOG (GST_CAT_CONTEXT,
|
||||
"setting GstD3D12Device(%" GST_PTR_FORMAT
|
||||
") with adapter index %d on context(%" GST_PTR_FORMAT ")",
|
||||
device, adapter_index, context);
|
||||
|
||||
s = gst_context_writable_structure (context);
|
||||
gst_structure_set (s, "device", GST_TYPE_D3D12_DEVICE, device,
|
||||
"adapter-index", G_TYPE_UINT, adapter_index,
|
||||
"adapter-luid", G_TYPE_INT64, adapter_luid,
|
||||
"device-id", G_TYPE_UINT, device_id,
|
||||
"vendor-id", G_TYPE_UINT, vendor_id,
|
||||
"description", G_TYPE_STRING, GST_STR_NULL (desc), nullptr);
|
||||
g_free (desc);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_handle_context_query (GstElement * element, GstQuery * query,
|
||||
GstD3D12Device * device)
|
||||
{
|
||||
const gchar *context_type;
|
||||
GstContext *context, *old_context;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
||||
g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
|
||||
|
||||
init_context_debug ();
|
||||
|
||||
GST_LOG_OBJECT (element, "handle context query %" GST_PTR_FORMAT, query);
|
||||
|
||||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
gst_query_parse_context_type (query, &context_type);
|
||||
if (g_strcmp0 (context_type, GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE) != 0)
|
||||
return FALSE;
|
||||
|
||||
gst_query_parse_context (query, &old_context);
|
||||
if (old_context)
|
||||
context = gst_context_copy (old_context);
|
||||
else
|
||||
context = gst_context_new (GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
|
||||
|
||||
context_set_d3d12_device (context, device);
|
||||
gst_query_set_context (query, context);
|
||||
gst_context_unref (context);
|
||||
|
||||
GST_DEBUG_OBJECT (element, "successfully set %" GST_PTR_FORMAT
|
||||
" on %" GST_PTR_FORMAT, device, query);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pad_query (const GValue * item, GValue * value, gpointer user_data)
|
||||
{
|
||||
GstPad *pad = (GstPad *) g_value_get_object (item);
|
||||
GstQuery *query = (GstQuery *) user_data;
|
||||
gboolean res;
|
||||
|
||||
res = gst_pad_peer_query (pad, query);
|
||||
|
||||
if (res) {
|
||||
g_value_set_boolean (value, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, pad, "pad peer query failed");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_query (GstElement * element, GstQuery * query, GstPadDirection direction)
|
||||
{
|
||||
GstIterator *it;
|
||||
GstIteratorFoldFunction func = pad_query;
|
||||
GValue res = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&res, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean (&res, FALSE);
|
||||
|
||||
/* Ask neighbor */
|
||||
if (direction == GST_PAD_SRC)
|
||||
it = gst_element_iterate_src_pads (element);
|
||||
else
|
||||
it = gst_element_iterate_sink_pads (element);
|
||||
|
||||
while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
|
||||
gst_iterator_resync (it);
|
||||
|
||||
gst_iterator_free (it);
|
||||
|
||||
return g_value_get_boolean (&res);
|
||||
}
|
||||
|
||||
static void
|
||||
run_d3d12_context_query (GstElement * element, GstD3D12Device ** device)
|
||||
{
|
||||
GstQuery *query;
|
||||
GstContext *ctxt = nullptr;
|
||||
|
||||
query = gst_query_new_context (GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE);
|
||||
if (run_query (element, query, GST_PAD_SRC)) {
|
||||
gst_query_parse_context (query, &ctxt);
|
||||
if (ctxt) {
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||
"found context (%" GST_PTR_FORMAT ") in downstream query", ctxt);
|
||||
gst_element_set_context (element, ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
if (*device == nullptr && run_query (element, query, GST_PAD_SINK)) {
|
||||
gst_query_parse_context (query, &ctxt);
|
||||
if (ctxt) {
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||
"found context (%" GST_PTR_FORMAT ") in upstream query", ctxt);
|
||||
gst_element_set_context (element, ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
if (*device == nullptr) {
|
||||
GstMessage *msg;
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||
"posting need context message");
|
||||
msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
|
||||
GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE);
|
||||
gst_element_post_message (element, msg);
|
||||
}
|
||||
|
||||
gst_query_unref (query);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_ensure_element_data (GstElement * element, gint adapter_index,
|
||||
GstD3D12Device ** device)
|
||||
{
|
||||
guint target_adapter = 0;
|
||||
std::lock_guard < std::recursive_mutex > lk (context_lock_);
|
||||
|
||||
g_return_val_if_fail (element != nullptr, FALSE);
|
||||
g_return_val_if_fail (device != nullptr, FALSE);
|
||||
|
||||
init_context_debug ();
|
||||
|
||||
if (*device) {
|
||||
GST_LOG_OBJECT (element, "already have a device %" GST_PTR_FORMAT, *device);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
run_d3d12_context_query (element, device);
|
||||
if (*device)
|
||||
return TRUE;
|
||||
|
||||
if (adapter_index > 0)
|
||||
target_adapter = adapter_index;
|
||||
|
||||
*device = gst_d3d12_device_new (target_adapter);
|
||||
|
||||
if (*device == nullptr) {
|
||||
GST_ERROR_OBJECT (element,
|
||||
"Couldn't create new device with adapter index %d", target_adapter);
|
||||
return FALSE;
|
||||
} else {
|
||||
GstContext *context;
|
||||
GstMessage *msg;
|
||||
|
||||
/* Propagate new D3D12 device context */
|
||||
|
||||
context = gst_context_new (GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
|
||||
context_set_d3d12_device (context, *device);
|
||||
|
||||
gst_element_set_context (element, context);
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||
"posting have context (%p) message with D3D12 device context (%p)",
|
||||
context, *device);
|
||||
msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
|
||||
gst_element_post_message (GST_ELEMENT_CAST (element), msg);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_ensure_element_data_for_adapter_luid (GstElement * element,
|
||||
gint64 adapter_luid, GstD3D12Device ** device)
|
||||
{
|
||||
std::lock_guard < std::recursive_mutex > lk (context_lock_);
|
||||
|
||||
g_return_val_if_fail (element != nullptr, FALSE);
|
||||
g_return_val_if_fail (device != nullptr, FALSE);
|
||||
|
||||
init_context_debug ();
|
||||
|
||||
if (*device) {
|
||||
GST_LOG_OBJECT (element, "already have a device %" GST_PTR_FORMAT, *device);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
run_d3d12_context_query (element, device);
|
||||
if (*device)
|
||||
return TRUE;
|
||||
|
||||
*device = gst_d3d12_device_new_for_adapter_luid (adapter_luid);
|
||||
|
||||
if (*device == nullptr) {
|
||||
GST_ERROR_OBJECT (element,
|
||||
"Couldn't create new device with adapter luid %" G_GINT64_FORMAT,
|
||||
adapter_luid);
|
||||
return FALSE;
|
||||
} else {
|
||||
GstContext *context;
|
||||
GstMessage *msg;
|
||||
|
||||
/* Propagate new D3D12 device context */
|
||||
context = gst_context_new (GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
|
||||
context_set_d3d12_device (context, *device);
|
||||
|
||||
gst_element_set_context (element, context);
|
||||
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
|
||||
"posting have context (%p) message with D3D12 device context (%p)",
|
||||
context, *device);
|
||||
msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
|
||||
gst_element_post_message (GST_ELEMENT_CAST (element), msg);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gint64
|
||||
gst_d3d12_luid_to_int64 (const LUID * luid)
|
||||
{
|
||||
LARGE_INTEGER val;
|
||||
|
||||
g_return_val_if_fail (luid != nullptr, 0);
|
||||
|
||||
val.LowPart = luid->LowPart;
|
||||
val.HighPart = luid->HighPart;
|
||||
|
||||
return val.QuadPart;
|
||||
}
|
||||
|
||||
GstContext *
|
||||
gst_d3d12_context_new (GstD3D12Device * device)
|
||||
{
|
||||
GstContext *context;
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr);
|
||||
|
||||
context = gst_context_new (GST_D3D12_DEVICE_HANDLE_CONTEXT_TYPE, TRUE);
|
||||
context_set_d3d12_device (context, device);
|
||||
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gst_d3d12_result (HRESULT hr, GstD3D12Device * device, GstDebugCategory * cat,
|
||||
const gchar * file, const gchar * function, gint line, GstDebugLevel level)
|
||||
{
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
gboolean ret = TRUE;
|
||||
|
||||
if (device)
|
||||
gst_d3d12_device_d3d12_debug (device, file, function, line);
|
||||
|
||||
if (FAILED (hr)) {
|
||||
gchar *error_text = nullptr;
|
||||
|
||||
error_text = g_win32_error_message ((guint) hr);
|
||||
/* g_win32_error_message() doesn't cover all HERESULT return code,
|
||||
* so it could be empty string, or nullptr if there was an error
|
||||
* in g_utf16_to_utf8() */
|
||||
gst_debug_log (cat, level, file, function, line,
|
||||
nullptr, "D3D12 call failed: 0x%x, %s", (guint) hr,
|
||||
GST_STR_NULL (error_text));
|
||||
g_free (error_text);
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return SUCCEEDED (hr);
|
||||
#endif
|
||||
}
|
||||
|
||||
guint
|
||||
gst_d3d12_calculate_subresource (guint mip_slice, guint array_slice,
|
||||
guint plane_slice, guint mip_level, guint array_size)
|
||||
{
|
||||
return mip_slice + array_slice * mip_level +
|
||||
plane_slice * mip_level * array_size;
|
||||
}
|
217
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12utils.h
Normal file
217
subprojects/gst-plugins-bad/sys/d3d12/gstd3d12utils.h
Normal file
|
@ -0,0 +1,217 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstd3d12_fwd.h"
|
||||
#include "gstd3d12device.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean gst_d3d12_handle_set_context (GstElement * element,
|
||||
GstContext * context,
|
||||
gint adapter_index,
|
||||
GstD3D12Device ** device);
|
||||
|
||||
gboolean gst_d3d12_handle_set_context_for_adapter_luid (GstElement * element,
|
||||
GstContext * context,
|
||||
gint64 adapter_luid,
|
||||
GstD3D12Device ** device);
|
||||
|
||||
gboolean gst_d3d12_handle_context_query (GstElement * element,
|
||||
GstQuery * query,
|
||||
GstD3D12Device * device);
|
||||
|
||||
gboolean gst_d3d12_ensure_element_data (GstElement * element,
|
||||
gint adapter_index,
|
||||
GstD3D12Device ** device);
|
||||
|
||||
gboolean gst_d3d12_ensure_element_data_for_adapter_luid (GstElement * element,
|
||||
gint64 adapter_luid,
|
||||
GstD3D12Device ** device);
|
||||
|
||||
gint64 gst_d3d12_luid_to_int64 (const LUID * luid);
|
||||
|
||||
GstContext * gst_d3d12_context_new (GstD3D12Device * device);
|
||||
|
||||
gboolean _gst_d3d12_result (HRESULT hr,
|
||||
GstD3D12Device * device,
|
||||
GstDebugCategory * cat,
|
||||
const gchar * file,
|
||||
const gchar * function,
|
||||
gint line,
|
||||
GstDebugLevel level);
|
||||
|
||||
/**
|
||||
* gst_d3d12_result:
|
||||
* @result: HRESULT D3D12 API return code
|
||||
* @device: (nullable): Associated #GstD3D12Device
|
||||
*
|
||||
* Returns: %TRUE if D3D12 API call result is SUCCESS
|
||||
*/
|
||||
#define gst_d3d12_result(result,device) \
|
||||
_gst_d3d12_result (result, device, GST_CAT_DEFAULT, __FILE__, GST_FUNCTION, __LINE__, GST_LEVEL_ERROR)
|
||||
|
||||
guint gst_d3d12_calculate_subresource (guint mip_slice,
|
||||
guint array_slice,
|
||||
guint plane_slice,
|
||||
guint mip_level,
|
||||
guint array_size);
|
||||
|
||||
#define GST_D3D12_CLEAR_COM(obj) G_STMT_START { \
|
||||
if (obj) { \
|
||||
(obj)->Release (); \
|
||||
(obj) = NULL; \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
struct CD3D12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES
|
||||
{
|
||||
CD3D12_HEAP_PROPERTIES (
|
||||
D3D12_HEAP_TYPE type,
|
||||
D3D12_CPU_PAGE_PROPERTY cpu_page_property = D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||
D3D12_MEMORY_POOL memory_pool_preference = D3D12_MEMORY_POOL_UNKNOWN,
|
||||
UINT creation_node_mask = 1,
|
||||
UINT visible_node_mask = 1)
|
||||
{
|
||||
Type = type;
|
||||
CPUPageProperty = cpu_page_property;
|
||||
MemoryPoolPreference = memory_pool_preference;
|
||||
CreationNodeMask = creation_node_mask;
|
||||
VisibleNodeMask = visible_node_mask;
|
||||
}
|
||||
};
|
||||
|
||||
struct CD3D12_RESOURCE_DESC : public D3D12_RESOURCE_DESC
|
||||
{
|
||||
CD3D12_RESOURCE_DESC(
|
||||
D3D12_RESOURCE_DIMENSION dimension,
|
||||
UINT64 alignment,
|
||||
UINT64 width,
|
||||
UINT height,
|
||||
UINT16 depth_or_array_size,
|
||||
UINT16 mip_levels,
|
||||
DXGI_FORMAT format,
|
||||
UINT sample_count,
|
||||
UINT sample_quality,
|
||||
D3D12_TEXTURE_LAYOUT layout,
|
||||
D3D12_RESOURCE_FLAGS flags)
|
||||
{
|
||||
Dimension = dimension;
|
||||
Alignment = alignment;
|
||||
Width = width;
|
||||
Height = height;
|
||||
DepthOrArraySize = depth_or_array_size;
|
||||
MipLevels = mip_levels;
|
||||
Format = format;
|
||||
SampleDesc.Count = sample_count;
|
||||
SampleDesc.Quality = sample_quality;
|
||||
Layout = layout;
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
static inline CD3D12_RESOURCE_DESC Buffer (
|
||||
UINT64 width,
|
||||
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
|
||||
UINT64 alignment = 0)
|
||||
{
|
||||
return CD3D12_RESOURCE_DESC (D3D12_RESOURCE_DIMENSION_BUFFER, alignment,
|
||||
width, 1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0,
|
||||
D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags);
|
||||
}
|
||||
|
||||
static inline CD3D12_RESOURCE_DESC Tex2D (
|
||||
DXGI_FORMAT format,
|
||||
UINT64 width,
|
||||
UINT height,
|
||||
UINT16 array_size = 1,
|
||||
UINT16 mip_levels = 0,
|
||||
UINT sample_count = 1,
|
||||
UINT sample_quality = 0,
|
||||
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
|
||||
D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||
UINT64 alignment = 0)
|
||||
{
|
||||
return CD3D12_RESOURCE_DESC(D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment,
|
||||
width, height, array_size, mip_levels, format, sample_count,
|
||||
sample_quality, layout, flags);
|
||||
}
|
||||
};
|
||||
|
||||
struct CD3D12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER
|
||||
{
|
||||
static inline CD3D12_RESOURCE_BARRIER Transition (
|
||||
ID3D12Resource * resource,
|
||||
D3D12_RESOURCE_STATES before,
|
||||
D3D12_RESOURCE_STATES after,
|
||||
UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||
D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE)
|
||||
{
|
||||
CD3D12_RESOURCE_BARRIER result;
|
||||
D3D12_RESOURCE_BARRIER &barrier = result;
|
||||
result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
result.Flags = flags;
|
||||
barrier.Transition.pResource = resource;
|
||||
barrier.Transition.StateBefore = before;
|
||||
barrier.Transition.StateAfter = after;
|
||||
barrier.Transition.Subresource = subresource;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct CD3D12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION
|
||||
{
|
||||
CD3D12_TEXTURE_COPY_LOCATION (ID3D12Resource * resource)
|
||||
{
|
||||
pResource = resource;
|
||||
Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
PlacedFootprint = {};
|
||||
}
|
||||
|
||||
CD3D12_TEXTURE_COPY_LOCATION (
|
||||
ID3D12Resource * resource,
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT const & foot_print)
|
||||
{
|
||||
pResource = resource;
|
||||
Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
PlacedFootprint = foot_print;
|
||||
}
|
||||
|
||||
CD3D12_TEXTURE_COPY_LOCATION (
|
||||
ID3D12Resource * resource,
|
||||
UINT subresource)
|
||||
{
|
||||
pResource = resource;
|
||||
Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
PlacedFootprint = {};
|
||||
SubresourceIndex = subresource;
|
||||
}
|
||||
};
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#define GST_D3D12_CALL_ONCE_BEGIN \
|
||||
static std::once_flag __once_flag; \
|
||||
std::call_once (__once_flag, [&]()
|
||||
|
||||
#define GST_D3D12_CALL_ONCE_END )
|
75
subprojects/gst-plugins-bad/sys/d3d12/meson.build
Normal file
75
subprojects/gst-plugins-bad/sys/d3d12/meson.build
Normal file
|
@ -0,0 +1,75 @@
|
|||
d3d12_sources = [
|
||||
'gstd3d12decoder.cpp',
|
||||
'gstd3d12device.cpp',
|
||||
'gstd3d12fence.cpp',
|
||||
'gstd3d12format.cpp',
|
||||
'gstd3d12h264dec.cpp',
|
||||
'gstd3d12memory.cpp',
|
||||
'gstd3d12utils.cpp',
|
||||
'plugin.cpp',
|
||||
]
|
||||
|
||||
extra_args = ['-DGST_USE_UNSTABLE_API']
|
||||
extra_dep = []
|
||||
|
||||
d3d12_option = get_option('d3d12')
|
||||
if host_system != 'windows' or d3d12_option.disabled()
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
d3d12_lib = cc.find_library('d3d12', required : d3d12_option)
|
||||
dxgi_lib = cc.find_library('dxgi', required : d3d12_option)
|
||||
|
||||
if not gstdxva_dep.found() or not d3d12_lib.found() or not dxgi_lib.found()
|
||||
if d3d12_option.enabled()
|
||||
error('The d3d12 was enabled explicitly, but required GstD3D11 dependencies were not found.')
|
||||
endif
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
d3d12_headers = [
|
||||
'd3d12.h',
|
||||
'd3d12video.h',
|
||||
'dxgi1_6.h',
|
||||
'wrl.h',
|
||||
]
|
||||
|
||||
have_d3d12_headers = true
|
||||
foreach h: d3d12_headers
|
||||
if not cc.has_header(h)
|
||||
have_d3d12_headers = false
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if not have_d3d12_headers
|
||||
if d3d12_option.enabled()
|
||||
error('The d3d12 plugin was enabled explicitly, but required dependencies were not found.')
|
||||
endif
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
if cc.has_header('d3d12sdklayers.h')
|
||||
extra_dep += ['-DHAVE_D3D12_SDKLAYERS_H']
|
||||
endif
|
||||
|
||||
# MinGW 32bits compiler seems to be complaining about redundant-decls
|
||||
# when ComPtr is in use. Let's just disable the warning
|
||||
if cc.get_id() != 'msvc'
|
||||
extra_mingw_args = cc.get_supported_arguments([
|
||||
'-Wno-redundant-decls',
|
||||
])
|
||||
|
||||
extra_args += extra_mingw_args
|
||||
endif
|
||||
|
||||
gstd3d12 = library('gstd3d12',
|
||||
d3d12_sources,
|
||||
c_args : gst_plugins_bad_args + extra_args,
|
||||
cpp_args: gst_plugins_bad_args + extra_args,
|
||||
include_directories : [configinc],
|
||||
dependencies : [gstbase_dep, gstvideo_dep, gstcodecs_dep,
|
||||
gstdxva_dep, d3d12_lib, dxgi_lib],
|
||||
install : true,
|
||||
install_dir : plugins_install_dir,
|
||||
)
|
||||
plugins += [gstd3d12]
|
94
subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp
Normal file
94
subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* 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 "gstd3d12device.h"
|
||||
#include "gstd3d12h264dec.h"
|
||||
|
||||
#include <wrl.h>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
using namespace Microsoft::WRL;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_debug);
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_allocator_debug);
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_command_list_debug);
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_decoder_debug);
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_fence_debug);
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_format_debug);
|
||||
GST_DEBUG_CATEGORY (gst_d3d12_utils_debug);
|
||||
|
||||
#define GST_CAT_DEFAULT gst_d3d12_debug
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_debug, "d3d12", 0, "d3d12");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_allocator_debug, "d3d12allocator", 0,
|
||||
"d3d12allocator");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_command_list_debug, "d3d12commandlist", 0,
|
||||
"d3d12commandlist");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_decoder_debug, "d3d12decoder", 0,
|
||||
"d3d12decoder");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_fence_debug, "d3d12fence", 0,
|
||||
"d3d12fence");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_format_debug, "d3d12format", 0,
|
||||
"d3d12format");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_d3d12_utils_debug,
|
||||
"d3d12utils", 0, "d3d12utils");
|
||||
|
||||
/* Enumerate devices to register decoders per device and to get the highest
|
||||
* feature level */
|
||||
/* AMD seems to be supporting up to 12 cards, and 8 for NVIDIA */
|
||||
for (guint i = 0; i < 12; i++) {
|
||||
GstD3D12Device *device = nullptr;
|
||||
ID3D12Device *device_handle;
|
||||
ComPtr < ID3D12VideoDevice > video_device;
|
||||
HRESULT hr;
|
||||
|
||||
device = gst_d3d12_device_new (i);
|
||||
if (!device)
|
||||
break;
|
||||
|
||||
device_handle = gst_d3d12_device_get_device_handle (device);
|
||||
hr = device_handle->QueryInterface (IID_PPV_ARGS (&video_device));
|
||||
if (FAILED (hr)) {
|
||||
gst_object_unref (device);
|
||||
continue;
|
||||
}
|
||||
|
||||
gst_d3d12_h264_dec_register (plugin, device, video_device.Get (),
|
||||
GST_RANK_NONE);
|
||||
|
||||
gst_object_unref (device);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
d3d12,
|
||||
"Direct3D12 plugin",
|
||||
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
|
@ -4,6 +4,7 @@ subdir('applemedia')
|
|||
subdir('asio')
|
||||
subdir('bluez')
|
||||
subdir('d3d11')
|
||||
subdir('d3d12')
|
||||
subdir('d3dvideosink')
|
||||
subdir('decklink')
|
||||
subdir('directsound')
|
||||
|
|
Loading…
Reference in a new issue