mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
d3d11videosink: Add support for rotation
Adding "rotate-method" property Fixes: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1396 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2708>
This commit is contained in:
parent
4e75ca0351
commit
5f39388ae5
5 changed files with 134 additions and 8 deletions
|
@ -61,6 +61,7 @@ enum
|
||||||
PROP_FULLSCREEN_TOGGLE_MODE,
|
PROP_FULLSCREEN_TOGGLE_MODE,
|
||||||
PROP_FULLSCREEN,
|
PROP_FULLSCREEN,
|
||||||
PROP_DRAW_ON_SHARED_TEXTURE,
|
PROP_DRAW_ON_SHARED_TEXTURE,
|
||||||
|
PROP_ROTATE_METHOD,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_ADAPTER -1
|
#define DEFAULT_ADAPTER -1
|
||||||
|
@ -131,6 +132,13 @@ struct _GstD3D11VideoSink
|
||||||
GRecMutex lock;
|
GRecMutex lock;
|
||||||
|
|
||||||
gchar *title;
|
gchar *title;
|
||||||
|
|
||||||
|
/* method configured via property */
|
||||||
|
GstVideoOrientationMethod method;
|
||||||
|
/* method parsed from tag */
|
||||||
|
GstVideoOrientationMethod tag_method;
|
||||||
|
/* method currently selected based on "method" and "tag_method" */
|
||||||
|
GstVideoOrientationMethod selected_method;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GST_D3D11_VIDEO_SINK_GET_LOCK(d) (&(GST_D3D11_VIDEO_SINK_CAST(d)->lock))
|
#define GST_D3D11_VIDEO_SINK_GET_LOCK(d) (&(GST_D3D11_VIDEO_SINK_CAST(d)->lock))
|
||||||
|
@ -177,10 +185,11 @@ static gboolean gst_d3d11_video_sink_unlock (GstBaseSink * sink);
|
||||||
static gboolean gst_d3d11_video_sink_unlock_stop (GstBaseSink * sink);
|
static gboolean gst_d3d11_video_sink_unlock_stop (GstBaseSink * sink);
|
||||||
static gboolean gst_d3d11_video_sink_event (GstBaseSink * sink,
|
static gboolean gst_d3d11_video_sink_event (GstBaseSink * sink,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf);
|
gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf);
|
||||||
static gboolean gst_d3d11_video_sink_prepare_window (GstD3D11VideoSink * self);
|
static gboolean gst_d3d11_video_sink_prepare_window (GstD3D11VideoSink * self);
|
||||||
|
static void gst_d3d11_video_sink_set_orientation (GstD3D11VideoSink * self,
|
||||||
|
GstVideoOrientationMethod method, gboolean from_tag);
|
||||||
|
|
||||||
#define gst_d3d11_video_sink_parent_class parent_class
|
#define gst_d3d11_video_sink_parent_class parent_class
|
||||||
G_DEFINE_TYPE_WITH_CODE (GstD3D11VideoSink, gst_d3d11_video_sink,
|
G_DEFINE_TYPE_WITH_CODE (GstD3D11VideoSink, gst_d3d11_video_sink,
|
||||||
|
@ -269,6 +278,19 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass)
|
||||||
(GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
|
(GParamFlags) (G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstD3D11VideoSink:rotate-method:
|
||||||
|
*
|
||||||
|
* Video rotation/flip method to use
|
||||||
|
*
|
||||||
|
* Since: 1.22
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ROTATE_METHOD,
|
||||||
|
g_param_spec_enum ("rotate-method", "Rotate Method",
|
||||||
|
"Rotate method to use",
|
||||||
|
GST_TYPE_VIDEO_ORIENTATION_METHOD, GST_VIDEO_ORIENTATION_IDENTITY,
|
||||||
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstD3D11VideoSink::begin-draw:
|
* GstD3D11VideoSink::begin-draw:
|
||||||
* @videosink: the #d3d11videosink
|
* @videosink: the #d3d11videosink
|
||||||
|
@ -398,6 +420,10 @@ gst_d3d11_videosink_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_DRAW_ON_SHARED_TEXTURE:
|
case PROP_DRAW_ON_SHARED_TEXTURE:
|
||||||
self->draw_on_shared_texture = g_value_get_boolean (value);
|
self->draw_on_shared_texture = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_ROTATE_METHOD:
|
||||||
|
gst_d3d11_video_sink_set_orientation (self,
|
||||||
|
(GstVideoOrientationMethod) g_value_get_enum (value), FALSE);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -435,6 +461,9 @@ gst_d3d11_videosink_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_DRAW_ON_SHARED_TEXTURE:
|
case PROP_DRAW_ON_SHARED_TEXTURE:
|
||||||
g_value_set_boolean (value, self->draw_on_shared_texture);
|
g_value_set_boolean (value, self->draw_on_shared_texture);
|
||||||
break;
|
break;
|
||||||
|
case PROP_ROTATE_METHOD:
|
||||||
|
g_value_set_enum (value, self->method);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -785,6 +814,8 @@ done:
|
||||||
"fullscreen", self->fullscreen,
|
"fullscreen", self->fullscreen,
|
||||||
"enable-navigation-events", self->enable_navigation_events, NULL);
|
"enable-navigation-events", self->enable_navigation_events, NULL);
|
||||||
|
|
||||||
|
gst_d3d11_window_set_orientation (self->window, self->selected_method);
|
||||||
|
|
||||||
g_signal_connect (self->window, "key-event",
|
g_signal_connect (self->window, "key-event",
|
||||||
G_CALLBACK (gst_d3d11_video_sink_key_event), self);
|
G_CALLBACK (gst_d3d11_video_sink_key_event), self);
|
||||||
g_signal_connect (self->window, "mouse-event",
|
g_signal_connect (self->window, "mouse-event",
|
||||||
|
@ -981,6 +1012,7 @@ gst_d3d11_video_sink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
case GST_EVENT_TAG:{
|
case GST_EVENT_TAG:{
|
||||||
GstTagList *taglist;
|
GstTagList *taglist;
|
||||||
gchar *title = nullptr;
|
gchar *title = nullptr;
|
||||||
|
GstVideoOrientationMethod method = GST_VIDEO_ORIENTATION_IDENTITY;
|
||||||
|
|
||||||
gst_event_parse_tag (event, &taglist);
|
gst_event_parse_tag (event, &taglist);
|
||||||
gst_tag_list_get_string (taglist, GST_TAG_TITLE, &title);
|
gst_tag_list_get_string (taglist, GST_TAG_TITLE, &title);
|
||||||
|
@ -1006,6 +1038,12 @@ gst_d3d11_video_sink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
|
|
||||||
g_free (title);
|
g_free (title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gst_video_orientation_from_tag (taglist, &method)) {
|
||||||
|
GST_D3D11_VIDEO_SINK_LOCK (self);
|
||||||
|
gst_d3d11_video_sink_set_orientation (self, method, TRUE);
|
||||||
|
GST_D3D11_VIDEO_SINK_UNLOCK (self);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1015,6 +1053,31 @@ gst_d3d11_video_sink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
|
return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called with lock */
|
||||||
|
static void
|
||||||
|
gst_d3d11_video_sink_set_orientation (GstD3D11VideoSink * self,
|
||||||
|
GstVideoOrientationMethod method, gboolean from_tag)
|
||||||
|
{
|
||||||
|
if (method == GST_VIDEO_ORIENTATION_CUSTOM) {
|
||||||
|
GST_WARNING_OBJECT (self, "Unsupported custom orientation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from_tag)
|
||||||
|
self->tag_method = method;
|
||||||
|
else
|
||||||
|
self->method = method;
|
||||||
|
|
||||||
|
if (self->method == GST_VIDEO_ORIENTATION_AUTO) {
|
||||||
|
self->selected_method = self->tag_method;
|
||||||
|
} else {
|
||||||
|
self->selected_method = self->method;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->window)
|
||||||
|
gst_d3d11_window_set_orientation (self->window, self->selected_method);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_d3d11_video_sink_check_device_update (GstD3D11VideoSink * self,
|
gst_d3d11_video_sink_check_device_update (GstD3D11VideoSink * self,
|
||||||
GstBuffer * buf)
|
GstBuffer * buf)
|
||||||
|
|
|
@ -334,8 +334,20 @@ gst_d3d11_window_on_resize_default (GstD3D11Window * self, guint width,
|
||||||
if (self->force_aspect_ratio) {
|
if (self->force_aspect_ratio) {
|
||||||
src_rect.x = 0;
|
src_rect.x = 0;
|
||||||
src_rect.y = 0;
|
src_rect.y = 0;
|
||||||
src_rect.w = GST_VIDEO_INFO_WIDTH (&self->render_info);
|
|
||||||
src_rect.h = GST_VIDEO_INFO_HEIGHT (&self->render_info);
|
switch (self->method) {
|
||||||
|
case GST_VIDEO_ORIENTATION_90R:
|
||||||
|
case GST_VIDEO_ORIENTATION_90L:
|
||||||
|
case GST_VIDEO_ORIENTATION_UL_LR:
|
||||||
|
case GST_VIDEO_ORIENTATION_UR_LL:
|
||||||
|
src_rect.w = GST_VIDEO_INFO_HEIGHT (&self->render_info);
|
||||||
|
src_rect.h = GST_VIDEO_INFO_WIDTH (&self->render_info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
src_rect.w = GST_VIDEO_INFO_WIDTH (&self->render_info);
|
||||||
|
src_rect.h = GST_VIDEO_INFO_HEIGHT (&self->render_info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
|
gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -677,9 +689,8 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
|
||||||
/* call resize to allocated resources */
|
/* call resize to allocated resources */
|
||||||
klass->on_resize (window, display_width, display_height);
|
klass->on_resize (window, display_width, display_height);
|
||||||
|
|
||||||
if (window->requested_fullscreen != window->fullscreen) {
|
if (window->requested_fullscreen != window->fullscreen)
|
||||||
klass->change_fullscreen_mode (window);
|
klass->change_fullscreen_mode (window);
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (window, "New swap chain 0x%p created", window->swap_chain);
|
GST_DEBUG_OBJECT (window, "New swap chain 0x%p created", window->swap_chain);
|
||||||
|
|
||||||
|
@ -800,7 +811,8 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
|
||||||
"dest-width",
|
"dest-width",
|
||||||
(gint) (self->render_rect.right - self->render_rect.left),
|
(gint) (self->render_rect.right - self->render_rect.left),
|
||||||
"dest-height",
|
"dest-height",
|
||||||
(gint) (self->render_rect.bottom - self->render_rect.top), nullptr);
|
(gint) (self->render_rect.bottom - self->render_rect.top),
|
||||||
|
"video-direction", self->method, nullptr);
|
||||||
gst_d3d11_overlay_compositor_update_viewport (self->compositor, &viewport);
|
gst_d3d11_overlay_compositor_update_viewport (self->compositor, &viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,3 +986,24 @@ gst_d3d11_window_get_native_type_to_string (GstD3D11WindowNativeType type)
|
||||||
|
|
||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_d3d11_window_set_orientation (GstD3D11Window * window,
|
||||||
|
GstVideoOrientationMethod method)
|
||||||
|
{
|
||||||
|
if (method == GST_VIDEO_ORIENTATION_AUTO ||
|
||||||
|
method == GST_VIDEO_ORIENTATION_CUSTOM) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_d3d11_device_lock (window->device);
|
||||||
|
if (window->method != method) {
|
||||||
|
window->method = method;
|
||||||
|
if (window->swap_chain) {
|
||||||
|
GstD3D11WindowClass *klass = GST_D3D11_WINDOW_GET_CLASS (window);
|
||||||
|
|
||||||
|
klass->on_resize (window, window->surface_width, window->surface_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gst_d3d11_device_unlock (window->device);
|
||||||
|
}
|
||||||
|
|
|
@ -116,6 +116,8 @@ struct _GstD3D11Window
|
||||||
GstBuffer *cached_buffer;
|
GstBuffer *cached_buffer;
|
||||||
gboolean first_present;
|
gboolean first_present;
|
||||||
gboolean allow_tearing;
|
gboolean allow_tearing;
|
||||||
|
|
||||||
|
GstVideoOrientationMethod method;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstD3D11WindowClass
|
struct _GstD3D11WindowClass
|
||||||
|
@ -177,6 +179,9 @@ void gst_d3d11_window_set_render_rectangle (GstD3D11Window * window,
|
||||||
void gst_d3d11_window_set_title (GstD3D11Window * window,
|
void gst_d3d11_window_set_title (GstD3D11Window * window,
|
||||||
const gchar *title);
|
const gchar *title);
|
||||||
|
|
||||||
|
void gst_d3d11_window_set_orientation (GstD3D11Window * window,
|
||||||
|
GstVideoOrientationMethod method);
|
||||||
|
|
||||||
gboolean gst_d3d11_window_prepare (GstD3D11Window * window,
|
gboolean gst_d3d11_window_prepare (GstD3D11Window * window,
|
||||||
guint display_width,
|
guint display_width,
|
||||||
guint display_height,
|
guint display_height,
|
||||||
|
|
|
@ -164,6 +164,20 @@ gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
|
||||||
src_rect.w = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
src_rect.w = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
||||||
src_rect.h = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
src_rect.h = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
||||||
|
|
||||||
|
switch (window->method) {
|
||||||
|
case GST_VIDEO_ORIENTATION_90R:
|
||||||
|
case GST_VIDEO_ORIENTATION_90L:
|
||||||
|
case GST_VIDEO_ORIENTATION_UL_LR:
|
||||||
|
case GST_VIDEO_ORIENTATION_UR_LL:
|
||||||
|
src_rect.w = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
||||||
|
src_rect.h = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
src_rect.w = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
||||||
|
src_rect.h = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
|
gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
|
||||||
} else {
|
} else {
|
||||||
rst_rect = dst_rect;
|
rst_rect = dst_rect;
|
||||||
|
|
|
@ -1036,8 +1036,19 @@ gst_d3d11_window_win32_show (GstD3D11Window * window)
|
||||||
GstD3D11WindowWin32 *self = GST_D3D11_WINDOW_WIN32 (window);
|
GstD3D11WindowWin32 *self = GST_D3D11_WINDOW_WIN32 (window);
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
|
||||||
width = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
switch (window->method) {
|
||||||
height = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
case GST_VIDEO_ORIENTATION_90R:
|
||||||
|
case GST_VIDEO_ORIENTATION_90L:
|
||||||
|
case GST_VIDEO_ORIENTATION_UL_LR:
|
||||||
|
case GST_VIDEO_ORIENTATION_UR_LL:
|
||||||
|
width = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
||||||
|
height = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
width = GST_VIDEO_INFO_WIDTH (&window->render_info);
|
||||||
|
height = GST_VIDEO_INFO_HEIGHT (&window->render_info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!self->visible) {
|
if (!self->visible) {
|
||||||
/* if no parent the real size has to be set now because this has not been done
|
/* if no parent the real size has to be set now because this has not been done
|
||||||
|
|
Loading…
Reference in a new issue