[vlc-devel] [PATCH] direct3d11: use a different pixel shader depending on the output format

Steve Lhomme robux4 at videolabs.io
Fri Mar 27 10:56:14 CET 2015


Differentiate between BT.601 (SD) and BT.709 (HD) for YUV pixel conversion
use the same precision values as the openGL vout
---
 modules/video_output/msw/direct3d11.c | 62 ++++++++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 12 deletions(-)

diff --git a/modules/video_output/msw/direct3d11.c b/modules/video_output/msw/direct3d11.c
index 09334fb..987c75e 100644
--- a/modules/video_output/msw/direct3d11.c
+++ b/modules/video_output/msw/direct3d11.c
@@ -168,7 +168,7 @@ static const char* globPixelShaderDefault = "\
   }\
 ";
 
-static const char* globPixelShaderBiplanarYUV2RGB = "\
+static const char *globPixelShaderBiplanarYUV_BT601_2RGB = "\
   Texture2D shaderTextureY;\
   Texture2D shaderTextureUV;\
   SamplerState SampleType;\
@@ -185,17 +185,44 @@ static const char* globPixelShaderBiplanarYUV2RGB = "\
     float4 rgba;\
     yuv.x  = shaderTextureY.Sample(SampleType, In.Texture).x;\
     yuv.yz = shaderTextureUV.Sample(SampleType, In.Texture).xy;\
-    yuv.x  = 1.164 * (yuv.x-0.0625);\
+    yuv.x  = 1.164383561643836 * (yuv.x-0.0625);\
     yuv.y  = yuv.y - 0.5;\
     yuv.z  = yuv.z - 0.5;\
-    rgba.x = saturate(yuv.x + 1.596 * yuv.z);\
-    rgba.y = saturate(yuv.x - 0.813 * yuv.z - 0.391 * yuv.y);\
-    rgba.z = saturate(yuv.x + 2.018 * yuv.y);\
+    rgba.x = saturate(yuv.x + 1.596026785714286 * yuv.z);\
+    rgba.y = saturate(yuv.x - 0.812967647237771 * yuv.z - 0.391762290094914 * yuv.y);\
+    rgba.z = saturate(yuv.x + 2.017232142857142 * yuv.y);\
     rgba.w = 1.0;\
     return rgba;\
   }\
 ";
 
+static const char *globPixelShaderBiplanarYUV_BT709_2RGB = "\
+  Texture2D shaderTextureY;\
+  Texture2D shaderTextureUV;\
+  SamplerState SampleType;\
+  \
+  struct PS_INPUT\
+  {\
+    float4 Position   : SV_POSITION;\
+    float2 Texture    : TEXCOORD0;\
+  };\
+  \
+  float4 PS( PS_INPUT In ) : SV_TARGET\
+  {\
+    float3 yuv;\
+    float4 rgba;\
+    yuv.x  = shaderTextureY.Sample(SampleType, In.Texture).x;\
+    yuv.yz = shaderTextureUV.Sample(SampleType, In.Texture).xy;\
+    yuv.x  = 1.164383561643836 * (yuv.x-0.0625);\
+    yuv.y  = yuv.y - 0.5;\
+    yuv.z  = yuv.z - 0.5;\
+    rgba.x = saturate(yuv.x + 1.792741071428571 * yuv.z);\
+    rgba.y = saturate(yuv.x - 0.532909328559444 * yuv.z - 0.21324861427373 * yuv.y);\
+    rgba.z = saturate(yuv.x + 2.112401785714286 * yuv.y);\
+    rgba.w = 1.0;\
+    return rgba;\
+  }\
+";
 
 static int Open(vlc_object_t *object)
 {
@@ -597,6 +624,21 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
             sys->vlcFormat    = d3d_formats[i].fourcc;
             sys->d3dFormatY   = d3d_formats[i].formatY;
             sys->d3dFormatUV  = d3d_formats[i].formatUV;
+            switch (sys->vlcFormat)
+            {
+            case VLC_CODEC_NV12:
+                if( fmt->i_height > 576 )
+                    sys->d3dPxShader = globPixelShaderBiplanarYUV_BT709_2RGB;
+                else
+                    sys->d3dPxShader = globPixelShaderBiplanarYUV_BT601_2RGB;
+                break;
+            case VLC_CODEC_RGB32:
+            case VLC_CODEC_BGRA:
+            case VLC_CODEC_RGB16:
+            default:
+                sys->d3dPxShader = globPixelShaderDefault;
+                break;
+            }
             break;
         }
     }
@@ -747,16 +789,12 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
     ID3DBlob* pPSBlob = NULL;
 
     /* TODO : Match the version to the D3D_FEATURE_LEVEL */
-    if( sys->d3dFormatUV )
-        hr = D3DCompile(globPixelShaderBiplanarYUV2RGB, strlen(globPixelShaderBiplanarYUV2RGB),
-                        NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
-    else
-        hr = D3DCompile(globPixelShaderDefault, strlen(globPixelShaderDefault),
-                        NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
+    hr = D3DCompile(sys->d3dPxShader, strlen(sys->d3dPxShader),
+                    NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
 
 
     if( FAILED(hr)) {
-      msg_Err(vd, "The Pixel Shader is invalid.");
+      msg_Err(vd, "The Pixel Shader is invalid. (hr=0x%lX)", hr );
       return VLC_EGENERIC;
     }
 
-- 
2.3.0




More information about the vlc-devel mailing list