d3d11: Add support for GRAY and more YUV formats
authorSeungha Yang <seungha@centricular.com>
Mon, 21 Jun 2021 08:13:33 +0000 (17:13 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 23 Jun 2021 15:35:36 +0000 (15:35 +0000)
By this commit, following formats will be newly supported by d3d11 elements

* Y444_{8, 12, 16}LE formats:
  Similar to other planar formats. Such Y444 variants are not supported
  by Direct3D11 natively, but we can simply map each plane by
  using R8 and/or R16 texture.
* P012_LE:
  It is not different from P016_LE, but defining P012 and P016 separately
  for more explicit signalling. Note that DXVA uses P016 texture
  for 12bits encoded bitstreams.
* GRAY:
  This format is required for some codecs (e.g., AV1) if monochrome
  is supported
* 4:2:0 planar 12bits (I420_12LE) and 4:2:2 planar 8, 10, 12bits
  formats (Y42B, I422_10LE, and I422_12LE)

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2346>

gst-libs/gst/d3d11/gstd3d11device.cpp
gst-libs/gst/d3d11/gstd3d11format.h
sys/d3d11/gstd3d11converter.cpp
sys/d3d11/gstd3d11deinterlace.cpp
tests/check/elements/d3d11colorconvert.c

index 41d48bf..0b03a0a 100644 (file)
@@ -95,7 +95,7 @@ enum
 #define DEFAULT_ADAPTER 0
 #define DEFAULT_CREATE_FLAGS 0
 
-#define GST_D3D11_N_FORMATS 18
+#define GST_D3D11_N_FORMATS 29
 
 struct _GstD3D11DevicePrivate
 {
@@ -627,6 +627,18 @@ gst_d3d11_device_setup_format_table (GstD3D11Device * self)
     priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
   n_formats++;
 
+  /* P012 is identical to P016 from runtime point of view */
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P012_LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
+  if (can_support_format (self, DXGI_FORMAT_P016,
+          D3D11_FORMAT_SUPPORT_RENDER_TARGET |
+          D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
+    priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_P016;
+  else
+    priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
+  n_formats++;
+
   priv->format_table[n_formats].format = GST_VIDEO_FORMAT_P016_LE;
   priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
   priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16G16_UNORM;
@@ -657,6 +669,69 @@ gst_d3d11_device_setup_format_table (GstD3D11Device * self)
   priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
   n_formats++;
 
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I420_12LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y42B;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I422_10LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_I422_12LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R8_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R8_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_10LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_12LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y444_16LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[1] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].resource_format[2] = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
+  /* GRAY */
+  /* NOTE: To support conversion by using video processor,
+   * mark DXGI_FORMAT_{R8,R16}_UNORM formats as known dxgi_format.
+   * Otherwise, d3d11 elements will not try to use video processor for
+   * those formats */
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_GRAY8;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R8_UNORM;
+  priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R8_UNORM;
+  n_formats++;
+
+  priv->format_table[n_formats].format = GST_VIDEO_FORMAT_GRAY16_LE;
+  priv->format_table[n_formats].resource_format[0] = DXGI_FORMAT_R16_UNORM;
+  priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_R16_UNORM;
+  n_formats++;
+
   g_assert (n_formats == GST_D3D11_N_FORMATS);
 }
 
index fb2980d..de0bb38 100644 (file)
@@ -28,7 +28,9 @@ G_BEGIN_DECLS
 
 #define GST_D3D11_COMMON_FORMATS \
     "BGRA, RGBA, RGB10A2_LE, BGRx, RGBx, VUYA, NV12, NV21, " \
-    "P010_10LE, P016_LE, I420, YV12, I420_10LE"
+    "P010_10LE, P012_LE, P016_LE, I420, YV12, I420_10LE, I420_12LE, " \
+    "Y42B, I422_10LE, I422_12LE, Y444, Y444_10LE, Y444_12LE, Y444_16LE, " \
+    "GRAY8, GRAY16_LE"
 
 #define GST_D3D11_EXTRA_IN_FORMATS \
     "YUY2, UYVY, VYUY, Y210, Y410"
index 0206080..dd63411 100644 (file)
@@ -115,6 +115,9 @@ static const gchar templ_alpha_const_buffer[] =
 static const PixelShaderTemplate templ_REORDER =
     { FALSE, TRUE, NULL };
 
+static const PixelShaderTemplate templ_REORDER_NO_ALPHA =
+    { FALSE, FALSE, NULL };
+
 static const PixelShaderTemplate templ_YUV_to_RGB =
     { TRUE, FALSE, HLSL_FUNC_YUV_TO_RGB };
 
@@ -288,6 +291,73 @@ static const gchar templ_PACKED_YUV_TO_SEMI_PLANAR_CHROMA_BODY[] =
     "  sample.y = shaderTexture[0].Sample(samplerState, input.Texture).%c;\n"
     "  output.Plane_0 = float4(sample.%c%c, 0.0, 0.0);\n";
 
+/* to GRAY */
+static const gchar templ_RGB_to_GRAY_BODY[] =
+    "  float4 sample, rgba;\n"
+    "  rgba.rgb = shaderTexture[0].Sample(samplerState, input.Texture).rgb;\n"
+    "  sample.x = rgb_to_yuv (sample.rgb).x;\n"
+    "  sample.y = 0.0;\n"
+    "  sample.z = 0.0;\n"
+    "  sample.a = 0.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+static const gchar templ_VUYA_to_GRAY_BODY[] =
+    "  float4 sample;\n"
+    "  sample.x = shaderTexture[0].Sample(samplerState, input.Texture).z;\n"
+    "  sample.y = 0.0;\n"
+    "  sample.z = 0.0;\n"
+    "  sample.a = 0.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+static const gchar templ_YUV_to_GRAY_BODY[] =
+    "  float4 sample;\n"
+    "  sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x * %u;\n"
+    "  sample.y = 0.0;\n"
+    "  sample.z = 0.0;\n"
+    "  sample.a = 0.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+static const gchar templ_GRAY_to_GRAY_BODY[] =
+    "  float4 sample;\n"
+    "  sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x;\n"
+    "  sample.y = 0.0;\n"
+    "  sample.z = 0.0;\n"
+    "  sample.a = 0.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+/* from GRAY */
+static const gchar templ_GRAY_to_RGB_BODY[] =
+    "  float4 sample, rgba;\n"
+    "  sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x;\n"
+    "  sample.y = sample.x;\n"
+    "  sample.z = sample.x;\n"
+    "  sample.a = 1.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+static const gchar templ_GRAY_to_VUYA_BODY[] =
+    "  float4 sample;\n"
+    "  sample.z = shaderTexture[0].Sample(samplerState, input.Texture).x;\n"
+    "  sample.x = 0.5;\n"
+    "  sample.y = 0.5;\n"
+    "  sample.a = 1.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+static const gchar templ_GRAY_to_LUMA_BODY[] =
+    "  float4 sample;\n"
+    "  sample.x = shaderTexture[0].Sample(samplerState, input.Texture).x / %u;\n"
+    "  sample.y = 0.0;\n"
+    "  sample.z = 0.0;\n"
+    "  sample.a = 0.0;\n"
+    "  output.Plane_0 = sample;\n";
+
+static const gchar templ_GRAY_to_PLANAR_CHROMA_BODY[] =
+    "  float val = 0.5 / %u;\n"
+    "  output.Plane_0 = float4(val, 0.0, 0.0, 0.0);\n"
+    "  output.Plane_1 = float4(val, 0.0, 0.0, 0.0);\n";
+
+static const gchar templ_GRAY_to_SEMI_PLANAR_CHROMA_BODY[] =
+    "  output.Plane_0 = float4(0.5, 0.5, 0.0, 0.0);\n";
+
 static const gchar templ_pixel_shader[] =
     /* constant buffer */
     "%s\n"
@@ -696,10 +766,21 @@ static void
 get_planar_component (const GstVideoInfo * info, gchar * u, gchar * v,
     guint * scale)
 {
-  if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_I420_10LE)
-    *scale = 64;
-  else
-    *scale = 1;
+  switch (GST_VIDEO_INFO_FORMAT (info)) {
+    case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+      *scale = (1 << 6);
+      break;
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+      *scale = (1 << 4);
+      break;
+    default:
+      *scale = 1;
+      break;
+  }
 
   if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_YV12) {
     *u = 'z';
@@ -754,6 +835,14 @@ setup_convert_info_yuv_to_rgb (GstD3D11Converter * self,
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
     {
       guint mul;
       gchar u, v;
@@ -767,6 +856,7 @@ setup_convert_info_yuv_to_rgb (GstD3D11Converter * self,
     case GST_VIDEO_FORMAT_NV12:
     case GST_VIDEO_FORMAT_NV21:
     case GST_VIDEO_FORMAT_P010_10LE:
+    case GST_VIDEO_FORMAT_P012_LE:
     case GST_VIDEO_FORMAT_P016_LE:
     {
       gchar u, v;
@@ -802,6 +892,7 @@ setup_convert_info_rgb_to_yuv (GstD3D11Converter * self,
     case GST_VIDEO_FORMAT_NV12:
     case GST_VIDEO_FORMAT_NV21:
     case GST_VIDEO_FORMAT_P010_10LE:
+    case GST_VIDEO_FORMAT_P012_LE:
     case GST_VIDEO_FORMAT_P016_LE:
     {
       gchar u, v;
@@ -817,6 +908,14 @@ setup_convert_info_rgb_to_yuv (GstD3D11Converter * self,
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
     {
       guint div;
       gchar u, v;
@@ -1106,6 +1205,14 @@ is_planar_format (const GstVideoInfo * info)
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
       return TRUE;
     default:
       break;
@@ -1172,6 +1279,180 @@ setup_convert_info_yuv_to_yuv (GstD3D11Converter * self,
 }
 
 static gboolean
+setup_convert_info_rgb_to_gray (GstD3D11Converter * self,
+    const GstVideoInfo * in_info, const GstVideoInfo * out_info)
+{
+  ConvertInfo *info = &self->convert_info;
+
+  info->templ = &templ_RGB_to_YUV;
+  info->ps_output[0] = HLSL_PS_OUTPUT_ONE_PLANE_BODY;
+
+  switch (GST_VIDEO_INFO_FORMAT (out_info)) {
+    case GST_VIDEO_FORMAT_GRAY8:
+    case GST_VIDEO_FORMAT_GRAY16_LE:
+      info->ps_body[0] = g_strdup_printf (templ_RGB_to_GRAY_BODY);
+      break;
+    default:
+      GST_FIXME_OBJECT (self,
+          "Unhandled output format %s",
+          gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info)));
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+setup_convert_info_yuv_to_gray (GstD3D11Converter * self,
+    const GstVideoInfo * in_info, const GstVideoInfo * out_info)
+{
+  ConvertInfo *info = &self->convert_info;
+
+  info->templ = &templ_REORDER_NO_ALPHA;
+  info->ps_output[0] = HLSL_PS_OUTPUT_ONE_PLANE_BODY;
+
+  if (GST_VIDEO_INFO_FORMAT (out_info) != GST_VIDEO_FORMAT_GRAY8 &&
+      GST_VIDEO_INFO_FORMAT (out_info) != GST_VIDEO_FORMAT_GRAY16_LE)
+    return FALSE;
+
+  switch (GST_VIDEO_INFO_FORMAT (in_info)) {
+    case GST_VIDEO_FORMAT_VUYA:
+      info->ps_body[0] = g_strdup_printf (templ_VUYA_to_GRAY_BODY);
+      break;
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
+    case GST_VIDEO_FORMAT_NV12:
+    case GST_VIDEO_FORMAT_NV21:
+    case GST_VIDEO_FORMAT_P010_10LE:
+    case GST_VIDEO_FORMAT_P012_LE:
+    case GST_VIDEO_FORMAT_P016_LE:
+    {
+      gchar u, v;
+      guint scale;
+
+      get_planar_component (in_info, &u, &v, &scale);
+
+      info->ps_body[0] = g_strdup_printf (templ_YUV_to_GRAY_BODY, scale);
+      break;
+    }
+    default:
+      GST_FIXME_OBJECT (self,
+          "Unhandled input format %s",
+          gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (in_info)));
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+setup_convert_info_gray_to_gray (GstD3D11Converter * self,
+    const GstVideoInfo * in_info, const GstVideoInfo * out_info)
+{
+  ConvertInfo *info = &self->convert_info;
+
+  info->templ = &templ_REORDER_NO_ALPHA;
+  info->ps_output[0] = HLSL_PS_OUTPUT_ONE_PLANE_BODY;
+
+  if (GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_FORMAT_GRAY8 &&
+      GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_FORMAT_GRAY16_LE)
+    return FALSE;
+
+  if (GST_VIDEO_INFO_FORMAT (out_info) != GST_VIDEO_FORMAT_GRAY8 &&
+      GST_VIDEO_INFO_FORMAT (out_info) != GST_VIDEO_FORMAT_GRAY16_LE)
+    return FALSE;
+
+  info->ps_body[0] = g_strdup_printf (templ_GRAY_to_GRAY_BODY);
+
+  return TRUE;
+}
+
+static gboolean
+setup_convert_info_gray_to_rgb (GstD3D11Converter * self,
+    const GstVideoInfo * in_info, const GstVideoInfo * out_info)
+{
+  ConvertInfo *info = &self->convert_info;
+
+  info->templ = &templ_REORDER_NO_ALPHA;
+  info->ps_output[0] = HLSL_PS_OUTPUT_ONE_PLANE_BODY;
+
+  if (GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_FORMAT_GRAY8 &&
+      GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_FORMAT_GRAY16_LE)
+    return FALSE;
+
+  info->ps_body[0] = g_strdup_printf (templ_GRAY_to_RGB_BODY);
+
+  return TRUE;
+}
+
+static gboolean
+setup_convert_info_gray_to_yuv (GstD3D11Converter * self,
+    const GstVideoInfo * in_info, const GstVideoInfo * out_info)
+{
+  ConvertInfo *info = &self->convert_info;
+
+  info->templ = &templ_REORDER_NO_ALPHA;
+  info->ps_output[0] = HLSL_PS_OUTPUT_ONE_PLANE_BODY;
+
+  if (GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_FORMAT_GRAY8 &&
+      GST_VIDEO_INFO_FORMAT (in_info) != GST_VIDEO_FORMAT_GRAY16_LE)
+    return FALSE;
+
+  switch (GST_VIDEO_INFO_FORMAT (out_info)) {
+    case GST_VIDEO_FORMAT_VUYA:
+      info->ps_body[0] = g_strdup_printf (templ_GRAY_to_VUYA_BODY);
+      break;
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I420_12LE:
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
+    {
+      gchar u, v;
+      guint div;
+
+      get_planar_component (out_info, &u, &v, &div);
+      info->ps_body[0] = g_strdup_printf (templ_GRAY_to_LUMA_BODY, div);
+      info->ps_body[1] =
+          g_strdup_printf (templ_GRAY_to_PLANAR_CHROMA_BODY, div);
+      info->ps_output[1] = HLSL_PS_OUTPUT_TWO_PLANES_BODY;
+      break;
+    }
+    case GST_VIDEO_FORMAT_NV12:
+    case GST_VIDEO_FORMAT_NV21:
+    case GST_VIDEO_FORMAT_P010_10LE:
+    case GST_VIDEO_FORMAT_P012_LE:
+    case GST_VIDEO_FORMAT_P016_LE:
+      info->ps_body[0] = g_strdup_printf (templ_GRAY_to_LUMA_BODY, 1);
+      info->ps_body[1] =
+          g_strdup_printf (templ_GRAY_to_SEMI_PLANAR_CHROMA_BODY);
+      info->ps_output[1] = HLSL_PS_OUTPUT_ONE_PLANE_BODY;
+    default:
+      GST_FIXME_OBJECT (self,
+          "Unhandled output format %s",
+          gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (out_info)));
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
 gst_d3d11_color_convert_setup_shader (GstD3D11Converter * self,
     GstD3D11Device * device, GstVideoInfo * in_info, GstVideoInfo * out_info)
 {
@@ -1562,6 +1843,9 @@ gst_d3d11_converter_new (GstD3D11Device * device,
     } else if (GST_VIDEO_INFO_IS_YUV (out_info)) {
       is_supported =
           setup_convert_info_rgb_to_yuv (converter, in_info, out_info);
+    } else if (GST_VIDEO_INFO_IS_GRAY (out_info)) {
+      is_supported =
+          setup_convert_info_rgb_to_gray (converter, in_info, out_info);
     }
   } else if (GST_VIDEO_INFO_IS_YUV (in_info)) {
     if (GST_VIDEO_INFO_IS_RGB (out_info)) {
@@ -1570,6 +1854,20 @@ gst_d3d11_converter_new (GstD3D11Device * device,
     } else if (GST_VIDEO_INFO_IS_YUV (out_info)) {
       is_supported =
           setup_convert_info_yuv_to_yuv (converter, in_info, out_info);
+    } else if (GST_VIDEO_INFO_IS_GRAY (out_info)) {
+      is_supported =
+          setup_convert_info_yuv_to_gray (converter, in_info, out_info);
+    }
+  } else if (GST_VIDEO_INFO_IS_GRAY (in_info)) {
+    if (GST_VIDEO_INFO_IS_RGB (out_info)) {
+      is_supported =
+          setup_convert_info_gray_to_rgb (converter, in_info, out_info);
+    } else if (GST_VIDEO_INFO_IS_YUV (out_info)) {
+      is_supported =
+          setup_convert_info_gray_to_yuv (converter, in_info, out_info);
+    } else if (GST_VIDEO_INFO_IS_GRAY (out_info)) {
+      is_supported =
+          setup_convert_info_gray_to_gray (converter, in_info, out_info);
     }
   }
 
@@ -1873,10 +2171,12 @@ gst_d3d11_converter_update_viewport (GstD3D11Converter * converter,
     case GST_VIDEO_FORMAT_NV12:
     case GST_VIDEO_FORMAT_NV21:
     case GST_VIDEO_FORMAT_P010_10LE:
+    case GST_VIDEO_FORMAT_P012_LE:
     case GST_VIDEO_FORMAT_P016_LE:
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_YV12:
     case GST_VIDEO_FORMAT_I420_10LE:
+    case GST_VIDEO_FORMAT_I420_12LE:
     {
       guint i;
       converter->viewport[1].TopLeftX = converter->viewport[0].TopLeftX / 2;
@@ -1889,6 +2189,31 @@ gst_d3d11_converter_update_viewport (GstD3D11Converter * converter,
 
       break;
     }
+    case GST_VIDEO_FORMAT_Y42B:
+    case GST_VIDEO_FORMAT_I422_10LE:
+    case GST_VIDEO_FORMAT_I422_12LE:
+    {
+      guint i;
+      converter->viewport[1].TopLeftX = converter->viewport[0].TopLeftX / 2;
+      converter->viewport[1].TopLeftY = converter->viewport[0].TopLeftY;
+      converter->viewport[1].Width = converter->viewport[0].Width / 2;
+      converter->viewport[1].Height = converter->viewport[0].Height;
+
+      for (i = 2; i < GST_VIDEO_INFO_N_PLANES (&converter->out_info); i++)
+        converter->viewport[i] = converter->viewport[1];
+
+      break;
+    }
+    case GST_VIDEO_FORMAT_Y444:
+    case GST_VIDEO_FORMAT_Y444_10LE:
+    case GST_VIDEO_FORMAT_Y444_12LE:
+    case GST_VIDEO_FORMAT_Y444_16LE:
+    {
+      guint i;
+      for (i = 1; i < GST_VIDEO_INFO_N_PLANES (&converter->out_info); i++)
+        converter->viewport[i] = converter->viewport[1];
+      break;
+    }
     default:
       if (converter->num_output_view > 1)
         g_assert_not_reached ();
index 8d49cb0..64e04b4 100644 (file)
@@ -2368,6 +2368,14 @@ gst_d3d11_deinterlace_register (GstPlugin * plugin, GstD3D11Device * device,
       g_value_init (supported_formats, GST_TYPE_LIST);
     }
 
+    if (formats_to_check[i] == DXGI_FORMAT_P016) {
+      /* This is used for P012 as well */
+      g_value_init (&val, G_TYPE_STRING);
+      g_value_set_static_string (&val,
+          gst_video_format_to_string (GST_VIDEO_FORMAT_P012_LE));
+      gst_value_list_append_and_take_value (supported_formats, &val);
+    }
+
     g_value_init (&val, G_TYPE_STRING);
     g_value_set_static_string (&val, gst_video_format_to_string (format));
     gst_value_list_append_and_take_value (supported_formats, &val);
index 675a68e..44e9376 100644 (file)
@@ -45,6 +45,24 @@ typedef struct _TestFrame
 static const guint8 rgba_reorder_data[] = { 0x49, 0x24, 0x72, 0xff };
 static const guint8 bgra_reorder_data[] = { 0x72, 0x24, 0x49, 0xff };
 
+static const gchar *YUV_FORMATS[] = {
+  "VUYA", "NV12", "P010_10LE", "P012_LE", "P016_LE", "I420", "I420_10LE",
+  "I420_12LE", "YV12", "NV21", "Y444", "Y444_10LE", "Y444_12LE", "Y444_16LE",
+  "Y42B", "I422_10LE", "I422_12LE",
+};
+
+static const gchar *RGB_FORMATS[] = {
+  "BGRA", "RGBA", "RGB10A2_LE", "BGRx", "RGBx",
+};
+
+static const gchar *PACKED_YUV_FORMATS[] = {
+  "YUY2", "UYVY", "VYUY", "Y210", "Y410",
+};
+
+static const gchar *GRAY_FORMATS[] = {
+  "GRAY8", "GRAY16_LE"
+};
+
 static TestFrame test_rgba_reorder[] = {
   {1, 1, GST_VIDEO_FORMAT_RGBA, {(guint8 *) & rgba_reorder_data}},
   {1, 1, GST_VIDEO_FORMAT_BGRA, {(guint8 *) & bgra_reorder_data}},
@@ -102,7 +120,6 @@ GST_START_TEST (test_d3d11_color_convert_rgba_reorder)
 
 GST_END_TEST;
 
-#if RUN_VISUAL_TEST
 static gboolean
 bus_cb (GstBus * bus, GstMessage * message, gpointer data)
 {
@@ -162,19 +179,15 @@ run_convert_pipelne (const gchar * in_format, const gchar * out_format)
 
 GST_START_TEST (test_d3d11_color_convert_yuv_yuv)
 {
-  const gchar *format_list[] = {
-    "VUYA", "NV12", "P010_10LE", "P016_LE", "I420", "I420_10LE", "YV12", "NV21"
-  };
-
   gint i, j;
 
-  for (i = 0; i < G_N_ELEMENTS (format_list); i++) {
-    for (j = 0; j < G_N_ELEMENTS (format_list); j++) {
+  for (i = 0; i < G_N_ELEMENTS (YUV_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (YUV_FORMATS); j++) {
       if (i == j)
         continue;
 
-      GST_DEBUG ("run conversion %s to %s", format_list[i], format_list[j]);
-      run_convert_pipelne (format_list[i], format_list[j]);
+      GST_DEBUG ("run conversion %s to %s", YUV_FORMATS[i], YUV_FORMATS[j]);
+      run_convert_pipelne (YUV_FORMATS[i], YUV_FORMATS[j]);
     }
   }
 }
@@ -183,24 +196,32 @@ GST_END_TEST;
 
 GST_START_TEST (test_d3d11_color_convert_yuv_rgb)
 {
-  const gchar *in_format_list[] = {
-    "VUYA", "NV12", "P010_10LE", "P016_LE", "I420", "I420_10LE", "YV12", "NV21"
-  };
-  const gchar *out_format_list[] = {
-    "BGRA", "RGBA", "RGB10A2_LE", "BGRx", "RGBx",
-  };
+  gint i, j;
+
+  for (i = 0; i < G_N_ELEMENTS (YUV_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (RGB_FORMATS); j++) {
+      if (i == j)
+        continue;
+
+      GST_DEBUG ("run conversion %s to %s", YUV_FORMATS[i], RGB_FORMATS[j]);
+      run_convert_pipelne (YUV_FORMATS[i], RGB_FORMATS[j]);
+    }
+  }
+}
 
+GST_END_TEST;
 
+GST_START_TEST (test_d3d11_color_convert_yuv_gray)
+{
   gint i, j;
 
-  for (i = 0; i < G_N_ELEMENTS (in_format_list); i++) {
-    for (j = 0; j < G_N_ELEMENTS (out_format_list); j++) {
+  for (i = 0; i < G_N_ELEMENTS (YUV_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (GRAY_FORMATS); j++) {
       if (i == j)
         continue;
 
-      GST_DEBUG ("run conversion %s to %s", in_format_list[i],
-          out_format_list[j]);
-      run_convert_pipelne (in_format_list[i], out_format_list[j]);
+      GST_DEBUG ("run conversion %s to %s", YUV_FORMATS[i], GRAY_FORMATS[j]);
+      run_convert_pipelne (YUV_FORMATS[i], GRAY_FORMATS[j]);
     }
   }
 }
@@ -209,20 +230,12 @@ GST_END_TEST;
 
 GST_START_TEST (test_d3d11_color_convert_rgb_yuv)
 {
-  const gchar *in_format_list[] = {
-    "BGRA", "RGBA", "RGB10A2_LE", "BGRx", "RGBx",
-  };
-  const gchar *out_format_list[] = {
-    "VUYA", "NV12", "P010_10LE", "P016_LE", "I420", "I420_10LE", "YV12", "NV21"
-  };
-
   gint i, j;
 
-  for (i = 0; i < G_N_ELEMENTS (in_format_list); i++) {
-    for (j = 0; j < G_N_ELEMENTS (out_format_list); j++) {
-      GST_DEBUG ("run conversion %s to %s", in_format_list[i],
-          out_format_list[j]);
-      run_convert_pipelne (in_format_list[i], out_format_list[j]);
+  for (i = 0; i < G_N_ELEMENTS (RGB_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (YUV_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", RGB_FORMATS[i], YUV_FORMATS[j]);
+      run_convert_pipelne (RGB_FORMATS[i], YUV_FORMATS[j]);
     }
   }
 }
@@ -231,41 +244,44 @@ GST_END_TEST;
 
 GST_START_TEST (test_d3d11_color_convert_rgb_rgb)
 {
-  const gchar *format_list[] = {
-    "BGRA", "RGBA", "RGB10A2_LE", "BGRx", "RGBx",
-  };
-
   gint i, j;
 
-  for (i = 0; i < G_N_ELEMENTS (format_list); i++) {
-    for (j = 0; j < G_N_ELEMENTS (format_list); j++) {
+  for (i = 0; i < G_N_ELEMENTS (RGB_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (RGB_FORMATS); j++) {
       if (i == j)
         continue;
 
-      GST_DEBUG ("run conversion %s to %s", format_list[i], format_list[j]);
-      run_convert_pipelne (format_list[i], format_list[j]);
+      GST_DEBUG ("run conversion %s to %s", RGB_FORMATS[i], RGB_FORMATS[j]);
+      run_convert_pipelne (RGB_FORMATS[i], RGB_FORMATS[j]);
     }
   }
 }
 
 GST_END_TEST;
 
-GST_START_TEST (test_d3d11_color_convert_packed_yuv_yuv)
+GST_START_TEST (test_d3d11_color_convert_rgb_gray)
 {
-  const gchar *in_format_list[] = {
-    "YUY2", "UYVY", "VYUY", "Y210", "Y410",
-  };
-  const gchar *out_format_list[] = {
-    "VUYA", "NV12", "P010_10LE", "P016_LE", "I420", "I420_10LE", "YV12", "NV21"
-  };
+  gint i, j;
 
+  for (i = 0; i < G_N_ELEMENTS (RGB_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (GRAY_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", RGB_FORMATS[i], GRAY_FORMATS[j]);
+      run_convert_pipelne (RGB_FORMATS[i], GRAY_FORMATS[j]);
+    }
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_d3d11_color_convert_packed_yuv_yuv)
+{
   gint i, j;
 
-  for (i = 0; i < G_N_ELEMENTS (in_format_list); i++) {
-    for (j = 0; j < G_N_ELEMENTS (out_format_list); j++) {
-      GST_DEBUG ("run conversion %s to %s", in_format_list[i],
-          out_format_list[j]);
-      run_convert_pipelne (in_format_list[i], out_format_list[j]);
+  for (i = 0; i < G_N_ELEMENTS (PACKED_YUV_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (YUV_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", PACKED_YUV_FORMATS[i],
+          YUV_FORMATS[j]);
+      run_convert_pipelne (PACKED_YUV_FORMATS[i], YUV_FORMATS[j]);
     }
   }
 }
@@ -274,43 +290,84 @@ GST_END_TEST;
 
 GST_START_TEST (test_d3d11_color_convert_packed_yuv_rgb)
 {
-  const gchar *in_format_list[] = {
-    "YUY2", "UYVY", "VYUY", "Y210", "Y410",
-  };
-  const gchar *out_format_list[] = {
-    "BGRA", "RGBA", "RGB10A2_LE", "BGRx", "RGBx",
-  };
+  gint i, j;
+
+  for (i = 0; i < G_N_ELEMENTS (PACKED_YUV_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (RGB_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", PACKED_YUV_FORMATS[i],
+          RGB_FORMATS[j]);
+      run_convert_pipelne (PACKED_YUV_FORMATS[i], RGB_FORMATS[j]);
+    }
+  }
+}
+
+GST_END_TEST;
 
+GST_START_TEST (test_d3d11_color_convert_packed_yuv_gray)
+{
   gint i, j;
 
-  for (i = 0; i < G_N_ELEMENTS (in_format_list); i++) {
-    for (j = 0; j < G_N_ELEMENTS (out_format_list); j++) {
-      GST_DEBUG ("run conversion %s to %s", in_format_list[i],
-          out_format_list[j]);
-      run_convert_pipelne (in_format_list[i], out_format_list[j]);
+  for (i = 0; i < G_N_ELEMENTS (PACKED_YUV_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (GRAY_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", PACKED_YUV_FORMATS[i],
+          GRAY_FORMATS[j]);
+      run_convert_pipelne (PACKED_YUV_FORMATS[i], GRAY_FORMATS[j]);
+    }
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_d3d11_color_convert_gray_yuv)
+{
+  gint i, j;
+
+  for (i = 0; i < G_N_ELEMENTS (GRAY_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (YUV_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", GRAY_FORMATS[i], YUV_FORMATS[j]);
+      run_convert_pipelne (GRAY_FORMATS[i], YUV_FORMATS[j]);
+    }
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_d3d11_color_convert_gray_rgb)
+{
+  gint i, j;
+
+  for (i = 0; i < G_N_ELEMENTS (GRAY_FORMATS); i++) {
+    for (j = 0; j < G_N_ELEMENTS (RGB_FORMATS); j++) {
+      GST_DEBUG ("run conversion %s to %s", GRAY_FORMATS[i], RGB_FORMATS[j]);
+      run_convert_pipelne (GRAY_FORMATS[i], RGB_FORMATS[j]);
     }
   }
 }
 
 GST_END_TEST;
-#endif /* RUN_VISUAL_TEST */
 
 static Suite *
 d3d11colorconvert_suite (void)
 {
   Suite *s = suite_create ("d3d11colorconvert");
   TCase *tc_basic = tcase_create ("general");
+  const gchar *run_visual_test = g_getenv ("RUN_VISUAL_TEST");
 
   suite_add_tcase (s, tc_basic);
   tcase_add_test (tc_basic, test_d3d11_color_convert_rgba_reorder);
-#if RUN_VISUAL_TEST
-  tcase_add_test (tc_basic, test_d3d11_color_convert_yuv_yuv);
-  tcase_add_test (tc_basic, test_d3d11_color_convert_yuv_rgb);
-  tcase_add_test (tc_basic, test_d3d11_color_convert_rgb_yuv);
-  tcase_add_test (tc_basic, test_d3d11_color_convert_rgb_rgb);
-  tcase_add_test (tc_basic, test_d3d11_color_convert_packed_yuv_yuv);
-  tcase_add_test (tc_basic, test_d3d11_color_convert_packed_yuv_rgb);
-#endif
+  if (run_visual_test != NULL) {
+    tcase_add_test (tc_basic, test_d3d11_color_convert_yuv_yuv);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_yuv_rgb);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_yuv_gray);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_rgb_yuv);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_rgb_rgb);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_rgb_gray);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_packed_yuv_yuv);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_packed_yuv_rgb);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_packed_yuv_gray);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_gray_yuv);
+    tcase_add_test (tc_basic, test_d3d11_color_convert_gray_rgb);
+  }
 
   return s;
 }