mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
d3d12videosink: Add support for 3D transformation
Add x, y, and z axis rotation with scaling support Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5891>
This commit is contained in:
parent
72237d2563
commit
368d8b9252
7 changed files with 302 additions and 9 deletions
|
@ -982,7 +982,6 @@ gst_d3d12_converter_apply_orientation (GstD3D12Converter * self)
|
|||
switch (priv->video_direction) {
|
||||
case GST_VIDEO_ORIENTATION_IDENTITY:
|
||||
case GST_VIDEO_ORIENTATION_AUTO:
|
||||
case GST_VIDEO_ORIENTATION_CUSTOM:
|
||||
default:
|
||||
priv->transform = g_matrix_identity;
|
||||
break;
|
||||
|
@ -1007,6 +1006,8 @@ gst_d3d12_converter_apply_orientation (GstD3D12Converter * self)
|
|||
case GST_VIDEO_ORIENTATION_UR_LL:
|
||||
priv->transform = g_matrix_ur_ll;
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_CUSTOM:
|
||||
priv->transform = priv->custom_transform;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -2277,3 +2278,84 @@ gst_d3d12_converter_update_blend_state (GstD3D12Converter * converter,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_converter_apply_transform (GstD3D12Converter * converter,
|
||||
GstVideoOrientationMethod orientation, gfloat viewport_width,
|
||||
gfloat viewport_height, gfloat fov, gboolean ortho, gfloat rotation_x,
|
||||
gfloat rotation_y, gfloat rotation_z, gfloat scale_x, gfloat scale_y)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_D3D12_CONVERTER (converter), FALSE);
|
||||
|
||||
auto priv = converter->priv;
|
||||
std::lock_guard < std::mutex > lk (priv->prop_lock);
|
||||
|
||||
gfloat aspect_ratio;
|
||||
gboolean rotated = FALSE;
|
||||
XMMATRIX rotate_matrix = XMMatrixIdentity ();
|
||||
|
||||
switch (orientation) {
|
||||
case GST_VIDEO_ORIENTATION_IDENTITY:
|
||||
case GST_VIDEO_ORIENTATION_AUTO:
|
||||
case GST_VIDEO_ORIENTATION_CUSTOM:
|
||||
default:
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_90R:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_90r);
|
||||
rotated = TRUE;
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_180:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_180);
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_90L:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_90l);
|
||||
rotated = TRUE;
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_HORIZ:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_horiz);
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_VERT:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_vert);
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_UL_LR:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_ul_lr);
|
||||
rotated = TRUE;
|
||||
break;
|
||||
case GST_VIDEO_ORIENTATION_UR_LL:
|
||||
rotate_matrix = XMLoadFloat4x4A (&g_matrix_ur_ll);
|
||||
rotated = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rotated)
|
||||
aspect_ratio = viewport_height / viewport_width;
|
||||
else
|
||||
aspect_ratio = viewport_width / viewport_height;
|
||||
|
||||
/* Apply user specified transform matrix first, then rotate-method */
|
||||
XMMATRIX scale = XMMatrixScaling (scale_x * aspect_ratio, scale_y, 1.0);
|
||||
|
||||
XMMATRIX rotate =
|
||||
XMMatrixRotationX (XMConvertToRadians (rotation_x)) *
|
||||
XMMatrixRotationY (XMConvertToRadians (-rotation_y)) *
|
||||
XMMatrixRotationZ (XMConvertToRadians (-rotation_z));
|
||||
|
||||
XMMATRIX view = XMMatrixLookAtLH (XMVectorSet (0.0, 0.0, -1.0, 0.0),
|
||||
XMVectorSet (0.0, 0.0, 0.0, 0.0), XMVectorSet (0.0, 1.0, 0.0, 0.0));
|
||||
|
||||
XMMATRIX proj;
|
||||
if (ortho) {
|
||||
proj = XMMatrixOrthographicOffCenterLH (-aspect_ratio,
|
||||
aspect_ratio, -1.0, 1.0, 0.1, 100.0);
|
||||
} else {
|
||||
proj = XMMatrixPerspectiveFovLH (XMConvertToRadians (fov),
|
||||
aspect_ratio, 0.1, 100.0);
|
||||
}
|
||||
|
||||
XMMATRIX mvp = scale * rotate * view * proj * rotate_matrix;
|
||||
XMStoreFloat4x4A (&priv->custom_transform, mvp);
|
||||
priv->update_transform = TRUE;
|
||||
priv->video_direction = GST_VIDEO_ORIENTATION_CUSTOM;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -150,4 +150,16 @@ gboolean gst_d3d12_converter_update_blend_state (GstD3D12Converter *
|
|||
const D3D12_BLEND_DESC * blend_desc,
|
||||
const gfloat blend_factor[4]);
|
||||
|
||||
gboolean gst_d3d12_converter_apply_transform (GstD3D12Converter * converter,
|
||||
GstVideoOrientationMethod orientation,
|
||||
gfloat viewport_width,
|
||||
gfloat viewport_height,
|
||||
gfloat fov,
|
||||
gboolean ortho,
|
||||
gfloat rotation_x,
|
||||
gfloat rotation_y,
|
||||
gfloat rotation_z,
|
||||
gfloat scale_x,
|
||||
gfloat scale_y);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
|
||||
#include "gstd3d12pluginutils.h"
|
||||
|
||||
#define _XM_NO_INTRINSICS_
|
||||
#include <DirectXMath.h>
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
using namespace DirectX;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
GType
|
||||
gst_d3d12_sampling_method_get_type (void)
|
||||
{
|
||||
|
@ -102,3 +109,20 @@ gst_d3d12_buffer_after_write (GstBuffer * buffer, guint64 fence_value)
|
|||
GST_MINI_OBJECT_FLAG_UNSET (dmem, GST_D3D12_MEMORY_TRANSFER_NEED_UPLOAD);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d12_need_transform (gfloat rotation_x, gfloat rotation_y,
|
||||
gfloat rotation_z, gfloat scale_x, gfloat scale_y)
|
||||
{
|
||||
const gfloat min_diff = 0.00001f;
|
||||
|
||||
if (!XMScalarNearEqual (rotation_x, 0.0f, min_diff) ||
|
||||
!XMScalarNearEqual (rotation_y, 0.0f, min_diff) ||
|
||||
!XMScalarNearEqual (rotation_z, 0.0f, min_diff) ||
|
||||
!XMScalarNearEqual (scale_x, 1.0f, min_diff) ||
|
||||
!XMScalarNearEqual (scale_y, 1.0f, min_diff)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -52,4 +52,10 @@ GType gst_d3d12_msaa_mode_get_type (void);
|
|||
void gst_d3d12_buffer_after_write (GstBuffer * buffer,
|
||||
guint64 fence_value);
|
||||
|
||||
gboolean gst_d3d12_need_transform (gfloat rotation_x,
|
||||
gfloat rotation_y,
|
||||
gfloat rotation_z,
|
||||
gfloat scale_x,
|
||||
gfloat scale_y);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -38,6 +38,14 @@ enum
|
|||
PROP_FULLSCREEN_ON_ALT_ENTER,
|
||||
PROP_FULLSCREEN,
|
||||
PROP_MSAA,
|
||||
PROP_REDRAW_ON_UPDATE,
|
||||
PROP_FOV,
|
||||
PROP_ORTHO,
|
||||
PROP_ROTATION_X,
|
||||
PROP_ROTATION_Y,
|
||||
PROP_ROTATION_Z,
|
||||
PROP_SCALE_X,
|
||||
PROP_SCALE_Y,
|
||||
};
|
||||
|
||||
#define DEFAULT_ADAPTER -1
|
||||
|
@ -47,6 +55,11 @@ enum
|
|||
#define DEFAULT_FULLSCREEN_ON_ALT_ENTER FALSE
|
||||
#define DEFAULT_FULLSCREEN FALSE
|
||||
#define DEFAULT_MSAA GST_D3D12_MSAA_DISABLED
|
||||
#define DEFAULT_REDROW_ON_UPDATE TRUE
|
||||
#define DEFAULT_ROTATION 0.0f
|
||||
#define DEFAULT_SCALE 1.0f
|
||||
#define DEFAULT_FOV 90.0f
|
||||
#define DEFAULT_ORTHO FALSE
|
||||
|
||||
static GstStaticPadTemplate sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||
|
@ -105,6 +118,14 @@ struct GstD3D12VideoSinkPrivate
|
|||
gboolean fullscreen_on_alt_enter = DEFAULT_FULLSCREEN_ON_ALT_ENTER;
|
||||
gboolean fullscreen = DEFAULT_FULLSCREEN;
|
||||
GstD3D12MSAAMode msaa = DEFAULT_MSAA;
|
||||
gboolean redraw_on_update = DEFAULT_REDROW_ON_UPDATE;
|
||||
gfloat fov = DEFAULT_FOV;
|
||||
gboolean ortho = DEFAULT_ORTHO;
|
||||
gfloat rotation_x = DEFAULT_ROTATION;
|
||||
gfloat rotation_y = DEFAULT_ROTATION;
|
||||
gfloat rotation_z = DEFAULT_ROTATION;
|
||||
gfloat scale_x = DEFAULT_SCALE;
|
||||
gfloat scale_y = DEFAULT_SCALE;
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -223,6 +244,55 @@ gst_d3d12_video_sink_class_init (GstD3D12VideoSinkClass * klass)
|
|||
GST_TYPE_D3D12_MSAA_MODE, DEFAULT_MSAA,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_REDRAW_ON_UPDATE,
|
||||
g_param_spec_boolean ("redraw-on-update",
|
||||
"redraw-on-update",
|
||||
"Immediately apply updated geometry related properties and redraw. "
|
||||
"If disabled, properties will be applied on the next frame or "
|
||||
"window resize", DEFAULT_REDROW_ON_UPDATE,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_FOV,
|
||||
g_param_spec_float ("fov", "Fov",
|
||||
"Field of view angle in degrees",
|
||||
0, G_MAXFLOAT, DEFAULT_FOV,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ORTHO,
|
||||
g_param_spec_boolean ("ortho", "Orthographic",
|
||||
"Use orthographic projection", DEFAULT_ORTHO,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ROTATION_X,
|
||||
g_param_spec_float ("rotation-x", "Rotation X",
|
||||
"x-axis rotation angle in degrees",
|
||||
-G_MAXFLOAT, G_MAXFLOAT, DEFAULT_ROTATION,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ROTATION_Y,
|
||||
g_param_spec_float ("rotation-y", "Rotation Y",
|
||||
"y-axis rotation angle in degrees",
|
||||
-G_MAXFLOAT, G_MAXFLOAT, DEFAULT_ROTATION,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ROTATION_Z,
|
||||
g_param_spec_float ("rotation-z", "Rotation Z",
|
||||
"z-axis rotation angle in degrees",
|
||||
-G_MAXFLOAT, G_MAXFLOAT, DEFAULT_ROTATION,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE_X,
|
||||
g_param_spec_float ("scale-x", "Scale X",
|
||||
"Scale multiplier for x-axis",
|
||||
-G_MAXFLOAT, G_MAXFLOAT, DEFAULT_SCALE,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE_Y,
|
||||
g_param_spec_float ("scale-y", "Scale Y",
|
||||
"Scale multiplier for y-axis",
|
||||
-G_MAXFLOAT, G_MAXFLOAT, DEFAULT_SCALE,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
element_class->set_context =
|
||||
GST_DEBUG_FUNCPTR (gst_d3d12_video_sink_set_context);
|
||||
|
||||
|
@ -314,6 +384,38 @@ gst_d3d12_videosink_set_property (GObject * object, guint prop_id,
|
|||
priv->msaa = (GstD3D12MSAAMode) g_value_get_enum (value);
|
||||
gst_d3d12_window_set_msaa (priv->window, priv->msaa);
|
||||
break;
|
||||
case PROP_REDRAW_ON_UPDATE:
|
||||
priv->redraw_on_update = g_value_get_boolean (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_FOV:
|
||||
priv->fov = g_value_get_float (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_ORTHO:
|
||||
priv->ortho = g_value_get_boolean (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_ROTATION_X:
|
||||
priv->rotation_x = g_value_get_float (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_ROTATION_Y:
|
||||
priv->rotation_y = g_value_get_float (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_ROTATION_Z:
|
||||
priv->rotation_z = g_value_get_float (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_SCALE_X:
|
||||
priv->scale_x = g_value_get_float (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
case PROP_SCALE_Y:
|
||||
priv->scale_y = g_value_get_float (value);
|
||||
gst_d3d12_video_sink_set_orientation (self, priv->orientation, FALSE);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -350,6 +452,30 @@ gst_d3d12_videosink_get_property (GObject * object, guint prop_id,
|
|||
case PROP_MSAA:
|
||||
g_value_set_enum (value, priv->msaa);
|
||||
break;
|
||||
case PROP_REDRAW_ON_UPDATE:
|
||||
g_value_set_boolean (value, priv->redraw_on_update);
|
||||
break;
|
||||
case PROP_FOV:
|
||||
g_value_set_float (value, priv->fov);
|
||||
break;
|
||||
case PROP_ORTHO:
|
||||
g_value_set_boolean (value, priv->ortho);
|
||||
break;
|
||||
case PROP_ROTATION_X:
|
||||
g_value_set_float (value, priv->rotation_x);
|
||||
break;
|
||||
case PROP_ROTATION_Y:
|
||||
g_value_set_float (value, priv->rotation_x);
|
||||
break;
|
||||
case PROP_ROTATION_Z:
|
||||
g_value_set_float (value, priv->rotation_z);
|
||||
break;
|
||||
case PROP_SCALE_X:
|
||||
g_value_set_float (value, priv->scale_x);
|
||||
break;
|
||||
case PROP_SCALE_Y:
|
||||
g_value_set_float (value, priv->scale_y);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -377,7 +503,10 @@ gst_d3d12_video_sink_set_orientation (GstD3D12VideoSink * self,
|
|||
else
|
||||
priv->orientation_selected = priv->orientation;
|
||||
|
||||
gst_d3d12_window_set_orientation (priv->window, priv->orientation_selected);
|
||||
gst_d3d12_window_set_orientation (priv->window,
|
||||
priv->redraw_on_update, priv->orientation_selected, priv->fov,
|
||||
priv->ortho, priv->rotation_x, priv->rotation_y, priv->rotation_z,
|
||||
priv->scale_x, priv->scale_y);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -172,6 +172,13 @@ struct GstD3D12WindowPrivate
|
|||
DXGI_FORMAT display_format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
GstVideoOrientationMethod orientation = GST_VIDEO_ORIENTATION_IDENTITY;
|
||||
gfloat fov = 90.0f;
|
||||
gboolean ortho = FALSE;
|
||||
gfloat rotation_x = 0;
|
||||
gfloat rotation_y = 0;
|
||||
gfloat rotation_z = 0;
|
||||
gfloat scale_x = 1.0f;
|
||||
gfloat scale_y = 1.0f;
|
||||
|
||||
/* fullscreen related variables */
|
||||
gboolean fullscreen_on_alt_enter = TRUE;
|
||||
|
@ -1407,8 +1414,19 @@ gst_d3d12_window_set_buffer (GstD3D12Window * window, GstBuffer * buffer)
|
|||
|
||||
g_object_set (priv->ctx->conv, "dest-x", priv->output_rect.x,
|
||||
"dest-y", priv->output_rect.y, "dest-width", priv->output_rect.w,
|
||||
"dest-height", priv->output_rect.h,
|
||||
"video-direction", priv->orientation, nullptr);
|
||||
"dest-height", priv->output_rect.h, nullptr);
|
||||
|
||||
if (gst_d3d12_need_transform (priv->rotation_x, priv->rotation_y,
|
||||
priv->rotation_z, priv->scale_x, priv->scale_y)) {
|
||||
gst_d3d12_converter_apply_transform (priv->ctx->conv, priv->orientation,
|
||||
priv->output_rect.w, priv->output_rect.h, priv->fov, priv->ortho,
|
||||
priv->rotation_x, priv->rotation_y, priv->rotation_z,
|
||||
priv->scale_x, priv->scale_y);
|
||||
} else {
|
||||
g_object_set (priv->ctx->conv,
|
||||
"video-direction", priv->orientation, nullptr);
|
||||
}
|
||||
|
||||
gst_d3d12_overlay_compositor_update_viewport (priv->ctx->comp,
|
||||
&priv->output_rect);
|
||||
}
|
||||
|
@ -1648,16 +1666,30 @@ gst_d3d12_window_set_enable_navigation_events (GstD3D12Window * window,
|
|||
}
|
||||
|
||||
void
|
||||
gst_d3d12_window_set_orientation (GstD3D12Window * window,
|
||||
GstVideoOrientationMethod orientation)
|
||||
gst_d3d12_window_set_orientation (GstD3D12Window * window, gboolean immediate,
|
||||
GstVideoOrientationMethod orientation, gfloat fov, gboolean ortho,
|
||||
gfloat rotation_x, gfloat rotation_y, gfloat rotation_z,
|
||||
gfloat scale_x, gfloat scale_y)
|
||||
{
|
||||
auto priv = window->priv;
|
||||
|
||||
std::lock_guard < std::recursive_mutex > lk (priv->lock);
|
||||
if (priv->orientation != orientation) {
|
||||
if (priv->orientation != orientation || priv->fov != fov
|
||||
|| priv->ortho != ortho
|
||||
|| priv->rotation_x != rotation_x || priv->rotation_y != rotation_y
|
||||
|| priv->rotation_z != rotation_z || priv->scale_x != scale_x
|
||||
|| priv->scale_y != scale_y) {
|
||||
priv->orientation = orientation;
|
||||
priv->fov = fov;
|
||||
priv->ortho = ortho;
|
||||
priv->rotation_x = rotation_x;
|
||||
priv->rotation_y = rotation_y;
|
||||
priv->rotation_z = rotation_z;
|
||||
priv->scale_x = scale_x;
|
||||
priv->scale_y = scale_y;
|
||||
priv->first_present = TRUE;
|
||||
gst_d3d12_window_set_buffer (window, nullptr);
|
||||
if (immediate)
|
||||
gst_d3d12_window_set_buffer (window, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,15 @@ void gst_d3d12_window_set_enable_navigation_events (GstD3D12Window *
|
|||
gboolean enable);
|
||||
|
||||
void gst_d3d12_window_set_orientation (GstD3D12Window * window,
|
||||
GstVideoOrientationMethod orientation);
|
||||
gboolean immediate,
|
||||
GstVideoOrientationMethod orientation,
|
||||
gfloat fov,
|
||||
gboolean ortho,
|
||||
gfloat rotation_x,
|
||||
gfloat rotation_y,
|
||||
gfloat rotation_z,
|
||||
gfloat scale_x,
|
||||
gfloat scale_y);
|
||||
|
||||
void gst_d3d12_window_set_title (GstD3D12Window * window,
|
||||
const gchar * title);
|
||||
|
|
Loading…
Reference in a new issue