diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp
index e1ed41bc6b..464468abc6 100644
--- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp
+++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp
@@ -69,6 +69,10 @@ enum
 #define DEFAULT_PRIMARIES_MODE GST_VIDEO_PRIMARIES_MODE_NONE
 #define DEFAULT_SAMPLING_METHOD GST_D3D12_SAMPLING_METHOD_BILINEAR
 #define DEFAULT_ASYNC_DEPTH 0
+#define DEFAULT_HUE 0.0
+#define DEFAULT_SATURATION 1.0
+#define DEFAULT_BRIGHTNESS 0.0
+#define DEFAULT_CONTRAST 1.0
 
 /* *INDENT-OFF* */
 struct ConvertContext
@@ -104,11 +108,33 @@ struct GstD3D12BaseConvertPrivate
   GstD3D12BaseConvertPrivate ()
   {
     fence_data_pool = gst_d3d12_fence_data_pool_new ();
+    const gchar *channels[4] = { "HUE", "SATURATION",
+      "BRIGHTNESS", "CONTRAST"
+    };
+
+    color_balance_channels = nullptr;
+    for (guint i = 0; i < G_N_ELEMENTS (channels); i++) {
+      auto ch = (GstColorBalanceChannel *)
+          g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, nullptr);
+      ch->label = g_strdup (channels[i]);
+      ch->min_value = -1000;
+      ch->max_value = 1000;
+
+      color_balance_channels = g_list_append (color_balance_channels, ch);
+    }
   }
 
   ~GstD3D12BaseConvertPrivate ()
   {
     gst_clear_object (&fence_data_pool);
+
+    auto iter = color_balance_channels;
+    while (iter) {
+      g_object_unref (iter->data);
+      iter = iter->next;
+    }
+
+    g_list_free (color_balance_channels);
   }
 
   std::unique_ptr < ConvertContext > ctx;
@@ -148,6 +174,14 @@ struct GstD3D12BaseConvertPrivate
   /* method previously selected and used for negotiation */
   GstVideoOrientationMethod active_method = GST_VIDEO_ORIENTATION_IDENTITY;
 
+  GList *color_balance_channels = nullptr;
+  gdouble hue = DEFAULT_HUE;
+  gdouble saturation = DEFAULT_SATURATION;
+  gdouble brightness = DEFAULT_BRIGHTNESS;
+  gdouble contrast = DEFAULT_CONTRAST;
+  gboolean color_balance_updated = FALSE;
+  gboolean need_color_balance = FALSE;
+
   std::atomic<guint> async_depth = { DEFAULT_ASYNC_DEPTH };
 
   std::mutex lock;
@@ -1667,6 +1701,7 @@ gst_d3d12_base_convert_set_info (GstD3D12BaseFilter * filter,
     GstVideoInfo * out_info)
 {
   auto self = GST_D3D12_BASE_CONVERT (filter);
+  auto klass = GST_D3D12_BASE_CONVERT_GET_CLASS (self);
   auto priv = self->priv;
   gint from_dar_n, from_dar_d, to_dar_n, to_dar_d;
   gint border_offset_x = 0;
@@ -1778,7 +1813,11 @@ gst_d3d12_base_convert_set_info (GstD3D12BaseFilter * filter,
       GST_TYPE_VIDEO_PRIMARIES_MODE, priv->active_primaries_mode,
       GST_D3D12_CONVERTER_OPT_SAMPLER_FILTER,
       GST_TYPE_D3D12_CONVERTER_SAMPLER_FILTER,
-      gst_d3d12_sampling_method_to_native (priv->sampling_method), nullptr);
+      gst_d3d12_sampling_method_to_native (priv->sampling_method),
+      GST_D3D12_CONVERTER_OPT_COLOR_BALANCE,
+      GST_TYPE_D3D12_CONVERTER_COLOR_BALANCE, klass->enable_color_balance ?
+      GST_D3D12_CONVERTER_COLOR_BALANCE_ENABLED :
+      GST_D3D12_CONVERTER_COLOR_BALANCE_DISABLED, nullptr);
 
   auto ctx = std::make_unique < ConvertContext > (filter->device);
 
@@ -1832,6 +1871,13 @@ gst_d3d12_base_convert_set_info (GstD3D12BaseFilter * filter,
         priv->border_color, nullptr);
   }
 
+  if (klass->enable_color_balance) {
+    priv->color_balance_updated = FALSE;
+    g_object_set (ctx->conv, "hue", priv->hue,
+        "saturation", priv->saturation, "brightness", priv->brightness,
+        "contrast", priv->contrast, nullptr);
+  }
+
   priv->ctx = std::move (ctx);
 
   return TRUE;
@@ -1848,6 +1894,12 @@ gst_d3d12_base_convert_generate_output (GstBaseTransform * trans,
   if (!trans->queued_buf)
     return GST_FLOW_OK;
 
+  {
+    std::lock_guard < std::mutex > lk (priv->lock);
+    if (priv->need_color_balance)
+      passthrough = FALSE;
+  }
+
   if (passthrough && !priv->downstream_supports_crop_meta) {
     if (gst_buffer_get_video_crop_meta (trans->queued_buf)) {
       GST_LOG_OBJECT (self,
@@ -1900,6 +1952,13 @@ gst_d3d12_base_convert_before_transform (GstBaseTransform * trans,
   GstCaps *out_caps;
   GstBaseTransformClass *klass;
   gboolean update = FALSE;
+  auto pts = GST_BUFFER_PTS (buffer);
+  if (GST_CLOCK_TIME_IS_VALID (pts)) {
+    auto stream_time = gst_segment_to_stream_time (&trans->segment,
+        GST_FORMAT_TIME, pts);
+    if (GST_CLOCK_TIME_IS_VALID (stream_time))
+      gst_object_sync_values (GST_OBJECT (trans), stream_time);
+  }
 
   GST_BASE_TRANSFORM_CLASS (parent_class)->before_transform (trans, buffer);
 
@@ -1965,6 +2024,16 @@ gst_d3d12_base_convert_transform (GstBaseTransform * trans, GstBuffer * inbuf,
         "src-height", (gint) in_rect.bottom - in_rect.top, nullptr);
   }
 
+  {
+    std::lock_guard < std::mutex > lk (priv->lock);
+    if (priv->color_balance_updated) {
+      priv->color_balance_updated = FALSE;
+      g_object_set (priv->ctx->conv, "hue", priv->hue,
+          "saturation", priv->saturation, "brightness", priv->brightness,
+          "contrast", priv->contrast, nullptr);
+    }
+  }
+
   GstD3D12CmdAlloc *gst_ca;
   if (!gst_d3d12_cmd_alloc_pool_acquire (priv->ctx->ca_pool, &gst_ca)) {
     GST_ERROR_OBJECT (self, "Couldn't acquire command allocator");
@@ -2062,6 +2131,10 @@ enum
   PROP_CONVERT_VIDEO_DIRECTION,
   PROP_CONVERT_GAMMA_MODE,
   PROP_CONVERT_PRIMARIES_MODE,
+  PROP_CONVERT_HUE,
+  PROP_CONVERT_SATURATION,
+  PROP_CONVERT_BRIGHTNESS,
+  PROP_CONVERT_CONTRAST,
 };
 
 struct _GstD3D12Convert
@@ -2075,10 +2148,170 @@ gst_d3d12_convert_video_direction_interface_init (GstVideoDirectionInterface *
 {
 }
 
+static const GList *
+gst_d3d12_base_convert_color_balance_list_channels (GstColorBalance * iface)
+{
+  auto self = GST_D3D12_BASE_CONVERT (iface);
+  auto priv = self->priv;
+
+  return priv->color_balance_channels;
+}
+
+static void
+gst_d3d12_base_convert_color_balance_set_value (GstColorBalance * iface,
+    GstColorBalanceChannel * channel, gint value)
+{
+  auto self = GST_D3D12_BASE_CONVERT (iface);
+  auto priv = self->priv;
+
+  gdouble new_val;
+  gboolean changed = FALSE;
+
+  g_return_if_fail (channel->label);
+
+  {
+    std::lock_guard < std::mutex > lk (priv->lock);
+    if (!g_ascii_strcasecmp (channel->label, "HUE")) {
+      new_val = (value + 1000.0) * 2.0 / 2000.0 - 1.0;
+      changed = priv->hue != new_val;
+    } else if (!g_ascii_strcasecmp (channel->label, "SATURATION")) {
+      new_val = (value + 1000.0) * 2.0 / 2000.0;
+      changed = priv->saturation != new_val;
+    } else if (!g_ascii_strcasecmp (channel->label, "BRIGHTNESS")) {
+      new_val = (value + 1000.0) * 2.0 / 2000.0 - 1.0;
+      changed = priv->brightness != new_val;
+    } else if (!g_ascii_strcasecmp (channel->label, "CONTRAST")) {
+      new_val = (value + 1000.0) * 2.0 / 2000.0;
+      changed = priv->contrast != new_val;
+    }
+  }
+
+  if (changed) {
+    gst_color_balance_value_changed (iface, channel,
+        gst_color_balance_get_value (iface, channel));
+  }
+}
+
+static gint
+gst_d3d12_base_convert_color_balance_get_value (GstColorBalance * iface,
+    GstColorBalanceChannel * channel)
+{
+  auto self = GST_D3D12_BASE_CONVERT (iface);
+  auto priv = self->priv;
+  gint value = 0;
+
+  g_return_val_if_fail (channel->label, 0);
+
+  {
+    std::lock_guard < std::mutex > lock (priv->lock);
+    if (!g_ascii_strcasecmp (channel->label, "HUE")) {
+      auto hue = priv->hue;
+      value = static_cast < gint > ((hue + 1) * 2000.0 / 2.0 - 1000.0);
+    } else if (!g_ascii_strcasecmp (channel->label, "SATURATION")) {
+      auto saturation = priv->saturation;
+      value = static_cast < gint > (saturation * 2000.0 / 2.0 - 1000.0);
+    } else if (!g_ascii_strcasecmp (channel->label, "BRIGHTNESS")) {
+      auto brightness = priv->brightness;
+      value = static_cast < gint > ((brightness + 1) * 2000.0 / 2.0 - 1000.0);
+    } else if (!g_ascii_strcasecmp (channel->label, "CONTRAST")) {
+      auto contrast = priv->contrast;
+      value = static_cast < gint > (contrast * 2000.0 / 2.0 - 1000.0);
+    }
+  }
+
+  return value;
+}
+
+static GstColorBalanceType
+gst_d3d12_base_convert_color_balance_get_balance_type (GstColorBalance * iface)
+{
+  return GST_COLOR_BALANCE_HARDWARE;
+}
+
+static void
+gst_d3d12_base_convert_color_balance_init (GstColorBalanceInterface * iface)
+{
+  iface->list_channels = gst_d3d12_base_convert_color_balance_list_channels;
+  iface->set_value = gst_d3d12_base_convert_color_balance_set_value;
+  iface->get_value = gst_d3d12_base_convert_color_balance_get_value;
+  iface->get_balance_type =
+      gst_d3d12_base_convert_color_balance_get_balance_type;
+}
+
+static void
+gst_d3d12_base_convert_update_color_balance (GstD3D12BaseConvert * self,
+    const gchar * name, gdouble * prev, gdouble value)
+{
+  auto priv = self->priv;
+  gboolean updated = FALSE;
+
+  {
+    std::lock_guard < std::mutex > lk (priv->lock);
+    if (*prev != value) {
+      *prev = value;
+      priv->color_balance_updated = TRUE;
+      priv->need_color_balance =
+          gst_d3d12_converter_is_color_balance_needed (priv->hue,
+          priv->saturation, priv->brightness, priv->contrast);
+      updated = TRUE;
+    }
+  }
+
+  if (updated) {
+    GList *iter = priv->color_balance_channels;
+    while (iter) {
+      auto ch = (GstColorBalanceChannel *) iter->data;
+      if (g_ascii_strcasecmp (ch->label, name) == 0) {
+        auto iface = GST_COLOR_BALANCE (self);
+        gst_color_balance_value_changed (iface, ch,
+            gst_color_balance_get_value (iface, ch));
+        break;
+      }
+
+      iter = g_list_next (iter);
+    }
+  }
+}
+
+static void
+gst_d3d12_base_convert_set_hue (GstD3D12BaseConvert * self, gdouble value)
+{
+  auto priv = self->priv;
+  gst_d3d12_base_convert_update_color_balance (self, "HUE", &priv->hue, value);
+}
+
+static void
+gst_d3d12_base_convert_set_saturation (GstD3D12BaseConvert * self,
+    gdouble value)
+{
+  auto priv = self->priv;
+  gst_d3d12_base_convert_update_color_balance (self,
+      "SATURATION", &priv->saturation, value);
+}
+
+static void
+gst_d3d12_base_convert_set_brightness (GstD3D12BaseConvert * self,
+    gdouble value)
+{
+  auto priv = self->priv;
+  gst_d3d12_base_convert_update_color_balance (self,
+      "BRIGHTNESS", &priv->brightness, value);
+}
+
+static void
+gst_d3d12_base_convert_set_contrast (GstD3D12BaseConvert * self, gdouble value)
+{
+  auto priv = self->priv;
+  gst_d3d12_base_convert_update_color_balance (self,
+      "CONTRAST", &priv->contrast, value);
+}
+
 G_DEFINE_TYPE_WITH_CODE (GstD3D12Convert, gst_d3d12_convert,
     GST_TYPE_D3D12_BASE_CONVERT,
     G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_DIRECTION,
-        gst_d3d12_convert_video_direction_interface_init));
+        gst_d3d12_convert_video_direction_interface_init);
+    G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
+        gst_d3d12_base_convert_color_balance_init));
 
 static void gst_d3d12_convert_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -2093,6 +2326,7 @@ gst_d3d12_convert_class_init (GstD3D12ConvertClass * klass)
   auto object_class = G_OBJECT_CLASS (klass);
   auto element_class = GST_ELEMENT_CLASS (klass);
   auto trans_class = GST_BASE_TRANSFORM_CLASS (klass);
+  auto conv_class = GST_D3D12_BASE_CONVERT_CLASS (klass);
 
   object_class->set_property = gst_d3d12_convert_set_property;
   object_class->get_property = gst_d3d12_convert_get_property;
@@ -2124,6 +2358,49 @@ gst_d3d12_convert_class_init (GstD3D12ConvertClass * klass)
           DEFAULT_PRIMARIES_MODE, (GParamFlags) (GST_PARAM_MUTABLE_PLAYING |
               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
 
+  /**
+   * GstD3D12Convert:hue:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_CONVERT_HUE,
+      g_param_spec_double ("hue", "Hue", "hue", -1.0, 1.0, DEFAULT_HUE,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  /**
+   * GstD3D12Convert:saturation:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_CONVERT_SATURATION,
+      g_param_spec_double ("saturation", "Saturation", "saturation", 0.0, 2.0,
+          DEFAULT_SATURATION,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  /**
+   * GstD3D12Convert:brightness:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_CONVERT_BRIGHTNESS,
+      g_param_spec_double ("brightness", "Brightness", "brightness", -1.0, 1.0,
+          DEFAULT_BRIGHTNESS,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  /**
+   * GstD3D12Convert:contrast:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_CONVERT_CONTRAST,
+      g_param_spec_double ("contrast", "Contrast", "contrast", 0.0, 2.0,
+          DEFAULT_CONTRAST,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
   gst_element_class_set_static_metadata (element_class,
       "Direct3D12 Converter",
       "Filter/Converter/Scaler/Effect/Video/Hardware",
@@ -2132,6 +2409,8 @@ gst_d3d12_convert_class_init (GstD3D12ConvertClass * klass)
       "Seungha Yang <seungha@centricular.com>");
 
   trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_d3d12_convert_sink_event);
+
+  conv_class->enable_color_balance = TRUE;
 }
 
 static void
@@ -2165,6 +2444,18 @@ gst_d3d12_convert_set_property (GObject * object, guint prop_id,
       gst_d3d12_base_convert_set_primaries_mode (self,
           (GstVideoPrimariesMode) g_value_get_enum (value));
       break;
+    case PROP_CONVERT_HUE:
+      gst_d3d12_base_convert_set_hue (self, g_value_get_double (value));
+      break;
+    case PROP_CONVERT_SATURATION:
+      gst_d3d12_base_convert_set_saturation (self, g_value_get_double (value));
+      break;
+    case PROP_CONVERT_BRIGHTNESS:
+      gst_d3d12_base_convert_set_brightness (self, g_value_get_double (value));
+      break;
+    case PROP_CONVERT_CONTRAST:
+      gst_d3d12_base_convert_set_contrast (self, g_value_get_double (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2195,6 +2486,18 @@ gst_d3d12_convert_get_property (GObject * object, guint prop_id,
     case PROP_CONVERT_PRIMARIES_MODE:
       g_value_set_enum (value, priv->primaries_mode);
       break;
+    case PROP_CONVERT_HUE:
+      g_value_set_double (value, priv->hue);
+      break;
+    case PROP_CONVERT_SATURATION:
+      g_value_set_double (value, priv->saturation);
+      break;
+    case PROP_CONVERT_BRIGHTNESS:
+      g_value_set_double (value, priv->brightness);
+      break;
+    case PROP_CONVERT_CONTRAST:
+      g_value_set_double (value, priv->contrast);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2229,8 +2532,10 @@ enum
 {
   PROP_COLOR_CONVERT_GAMMA_MODE = 1,
   PROP_COLOR_CONVERT_PRIMARIES_MODE,
-  PROP_COLOR_CONVERT_SRC_ALPHA_MODE,
-  PROP_COLOR_CONVERT_DEST_ALPHA_MODE,
+  PROP_COLOR_CONVERT_HUE,
+  PROP_COLOR_CONVERT_SATURATION,
+  PROP_COLOR_CONVERT_BRIGHTNESS,
+  PROP_COLOR_CONVERT_CONTRAST,
 };
 
 struct _GstD3D12ColorConvert
@@ -2247,8 +2552,10 @@ static GstCaps *gst_d3d12_color_convert_transform_caps (GstBaseTransform *
 static GstCaps *gst_d3d12_color_convert_fixate_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
 
-G_DEFINE_TYPE (GstD3D12ColorConvert, gst_d3d12_color_convert,
-    GST_TYPE_D3D12_BASE_CONVERT);
+G_DEFINE_TYPE_WITH_CODE (GstD3D12ColorConvert, gst_d3d12_color_convert,
+    GST_TYPE_D3D12_BASE_CONVERT,
+    G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
+        gst_d3d12_base_convert_color_balance_init));
 
 static void
 gst_d3d12_color_convert_class_init (GstD3D12ColorConvertClass * klass)
@@ -2256,6 +2563,7 @@ gst_d3d12_color_convert_class_init (GstD3D12ColorConvertClass * klass)
   auto object_class = G_OBJECT_CLASS (klass);
   auto element_class = GST_ELEMENT_CLASS (klass);
   auto trans_class = GST_BASE_TRANSFORM_CLASS (klass);
+  auto conv_class = GST_D3D12_BASE_CONVERT_CLASS (klass);
 
   object_class->set_property = gst_d3d12_color_convert_set_property;
   object_class->get_property = gst_d3d12_color_convert_get_property;
@@ -2273,6 +2581,49 @@ gst_d3d12_color_convert_class_init (GstD3D12ColorConvertClass * klass)
           DEFAULT_PRIMARIES_MODE, (GParamFlags) (GST_PARAM_MUTABLE_PLAYING |
               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
 
+  /**
+   * GstD3D12ColorConvert:hue:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_COLOR_CONVERT_HUE,
+      g_param_spec_double ("hue", "Hue", "hue", -1.0, 1.0, DEFAULT_HUE,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  /**
+   * GstD3D12ColorConvert:saturation:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_COLOR_CONVERT_SATURATION,
+      g_param_spec_double ("saturation", "Saturation", "saturation", 0.0, 2.0,
+          DEFAULT_SATURATION,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  /**
+   * GstD3D12ColorConvert:brightness:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_COLOR_CONVERT_BRIGHTNESS,
+      g_param_spec_double ("brightness", "Brightness", "brightness", -1.0, 1.0,
+          DEFAULT_BRIGHTNESS,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+  /**
+   * GstD3D12ColorConvert:contrast:
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (object_class, PROP_COLOR_CONVERT_CONTRAST,
+      g_param_spec_double ("contrast", "Contrast", "contrast", 0.0, 2.0,
+          DEFAULT_CONTRAST,
+          (GParamFlags) (GST_PARAM_CONTROLLABLE |
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
   gst_element_class_set_static_metadata (element_class,
       "Direct3D12 Colorspace Converter",
       "Filter/Converter/Video/Hardware",
@@ -2283,6 +2634,8 @@ gst_d3d12_color_convert_class_init (GstD3D12ColorConvertClass * klass)
       GST_DEBUG_FUNCPTR (gst_d3d12_color_convert_transform_caps);
   trans_class->fixate_caps =
       GST_DEBUG_FUNCPTR (gst_d3d12_color_convert_fixate_caps);
+
+  conv_class->enable_color_balance = TRUE;
 }
 
 static void
@@ -2294,17 +2647,29 @@ static void
 gst_d3d12_color_convert_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  auto base = GST_D3D12_BASE_CONVERT (object);
+  auto self = GST_D3D12_BASE_CONVERT (object);
 
   switch (prop_id) {
     case PROP_COLOR_CONVERT_GAMMA_MODE:
-      gst_d3d12_base_convert_set_gamma_mode (base,
+      gst_d3d12_base_convert_set_gamma_mode (self,
           (GstVideoGammaMode) g_value_get_enum (value));
       break;
     case PROP_COLOR_CONVERT_PRIMARIES_MODE:
-      gst_d3d12_base_convert_set_primaries_mode (base,
+      gst_d3d12_base_convert_set_primaries_mode (self,
           (GstVideoPrimariesMode) g_value_get_enum (value));
       break;
+    case PROP_COLOR_CONVERT_HUE:
+      gst_d3d12_base_convert_set_hue (self, g_value_get_double (value));
+      break;
+    case PROP_COLOR_CONVERT_SATURATION:
+      gst_d3d12_base_convert_set_saturation (self, g_value_get_double (value));
+      break;
+    case PROP_COLOR_CONVERT_BRIGHTNESS:
+      gst_d3d12_base_convert_set_brightness (self, g_value_get_double (value));
+      break;
+    case PROP_COLOR_CONVERT_CONTRAST:
+      gst_d3d12_base_convert_set_contrast (self, g_value_get_double (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2326,6 +2691,18 @@ gst_d3d12_color_convert_get_property (GObject * object, guint prop_id,
     case PROP_COLOR_CONVERT_PRIMARIES_MODE:
       g_value_set_enum (value, priv->primaries_mode);
       break;
+    case PROP_COLOR_CONVERT_HUE:
+      g_value_set_double (value, priv->hue);
+      break;
+    case PROP_COLOR_CONVERT_SATURATION:
+      g_value_set_double (value, priv->saturation);
+      break;
+    case PROP_COLOR_CONVERT_BRIGHTNESS:
+      g_value_set_double (value, priv->brightness);
+      break;
+    case PROP_COLOR_CONVERT_CONTRAST:
+      g_value_set_double (value, priv->contrast);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.h
index 7d40cc8f49..dcb1bbdd99 100644
--- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.h
+++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.h
@@ -37,6 +37,7 @@ typedef struct _GstD3D12BaseConvertClass GstD3D12BaseConvertClass;
 struct _GstD3D12BaseConvertClass
 {
   GstD3D12BaseFilterClass parent_class;
+  gboolean enable_color_balance;
 };
 
 GType gst_d3d12_base_convert_get_type (void);