d3d11videosink: Add gamma-mode and primaries-mode properties
authorSeungha Yang <seungha@centricular.com>
Tue, 2 Aug 2022 16:47:46 +0000 (01:47 +0900)
committerSeungha Yang <seungha@centricular.com>
Wed, 3 Aug 2022 17:48:57 +0000 (02:48 +0900)
Allows controlling gamma remap and/or chromatic adaptation behavior.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2831>

subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp

index 76389d9..0a0f47e 100644 (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;
@@ -291,6 +297,32 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass)
           (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);
index bdb7801..1222669 100644 (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");
index 3a4bfdc..bc5181f 100644 (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,
index c92ccd0..32a5e69 100644 (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;
 
-  config = gst_structure_new ("converter-config",
-      GST_D3D11_CONVERTER_OPT_BACKEND, GST_TYPE_D3D11_CONVERTER_BACKEND,
-      GST_D3D11_CONVERTER_BACKEND_SHADER, nullptr);
+  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,