d3d11: Move GstD3D11Converter to gst-libs
authorSeungha Yang <seungha@centricular.com>
Wed, 20 Jul 2022 20:13:21 +0000 (05:13 +0900)
committerSeungha Yang <seungha@centricular.com>
Thu, 21 Jul 2022 15:08:51 +0000 (00:08 +0900)
The object is equivalent to GstVideoConverter but for D3D11.
Application can use this object directly for various conversions,
such as color space conversion, rescale, crop and flip/rotation.

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

15 files changed:
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11.h
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11_fwd.h
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11_private.h
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converter.cpp [moved from subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.cpp with 98% similarity]
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11converter.h [moved from subprojects/gst-plugins-bad/sys/d3d11/gstd3d11converter.h with 83% similarity]
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11format.cpp
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/meson.build
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11compositor.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11convert.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11decoder.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.h
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11testsrc.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.h
subprojects/gst-plugins-bad/sys/d3d11/meson.build

index fe85170..55bd124 100644 (file)
@@ -29,6 +29,7 @@
 #include <gst/d3d11/gstd3d11_fwd.h>
 #include <gst/d3d11/gstd3d11bufferpool.h>
 #include <gst/d3d11/gstd3d11compile.h>
+#include <gst/d3d11/gstd3d11converter.h>
 #include <gst/d3d11/gstd3d11device.h>
 #include <gst/d3d11/gstd3d11format.h>
 #include <gst/d3d11/gstd3d11memory.h>
index 259b1b3..e4601ae 100644 (file)
@@ -59,5 +59,9 @@ typedef struct _GstD3D11StagingBufferPoolPrivate GstD3D11StagingBufferPoolPrivat
 
 typedef struct _GstD3D11Format GstD3D11Format;
 
+typedef struct _GstD3D11Converter GstD3D11Converter;
+typedef struct _GstD3D11ConverterClass GstD3D11ConverterClass;
+typedef struct _GstD3D11ConverterPrivate GstD3D11ConverterPrivate;
+
 G_END_DECLS
 
index c6ab986..8b34760 100644 (file)
@@ -111,6 +111,37 @@ static const GstD3D11Format _gst_d3d11_default_format_map[] = {
 
 #define GST_D3D11_N_FORMATS G_N_ELEMENTS(_gst_d3d11_default_format_map)
 
+typedef struct _GstD3D11ColorMatrix
+{
+  gdouble matrix[3][3];
+  gdouble offset[3];
+  gdouble min[3];
+  gdouble max[3];
+} GstD3D11ColorMatrix;
+
+GST_D3D11_API
+gchar *         gst_d3d11_dump_color_matrix (GstD3D11ColorMatrix * matrix);
+
+GST_D3D11_API
+gboolean        gst_d3d11_color_range_adjust_matrix_unorm (const GstVideoInfo * in_info,
+                                                           const GstVideoInfo * out_info,
+                                                           GstD3D11ColorMatrix * matrix);
+
+GST_D3D11_API
+gboolean        gst_d3d11_yuv_to_rgb_matrix_unorm (const GstVideoInfo * in_yuv_info,
+                                                   const GstVideoInfo * out_rgb_info,
+                                                   GstD3D11ColorMatrix * matrix);
+
+GST_D3D11_API
+gboolean        gst_d3d11_rgb_to_yuv_matrix_unorm (const GstVideoInfo * in_rgb_info,
+                                                   const GstVideoInfo * out_yuv_info,
+                                                   GstD3D11ColorMatrix * matrix);
+
+GST_D3D11_API
+gboolean        gst_d3d11_color_primaries_matrix_unorm (const GstVideoColorPrimariesInfo * in_info,
+                                                        const GstVideoColorPrimariesInfo * out_info,
+                                                        GstD3D11ColorMatrix * matrix);
+
 G_END_DECLS
 
 #ifdef __cplusplus
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) <2019> Seungha Yang <seungha.yang@navercorp.com>
  * Copyright (C) <2019> Jeongki Kim <jeongki.kim@jeongki.kim>
+ * Copyright (C) <2022> Seungha Yang <seungha@centricular.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #  include <config.h>
 #endif
 
+#include "gstd3d11_private.h"
 #include "gstd3d11converter.h"
-#include "gstd3d11pluginutils.h"
+#include "gstd3d11device.h"
+#include "gstd3d11utils.h"
+#include "gstd3d11memory.h"
+#include "gstd3d11compile.h"
+#include "gstd3d11bufferpool.h"
 #include <wrl.h>
 #include <string.h>
 #include <math.h>
@@ -2860,6 +2866,23 @@ gst_d3d11_converter_setup_processor (GstD3D11Converter * self)
   return TRUE;
 }
 
+/**
+ * gst_d3d11_converter_new:
+ * @device: a #GstD3D11Device
+ * @in_info: a #GstVideoInfo
+ * @out_info: a #GstVideoInfo
+ * @method: (inout) (optional) (nullable): a #GstD3D11ConverterMethod
+
+ * Create a new converter object to convert between @in_info and @out_info
+ * with @method. When @method is not specified, converter will configure
+ * conversion path for all available method. Otherwise, converter will configure
+ * conversion path only for specified method(s) and set @method will be updated
+ * with supported method.
+ *
+ * Returns: a #GstD3D11Converter or %NULL if conversion is not possible
+ *
+ * Since: 1.22
+ */
 GstD3D11Converter *
 gst_d3d11_converter_new (GstD3D11Device * device, const GstVideoInfo * in_info,
     const GstVideoInfo * out_info, GstStructure * config)
@@ -3815,6 +3838,18 @@ out:
   return ret;
 }
 
+/**
+ * gst_d3d11_converter_convert_buffer:
+ * @converter: a #GstD3D11Converter
+ * @in_buf: a #GstBuffer
+ * @out_buf: a #GstBuffer
+ *
+ * Converts @in_buf into @out_buf
+ *
+ * Returns: %TRUE if conversion is successful
+ *
+ * Since: 1.22
+ */
 gboolean
 gst_d3d11_converter_convert_buffer (GstD3D11Converter * converter,
     GstBuffer * in_buf, GstBuffer * out_buf)
@@ -3829,6 +3864,21 @@ gst_d3d11_converter_convert_buffer (GstD3D11Converter * converter,
       in_buf, out_buf);
 }
 
+/**
+ * gst_d3d11_converter_convert_buffer_unlocked:
+ * @converter: a #GstD3D11Converter
+ * @in_buf: a #GstBuffer
+ * @out_buf: a #GstBuffer
+ *
+ * Converts @in_buf into @out_buf. Caller should take d3d11 device lock
+ * in case that multiple threads can perform GPU processing using the
+ * same #GstD3D11Device
+ *
+ * Returns: %TRUE if conversion is successful
+ *
+ * Since: 1.22
+ */
+
 gboolean
 gst_d3d11_converter_convert_buffer_unlocked (GstD3D11Converter * converter,
     GstBuffer * in_buf, GstBuffer * out_buf)
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) <2019> Seungha Yang <seungha.yang@navercorp.com>
+ * Copyright (C) <2022> Seungha Yang <seungha@centricular.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef __GST_D3D11_COLOR_CONVERTER_H__
-#define __GST_D3D11_COLOR_CONVERTER_H__
+#pragma once
 
 #include <gst/gst.h>
 #include <gst/video/video.h>
-#include <gst/d3d11/gstd3d11.h>
+#include <gst/d3d11/gstd3d11_fwd.h>
 
 G_BEGIN_DECLS
 
@@ -34,17 +34,31 @@ G_BEGIN_DECLS
 #define GST_IS_D3D11_CONVERTER_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_CONVERTER))
 #define GST_D3D11_CONVERTER_CAST(obj)        ((GstD3D11Converter*)(obj))
 
-typedef struct _GstD3D11Converter GstD3D11Converter;
-typedef struct _GstD3D11ConverterClass GstD3D11ConverterClass;
-typedef struct _GstD3D11ConverterPrivate GstD3D11ConverterPrivate;
-
+/**
+ * GstD3D11ConverterMethod:
+ * @GST_D3D11_CONVERTER_METHOD_SHADER: Performs conversion using pixel shader
+ * @GST_D3D11_CONVERTER_METHOD_VIDEO_PROCESSOR: Performs conversion using video processor
+ *
+ * Since: 1.22
+ */
 typedef enum
 {
   GST_D3D11_CONVERTER_BACKEND_SHADER = (1 << 0),
   GST_D3D11_CONVERTER_BACKEND_VIDEO_PROCESSOR = (1 << 1),
 } GstD3D11ConverterBackend;
+
+GST_D3D11_API
+GType gst_d3d11_converter_backend_get_type (void);
 #define GST_TYPE_D3D11_CONVERTER_BACKEND (gst_d3d11_converter_backend_get_type())
 
+/**
+ * GST_D3D11_CONVERTER_OPT_BACKEND:
+ *
+ * #GstD3D11ConverterBackend, the conversion backend
+ * (e.g., pixel shader and/or video processor) to use
+ *
+ * Since: 1.22
+ */
 #define GST_D3D11_CONVERTER_OPT_BACKEND "GstD3D11Converter.backend"
 
 struct _GstD3D11Converter
@@ -66,23 +80,23 @@ struct _GstD3D11ConverterClass
   gpointer _gst_reserved[GST_PADDING];
 };
 
-GType               gst_d3d11_converter_backend_get_type (void);
-
+GST_D3D11_API
 GType               gst_d3d11_converter_get_type (void);
 
+GST_D3D11_API
 GstD3D11Converter * gst_d3d11_converter_new  (GstD3D11Device * device,
                                               const GstVideoInfo * in_info,
                                               const GstVideoInfo * out_info,
                                               GstStructure * config);
 
+GST_D3D11_API
 gboolean            gst_d3d11_converter_convert_buffer (GstD3D11Converter * converter,
                                                         GstBuffer * in_buf,
                                                         GstBuffer * out_buf);
 
+GST_D3D11_API
 gboolean            gst_d3d11_converter_convert_buffer_unlocked (GstD3D11Converter * converter,
                                                                  GstBuffer * in_buf,
                                                                  GstBuffer * out_buf);
 
 G_END_DECLS
-
-#endif /* __GST_D3D11_COLOR_CONVERTER_H__ */
index 242b620..ae8b3c5 100644 (file)
@@ -913,3 +913,758 @@ gst_video_info_apply_dxgi_color_space (DXGI_COLOR_SPACE_TYPE color_space,
 
   return TRUE;
 }
+
+gchar *
+gst_d3d11_dump_color_matrix (GstD3D11ColorMatrix * matrix)
+{
+  /* *INDENT-OFF* */
+  static const gchar format[] =
+      "[MATRIX]\n"
+      "|% .6f, % .6f, % .6f|\n"
+      "|% .6f, % .6f, % .6f|\n"
+      "|% .6f, % .6f, % .6f|\n"
+      "[OFFSET]\n"
+      "|% .6f, % .6f, % .6f|\n"
+      "[MIN]\n"
+      "|% .6f, % .6f, % .6f|\n"
+      "[MAX]\n"
+      "|% .6f, % .6f, % .6f|";
+  /* *INDENT-ON* */
+
+  g_return_val_if_fail (matrix != nullptr, nullptr);
+
+  return g_strdup_printf (format,
+      matrix->matrix[0][0], matrix->matrix[0][1], matrix->matrix[0][2],
+      matrix->matrix[1][0], matrix->matrix[1][1], matrix->matrix[1][2],
+      matrix->matrix[2][0], matrix->matrix[2][1], matrix->matrix[2][2],
+      matrix->offset[0], matrix->offset[1], matrix->offset[2],
+      matrix->min[0], matrix->min[1], matrix->min[2],
+      matrix->max[0], matrix->max[1], matrix->max[2]);
+}
+
+static void
+color_matrix_copy (GstD3D11ColorMatrix * dst, const GstD3D11ColorMatrix * src)
+{
+  for (guint i = 0; i < 3; i++) {
+    for (guint j = 0; j < 3; j++) {
+      dst->matrix[i][j] = src->matrix[i][j];
+    }
+  }
+}
+
+static void
+color_matrix_multiply (GstD3D11ColorMatrix * dst, GstD3D11ColorMatrix * a,
+    GstD3D11ColorMatrix * b)
+{
+  GstD3D11ColorMatrix tmp;
+
+  for (guint i = 0; i < 3; i++) {
+    for (guint j = 0; j < 3; j++) {
+      gdouble val = 0;
+      for (guint k = 0; k < 3; k++) {
+        val += a->matrix[i][k] * b->matrix[k][j];
+      }
+
+      tmp.matrix[i][j] = val;
+    }
+  }
+
+  color_matrix_copy (dst, &tmp);
+}
+
+static void
+color_matrix_identity (GstD3D11ColorMatrix * m)
+{
+  for (guint i = 0; i < 3; i++) {
+    for (guint j = 0; j < 3; j++) {
+      if (i == j)
+        m->matrix[i][j] = 1.0;
+      else
+        m->matrix[i][j] = 0;
+    }
+  }
+}
+
+static gboolean
+color_matrix_invert (GstD3D11ColorMatrix * dst, GstD3D11ColorMatrix * src)
+{
+  GstD3D11ColorMatrix tmp;
+  gdouble det;
+
+  color_matrix_identity (&tmp);
+  for (guint j = 0; j < 3; j++) {
+    for (guint i = 0; i < 3; i++) {
+      tmp.matrix[j][i] =
+          src->matrix[(i + 1) % 3][(j + 1) % 3] *
+          src->matrix[(i + 2) % 3][(j + 2) % 3] -
+          src->matrix[(i + 1) % 3][(j + 2) % 3] *
+          src->matrix[(i + 2) % 3][(j + 1) % 3];
+    }
+  }
+
+  det = tmp.matrix[0][0] * src->matrix[0][0] +
+      tmp.matrix[0][1] * src->matrix[1][0] +
+      tmp.matrix[0][2] * src->matrix[2][0];
+  if (det == 0)
+    return FALSE;
+
+  for (guint j = 0; j < 3; j++) {
+    for (guint i = 0; i < 3; i++) {
+      tmp.matrix[i][j] /= det;
+    }
+  }
+
+  color_matrix_copy (dst, &tmp);
+
+  return TRUE;
+}
+
+/**
+ * gst_d3d11_color_range_adjust_matrix_unorm:
+ * @in_info: a #GstVideoInfo
+ * @out_info: a #GstVideoInfo
+ * @matrix: a #GstD3D11ColorMatrix
+ *
+ * Calculates matrix for color range adjustment. Both input and output
+ * signals are in normalized [0.0..1.0] space.
+ *
+ * Resulting values can be calculated by
+ * | Yout |                           | Yin |   | matrix.offset[0] |
+ * | Uout | = clamp ( matrix.matrix * | Uin | + | matrix.offset[1] |, matrix.min, matrix.max )
+ * | Vout |                           | Vin |   | matrix.offset[2] |
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+gst_d3d11_color_range_adjust_matrix_unorm (const GstVideoInfo * in_info,
+    const GstVideoInfo * out_info, GstD3D11ColorMatrix * matrix)
+{
+  gboolean in_rgb, out_rgb;
+  gint in_offset[GST_VIDEO_MAX_COMPONENTS];
+  gint in_scale[GST_VIDEO_MAX_COMPONENTS];
+  gint out_offset[GST_VIDEO_MAX_COMPONENTS];
+  gint out_scale[GST_VIDEO_MAX_COMPONENTS];
+  GstVideoColorRange in_range;
+  GstVideoColorRange out_range;
+  gdouble src_fullscale, dst_fullscale;
+
+  g_return_val_if_fail (in_info != nullptr, FALSE);
+  g_return_val_if_fail (out_info != nullptr, FALSE);
+  g_return_val_if_fail (matrix != nullptr, FALSE);
+
+  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
+  for (guint i = 0; i < 3; i++) {
+    matrix->matrix[i][i] = 1.0;
+    matrix->matrix[i][i] = 1.0;
+    matrix->matrix[i][i] = 1.0;
+    matrix->max[i] = 1.0;
+  }
+
+  in_rgb = GST_VIDEO_INFO_IS_RGB (in_info);
+  out_rgb = GST_VIDEO_INFO_IS_RGB (out_info);
+
+  if (in_rgb != out_rgb) {
+    GST_WARNING ("Invalid format conversion");
+    return FALSE;
+  }
+
+  in_range = in_info->colorimetry.range;
+  out_range = out_info->colorimetry.range;
+
+  if (in_range == GST_VIDEO_COLOR_RANGE_UNKNOWN) {
+    GST_WARNING ("Unknown input color range");
+    if (in_rgb || GST_VIDEO_INFO_IS_GRAY (in_info))
+      in_range = GST_VIDEO_COLOR_RANGE_0_255;
+    else
+      in_range = GST_VIDEO_COLOR_RANGE_16_235;
+  }
+
+  if (out_range == GST_VIDEO_COLOR_RANGE_UNKNOWN) {
+    GST_WARNING ("Unknown output color range");
+    if (out_rgb || GST_VIDEO_INFO_IS_GRAY (out_info))
+      out_range = GST_VIDEO_COLOR_RANGE_0_255;
+    else
+      out_range = GST_VIDEO_COLOR_RANGE_16_235;
+  }
+
+  src_fullscale = (gdouble) ((1 << in_info->finfo->depth[0]) - 1);
+  dst_fullscale = (gdouble) ((1 << out_info->finfo->depth[0]) - 1);
+
+  gst_video_color_range_offsets (in_range, in_info->finfo, in_offset, in_scale);
+  gst_video_color_range_offsets (out_range,
+      out_info->finfo, out_offset, out_scale);
+
+  matrix->min[0] = matrix->min[1] = matrix->min[2] =
+      (gdouble) out_offset[0] / dst_fullscale;
+
+  matrix->max[0] = (out_scale[0] + out_offset[0]) / dst_fullscale;
+  matrix->max[1] = matrix->max[2] =
+      (out_scale[1] + out_offset[0]) / dst_fullscale;
+
+  if (in_info->colorimetry.range == out_info->colorimetry.range) {
+    GST_DEBUG ("Same color range");
+    return TRUE;
+  }
+
+  /* Formula
+   *
+   * 1) Scales and offset compensates input to [0..1] range
+   * SRC_NORM[i] = (src[i] * src_fullscale - in_offset[i]) / in_scale[i]
+   *             = (src[i] * src_fullscale / in_scale[i]) - in_offset[i] / in_scale[i]
+   *
+   * 2) Reverse to output UNIT scale
+   * DST_UINT[i] = SRC_NORM[i] * out_scale[i] + out_offset[i]
+   *             = src[i] * src_fullscale * out_scale[i] / in_scale[i]
+   *               - in_offset[i] * out_scale[i] / in_scale[i]
+   *               + out_offset[i]
+   *
+   * 3) Back to [0..1] scale
+   * dst[i] = DST_UINT[i] / dst_fullscale
+   *        = COEFF[i] * src[i] + OFF[i]
+   * where
+   *             src_fullscale * out_scale[i]
+   * COEFF[i] = ------------------------------
+   *             dst_fullscale * in_scale[i]
+   *
+   *            out_offset[i]     in_offset[i] * out_scale[i]
+   * OFF[i] =  -------------- -  ------------------------------
+   *            dst_fullscale     dst_fullscale * in_scale[i]
+   */
+  for (guint i = 0; i < 3; i++) {
+    matrix->matrix[i][i] = (src_fullscale * out_scale[i]) /
+        (dst_fullscale * in_scale[i]);
+    matrix->offset[i] = (out_offset[i] / dst_fullscale) -
+        ((gdouble) in_offset[i] * out_scale[i] / (dst_fullscale * in_scale[i]));
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_d3d11_yuv_to_rgb_matrix_unorm:
+ * @in_yuv_info: a #GstVideoInfo of input YUV signal
+ * @out_rgb_info: a #GstVideoInfo of output RGB signal
+ * @matrix: a #GstD3D11ColorMatrix
+ *
+ * Calculates transform matrix from YUV to RGB conversion. Both input and output
+ * signals are in normalized [0.0..1.0] space and additional gamma decoding
+ * or primary/transfer function transform is not performed by this matrix.
+ *
+ * Resulting non-linear RGB values can be calculated by
+ * | R' |                           | Y' |   | matrix.offset[0] |
+ * | G' | = clamp ( matrix.matrix * | Cb | + | matrix.offset[1] | matrix.min, matrix.max )
+ * | B' |                           | Cr |   | matrix.offset[2] |
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+gst_d3d11_yuv_to_rgb_matrix_unorm (const GstVideoInfo * in_yuv_info,
+    const GstVideoInfo * out_rgb_info, GstD3D11ColorMatrix * matrix)
+{
+  gint offset[4], scale[4];
+  gdouble Kr, Kb, Kg;
+
+  g_return_val_if_fail (in_yuv_info != nullptr, FALSE);
+  g_return_val_if_fail (out_rgb_info != nullptr, FALSE);
+  g_return_val_if_fail (matrix != nullptr, FALSE);
+
+  /*
+   * <Formula>
+   *
+   * Input: Unsigned normalized Y'CbCr(unorm), [0.0..1.0] range
+   * Output: Unsigned normalized non-linear R'G'B'(unorm), [0.0..1.0] range
+   *
+   * 1) Y'CbCr(unorm) to scaled Y'CbCr
+   * | Y' |     | Y'(unorm) |
+   * | Cb | = S | Cb(unorm) |
+   * | Cb |     | Cr(unorm) |
+   * where S = (2 ^ bitdepth) - 1
+   *
+   * 2) Y'CbCr to YPbPr
+   * Y  = (Y' - offsetY )    / scaleY
+   * Pb = [(Cb - offsetCbCr) / scaleCbCr]
+   * Pr = [(Cr - offsetCrCr) / scaleCrCr]
+   * =>
+   * Y  = Y'(unorm) * Sy  + Oy
+   * Pb = Cb(unorm) * Suv + Ouv
+   * Pb = Cr(unorm) * Suv + Ouv
+   * where
+   * Sy  = S / scaleY
+   * Suv = S / scaleCbCr
+   * Oy  = -(offsetY / scaleY)
+   * Ouv = -(offsetCbCr / scaleCbCr)
+   *
+   * 3) YPbPr to R'G'B'
+   * | R' |      | Y  |
+   * | G' | = M *| Pb |
+   * | B' |      | Pr |
+   * where
+   *     | vecR |
+   * M = | vecG |
+   *     | vecB |
+   * vecR = | 1,         0           ,       2(1 - Kr)      |
+   * vecG = | 1, -(Kb/Kg) * 2(1 - Kb), -(Kr/Kg) * 2(1 - Kr) |
+   * vecB = | 1,       2(1 - Kb)     ,          0           |
+   * =>
+   * R' = dot(vecR, (Syuv * Y'CbCr(unorm))) + dot(vecR, Offset)
+   * G' = dot(vecG, (Svuy * Y'CbCr(unorm))) + dot(vecG, Offset)
+   * B' = dot(vecB, (Syuv * Y'CbCr(unorm)) + dot(vecB, Offset)
+   * where
+   *        | Sy,   0,   0 |
+   * Syuv = |  0, Suv,   0 |
+   *        |  0    0, Suv |
+   *
+   *          | Oy  |
+   * Offset = | Ouv |
+   *          | Ouv |
+   *
+   * 4) YUV -> RGB matrix
+   * | R' |            | Y'(unorm) |   | offsetA |
+   * | G' | = Matrix * | Cb(unorm) | + | offsetB |
+   * | B' |            | Cr(unorm) |   | offsetC |
+   *
+   * where
+   *          | vecR |
+   * Matrix = | vecG | * Syuv
+   *          | vecB |
+   *
+   * offsetA = dot(vecR, Offset)
+   * offsetB = dot(vecG, Offset)
+   * offsetC = dot(vecB, Offset)
+   *
+   * 4) Consider 16-235 scale RGB
+   * RGBfull(0..255) -> RGBfull(16..235) matrix is represented by
+   * | Rs |      | Rf |   | Or |
+   * | Gs | = Ms | Gf | + | Og |
+   * | Bs |      | Bf |   | Ob |
+   *
+   * Combining all matrix into
+   * | Rs |                   | Y'(unorm) |   | offsetA |     | Or |
+   * | Gs | = Ms * ( Matrix * | Cb(unorm) | + | offsetB | ) + | Og |
+   * | Bs |                   | Cr(unorm) |   | offsetC |     | Ob |
+   *
+   *                        | Y'(unorm) |      | offsetA |   | Or |
+   *        = Ms * Matrix * | Cb(unorm) | + Ms | offsetB | + | Og |
+   *                        | Cr(unorm) |      | offsetC |   | Ob |
+   */
+
+  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
+  for (guint i = 0; i < 3; i++)
+    matrix->max[i] = 1.0;
+
+  gst_video_color_range_offsets (in_yuv_info->colorimetry.range,
+      in_yuv_info->finfo, offset, scale);
+
+  if (gst_video_color_matrix_get_Kr_Kb (in_yuv_info->colorimetry.matrix,
+          &Kr, &Kb)) {
+    guint S;
+    gdouble Sy, Suv;
+    gdouble Oy, Ouv;
+    gdouble vecR[3], vecG[3], vecB[3];
+
+    Kg = 1.0 - Kr - Kb;
+
+    vecR[0] = 1.0;
+    vecR[1] = 0;
+    vecR[2] = 2 * (1 - Kr);
+
+    vecG[0] = 1.0;
+    vecG[1] = -(Kb / Kg) * 2 * (1 - Kb);
+    vecG[2] = -(Kr / Kg) * 2 * (1 - Kr);
+
+    vecB[0] = 1.0;
+    vecB[1] = 2 * (1 - Kb);
+    vecB[2] = 0;
+
+    /* Assume all components has the same bitdepth */
+    S = (1 << in_yuv_info->finfo->depth[0]) - 1;
+    Sy = (gdouble) S / scale[0];
+    Suv = (gdouble) S / scale[1];
+    Oy = -((gdouble) offset[0] / scale[0]);
+    Ouv = -((gdouble) offset[1] / scale[1]);
+
+    matrix->matrix[0][0] = Sy * vecR[0];
+    matrix->matrix[1][0] = Sy * vecG[0];
+    matrix->matrix[2][0] = Sy * vecB[0];
+
+    matrix->matrix[0][1] = Suv * vecR[1];
+    matrix->matrix[1][1] = Suv * vecG[1];
+    matrix->matrix[2][1] = Suv * vecB[1];
+
+    matrix->matrix[0][2] = Suv * vecR[2];
+    matrix->matrix[1][2] = Suv * vecG[2];
+    matrix->matrix[2][2] = Suv * vecB[2];
+
+    matrix->offset[0] = vecR[0] * Oy + vecR[1] * Ouv + vecR[2] * Ouv;
+    matrix->offset[1] = vecG[0] * Oy + vecG[1] * Ouv + vecG[2] * Ouv;
+    matrix->offset[2] = vecB[0] * Oy + vecB[1] * Ouv + vecB[2] * Ouv;
+
+    /* Apply RGB range scale matrix */
+    if (out_rgb_info->colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
+      GstD3D11ColorMatrix scale_matrix, rst;
+      GstVideoInfo full_rgb = *out_rgb_info;
+
+      full_rgb.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
+
+      if (gst_d3d11_color_range_adjust_matrix_unorm (&full_rgb,
+              out_rgb_info, &scale_matrix)) {
+        /* Ms * Matrix */
+        color_matrix_multiply (&rst, &scale_matrix, matrix);
+
+        /* Ms * transform offsets */
+        for (guint i = 0; i < 3; i++) {
+          gdouble val = 0;
+          for (guint j = 0; j < 3; j++) {
+            val += scale_matrix.matrix[i][j] * matrix->offset[j];
+          }
+          rst.offset[i] = val + scale_matrix.offset[i];
+        }
+
+        /* copy back to output matrix */
+        for (guint i = 0; i < 3; i++) {
+          for (guint j = 0; j < 3; j++) {
+            matrix->matrix[i][j] = rst.matrix[i][j];
+          }
+          matrix->offset[i] = rst.offset[i];
+          matrix->min[i] = scale_matrix.min[i];
+          matrix->max[i] = scale_matrix.max[i];
+        }
+      }
+    }
+  } else {
+    /* Unknown matrix */
+    matrix->matrix[0][0] = 1.0;
+    matrix->matrix[1][1] = 1.0;
+    matrix->matrix[2][2] = 1.0;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_d3d11_rgb_to_yuv_matrix_unorm:
+ * @in_rgb_info: a #GstVideoInfo of input RGB signal
+ * @out_yuv_info: a #GstVideoInfo of output YUV signal
+ * @matrix: a #GstD3D11ColorMatrix
+ *
+ * Calculates transform matrix from RGB to YUV conversion. Both input and output
+ * signals are in normalized [0.0..1.0] space and additional gamma decoding
+ * or primary/transfer function transform is not performed by this matrix.
+ *
+ * Resulting RGB values can be calculated by
+ * | Y' |                           | R' |   | matrix.offset[0] |
+ * | Cb | = clamp ( matrix.matrix * | G' | + | matrix.offset[1] |, matrix.min, matrix.max )
+ * | Cr |                           | B' |   | matrix.offset[2] |
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+gst_d3d11_rgb_to_yuv_matrix_unorm (const GstVideoInfo * in_rgb_info,
+    const GstVideoInfo * out_yuv_info, GstD3D11ColorMatrix * matrix)
+{
+  gint offset[4], scale[4];
+  gdouble Kr, Kb, Kg;
+
+  g_return_val_if_fail (in_rgb_info != nullptr, FALSE);
+  g_return_val_if_fail (out_yuv_info != nullptr, FALSE);
+  g_return_val_if_fail (matrix != nullptr, FALSE);
+
+  /*
+   * <Formula>
+   *
+   * Input: Unsigned normalized non-linear R'G'B'(unorm), [0.0..1.0] range
+   * Output: Unsigned normalized Y'CbCr(unorm), [0.0..1.0] range
+   *
+   * 1) R'G'B' to YPbPr
+   * | Y  |      | R' |
+   * | Pb | = M *| G' |
+   * | Pr |      | B' |
+   * where
+   *     | vecY |
+   * M = | vecU |
+   *     | vecV |
+   * vecY = |       Kr      ,       Kg      ,      Kb       |
+   * vecU = | -0.5*Kr/(1-Kb), -0.5*Kg/(1-Kb),     0.5       |
+   * vecV = |      0.5      , -0.5*Kg/(1-Kr), -0.5*Kb(1-Kr) |
+   *
+   * 2) YPbPr to Y'CbCr(unorm)
+   * Y'(unorm) = (Y  * scaleY + offsetY)       / S
+   * Cb(unorm) = (Pb * scaleCbCr + offsetCbCr) / S
+   * Cr(unorm) = (Pr * scaleCbCr + offsetCbCr) / S
+   * =>
+   * Y'(unorm) = (Y  * scaleY    / S) + (offsetY    / S)
+   * Cb(unorm) = (Pb * scaleCbCr / S) + (offsetCbCr / S)
+   * Cr(unorm) = (Pb * scaleCbCr / S) + (offsetCbCr / S)
+   * where S = (2 ^ bitdepth) - 1
+   *
+   * 3) RGB -> YUV matrix
+   * | Y'(unorm) |            | R' |   | offsetA |
+   * | Cb(unorm) | = Matrix * | G' | + | offsetB |
+   * | Cr(unorm) |            | B' |   | offsetC |
+   *
+   * where
+   *          | (scaleY/S)    * vecY |
+   * Matrix = | (scaleCbCr/S) * vecU |
+   *          | (scaleCbCr/S) * vecV |
+   *
+   * offsetA = offsetY    / S
+   * offsetB = offsetCbCr / S
+   * offsetC = offsetCbCr / S
+   *
+   * 4) Consider 16-235 scale RGB
+   * RGBstudio(16..235) -> RGBfull(0..255) matrix is represented by
+   * | Rf |      | Rs |   | Or |
+   * | Gf | = Ms | Gs | + | Og |
+   * | Bf |      | Bs |   | Ob |
+   *
+   * Combining all matrix into
+   * | Y'(unorm) |                 | Rs |   | Or |     | offsetA |
+   * | Cb(unorm) | = Matrix * ( Ms | Gs | + | Og | ) + | offsetB |
+   * | Cr(unorm) |                 | Bs |   | Ob |     | offsetC |
+   *
+   *                             | Rs |          | Or |   | offsetA |
+   *               = Matrix * Ms | Gs | + Matrix | Og | + | offsetB |
+   *                             | Bs |          | Ob |   | offsetB |
+   */
+
+  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
+  for (guint i = 0; i < 3; i++)
+    matrix->max[i] = 1.0;
+
+  gst_video_color_range_offsets (out_yuv_info->colorimetry.range,
+      out_yuv_info->finfo, offset, scale);
+
+  if (gst_video_color_matrix_get_Kr_Kb (out_yuv_info->colorimetry.matrix,
+          &Kr, &Kb)) {
+    guint S;
+    gdouble Sy, Suv;
+    gdouble Oy, Ouv;
+    gdouble vecY[3], vecU[3], vecV[3];
+
+    Kg = 1.0 - Kr - Kb;
+
+    vecY[0] = Kr;
+    vecY[1] = Kg;
+    vecY[2] = Kb;
+
+    vecU[0] = -0.5 * Kr / (1 - Kb);
+    vecU[1] = -0.5 * Kg / (1 - Kb);
+    vecU[2] = 0.5;
+
+    vecV[0] = 0.5;
+    vecV[1] = -0.5 * Kg / (1 - Kr);
+    vecV[2] = -0.5 * Kb / (1 - Kr);
+
+    /* Assume all components has the same bitdepth */
+    S = (1 << out_yuv_info->finfo->depth[0]) - 1;
+    Sy = (gdouble) scale[0] / S;
+    Suv = (gdouble) scale[1] / S;
+    Oy = (gdouble) offset[0] / S;
+    Ouv = (gdouble) offset[1] / S;
+
+    for (guint i = 0; i < 3; i++) {
+      matrix->matrix[0][i] = Sy * vecY[i];
+      matrix->matrix[1][i] = Suv * vecU[i];
+      matrix->matrix[2][i] = Suv * vecV[i];
+    }
+
+    matrix->offset[0] = Oy;
+    matrix->offset[1] = Ouv;
+    matrix->offset[2] = Ouv;
+
+    matrix->min[0] = Oy;
+    matrix->min[1] = Oy;
+    matrix->min[2] = Oy;
+
+    matrix->max[0] = ((gdouble) scale[0] + offset[0]) / S;
+    matrix->max[1] = ((gdouble) scale[1] + offset[0]) / S;
+    matrix->max[2] = ((gdouble) scale[1] + offset[0]) / S;
+
+    /* Apply RGB range scale matrix */
+    if (in_rgb_info->colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
+      GstD3D11ColorMatrix scale_matrix, rst;
+      GstVideoInfo full_rgb = *in_rgb_info;
+
+      full_rgb.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
+
+      if (gst_d3d11_color_range_adjust_matrix_unorm (in_rgb_info,
+              &full_rgb, &scale_matrix)) {
+        /* Matrix * Ms */
+        color_matrix_multiply (&rst, matrix, &scale_matrix);
+
+        /* Matrix * scale offsets */
+        for (guint i = 0; i < 3; i++) {
+          gdouble val = 0;
+          for (guint j = 0; j < 3; j++) {
+            val += matrix->matrix[i][j] * scale_matrix.offset[j];
+          }
+          rst.offset[i] = val + matrix->offset[i];
+        }
+
+        /* copy back to output matrix */
+        for (guint i = 0; i < 3; i++) {
+          for (guint j = 0; j < 3; j++) {
+            matrix->matrix[i][j] = rst.matrix[i][j];
+          }
+          matrix->offset[i] = rst.offset[i];
+        }
+      }
+    }
+  } else {
+    /* Unknown matrix */
+    matrix->matrix[0][0] = 1.0;
+    matrix->matrix[1][1] = 1.0;
+    matrix->matrix[2][2] = 1.0;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+rgb_to_xyz_matrix (const GstVideoColorPrimariesInfo * info,
+    GstD3D11ColorMatrix * matrix)
+{
+  GstD3D11ColorMatrix m, im;
+  gdouble Sr, Sg, Sb;
+  gdouble Xw, Yw, Zw;
+
+  if (info->Rx == 0 || info->Gx == 0 || info->By == 0 || info->Wy == 0)
+    return FALSE;
+
+  color_matrix_identity (&m);
+
+  m.matrix[0][0] = info->Rx / info->Ry;
+  m.matrix[1][0] = 1.0;
+  m.matrix[2][0] = (1.0 - info->Rx - info->Ry) / info->Ry;
+
+  m.matrix[0][1] = info->Gx / info->Gy;
+  m.matrix[1][1] = 1.0;
+  m.matrix[2][1] = (1.0 - info->Gx - info->Gy) / info->Gy;
+
+  m.matrix[0][2] = info->Bx / info->By;
+  m.matrix[1][2] = 1.0;
+  m.matrix[2][2] = (1.0 - info->Bx - info->By) / info->By;
+
+  if (!color_matrix_invert (&im, &m))
+    return FALSE;
+
+  Xw = info->Wx / info->Wy;
+  Yw = 1.0;
+  Zw = (1.0 - info->Wx - info->Wy) / info->Wy;
+
+  Sr = im.matrix[0][0] * Xw + im.matrix[0][1] * Yw + im.matrix[0][2] * Zw;
+  Sg = im.matrix[1][0] * Xw + im.matrix[1][1] * Yw + im.matrix[1][2] * Zw;
+  Sb = im.matrix[2][0] * Xw + im.matrix[2][1] * Yw + im.matrix[2][2] * Zw;
+
+  for (guint i = 0; i < 3; i++) {
+    m.matrix[i][0] *= Sr;
+    m.matrix[i][1] *= Sg;
+    m.matrix[i][2] *= Sb;
+  }
+
+  color_matrix_copy (matrix, &m);
+
+  return TRUE;
+}
+
+/**
+ * gst_d3d11_color_primaries_matrix_unorm:
+ * @in_info: a #GstVideoColorPrimariesInfo of input signal
+ * @out_info: a #GstVideoColorPrimariesInfo of output signal
+ * @matrix: a #GstD3D11ColorMatrix
+ *
+ * Calculates color primaries conversion matrix
+ *
+ * Resulting RGB values can be calculated by
+ * | Rout |                              | Rin |
+ * | Gout | = saturate ( matrix.matrix * | Gin | )
+ * | Bout |                              | Bin |
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+gst_d3d11_color_primaries_matrix_unorm (const GstVideoColorPrimariesInfo *
+    in_info, const GstVideoColorPrimariesInfo * out_info,
+    GstD3D11ColorMatrix * matrix)
+{
+  GstD3D11ColorMatrix Ms, invMd, ret;
+
+  g_return_val_if_fail (in_info != nullptr, FALSE);
+  g_return_val_if_fail (out_info != nullptr, FALSE);
+  g_return_val_if_fail (matrix != nullptr, FALSE);
+
+  /*
+   * <Formula>
+   *
+   * 1) RGB -> XYZ conversion
+   * | X |     | R |
+   * | Y | = M | G |
+   * | Z |     | B |
+   * where
+   *     | SrXr, SgXg, SbXb |
+   * M = | SrYr, SgYg, SbYb |
+   *     | SrZr, SgZg, SbZb |
+   *
+   * Xr = xr / yr
+   * Yr = 1
+   * Zr = (1 - xr - yr) / yr
+   * xr and yr are xy coordinates of red primary in the CIE 1931 color space.
+   * And its applied to G and B components
+   *
+   * | Sr |        | Xr, Xg, Xb |     | Xw |
+   * | Sg | = inv( | Yr, Yg, Yb | ) * | Yw |
+   * | Sb |        | Zr, Zg, Zb |     | Zw |
+   *
+   * 2) XYZsrc -> XYZdst conversion
+   * Apply chromatic adaptation
+   * | Xdst |      | Xsrc |
+   * | Ydst | = Mc | Ysrc |
+   * | Zdst |      | Zsrc |
+   * where
+   *      | Xwdst / Xwsrc,       0      ,       0       |
+   * Mc = |       0      , Ywdst / Ywsrc,       0       |
+   *      |       0      ,       0      , Zwdst / Zwsrc |
+   *
+   * where
+   *
+   * 3) Final matrix
+   * | Rd |                      | Rs |
+   * | Gd | = inv (Md) * Mc * Ms | Gs |
+   * | Bd |                      | Bs |
+   */
+
+  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
+  for (guint i = 0; i < 3; i++)
+    matrix->max[i] = 1.0;
+
+  if (!rgb_to_xyz_matrix (in_info, &Ms)) {
+    GST_WARNING ("Failed to get src XYZ matrix");
+    return FALSE;
+  }
+
+  if (!rgb_to_xyz_matrix (out_info, &invMd) ||
+      !color_matrix_invert (&invMd, &invMd)) {
+    GST_WARNING ("Failed to get dst XYZ matrix");
+    return FALSE;
+  }
+
+  if (in_info->Wx != out_info->Wx || in_info->Wy != out_info->Wy) {
+    GstD3D11ColorMatrix Mc;
+
+    color_matrix_identity (&Mc);
+    Mc.matrix[0][0] = (out_info->Wx / out_info->Wy) /
+        (in_info->Wx / in_info->Wy);
+    /* Yw == 1.0 */
+    Mc.matrix[2][2] = ((1.0 - out_info->Wx - out_info->Wy) / out_info->Wy) /
+        ((1.0 - in_info->Wx - in_info->Wy) / in_info->Wy);
+
+    color_matrix_multiply (&ret, &Mc, &Ms);
+  } else {
+    color_matrix_copy (&ret, &Ms);
+  }
+
+  color_matrix_multiply (&ret, &invMd, &ret);
+  color_matrix_copy (matrix, &ret);
+
+  return TRUE;
+}
index abb3c83..65d54f1 100644 (file)
@@ -1,6 +1,7 @@
 d3d11_sources = [
   'gstd3d11bufferpool.cpp',
   'gstd3d11compile.cpp',
+  'gstd3d11converter.cpp',
   'gstd3d11device.cpp',
   'gstd3d11format.cpp',
   'gstd3d11memory.cpp',
@@ -12,6 +13,7 @@ d3d11_headers = [
   'gstd3d11_fwd.h',
   'gstd3d11.h',
   'gstd3d11bufferpool.h',
+  'gstd3d11converter.h',
   'gstd3d11device.h',
   'gstd3d11format.h',
   'gstd3d11memory.h',
@@ -21,6 +23,7 @@ d3d11_headers = [
 d3d11_enum_types_headers = [
   'gstd3d11_fwd.h',
   'gstd3d11bufferpool.h',
+  'gstd3d11converter.h',
   'gstd3d11device.h',
   'gstd3d11format.h',
   'gstd3d11memory.h',
index d91c887..fab6e67 100644 (file)
@@ -43,7 +43,6 @@
 #endif
 
 #include "gstd3d11compositor.h"
-#include "gstd3d11converter.h"
 #include "gstd3d11pluginutils.h"
 #include <string.h>
 #include <wrl.h>
index 8530e9a..39d355d 100644 (file)
@@ -27,7 +27,6 @@
 #endif
 
 #include "gstd3d11convert.h"
-#include "gstd3d11converter.h"
 #include "gstd3d11pluginutils.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_convert_debug);
index fd000c0..9405b69 100644 (file)
@@ -52,7 +52,6 @@
 #endif
 
 #include "gstd3d11decoder.h"
-#include "gstd3d11converter.h"
 #include "gstd3d11pluginutils.h"
 #include <string.h>
 #include <string>
index da495cd..02fa4b3 100644 (file)
@@ -655,758 +655,3 @@ gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
 
   return pool;
 }
-
-gchar *
-gst_d3d11_dump_color_matrix (GstD3D11ColorMatrix * matrix)
-{
-  /* *INDENT-OFF* */
-  static const gchar format[] =
-      "[MATRIX]\n"
-      "|% .6f, % .6f, % .6f|\n"
-      "|% .6f, % .6f, % .6f|\n"
-      "|% .6f, % .6f, % .6f|\n"
-      "[OFFSET]\n"
-      "|% .6f, % .6f, % .6f|\n"
-      "[MIN]\n"
-      "|% .6f, % .6f, % .6f|\n"
-      "[MAX]\n"
-      "|% .6f, % .6f, % .6f|";
-  /* *INDENT-ON* */
-
-  g_return_val_if_fail (matrix != nullptr, nullptr);
-
-  return g_strdup_printf (format,
-      matrix->matrix[0][0], matrix->matrix[0][1], matrix->matrix[0][2],
-      matrix->matrix[1][0], matrix->matrix[1][1], matrix->matrix[1][2],
-      matrix->matrix[2][0], matrix->matrix[2][1], matrix->matrix[2][2],
-      matrix->offset[0], matrix->offset[1], matrix->offset[2],
-      matrix->min[0], matrix->min[1], matrix->min[2],
-      matrix->max[0], matrix->max[1], matrix->max[2]);
-}
-
-static void
-color_matrix_copy (GstD3D11ColorMatrix * dst, const GstD3D11ColorMatrix * src)
-{
-  for (guint i = 0; i < 3; i++) {
-    for (guint j = 0; j < 3; j++) {
-      dst->matrix[i][j] = src->matrix[i][j];
-    }
-  }
-}
-
-static void
-color_matrix_multiply (GstD3D11ColorMatrix * dst, GstD3D11ColorMatrix * a,
-    GstD3D11ColorMatrix * b)
-{
-  GstD3D11ColorMatrix tmp;
-
-  for (guint i = 0; i < 3; i++) {
-    for (guint j = 0; j < 3; j++) {
-      gdouble val = 0;
-      for (guint k = 0; k < 3; k++) {
-        val += a->matrix[i][k] * b->matrix[k][j];
-      }
-
-      tmp.matrix[i][j] = val;
-    }
-  }
-
-  color_matrix_copy (dst, &tmp);
-}
-
-static void
-color_matrix_identity (GstD3D11ColorMatrix * m)
-{
-  for (guint i = 0; i < 3; i++) {
-    for (guint j = 0; j < 3; j++) {
-      if (i == j)
-        m->matrix[i][j] = 1.0;
-      else
-        m->matrix[i][j] = 0;
-    }
-  }
-}
-
-static gboolean
-color_matrix_invert (GstD3D11ColorMatrix * dst, GstD3D11ColorMatrix * src)
-{
-  GstD3D11ColorMatrix tmp;
-  gdouble det;
-
-  color_matrix_identity (&tmp);
-  for (guint j = 0; j < 3; j++) {
-    for (guint i = 0; i < 3; i++) {
-      tmp.matrix[j][i] =
-          src->matrix[(i + 1) % 3][(j + 1) % 3] *
-          src->matrix[(i + 2) % 3][(j + 2) % 3] -
-          src->matrix[(i + 1) % 3][(j + 2) % 3] *
-          src->matrix[(i + 2) % 3][(j + 1) % 3];
-    }
-  }
-
-  det = tmp.matrix[0][0] * src->matrix[0][0] +
-      tmp.matrix[0][1] * src->matrix[1][0] +
-      tmp.matrix[0][2] * src->matrix[2][0];
-  if (det == 0)
-    return FALSE;
-
-  for (guint j = 0; j < 3; j++) {
-    for (guint i = 0; i < 3; i++) {
-      tmp.matrix[i][j] /= det;
-    }
-  }
-
-  color_matrix_copy (dst, &tmp);
-
-  return TRUE;
-}
-
-/**
- * gst_d3d11_color_range_adjust_matrix_unorm:
- * @in_info: a #GstVideoInfo
- * @out_info: a #GstVideoInfo
- * @matrix: a #GstD3D11ColorMatrix
- *
- * Calculates matrix for color range adjustment. Both input and output
- * signals are in normalized [0.0..1.0] space.
- *
- * Resulting values can be calculated by
- * | Yout |                           | Yin |   | matrix.offset[0] |
- * | Uout | = clamp ( matrix.matrix * | Uin | + | matrix.offset[1] |, matrix.min, matrix.max )
- * | Vout |                           | Vin |   | matrix.offset[2] |
- *
- * Returns: %TRUE if successful
- */
-gboolean
-gst_d3d11_color_range_adjust_matrix_unorm (const GstVideoInfo * in_info,
-    const GstVideoInfo * out_info, GstD3D11ColorMatrix * matrix)
-{
-  gboolean in_rgb, out_rgb;
-  gint in_offset[GST_VIDEO_MAX_COMPONENTS];
-  gint in_scale[GST_VIDEO_MAX_COMPONENTS];
-  gint out_offset[GST_VIDEO_MAX_COMPONENTS];
-  gint out_scale[GST_VIDEO_MAX_COMPONENTS];
-  GstVideoColorRange in_range;
-  GstVideoColorRange out_range;
-  gdouble src_fullscale, dst_fullscale;
-
-  g_return_val_if_fail (in_info != nullptr, FALSE);
-  g_return_val_if_fail (out_info != nullptr, FALSE);
-  g_return_val_if_fail (matrix != nullptr, FALSE);
-
-  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
-  for (guint i = 0; i < 3; i++) {
-    matrix->matrix[i][i] = 1.0;
-    matrix->matrix[i][i] = 1.0;
-    matrix->matrix[i][i] = 1.0;
-    matrix->max[i] = 1.0;
-  }
-
-  in_rgb = GST_VIDEO_INFO_IS_RGB (in_info);
-  out_rgb = GST_VIDEO_INFO_IS_RGB (out_info);
-
-  if (in_rgb != out_rgb) {
-    GST_WARNING ("Invalid format conversion");
-    return FALSE;
-  }
-
-  in_range = in_info->colorimetry.range;
-  out_range = out_info->colorimetry.range;
-
-  if (in_range == GST_VIDEO_COLOR_RANGE_UNKNOWN) {
-    GST_WARNING ("Unknown input color range");
-    if (in_rgb || GST_VIDEO_INFO_IS_GRAY (in_info))
-      in_range = GST_VIDEO_COLOR_RANGE_0_255;
-    else
-      in_range = GST_VIDEO_COLOR_RANGE_16_235;
-  }
-
-  if (out_range == GST_VIDEO_COLOR_RANGE_UNKNOWN) {
-    GST_WARNING ("Unknown output color range");
-    if (out_rgb || GST_VIDEO_INFO_IS_GRAY (out_info))
-      out_range = GST_VIDEO_COLOR_RANGE_0_255;
-    else
-      out_range = GST_VIDEO_COLOR_RANGE_16_235;
-  }
-
-  src_fullscale = (gdouble) ((1 << in_info->finfo->depth[0]) - 1);
-  dst_fullscale = (gdouble) ((1 << out_info->finfo->depth[0]) - 1);
-
-  gst_video_color_range_offsets (in_range, in_info->finfo, in_offset, in_scale);
-  gst_video_color_range_offsets (out_range,
-      out_info->finfo, out_offset, out_scale);
-
-  matrix->min[0] = matrix->min[1] = matrix->min[2] =
-      (gdouble) out_offset[0] / dst_fullscale;
-
-  matrix->max[0] = (out_scale[0] + out_offset[0]) / dst_fullscale;
-  matrix->max[1] = matrix->max[2] =
-      (out_scale[1] + out_offset[0]) / dst_fullscale;
-
-  if (in_info->colorimetry.range == out_info->colorimetry.range) {
-    GST_DEBUG ("Same color range");
-    return TRUE;
-  }
-
-  /* Formula
-   *
-   * 1) Scales and offset compensates input to [0..1] range
-   * SRC_NORM[i] = (src[i] * src_fullscale - in_offset[i]) / in_scale[i]
-   *             = (src[i] * src_fullscale / in_scale[i]) - in_offset[i] / in_scale[i]
-   *
-   * 2) Reverse to output UNIT scale
-   * DST_UINT[i] = SRC_NORM[i] * out_scale[i] + out_offset[i]
-   *             = src[i] * src_fullscale * out_scale[i] / in_scale[i]
-   *               - in_offset[i] * out_scale[i] / in_scale[i]
-   *               + out_offset[i]
-   *
-   * 3) Back to [0..1] scale
-   * dst[i] = DST_UINT[i] / dst_fullscale
-   *        = COEFF[i] * src[i] + OFF[i]
-   * where
-   *             src_fullscale * out_scale[i]
-   * COEFF[i] = ------------------------------
-   *             dst_fullscale * in_scale[i]
-   *
-   *            out_offset[i]     in_offset[i] * out_scale[i]
-   * OFF[i] =  -------------- -  ------------------------------
-   *            dst_fullscale     dst_fullscale * in_scale[i]
-   */
-  for (guint i = 0; i < 3; i++) {
-    matrix->matrix[i][i] = (src_fullscale * out_scale[i]) /
-        (dst_fullscale * in_scale[i]);
-    matrix->offset[i] = (out_offset[i] / dst_fullscale) -
-        ((gdouble) in_offset[i] * out_scale[i] / (dst_fullscale * in_scale[i]));
-  }
-
-  return TRUE;
-}
-
-/**
- * gst_d3d11_yuv_to_rgb_matrix_unorm:
- * @in_yuv_info: a #GstVideoInfo of input YUV signal
- * @out_rgb_info: a #GstVideoInfo of output RGB signal
- * @matrix: a #GstD3D11ColorMatrix
- *
- * Calculates transform matrix from YUV to RGB conversion. Both input and output
- * signals are in normalized [0.0..1.0] space and additional gamma decoding
- * or primary/transfer function transform is not performed by this matrix.
- *
- * Resulting non-linear RGB values can be calculated by
- * | R' |                           | Y' |   | matrix.offset[0] |
- * | G' | = clamp ( matrix.matrix * | Cb | + | matrix.offset[1] | matrix.min, matrix.max )
- * | B' |                           | Cr |   | matrix.offset[2] |
- *
- * Returns: %TRUE if successful
- */
-gboolean
-gst_d3d11_yuv_to_rgb_matrix_unorm (const GstVideoInfo * in_yuv_info,
-    const GstVideoInfo * out_rgb_info, GstD3D11ColorMatrix * matrix)
-{
-  gint offset[4], scale[4];
-  gdouble Kr, Kb, Kg;
-
-  g_return_val_if_fail (in_yuv_info != nullptr, FALSE);
-  g_return_val_if_fail (out_rgb_info != nullptr, FALSE);
-  g_return_val_if_fail (matrix != nullptr, FALSE);
-
-  /*
-   * <Formula>
-   *
-   * Input: Unsigned normalized Y'CbCr(unorm), [0.0..1.0] range
-   * Output: Unsigned normalized non-linear R'G'B'(unorm), [0.0..1.0] range
-   *
-   * 1) Y'CbCr(unorm) to scaled Y'CbCr
-   * | Y' |     | Y'(unorm) |
-   * | Cb | = S | Cb(unorm) |
-   * | Cb |     | Cr(unorm) |
-   * where S = (2 ^ bitdepth) - 1
-   *
-   * 2) Y'CbCr to YPbPr
-   * Y  = (Y' - offsetY )    / scaleY
-   * Pb = [(Cb - offsetCbCr) / scaleCbCr]
-   * Pr = [(Cr - offsetCrCr) / scaleCrCr]
-   * =>
-   * Y  = Y'(unorm) * Sy  + Oy
-   * Pb = Cb(unorm) * Suv + Ouv
-   * Pb = Cr(unorm) * Suv + Ouv
-   * where
-   * Sy  = S / scaleY
-   * Suv = S / scaleCbCr
-   * Oy  = -(offsetY / scaleY)
-   * Ouv = -(offsetCbCr / scaleCbCr)
-   *
-   * 3) YPbPr to R'G'B'
-   * | R' |      | Y  |
-   * | G' | = M *| Pb |
-   * | B' |      | Pr |
-   * where
-   *     | vecR |
-   * M = | vecG |
-   *     | vecB |
-   * vecR = | 1,         0           ,       2(1 - Kr)      |
-   * vecG = | 1, -(Kb/Kg) * 2(1 - Kb), -(Kr/Kg) * 2(1 - Kr) |
-   * vecB = | 1,       2(1 - Kb)     ,          0           |
-   * =>
-   * R' = dot(vecR, (Syuv * Y'CbCr(unorm))) + dot(vecR, Offset)
-   * G' = dot(vecG, (Svuy * Y'CbCr(unorm))) + dot(vecG, Offset)
-   * B' = dot(vecB, (Syuv * Y'CbCr(unorm)) + dot(vecB, Offset)
-   * where
-   *        | Sy,   0,   0 |
-   * Syuv = |  0, Suv,   0 |
-   *        |  0    0, Suv |
-   *
-   *          | Oy  |
-   * Offset = | Ouv |
-   *          | Ouv |
-   *
-   * 4) YUV -> RGB matrix
-   * | R' |            | Y'(unorm) |   | offsetA |
-   * | G' | = Matrix * | Cb(unorm) | + | offsetB |
-   * | B' |            | Cr(unorm) |   | offsetC |
-   *
-   * where
-   *          | vecR |
-   * Matrix = | vecG | * Syuv
-   *          | vecB |
-   *
-   * offsetA = dot(vecR, Offset)
-   * offsetB = dot(vecG, Offset)
-   * offsetC = dot(vecB, Offset)
-   *
-   * 4) Consider 16-235 scale RGB
-   * RGBfull(0..255) -> RGBfull(16..235) matrix is represented by
-   * | Rs |      | Rf |   | Or |
-   * | Gs | = Ms | Gf | + | Og |
-   * | Bs |      | Bf |   | Ob |
-   *
-   * Combining all matrix into
-   * | Rs |                   | Y'(unorm) |   | offsetA |     | Or |
-   * | Gs | = Ms * ( Matrix * | Cb(unorm) | + | offsetB | ) + | Og |
-   * | Bs |                   | Cr(unorm) |   | offsetC |     | Ob |
-   *
-   *                        | Y'(unorm) |      | offsetA |   | Or |
-   *        = Ms * Matrix * | Cb(unorm) | + Ms | offsetB | + | Og |
-   *                        | Cr(unorm) |      | offsetC |   | Ob |
-   */
-
-  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
-  for (guint i = 0; i < 3; i++)
-    matrix->max[i] = 1.0;
-
-  gst_video_color_range_offsets (in_yuv_info->colorimetry.range,
-      in_yuv_info->finfo, offset, scale);
-
-  if (gst_video_color_matrix_get_Kr_Kb (in_yuv_info->colorimetry.matrix,
-          &Kr, &Kb)) {
-    guint S;
-    gdouble Sy, Suv;
-    gdouble Oy, Ouv;
-    gdouble vecR[3], vecG[3], vecB[3];
-
-    Kg = 1.0 - Kr - Kb;
-
-    vecR[0] = 1.0;
-    vecR[1] = 0;
-    vecR[2] = 2 * (1 - Kr);
-
-    vecG[0] = 1.0;
-    vecG[1] = -(Kb / Kg) * 2 * (1 - Kb);
-    vecG[2] = -(Kr / Kg) * 2 * (1 - Kr);
-
-    vecB[0] = 1.0;
-    vecB[1] = 2 * (1 - Kb);
-    vecB[2] = 0;
-
-    /* Assume all components has the same bitdepth */
-    S = (1 << in_yuv_info->finfo->depth[0]) - 1;
-    Sy = (gdouble) S / scale[0];
-    Suv = (gdouble) S / scale[1];
-    Oy = -((gdouble) offset[0] / scale[0]);
-    Ouv = -((gdouble) offset[1] / scale[1]);
-
-    matrix->matrix[0][0] = Sy * vecR[0];
-    matrix->matrix[1][0] = Sy * vecG[0];
-    matrix->matrix[2][0] = Sy * vecB[0];
-
-    matrix->matrix[0][1] = Suv * vecR[1];
-    matrix->matrix[1][1] = Suv * vecG[1];
-    matrix->matrix[2][1] = Suv * vecB[1];
-
-    matrix->matrix[0][2] = Suv * vecR[2];
-    matrix->matrix[1][2] = Suv * vecG[2];
-    matrix->matrix[2][2] = Suv * vecB[2];
-
-    matrix->offset[0] = vecR[0] * Oy + vecR[1] * Ouv + vecR[2] * Ouv;
-    matrix->offset[1] = vecG[0] * Oy + vecG[1] * Ouv + vecG[2] * Ouv;
-    matrix->offset[2] = vecB[0] * Oy + vecB[1] * Ouv + vecB[2] * Ouv;
-
-    /* Apply RGB range scale matrix */
-    if (out_rgb_info->colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
-      GstD3D11ColorMatrix scale_matrix, rst;
-      GstVideoInfo full_rgb = *out_rgb_info;
-
-      full_rgb.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
-
-      if (gst_d3d11_color_range_adjust_matrix_unorm (&full_rgb,
-              out_rgb_info, &scale_matrix)) {
-        /* Ms * Matrix */
-        color_matrix_multiply (&rst, &scale_matrix, matrix);
-
-        /* Ms * transform offsets */
-        for (guint i = 0; i < 3; i++) {
-          gdouble val = 0;
-          for (guint j = 0; j < 3; j++) {
-            val += scale_matrix.matrix[i][j] * matrix->offset[j];
-          }
-          rst.offset[i] = val + scale_matrix.offset[i];
-        }
-
-        /* copy back to output matrix */
-        for (guint i = 0; i < 3; i++) {
-          for (guint j = 0; j < 3; j++) {
-            matrix->matrix[i][j] = rst.matrix[i][j];
-          }
-          matrix->offset[i] = rst.offset[i];
-          matrix->min[i] = scale_matrix.min[i];
-          matrix->max[i] = scale_matrix.max[i];
-        }
-      }
-    }
-  } else {
-    /* Unknown matrix */
-    matrix->matrix[0][0] = 1.0;
-    matrix->matrix[1][1] = 1.0;
-    matrix->matrix[2][2] = 1.0;
-  }
-
-  return TRUE;
-}
-
-/**
- * gst_d3d11_rgb_to_yuv_matrix_unorm:
- * @in_rgb_info: a #GstVideoInfo of input RGB signal
- * @out_yuv_info: a #GstVideoInfo of output YUV signal
- * @matrix: a #GstD3D11ColorMatrix
- *
- * Calculates transform matrix from RGB to YUV conversion. Both input and output
- * signals are in normalized [0.0..1.0] space and additional gamma decoding
- * or primary/transfer function transform is not performed by this matrix.
- *
- * Resulting RGB values can be calculated by
- * | Y' |                           | R' |   | matrix.offset[0] |
- * | Cb | = clamp ( matrix.matrix * | G' | + | matrix.offset[1] |, matrix.min, matrix.max )
- * | Cr |                           | B' |   | matrix.offset[2] |
- *
- * Returns: %TRUE if successful
- */
-gboolean
-gst_d3d11_rgb_to_yuv_matrix_unorm (const GstVideoInfo * in_rgb_info,
-    const GstVideoInfo * out_yuv_info, GstD3D11ColorMatrix * matrix)
-{
-  gint offset[4], scale[4];
-  gdouble Kr, Kb, Kg;
-
-  g_return_val_if_fail (in_rgb_info != nullptr, FALSE);
-  g_return_val_if_fail (out_yuv_info != nullptr, FALSE);
-  g_return_val_if_fail (matrix != nullptr, FALSE);
-
-  /*
-   * <Formula>
-   *
-   * Input: Unsigned normalized non-linear R'G'B'(unorm), [0.0..1.0] range
-   * Output: Unsigned normalized Y'CbCr(unorm), [0.0..1.0] range
-   *
-   * 1) R'G'B' to YPbPr
-   * | Y  |      | R' |
-   * | Pb | = M *| G' |
-   * | Pr |      | B' |
-   * where
-   *     | vecY |
-   * M = | vecU |
-   *     | vecV |
-   * vecY = |       Kr      ,       Kg      ,      Kb       |
-   * vecU = | -0.5*Kr/(1-Kb), -0.5*Kg/(1-Kb),     0.5       |
-   * vecV = |      0.5      , -0.5*Kg/(1-Kr), -0.5*Kb(1-Kr) |
-   *
-   * 2) YPbPr to Y'CbCr(unorm)
-   * Y'(unorm) = (Y  * scaleY + offsetY)       / S
-   * Cb(unorm) = (Pb * scaleCbCr + offsetCbCr) / S
-   * Cr(unorm) = (Pr * scaleCbCr + offsetCbCr) / S
-   * =>
-   * Y'(unorm) = (Y  * scaleY    / S) + (offsetY    / S)
-   * Cb(unorm) = (Pb * scaleCbCr / S) + (offsetCbCr / S)
-   * Cr(unorm) = (Pb * scaleCbCr / S) + (offsetCbCr / S)
-   * where S = (2 ^ bitdepth) - 1
-   *
-   * 3) RGB -> YUV matrix
-   * | Y'(unorm) |            | R' |   | offsetA |
-   * | Cb(unorm) | = Matrix * | G' | + | offsetB |
-   * | Cr(unorm) |            | B' |   | offsetC |
-   *
-   * where
-   *          | (scaleY/S)    * vecY |
-   * Matrix = | (scaleCbCr/S) * vecU |
-   *          | (scaleCbCr/S) * vecV |
-   *
-   * offsetA = offsetY    / S
-   * offsetB = offsetCbCr / S
-   * offsetC = offsetCbCr / S
-   *
-   * 4) Consider 16-235 scale RGB
-   * RGBstudio(16..235) -> RGBfull(0..255) matrix is represented by
-   * | Rf |      | Rs |   | Or |
-   * | Gf | = Ms | Gs | + | Og |
-   * | Bf |      | Bs |   | Ob |
-   *
-   * Combining all matrix into
-   * | Y'(unorm) |                 | Rs |   | Or |     | offsetA |
-   * | Cb(unorm) | = Matrix * ( Ms | Gs | + | Og | ) + | offsetB |
-   * | Cr(unorm) |                 | Bs |   | Ob |     | offsetC |
-   *
-   *                             | Rs |          | Or |   | offsetA |
-   *               = Matrix * Ms | Gs | + Matrix | Og | + | offsetB |
-   *                             | Bs |          | Ob |   | offsetB |
-   */
-
-  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
-  for (guint i = 0; i < 3; i++)
-    matrix->max[i] = 1.0;
-
-  gst_video_color_range_offsets (out_yuv_info->colorimetry.range,
-      out_yuv_info->finfo, offset, scale);
-
-  if (gst_video_color_matrix_get_Kr_Kb (out_yuv_info->colorimetry.matrix,
-          &Kr, &Kb)) {
-    guint S;
-    gdouble Sy, Suv;
-    gdouble Oy, Ouv;
-    gdouble vecY[3], vecU[3], vecV[3];
-
-    Kg = 1.0 - Kr - Kb;
-
-    vecY[0] = Kr;
-    vecY[1] = Kg;
-    vecY[2] = Kb;
-
-    vecU[0] = -0.5 * Kr / (1 - Kb);
-    vecU[1] = -0.5 * Kg / (1 - Kb);
-    vecU[2] = 0.5;
-
-    vecV[0] = 0.5;
-    vecV[1] = -0.5 * Kg / (1 - Kr);
-    vecV[2] = -0.5 * Kb / (1 - Kr);
-
-    /* Assume all components has the same bitdepth */
-    S = (1 << out_yuv_info->finfo->depth[0]) - 1;
-    Sy = (gdouble) scale[0] / S;
-    Suv = (gdouble) scale[1] / S;
-    Oy = (gdouble) offset[0] / S;
-    Ouv = (gdouble) offset[1] / S;
-
-    for (guint i = 0; i < 3; i++) {
-      matrix->matrix[0][i] = Sy * vecY[i];
-      matrix->matrix[1][i] = Suv * vecU[i];
-      matrix->matrix[2][i] = Suv * vecV[i];
-    }
-
-    matrix->offset[0] = Oy;
-    matrix->offset[1] = Ouv;
-    matrix->offset[2] = Ouv;
-
-    matrix->min[0] = Oy;
-    matrix->min[1] = Oy;
-    matrix->min[2] = Oy;
-
-    matrix->max[0] = ((gdouble) scale[0] + offset[0]) / S;
-    matrix->max[1] = ((gdouble) scale[1] + offset[0]) / S;
-    matrix->max[2] = ((gdouble) scale[1] + offset[0]) / S;
-
-    /* Apply RGB range scale matrix */
-    if (in_rgb_info->colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
-      GstD3D11ColorMatrix scale_matrix, rst;
-      GstVideoInfo full_rgb = *in_rgb_info;
-
-      full_rgb.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
-
-      if (gst_d3d11_color_range_adjust_matrix_unorm (in_rgb_info,
-              &full_rgb, &scale_matrix)) {
-        /* Matrix * Ms */
-        color_matrix_multiply (&rst, matrix, &scale_matrix);
-
-        /* Matrix * scale offsets */
-        for (guint i = 0; i < 3; i++) {
-          gdouble val = 0;
-          for (guint j = 0; j < 3; j++) {
-            val += matrix->matrix[i][j] * scale_matrix.offset[j];
-          }
-          rst.offset[i] = val + matrix->offset[i];
-        }
-
-        /* copy back to output matrix */
-        for (guint i = 0; i < 3; i++) {
-          for (guint j = 0; j < 3; j++) {
-            matrix->matrix[i][j] = rst.matrix[i][j];
-          }
-          matrix->offset[i] = rst.offset[i];
-        }
-      }
-    }
-  } else {
-    /* Unknown matrix */
-    matrix->matrix[0][0] = 1.0;
-    matrix->matrix[1][1] = 1.0;
-    matrix->matrix[2][2] = 1.0;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-rgb_to_xyz_matrix (const GstVideoColorPrimariesInfo * info,
-    GstD3D11ColorMatrix * matrix)
-{
-  GstD3D11ColorMatrix m, im;
-  gdouble Sr, Sg, Sb;
-  gdouble Xw, Yw, Zw;
-
-  if (info->Rx == 0 || info->Gx == 0 || info->By == 0 || info->Wy == 0)
-    return FALSE;
-
-  color_matrix_identity (&m);
-
-  m.matrix[0][0] = info->Rx / info->Ry;
-  m.matrix[1][0] = 1.0;
-  m.matrix[2][0] = (1.0 - info->Rx - info->Ry) / info->Ry;
-
-  m.matrix[0][1] = info->Gx / info->Gy;
-  m.matrix[1][1] = 1.0;
-  m.matrix[2][1] = (1.0 - info->Gx - info->Gy) / info->Gy;
-
-  m.matrix[0][2] = info->Bx / info->By;
-  m.matrix[1][2] = 1.0;
-  m.matrix[2][2] = (1.0 - info->Bx - info->By) / info->By;
-
-  if (!color_matrix_invert (&im, &m))
-    return FALSE;
-
-  Xw = info->Wx / info->Wy;
-  Yw = 1.0;
-  Zw = (1.0 - info->Wx - info->Wy) / info->Wy;
-
-  Sr = im.matrix[0][0] * Xw + im.matrix[0][1] * Yw + im.matrix[0][2] * Zw;
-  Sg = im.matrix[1][0] * Xw + im.matrix[1][1] * Yw + im.matrix[1][2] * Zw;
-  Sb = im.matrix[2][0] * Xw + im.matrix[2][1] * Yw + im.matrix[2][2] * Zw;
-
-  for (guint i = 0; i < 3; i++) {
-    m.matrix[i][0] *= Sr;
-    m.matrix[i][1] *= Sg;
-    m.matrix[i][2] *= Sb;
-  }
-
-  color_matrix_copy (matrix, &m);
-
-  return TRUE;
-}
-
-/**
- * gst_d3d11_color_primaries_matrix_unorm:
- * @in_info: a #GstVideoColorPrimariesInfo of input signal
- * @out_info: a #GstVideoColorPrimariesInfo of output signal
- * @matrix: a #GstD3D11ColorMatrix
- *
- * Calculates color primaries conversion matrix
- *
- * Resulting RGB values can be calculated by
- * | Rout |                              | Rin |
- * | Gout | = saturate ( matrix.matrix * | Gin | )
- * | Bout |                              | Bin |
- *
- * Returns: %TRUE if successful
- */
-gboolean
-gst_d3d11_color_primaries_matrix_unorm (const GstVideoColorPrimariesInfo *
-    in_info, const GstVideoColorPrimariesInfo * out_info,
-    GstD3D11ColorMatrix * matrix)
-{
-  GstD3D11ColorMatrix Ms, invMd, ret;
-
-  g_return_val_if_fail (in_info != nullptr, FALSE);
-  g_return_val_if_fail (out_info != nullptr, FALSE);
-  g_return_val_if_fail (matrix != nullptr, FALSE);
-
-  /*
-   * <Formula>
-   *
-   * 1) RGB -> XYZ conversion
-   * | X |     | R |
-   * | Y | = M | G |
-   * | Z |     | B |
-   * where
-   *     | SrXr, SgXg, SbXb |
-   * M = | SrYr, SgYg, SbYb |
-   *     | SrZr, SgZg, SbZb |
-   *
-   * Xr = xr / yr
-   * Yr = 1
-   * Zr = (1 - xr - yr) / yr
-   * xr and yr are xy coordinates of red primary in the CIE 1931 color space.
-   * And its applied to G and B components
-   *
-   * | Sr |        | Xr, Xg, Xb |     | Xw |
-   * | Sg | = inv( | Yr, Yg, Yb | ) * | Yw |
-   * | Sb |        | Zr, Zg, Zb |     | Zw |
-   *
-   * 2) XYZsrc -> XYZdst conversion
-   * Apply chromatic adaptation
-   * | Xdst |      | Xsrc |
-   * | Ydst | = Mc | Ysrc |
-   * | Zdst |      | Zsrc |
-   * where
-   *      | Xwdst / Xwsrc,       0      ,       0       |
-   * Mc = |       0      , Ywdst / Ywsrc,       0       |
-   *      |       0      ,       0      , Zwdst / Zwsrc |
-   *
-   * where
-   *
-   * 3) Final matrix
-   * | Rd |                      | Rs |
-   * | Gd | = inv (Md) * Mc * Ms | Gs |
-   * | Bd |                      | Bs |
-   */
-
-  memset (matrix, 0, sizeof (GstD3D11ColorMatrix));
-  for (guint i = 0; i < 3; i++)
-    matrix->max[i] = 1.0;
-
-  if (!rgb_to_xyz_matrix (in_info, &Ms)) {
-    GST_WARNING ("Failed to get src XYZ matrix");
-    return FALSE;
-  }
-
-  if (!rgb_to_xyz_matrix (out_info, &invMd) ||
-      !color_matrix_invert (&invMd, &invMd)) {
-    GST_WARNING ("Failed to get dst XYZ matrix");
-    return FALSE;
-  }
-
-  if (in_info->Wx != out_info->Wx || in_info->Wy != out_info->Wy) {
-    GstD3D11ColorMatrix Mc;
-
-    color_matrix_identity (&Mc);
-    Mc.matrix[0][0] = (out_info->Wx / out_info->Wy) /
-        (in_info->Wx / in_info->Wy);
-    /* Yw == 1.0 */
-    Mc.matrix[2][2] = ((1.0 - out_info->Wx - out_info->Wy) / out_info->Wy) /
-        ((1.0 - in_info->Wx - in_info->Wy) / in_info->Wy);
-
-    color_matrix_multiply (&ret, &Mc, &Ms);
-  } else {
-    color_matrix_copy (&ret, &Ms);
-  }
-
-  color_matrix_multiply (&ret, &invMd, &ret);
-  color_matrix_copy (matrix, &ret);
-
-  return TRUE;
-}
index c378a41..5915d51 100644 (file)
@@ -38,14 +38,6 @@ typedef enum
   GST_D3D11_DEVICE_VENDOR_XBOX,
 } GstD3D11DeviceVendor;
 
-typedef struct _GstD3D11ColorMatrix
-{
-  gdouble matrix[3][3];
-  gdouble offset[3];
-  gdouble min[3];
-  gdouble max[3];
-} GstD3D11ColorMatrix;
-
 void            gst_d3d11_plugin_utils_init         (D3D_FEATURE_LEVEL feature_level);
 
 GstCaps *       gst_d3d11_get_updated_template_caps (GstStaticCaps * template_caps);
@@ -95,24 +87,6 @@ GstBufferPool * gst_d3d11_buffer_pool_new_with_options  (GstD3D11Device * device
                                                          guint min_buffers,
                                                          guint max_buffers);
 
-gchar *         gst_d3d11_dump_color_matrix (GstD3D11ColorMatrix * matrix);
-
-gboolean        gst_d3d11_color_range_adjust_matrix_unorm (const GstVideoInfo * in_info,
-                                                           const GstVideoInfo * out_info,
-                                                           GstD3D11ColorMatrix * matrix);
-
-gboolean        gst_d3d11_yuv_to_rgb_matrix_unorm (const GstVideoInfo * in_yuv_info,
-                                                   const GstVideoInfo * out_rgb_info,
-                                                   GstD3D11ColorMatrix * matrix);
-
-gboolean        gst_d3d11_rgb_to_yuv_matrix_unorm (const GstVideoInfo * in_rgb_info,
-                                                   const GstVideoInfo * out_yuv_info,
-                                                   GstD3D11ColorMatrix * matrix);
-
-gboolean        gst_d3d11_color_primaries_matrix_unorm (const GstVideoColorPrimariesInfo * in_info,
-                                                        const GstVideoColorPrimariesInfo * out_info,
-                                                        GstD3D11ColorMatrix * matrix);
-
 G_END_DECLS
 
 #endif /* __GST_D3D11_PLUGIN_UTILS_H__ */
index afc964d..5724e31 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "gstd3d11testsrc.h"
 #include "gstd3d11pluginutils.h"
-#include "gstd3d11converter.h"
 #include <wrl.h>
 #include <string.h>
 
index 8f47cda..3a4bfdc 100644 (file)
@@ -25,7 +25,6 @@
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include <gst/d3d11/gstd3d11.h>
-#include "gstd3d11converter.h"
 #include "gstd3d11overlaycompositor.h"
 #include "gstd3d11pluginutils.h"
 
index 2a780b5..9084c68 100644 (file)
@@ -3,7 +3,6 @@ d3d11_sources = [
   'gstd3d11basefilter.cpp',
   'gstd3d11compositor.cpp',
   'gstd3d11convert.cpp',
-  'gstd3d11converter.cpp',
   'gstd3d11decoder.cpp',
   'gstd3d11deinterlace.cpp',
   'gstd3d11download.cpp',