*/
/**
- * 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
*
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_debug);
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;
* 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:
/**
* 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
*/
/**
* 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
}
static GstCaps *
-gst_d3d11_video_sink_get_supported_caps (GstD3D11VideoSink * self,
- D3D11_FORMAT_SUPPORT flags)
+gst_d3d11_video_sink_get_caps (GstBaseSink * sink, GstCaps * filter)
{
- 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);
- }
- }
+ GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
+ GstCaps *caps = NULL;
- 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);
+ caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
- gst_caps_set_features_simple (supported_caps,
- gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY));
+ if (self->device) {
+ gboolean is_hardware = FALSE;
- return supported_caps;
-}
+ g_object_get (self->device, "hardware", &is_hardware, NULL);
-static GstCaps *
-gst_d3d11_video_sink_get_caps (GstBaseSink * sink, GstCaps * filter)
-{
- GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
- GstCaps *caps = 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;
- if (self->device && !self->can_convert) {
- GstCaps *overlaycaps;
- GstCapsFeatures *features;
+ g_value_init (&format_list, GST_TYPE_LIST);
+ g_value_init (&format, G_TYPE_STRING);
- 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);
- }
+ g_value_set_string (&format, "RGBA");
+ gst_value_list_append_and_take_value (&format_list, &format);
- if (!caps)
- caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
+ 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);
- if (caps && filter) {
+ caps = gst_caps_make_writable (caps);
+ gst_caps_set_value (caps, "format", &format_list);
+ g_value_unset (&format_list);
+ }
+ }
+
+ if (filter) {
GstCaps *isect;
isect = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (caps);
gst_d3d11_video_sink_start (GstBaseSink * sink)
{
GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
- gboolean is_hardware = TRUE;
GST_DEBUG_OBJECT (self, "Start");
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;
}
size = info.size;
if (need_pool) {
- GstD3D11AllocationParams *d3d11_params;
+ GstCapsFeatures *features;
+ GstStructure *config;
+ gboolean is_d3d11 = false;
+
+ 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 ();
+ }
- GST_DEBUG_OBJECT (self, "create new pool");
+ config = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_add_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
- 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);
+ /* 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
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;
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);
-}
+++ /dev/null
-/* 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;
-}