d3d11: Remove d3d11videosink wrapper bin

Drop d3d11videosink wrapper bin and handle texture upload
in d3d11videosink.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2169>
This commit is contained in:
Seungha Yang 2021-04-17 20:37:13 +09:00
parent 8b1051cdea
commit 094bfbedfc
6 changed files with 89 additions and 733 deletions

View file

@ -19,18 +19,16 @@
*/
/**
* SECTION:element-d3d11videosinkelement
* @title: d3d11videosinkelement
* SECTION:element-d3d11videosink
* @title: d3d11videosink
*
* Direct3D11 based video render element. This element allows only Direct3D11
* textures as a input. Use #d3d11videosink instead which is a convenient
* wrapper of #d3d11videosinkelement with #d3d11upload.
* Direct3D11 based video render element
*
* ## Example launch line
* ```
* gst-launch-1.0 videotestsrc ! d3d11upload ! d3d11videosinkelement
* gst-launch-1.0 videotestsrc ! d3d11upload ! d3d11videosink
* ```
* This pipeline will display test video stream on screen via d3d11videosinkelement
* This pipeline will display test video stream on screen via d3d11videosink
*
* Since: 1.18
*
@ -90,6 +88,11 @@ static GstStaticCaps pad_template_caps =
(GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SINK_FORMATS) "; "
GST_VIDEO_CAPS_MAKE_WITH_FEATURES
(GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY ","
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
GST_D3D11_SINK_FORMATS) ";"
GST_VIDEO_CAPS_MAKE (GST_D3D11_SINK_FORMATS) "; "
GST_VIDEO_CAPS_MAKE_WITH_FEATURES
(GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ","
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
GST_D3D11_SINK_FORMATS));
@ -121,13 +124,10 @@ struct _GstD3D11VideoSink
gboolean pending_render_rect;
GstBufferPool *fallback_pool;
gboolean can_convert;
gboolean have_video_processor;
gboolean processor_in_use;
/* For drawing on user texture */
GstD3D11VideoSinkCallbacks callbacks;
gpointer user_data;
gboolean drawing;
GstBuffer *current_buffer;
GRecMutex draw_lock;
@ -230,8 +230,8 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass)
* GstD3D11VideoSink:draw-on-shared-texture:
*
* Instruct the sink to draw on a shared texture provided by user.
* User must watch #d3d11videosinkelement::begin-draw signal and should call
* #d3d11videosinkelement::draw method on the #d3d11videosinkelement::begin-draw
* User must watch #d3d11videosink::begin-draw signal and should call
* #d3d11videosink::draw method on the #d3d11videosink::begin-draw
* signal handler.
*
* Currently supported formats for user texture are:
@ -257,11 +257,11 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass)
/**
* GstD3D11VideoSink::begin-draw:
* @videosink: the #d3d11videosinkelement
* @videosink: the #d3d11videosink
*
* Emitted when sink has a texture to draw. Application needs to invoke
* #d3d11videosinkelement::draw action signal before returning from
* #d3d11videosinkelement::begin-draw signal handler.
* #d3d11videosink::draw action signal before returning from
* #d3d11videosink::begin-draw signal handler.
*
* Since: 1.20
*/
@ -272,7 +272,7 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass)
/**
* GstD3D11VideoSink::draw:
* @videosink: the #d3d11videosinkelement
* @videosink: the #d3d11videosink
* @shard_handle: a pointer to HANDLE
* @texture_misc_flags: a D3D11_RESOURCE_MISC_FLAG value
* @acquire_key: a key value used for IDXGIKeyedMutex::AcquireSync
@ -445,94 +445,43 @@ gst_d3d11_video_sink_set_context (GstElement * element, GstContext * context)
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
}
static GstCaps *
gst_d3d11_video_sink_get_supported_caps (GstD3D11VideoSink * self,
D3D11_FORMAT_SUPPORT flags)
{
GstD3D11Device *device;
ID3D11Device *d3d11_device;
HRESULT hr;
guint i;
GValue v_list = G_VALUE_INIT;
GstCaps *supported_caps;
static const GstVideoFormat format_list[] = {
GST_VIDEO_FORMAT_BGRA,
GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_FORMAT_RGB10A2_LE,
GST_VIDEO_FORMAT_VUYA,
GST_VIDEO_FORMAT_NV12,
GST_VIDEO_FORMAT_P010_10LE,
GST_VIDEO_FORMAT_P016_LE,
GST_VIDEO_FORMAT_I420,
GST_VIDEO_FORMAT_I420_10LE,
};
device = self->device;
d3d11_device = gst_d3d11_device_get_device_handle (device);
g_value_init (&v_list, GST_TYPE_LIST);
for (i = 0; i < G_N_ELEMENTS (format_list); i++) {
UINT format_support = 0;
GstVideoFormat format;
const GstD3D11Format *d3d11_format;
d3d11_format = gst_d3d11_device_format_from_gst (device, format_list[i]);
if (!d3d11_format || d3d11_format->dxgi_format == DXGI_FORMAT_UNKNOWN)
continue;
format = d3d11_format->format;
hr = d3d11_device->CheckFormatSupport (d3d11_format->dxgi_format,
&format_support);
if (SUCCEEDED (hr) && ((format_support & flags) == flags)) {
GValue v_str = G_VALUE_INIT;
g_value_init (&v_str, G_TYPE_STRING);
GST_LOG_OBJECT (self, "d3d11 device can support %s with flags 0x%x",
gst_video_format_to_string (format), flags);
g_value_set_string (&v_str, gst_video_format_to_string (format));
gst_value_list_append_and_take_value (&v_list, &v_str);
}
}
supported_caps = gst_caps_new_simple ("video/x-raw",
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
gst_caps_set_value (supported_caps, "format", &v_list);
g_value_unset (&v_list);
gst_caps_set_features_simple (supported_caps,
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY));
return supported_caps;
}
static GstCaps *
gst_d3d11_video_sink_get_caps (GstBaseSink * sink, GstCaps * filter)
{
GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
GstCaps *caps = NULL;
if (self->device && !self->can_convert) {
GstCaps *overlaycaps;
GstCapsFeatures *features;
caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
caps = gst_d3d11_video_sink_get_supported_caps (self,
(D3D11_FORMAT_SUPPORT) (D3D11_FORMAT_SUPPORT_TEXTURE2D |
D3D11_FORMAT_SUPPORT_DISPLAY));
overlaycaps = gst_caps_copy (caps);
features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL);
gst_caps_set_features_simple (overlaycaps, features);
gst_caps_append (caps, overlaycaps);
if (self->device) {
gboolean is_hardware = FALSE;
g_object_get (self->device, "hardware", &is_hardware, NULL);
/* In case of WARP device, conversion via shader would be inefficient than
* upstream videoconvert. Allow native formats in this case */
if (!is_hardware) {
GValue format_list = G_VALUE_INIT;
GValue format = G_VALUE_INIT;
g_value_init (&format_list, GST_TYPE_LIST);
g_value_init (&format, G_TYPE_STRING);
g_value_set_string (&format, "RGBA");
gst_value_list_append_and_take_value (&format_list, &format);
format = G_VALUE_INIT;
g_value_init (&format, G_TYPE_STRING);
g_value_set_string (&format, "BGRA");
gst_value_list_append_and_take_value (&format_list, &format);
caps = gst_caps_make_writable (caps);
gst_caps_set_value (caps, "format", &format_list);
g_value_unset (&format_list);
}
}
if (!caps)
caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
if (caps && filter) {
if (filter) {
GstCaps *isect;
isect = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (caps);
@ -735,7 +684,6 @@ static gboolean
gst_d3d11_video_sink_start (GstBaseSink * sink)
{
GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
gboolean is_hardware = TRUE;
GST_DEBUG_OBJECT (self, "Start");
@ -745,15 +693,6 @@ gst_d3d11_video_sink_start (GstBaseSink * sink)
return FALSE;
}
g_object_get (self->device, "hardware", &is_hardware, NULL);
if (!is_hardware) {
GST_WARNING_OBJECT (self, "D3D11 device is running on software emulation");
self->can_convert = FALSE;
} else {
self->can_convert = TRUE;
}
return TRUE;
}
@ -886,22 +825,54 @@ gst_d3d11_video_sink_propose_allocation (GstBaseSink * sink, GstQuery * query)
size = info.size;
if (need_pool) {
GstD3D11AllocationParams *d3d11_params;
GstCapsFeatures *features;
GstStructure *config;
gboolean is_d3d11 = false;
GST_DEBUG_OBJECT (self, "create new pool");
features = gst_caps_get_features (caps, 0);
if (features
&& gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
GST_DEBUG_OBJECT (self, "upstream support d3d11 memory");
pool = gst_d3d11_buffer_pool_new (self->device);
is_d3d11 = true;
} else {
pool = gst_video_buffer_pool_new ();
}
d3d11_params = gst_d3d11_allocation_params_new (self->device, &info,
(GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE);
pool = gst_d3d11_buffer_pool_new_with_options (self->device, caps,
d3d11_params, 2, 0);
gst_d3d11_allocation_params_free (d3d11_params);
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_add_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_META);
/* d3d11 pool does not support video alignment */
if (!is_d3d11) {
gst_buffer_pool_config_add_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
}
size = GST_VIDEO_INFO_SIZE (&info);
if (is_d3d11) {
GstD3D11AllocationParams *d3d11_params;
d3d11_params =
gst_d3d11_allocation_params_new (self->device,
&info, (GstD3D11AllocationFlags) 0, D3D11_BIND_SHADER_RESOURCE);
gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
gst_d3d11_allocation_params_free (d3d11_params);
}
gst_buffer_pool_config_set_params (config, caps, (guint) size, 2, 0);
if (!gst_buffer_pool_set_config (pool, config)) {
GST_ERROR_OBJECT (pool, "Couldn't set config");
gst_object_unref (pool);
if (!pool) {
GST_ERROR_OBJECT (self, "Failed to create buffer pool");
return FALSE;
}
size = GST_D3D11_BUFFER_POOL (pool)->buffer_size;
if (is_d3d11)
size = GST_D3D11_BUFFER_POOL (pool)->buffer_size;
}
/* We need at least 2 buffers because we hold on to the last one for redrawing
@ -1130,12 +1101,8 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
GST_LOG_OBJECT (self, "Begin drawing");
/* Application should call draw method on this callback */
if (self->callbacks.begin_draw) {
self->callbacks.begin_draw (self, self->user_data);
} else {
g_signal_emit (self, gst_d3d11_video_sink_signals[SIGNAL_BEGIN_DRAW], 0,
NULL);
}
g_signal_emit (self, gst_d3d11_video_sink_signals[SIGNAL_BEGIN_DRAW], 0,
NULL);
GST_LOG_OBJECT (self, "End drawing");
self->drawing = FALSE;
@ -1320,24 +1287,3 @@ gst_d3d11_video_sink_draw_action (GstD3D11VideoSink * self,
return ret == GST_FLOW_OK;
}
void
gst_d3d11_video_sink_set_callbacks (GstD3D11VideoSink * videosink,
GstD3D11VideoSinkCallbacks * callbacks, gpointer user_data)
{
g_return_if_fail (GST_IS_D3D11_VIDEO_SINK (videosink));
videosink->callbacks = *callbacks;
videosink->user_data = user_data;
}
gboolean
gst_d3d11_video_sink_draw (GstD3D11VideoSink * videosink,
gpointer shared_handle, guint texture_misc_flags, guint64 acquire_key,
guint64 release_key)
{
g_return_val_if_fail (GST_IS_D3D11_VIDEO_SINK (videosink), FALSE);
return gst_d3d11_video_sink_draw_action (videosink, shared_handle,
texture_misc_flags, acquire_key, release_key);
}

View file

@ -40,14 +40,6 @@ G_BEGIN_DECLS
typedef struct _GstD3D11VideoSink GstD3D11VideoSink;
typedef struct _GstD3D11VideoSinkClass GstD3D11VideoSinkClass;
typedef struct
{
void (*begin_draw) (GstD3D11VideoSink * videosink,
gpointer user_data);
} GstD3D11VideoSinkCallbacks;
struct _GstD3D11VideoSinkClass
{
GstVideoSinkClass parent_class;
@ -65,19 +57,6 @@ struct _GstD3D11VideoSinkClass
GType gst_d3d11_video_sink_get_type (void);
/* Internal methods, called by d3d11videosinkbin */
void
gst_d3d11_video_sink_set_callbacks (GstD3D11VideoSink * videosink,
GstD3D11VideoSinkCallbacks * callbacks,
gpointer user_data);
gboolean
gst_d3d11_video_sink_draw (GstD3D11VideoSink * videosink,
gpointer shared_handle,
guint texture_misc_flags,
guint64 acquire_key,
guint64 release_key);
G_END_DECLS
#endif /* __GST_D3D11_VIDEO_SINK_H__ */

View file

@ -1,507 +0,0 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 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.
*/
/**
* SECTION:element-d3d11videosink
* @title: d3d11videosink
*
* Direct3D11 based video render element
*
* ## Example launch line
* ```
* gst-launch-1.0 videotestsrc ! d3d11videosink
* ```
* This pipeline will display test video stream on screen via #d3d11videosink
*
* Since: 1.18
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/video/video.h>
#include <gst/video/gstvideosink.h>
#include <gst/video/videooverlay.h>
#include <gst/video/navigation.h>
#include <gst/d3d11/gstd3d11.h>
#include "gstd3d11videosink.h"
#include "gstd3d11videosinkbin.h"
#include "gstd3d11pluginutils.h"
enum
{
PROP_0,
/* basesink */
PROP_SYNC,
PROP_MAX_LATENESS,
PROP_QOS,
PROP_ASYNC,
PROP_TS_OFFSET,
PROP_ENABLE_LAST_SAMPLE,
PROP_LAST_SAMPLE,
PROP_BLOCKSIZE,
PROP_RENDER_DELAY,
PROP_THROTTLE_TIME,
PROP_MAX_BITRATE,
PROP_PROCESSING_DEADLINE,
PROP_STATS,
/* videosink */
PROP_SHOW_PREROLL_FRAME,
/* d3d11videosink */
PROP_ADAPTER,
PROP_FORCE_ASPECT_RATIO,
PROP_ENABLE_NAVIGATION_EVENTS,
PROP_FULLSCREEN_TOGGLE_MODE,
PROP_FULLSCREEN,
PROP_RENDER_STATS,
PROP_DRAW_ON_SHARED_TEXTURE,
};
/* basesink */
#define DEFAULT_SYNC TRUE
#define DEFAULT_MAX_LATENESS -1
#define DEFAULT_QOS FALSE
#define DEFAULT_ASYNC TRUE
#define DEFAULT_TS_OFFSET 0
#define DEFAULT_BLOCKSIZE 4096
#define DEFAULT_RENDER_DELAY 0
#define DEFAULT_ENABLE_LAST_SAMPLE TRUE
#define DEFAULT_THROTTLE_TIME 0
#define DEFAULT_MAX_BITRATE 0
#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE
#define DEFAULT_PROCESSING_DEADLINE (20 * GST_MSECOND)
/* videosink */
#define DEFAULT_SHOW_PREROLL_FRAME TRUE
/* d3d11videosink */
#define DEFAULT_ADAPTER -1
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
#define DEFAULT_ENABLE_NAVIGATION_EVENTS TRUE
#define DEFAULT_FULLSCREEN_TOGGLE_MODE GST_D3D11_WINDOW_FULLSCREEN_TOGGLE_MODE_NONE
#define DEFAULT_FULLSCREEN FALSE
#define DEFAULT_RENDER_STATS FALSE
#define DEFAULT_DRAW_ON_SHARED_TEXTURE FALSE
enum
{
/* signals */
SIGNAL_BEGIN_DRAW,
/* actions */
SIGNAL_DRAW,
LAST_SIGNAL
};
static guint gst_d3d11_video_sink_bin_signals[LAST_SIGNAL] = { 0, };
static GstStaticCaps pad_template_caps =
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
(GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_SINK_FORMATS) "; "
GST_VIDEO_CAPS_MAKE_WITH_FEATURES
(GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY ","
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
GST_D3D11_SINK_FORMATS) ";"
GST_VIDEO_CAPS_MAKE (GST_D3D11_SINK_FORMATS) "; "
GST_VIDEO_CAPS_MAKE_WITH_FEATURES
(GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ","
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
GST_D3D11_SINK_FORMATS));
GST_DEBUG_CATEGORY (d3d11_video_sink_bin_debug);
#define GST_CAT_DEFAULT d3d11_video_sink_bin_debug
struct _GstD3D11VideoSinkBin
{
GstBin parent;
GstPad *sinkpad;
GstElement *upload;
GstElement *sink;
};
static void gst_d3d11_video_sink_bin_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_d3d11_video_sink_bin_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
static void
gst_d3d11_video_sink_bin_video_overlay_init (GstVideoOverlayInterface * iface);
static void
gst_d3d11_video_sink_bin_navigation_init (GstNavigationInterface * iface);
static void gst_d311_video_sink_bin_on_begin_draw (GstD3D11VideoSink * sink,
gpointer self);
static gboolean
gst_d3d11_video_sink_bin_draw_action (GstD3D11VideoSinkBin * self,
gpointer shared_handle, guint texture_misc_flags, guint64 acquire_key,
guint64 release_key);
#define gst_d3d11_video_sink_bin_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstD3D11VideoSinkBin, gst_d3d11_video_sink_bin,
GST_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
gst_d3d11_video_sink_bin_video_overlay_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
gst_d3d11_video_sink_bin_navigation_init);
GST_DEBUG_CATEGORY_INIT (d3d11_video_sink_bin_debug,
"d3d11videosink", 0, "Direct3D11 Video Sink"));
static void
gst_d3d11_video_sink_bin_class_init (GstD3D11VideoSinkBinClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GstCaps *caps;
gobject_class->set_property = gst_d3d11_video_sink_bin_set_property;
gobject_class->get_property = gst_d3d11_video_sink_bin_get_property;
/* basesink */
g_object_class_install_property (gobject_class, PROP_SYNC,
g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_MAX_LATENESS,
g_param_spec_int64 ("max-lateness", "Max Lateness",
"Maximum number of nanoseconds that a buffer can be late before it "
"is dropped (-1 unlimited)", -1, G_MAXINT64, DEFAULT_MAX_LATENESS,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_QOS,
g_param_spec_boolean ("qos", "Qos",
"Generate Quality-of-Service events upstream", DEFAULT_QOS,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_ASYNC,
g_param_spec_boolean ("async", "Async",
"Go asynchronously to PAUSED", DEFAULT_ASYNC,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_TS_OFFSET,
g_param_spec_int64 ("ts-offset", "TS Offset",
"Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64,
DEFAULT_TS_OFFSET,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_SAMPLE,
g_param_spec_boolean ("enable-last-sample", "Enable Last Buffer",
"Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_LAST_SAMPLE,
g_param_spec_boxed ("last-sample", "Last Sample",
"The last sample received in the sink", GST_TYPE_SAMPLE,
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
g_param_spec_uint ("blocksize", "Block size",
"Size in bytes to pull per buffer (0 = default)", 0, G_MAXUINT,
DEFAULT_BLOCKSIZE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_RENDER_DELAY,
g_param_spec_uint64 ("render-delay", "Render Delay",
"Additional render delay of the sink in nanoseconds", 0, G_MAXUINT64,
DEFAULT_RENDER_DELAY,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_THROTTLE_TIME,
g_param_spec_uint64 ("throttle-time", "Throttle time",
"The time to keep between rendered buffers (0 = disabled)", 0,
G_MAXUINT64, DEFAULT_THROTTLE_TIME,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
g_param_spec_uint64 ("max-bitrate", "Max Bitrate",
"The maximum bits per second to render (0 = disabled)", 0,
G_MAXUINT64, DEFAULT_MAX_BITRATE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_PROCESSING_DEADLINE,
g_param_spec_uint64 ("processing-deadline", "Processing deadline",
"Maximum processing deadline in nanoseconds", 0, G_MAXUINT64,
DEFAULT_PROCESSING_DEADLINE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_STATS,
g_param_spec_boxed ("stats", "Statistics",
"Sink Statistics", GST_TYPE_STRUCTURE,
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
/* videosink */
g_object_class_install_property (gobject_class, PROP_SHOW_PREROLL_FRAME,
g_param_spec_boolean ("show-preroll-frame", "Show preroll frame",
"Whether to render video frames during preroll",
DEFAULT_SHOW_PREROLL_FRAME,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS)));
/* d3d11videosink */
g_object_class_install_property (gobject_class, PROP_ADAPTER,
g_param_spec_int ("adapter", "Adapter",
"Adapter index for creating device (-1 for default)",
-1, G_MAXINT32, DEFAULT_ADAPTER,
(GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
g_param_spec_boolean ("force-aspect-ratio",
"Force aspect ratio",
"When enabled, scaling will respect original aspect ratio",
DEFAULT_FORCE_ASPECT_RATIO,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_ENABLE_NAVIGATION_EVENTS,
g_param_spec_boolean ("enable-navigation-events",
"Enable navigation events",
"When enabled, navigation events are sent upstream",
DEFAULT_ENABLE_NAVIGATION_EVENTS,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_FULLSCREEN_TOGGLE_MODE,
g_param_spec_flags ("fullscreen-toggle-mode",
"Full screen toggle mode",
"Full screen toggle mode used to trigger fullscreen mode change",
GST_D3D11_WINDOW_TOGGLE_MODE_GET_TYPE, DEFAULT_FULLSCREEN_TOGGLE_MODE,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (gobject_class, PROP_FULLSCREEN,
g_param_spec_boolean ("fullscreen",
"fullscreen",
"Ignored when \"fullscreen-toggle-mode\" does not include \"property\"",
DEFAULT_FULLSCREEN,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
/**
* GstD3D11VideoSinkBin:draw-on-shared-texture:
*
* Instruct the sink to draw on a shared texture provided by user.
* User must watch #d3d11videosink::begin-draw signal and should call
* #d3d11videosink::draw method on the #d3d11videosink::begin-draw
* signal handler.
*
* Currently supported formats for user texture are:
* - DXGI_FORMAT_R8G8B8A8_UNORM
* - DXGI_FORMAT_B8G8R8A8_UNORM
* - DXGI_FORMAT_R10G10B10A2_UNORM
*
* Since: 1.20
*/
g_object_class_install_property (gobject_class, PROP_DRAW_ON_SHARED_TEXTURE,
g_param_spec_boolean ("draw-on-shared-texture",
"Draw on shared texture",
"Draw on user provided shared texture instead of window. "
"When enabled, user can pass application's own texture to sink "
"by using \"draw\" action signal on \"begin-draw\" signal handler, "
"so that sink can draw video data on application's texture. "
"Supported texture formats for user texture are "
"DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, and "
"DXGI_FORMAT_R10G10B10A2_UNORM.",
DEFAULT_DRAW_ON_SHARED_TEXTURE,
(GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
G_PARAM_STATIC_STRINGS)));
/**
* GstD3D11VideoSinkBin::begin-draw:
* @videosink: the #d3d11videosink
*
* Emitted when sink has a texture to draw. Application needs to invoke
* #d3d11videosink::draw action signal before returning from
* #d3d11videosink::begin-draw signal handler.
*
* Since: 1.20
*/
gst_d3d11_video_sink_bin_signals[SIGNAL_BEGIN_DRAW] =
g_signal_new ("begin-draw", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstD3D11VideoSinkBinClass, begin_draw),
NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
/**
* GstD3D11VideoSinkBin::draw:
* @videosink: the #d3d11videosink
* @shard_handle: a pointer to HANDLE
* @texture_misc_flags: a D3D11_RESOURCE_MISC_FLAG value
* @acquire_key: a key value used for IDXGIKeyedMutex::AcquireSync
* @release_key: a key value used for IDXGIKeyedMutex::ReleaseSync
*
* Draws on a shared texture. @shard_handle must be a valid pointer to
* a HANDLE which was obtained via IDXGIResource::GetSharedHandle or
* IDXGIResource1::CreateSharedHandle.
*
* If the texture was created with D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX flag,
* caller must specify valid @acquire_key and @release_key.
* Otherwise (i.e., created with D3D11_RESOURCE_MISC_SHARED flag),
* @acquire_key and @release_key will be ignored.
*
* Since: 1.20
*/
gst_d3d11_video_sink_bin_signals[SIGNAL_DRAW] =
g_signal_new ("draw", G_TYPE_FROM_CLASS (klass),
(GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
G_STRUCT_OFFSET (GstD3D11VideoSinkBinClass, draw), NULL, NULL, NULL,
G_TYPE_BOOLEAN, 4, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT64,
G_TYPE_UINT64);
klass->draw = gst_d3d11_video_sink_bin_draw_action;
gst_element_class_set_static_metadata (element_class,
"Direct3D11 video sink bin", "Sink/Video",
"A Direct3D11 based videosink bin",
"Seungha Yang <seungha.yang@navercorp.com>");
caps = gst_d3d11_get_updated_template_caps (&pad_template_caps);
gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps));
gst_caps_unref (caps);
}
static void
gst_d3d11_video_sink_bin_init (GstD3D11VideoSinkBin * self)
{
GstPad *pad;
GstD3D11VideoSinkCallbacks callbacks;
self->upload = gst_element_factory_make ("d3d11upload", NULL);
if (!self->upload) {
GST_ERROR_OBJECT (self, "d3d11upload unavailable");
return;
}
self->sink = gst_element_factory_make ("d3d11videosinkelement", NULL);
if (!self->sink) {
gst_clear_object (&self->upload);
GST_ERROR_OBJECT (self, "d3d11videosinkelement unavailable");
return;
}
callbacks.begin_draw = gst_d311_video_sink_bin_on_begin_draw;
gst_d3d11_video_sink_set_callbacks (GST_D3D11_VIDEO_SINK (self->sink),
&callbacks, self);
gst_bin_add_many (GST_BIN (self), self->upload, self->sink, NULL);
gst_element_link_many (self->upload, self->sink, NULL);
pad = gst_element_get_static_pad (self->upload, "sink");
self->sinkpad = gst_ghost_pad_new ("sink", pad);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->sinkpad);
gst_object_unref (pad);
}
static void
gst_d3d11_video_sink_bin_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (object);
GParamSpec *sink_pspec;
sink_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (self->sink),
pspec->name);
if (sink_pspec && G_PARAM_SPEC_TYPE (sink_pspec) == G_PARAM_SPEC_TYPE (pspec)) {
g_object_set_property (G_OBJECT (self->sink), pspec->name, value);
} else {
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_d3d11_video_sink_bin_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (object);
g_object_get_property (G_OBJECT (self->sink), pspec->name, value);
}
static void
gst_d311_video_sink_bin_on_begin_draw (GstD3D11VideoSink * sink, gpointer self)
{
g_signal_emit (self, gst_d3d11_video_sink_bin_signals[SIGNAL_BEGIN_DRAW], 0,
NULL);
}
static gboolean
gst_d3d11_video_sink_bin_draw_action (GstD3D11VideoSinkBin * self,
gpointer shared_handle, guint texture_misc_flags, guint64 acquire_key,
guint64 release_key)
{
if (!self->sink) {
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
("D3D11VideoSink element wasn't configured"), (NULL));
return FALSE;
}
return gst_d3d11_video_sink_draw (GST_D3D11_VIDEO_SINK (self->sink),
shared_handle, texture_misc_flags, acquire_key, release_key);
}
/* VideoOverlay interface */
static void
gst_d3d11_video_sink_bin_set_window_handle (GstVideoOverlay * overlay,
guintptr window_id)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (overlay);
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (self->sink),
window_id);
}
static void
gst_d3d11_video_sink_bin_set_render_rectangle (GstVideoOverlay * overlay,
gint x, gint y, gint width, gint height)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (overlay);
gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (self->sink),
x, y, width, height);
}
static void
gst_d3d11_video_sink_bin_expose (GstVideoOverlay * overlay)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (overlay);
gst_video_overlay_expose (GST_VIDEO_OVERLAY (self->sink));
}
static void
gst_d3d11_video_sink_bin_handle_events (GstVideoOverlay * overlay,
gboolean handle_events)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (overlay);
gst_video_overlay_handle_events (GST_VIDEO_OVERLAY (self->sink),
handle_events);
}
static void
gst_d3d11_video_sink_bin_video_overlay_init (GstVideoOverlayInterface * iface)
{
iface->set_window_handle = gst_d3d11_video_sink_bin_set_window_handle;
iface->set_render_rectangle = gst_d3d11_video_sink_bin_set_render_rectangle;
iface->expose = gst_d3d11_video_sink_bin_expose;
iface->handle_events = gst_d3d11_video_sink_bin_handle_events;
}
/* Navigation interface */
static void
gst_d3d11_video_sink_bin_navigation_send_event (GstNavigation * navigation,
GstStructure * structure)
{
GstD3D11VideoSinkBin *self = GST_D3D11_VIDEO_SINK_BIN (navigation);
gst_navigation_send_event (GST_NAVIGATION (self->sink), structure);
}
static void
gst_d3d11_video_sink_bin_navigation_init (GstNavigationInterface * iface)
{
iface->send_event = gst_d3d11_video_sink_bin_navigation_send_event;
}

View file

@ -1,57 +0,0 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 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.
*/
#ifndef __GST_D3D11_VIDEO_SINK_BIN_H__
#define __GST_D3D11_VIDEO_SINK_BIN_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_D3D11_VIDEO_SINK_BIN (gst_d3d11_video_sink_bin_get_type())
#define GST_D3D11_VIDEO_SINK_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_D3D11_VIDEO_SINK_BIN, GstD3D11VideoSinkBin))
#define GST_D3D11_VIDEO_SINK_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_D3D11_VIDEO_SINK_BIN, GstD3D11VideoSinkBinClass))
#define GST_IS_D3D11_VIDEO_SINK_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_D3D11_VIDEO_SINK_BIN))
#define GST_IS_D3D11_VIDEO_SINK_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_D3D11_VIDEO_SINK_BIN))
#define GST_D3D11_VIDEO_SINK_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_D3D11_VIDEO_SINK_BIN, GstD3D11VideoSinkBinClass))
typedef struct _GstD3D11VideoSinkBin GstD3D11VideoSinkBin;
typedef struct _GstD3D11VideoSinkBinClass GstD3D11VideoSinkBinClass;
struct _GstD3D11VideoSinkBinClass
{
GstBinClass parent_class;
/* signals */
void (*begin_draw) (GstD3D11VideoSinkBin * videosink);
/* actions */
gboolean (*draw) (GstD3D11VideoSinkBin * videosink,
gpointer shared_handle,
guint texture_misc_flags,
guint64 acquire_key,
guint64 release_key);
};
GType gst_d3d11_video_sink_bin_get_type (void);
G_END_DECLS
#endif /* __GST_D3D11_VIDEO_SINK_BIN_H__ */

View file

@ -11,7 +11,6 @@ d3d11_sources = [
'gstd3d11upload.cpp',
'gstd3d11videoprocessor.cpp',
'gstd3d11videosink.cpp',
'gstd3d11videosinkbin.cpp',
'gstd3d11window.cpp',
'gstd3d11window_dummy.cpp',
'plugin.c',

View file

@ -27,7 +27,6 @@
#include "gstd3d11upload.h"
#include "gstd3d11download.h"
#include "gstd3d11convert.h"
#include "gstd3d11videosinkbin.h"
#include "gstd3d11shader.h"
#include "gstd3d11compositor.h"
#include "gstd3d11compositorbin.h"
@ -214,10 +213,7 @@ plugin_init (GstPlugin * plugin)
gst_element_register (plugin,
"d3d11scale", GST_RANK_NONE, GST_TYPE_D3D11_SCALE);
gst_element_register (plugin,
"d3d11videosinkelement", GST_RANK_NONE, GST_TYPE_D3D11_VIDEO_SINK);
gst_element_register (plugin,
"d3d11videosink", video_sink_rank, GST_TYPE_D3D11_VIDEO_SINK_BIN);
"d3d11videosink", video_sink_rank, GST_TYPE_D3D11_VIDEO_SINK);
gst_element_register (plugin,
"d3d11compositorelement", GST_RANK_NONE, GST_TYPE_D3D11_COMPOSITOR);