d3d11videosink: Add gamma-mode and primaries-mode properties

Allows controlling gamma remap and/or chromatic adaptation behavior.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2831>
This commit is contained in:
Seungha Yang 2022-08-03 01:47:46 +09:00
parent 0ac7077d2d
commit f89cb98495
4 changed files with 90 additions and 13 deletions

View file

@ -61,6 +61,8 @@ enum
PROP_FULLSCREEN,
PROP_DRAW_ON_SHARED_TEXTURE,
PROP_ROTATE_METHOD,
PROP_GAMMA_MODE,
PROP_PRIMARIES_MODE,
};
#define DEFAULT_ADAPTER -1
@ -69,6 +71,8 @@ enum
#define DEFAULT_FULLSCREEN_TOGGLE_MODE GST_D3D11_WINDOW_FULLSCREEN_TOGGLE_MODE_NONE
#define DEFAULT_FULLSCREEN FALSE
#define DEFAULT_DRAW_ON_SHARED_TEXTURE FALSE
#define DEFAULT_GAMMA_MODE GST_VIDEO_GAMMA_MODE_NONE
#define DEFAULT_PRIMARIES_MODE GST_VIDEO_PRIMARIES_MODE_NONE
enum
{
@ -120,6 +124,8 @@ struct _GstD3D11VideoSink
GstD3D11WindowFullscreenToggleMode fullscreen_toggle_mode;
gboolean fullscreen;
gboolean draw_on_shared_texture;
GstVideoGammaMode gamma_mode;
GstVideoPrimariesMode primaries_mode;
/* saved render rectangle until we have a window */
GstVideoRectangle render_rect;
@ -290,6 +296,32 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass)
GST_TYPE_VIDEO_ORIENTATION_METHOD, GST_VIDEO_ORIENTATION_IDENTITY,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
/**
* GstD3D11VideoSink:gamma-mode:
*
* Gamma conversion mode
*
* Since: 1.22
*/
g_object_class_install_property (gobject_class, PROP_GAMMA_MODE,
g_param_spec_enum ("gamma-mode", "Gamma mode",
"Gamma conversion mode", GST_TYPE_VIDEO_GAMMA_MODE,
DEFAULT_GAMMA_MODE, (GParamFlags) (GST_PARAM_MUTABLE_READY |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
/**
* GstD3D11VideoSink:primaries-mode:
*
* Primaries conversion mode
*
* Since: 1.22
*/
g_object_class_install_property (gobject_class, PROP_PRIMARIES_MODE,
g_param_spec_enum ("primaries-mode", "Primaries Mode",
"Primaries conversion mode", GST_TYPE_VIDEO_PRIMARIES_MODE,
DEFAULT_PRIMARIES_MODE, (GParamFlags) (GST_PARAM_MUTABLE_READY |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
/**
* GstD3D11VideoSink::begin-draw:
* @videosink: the #d3d11videosink
@ -374,6 +406,8 @@ gst_d3d11_video_sink_init (GstD3D11VideoSink * self)
self->fullscreen_toggle_mode = DEFAULT_FULLSCREEN_TOGGLE_MODE;
self->fullscreen = DEFAULT_FULLSCREEN;
self->draw_on_shared_texture = DEFAULT_DRAW_ON_SHARED_TEXTURE;
self->gamma_mode = DEFAULT_GAMMA_MODE;
self->primaries_mode = DEFAULT_PRIMARIES_MODE;
g_rec_mutex_init (&self->lock);
}
@ -423,6 +457,12 @@ gst_d3d11_videosink_set_property (GObject * object, guint prop_id,
gst_d3d11_video_sink_set_orientation (self,
(GstVideoOrientationMethod) g_value_get_enum (value), FALSE);
break;
case PROP_GAMMA_MODE:
self->gamma_mode = (GstVideoGammaMode) g_value_get_enum (value);
break;
case PROP_PRIMARIES_MODE:
self->primaries_mode = (GstVideoPrimariesMode) g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -463,6 +503,12 @@ gst_d3d11_videosink_get_property (GObject * object, guint prop_id,
case PROP_ROTATE_METHOD:
g_value_set_enum (value, self->method);
break;
case PROP_GAMMA_MODE:
g_value_set_enum (value, self->gamma_mode);
break;
case PROP_PRIMARIES_MODE:
g_value_set_enum (value, self->primaries_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -558,6 +604,7 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
gint display_par_n = 1, display_par_d = 1; /* display's PAR */
guint num, den;
GError *error = NULL;
GstStructure *config;
GST_DEBUG_OBJECT (self, "Updating window with caps %" GST_PTR_FORMAT, caps);
@ -649,8 +696,14 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
gst_d3d11_window_set_render_rectangle (self->window, &rect);
}
config = gst_structure_new ("convert-config",
GST_D3D11_CONVERTER_OPT_GAMMA_MODE,
GST_TYPE_VIDEO_GAMMA_MODE, self->gamma_mode,
GST_D3D11_CONVERTER_OPT_PRIMARIES_MODE,
GST_TYPE_VIDEO_PRIMARIES_MODE, self->primaries_mode, nullptr);
if (!gst_d3d11_window_prepare (self->window, GST_VIDEO_SINK_WIDTH (self),
GST_VIDEO_SINK_HEIGHT (self), caps, &error)) {
GST_VIDEO_SINK_HEIGHT (self), caps, config, &error)) {
GstMessage *error_msg;
GST_D3D11_VIDEO_SINK_UNLOCK (self);

View file

@ -107,7 +107,8 @@ static GstFlowReturn gst_d3d111_window_present (GstD3D11Window * self,
static void gst_d3d11_window_on_resize_default (GstD3D11Window * window,
guint width, guint height);
static gboolean gst_d3d11_window_prepare_default (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, GError ** error);
guint display_width, guint display_height, GstCaps * caps,
GstStructure * config, GError ** error);
static void
gst_d3d11_window_class_init (GstD3D11WindowClass * klass)
@ -496,7 +497,8 @@ typedef struct
gboolean
gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width,
guint display_height, GstCaps * caps, GError ** error)
guint display_height, GstCaps * caps, GstStructure * config,
GError ** error)
{
GstD3D11WindowClass *klass;
@ -508,12 +510,14 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width,
GST_DEBUG_OBJECT (window, "Prepare window, display resolution %dx%d, caps %"
GST_PTR_FORMAT, display_width, display_height, caps);
return klass->prepare (window, display_width, display_height, caps, error);
return klass->prepare (window, display_width, display_height, caps, config,
error);
}
static gboolean
gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
guint display_height, GstCaps * caps, GError ** error)
guint display_height, GstCaps * caps, GstStructure * config,
GError ** error)
{
GstD3D11Device *device = window->device;
GstD3D11WindowClass *klass;
@ -549,6 +553,9 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
(GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
if (!window->allocator) {
GST_ERROR_OBJECT (window, "Allocator is unavailable");
if (config)
gst_structure_free (config);
return FALSE;
}
}
@ -580,6 +587,9 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
GST_ERROR_OBJECT (window, "Cannot determine render format");
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
"Cannot determine render format");
if (config)
gst_structure_free (config);
return FALSE;
}
@ -644,6 +654,9 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
GST_ERROR_OBJECT (window, "Cannot create swapchain");
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
"Cannot create swapchain");
if (config)
gst_structure_free (config);
return FALSE;
}
@ -726,7 +739,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
&window->render_info);
window->converter = gst_d3d11_converter_new (device,
&window->info, &window->render_info, nullptr);
&window->info, &window->render_info, config);
if (!window->converter) {
GST_ERROR_OBJECT (window, "Cannot create converter");

View file

@ -150,6 +150,7 @@ struct _GstD3D11WindowClass
guint display_width,
guint display_height,
GstCaps * caps,
GstStructure * config,
GError ** error);
void (*unprepare) (GstD3D11Window * window);
@ -184,6 +185,7 @@ gboolean gst_d3d11_window_prepare (GstD3D11Window * window,
guint display_width,
guint display_height,
GstCaps * caps,
GstStructure * config,
GError ** error);
GstFlowReturn gst_d3d11_window_render (GstD3D11Window * window,

View file

@ -51,7 +51,8 @@ G_DEFINE_TYPE (GstD3D11WindowDummy, gst_d3d11_window_dummy,
static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
guint width, guint height);
static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, GError ** error);
guint display_width, guint display_height, GstCaps * caps,
GstStructure * config, GError ** error);
static void gst_d3d11_window_dummy_unprepare (GstD3D11Window * window);
static gboolean
gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
@ -83,15 +84,17 @@ gst_d3d11_window_dummy_init (GstD3D11WindowDummy * self)
static gboolean
gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, GError ** error)
guint display_width, guint display_height, GstCaps * caps,
GstStructure * config, GError ** error)
{
GstStructure *config;
if (!window->allocator) {
window->allocator =
(GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
if (!window->allocator) {
GST_ERROR_OBJECT (window, "Allocator is unavailable");
if (config)
gst_structure_free (config);
return FALSE;
}
}
@ -122,9 +125,15 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
window->render_info.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
if (config) {
gst_structure_set (config, GST_D3D11_CONVERTER_OPT_BACKEND,
GST_TYPE_D3D11_CONVERTER_BACKEND, GST_D3D11_CONVERTER_BACKEND_SHADER,
nullptr);
} else {
config = gst_structure_new ("converter-config",
GST_D3D11_CONVERTER_OPT_BACKEND, GST_TYPE_D3D11_CONVERTER_BACKEND,
GST_D3D11_CONVERTER_BACKEND_SHADER, nullptr);
}
GstD3D11DeviceLockGuard lk (window->device);
window->converter = gst_d3d11_converter_new (window->device, &window->info,