/*******************************************************************/ /* */ /* ADOBE CONFIDENTIAL */ /* _ _ _ _ _ _ _ _ _ _ _ _ _ */ /* */ /* Copyright 2004 Adobe Systems Incorporated */ /* All Rights Reserved. */ /* */ /* NOTICE: All information contained herein is, and remains the */ /* property of Adobe Systems Incorporated and its suppliers, if */ /* any. The intellectual and technical concepts contained */ /* herein are proprietary to Adobe Systems Incorporated and its */ /* suppliers and may be covered by U.S. and Foreign Patents, */ /* patents in process, and are protected by trade secret or */ /* copyright law. Dissemination of this information or */ /* reproduction of this material is strictly forbidden unless */ /* prior written permission is obtained from Adobe Systems */ /* Incorporated. */ /* */ /*******************************************************************/ #include "ScreenQuadInclude.fx" #include "VideoSourceTextureInclude.fx" #include "ColorSpaceConversionsInclude.fx" /* ** HostMediaSource */ /* ** Straight RGBA copy */ float4 CopyBGRA_4444_8u_PS( QuadVertexOutput inVertexInfo) : COLOR { float4 texturePixel = tex2D(ImageSampler, inVertexInfo.UV); return texturePixel; } /* ** Premultiplied RGBA copy */ float4 CopyPremultipliedBGRA_4444_8u_PS( QuadVertexOutput inVertexInfo) : COLOR { float4 texturePixel = tex2D(ImageSampler, inVertexInfo.UV); texturePixel.rgb *= texturePixel.a; return texturePixel; } /* ** Premultiplied RGBA copy - Invert alpha */ float4 CopyPremultipliedBGRA_4444_8u_InvertAlpha_PS( QuadVertexOutput inVertexInfo) : COLOR { float4 texturePixel = tex2D(ImageSampler, inVertexInfo.UV); texturePixel.a = (1.0 - texturePixel.a); texturePixel.rgb *= texturePixel.a; return texturePixel; } /* ** Premultiplied RGBA copy - Ignore alpha */ float4 CopyPremultipliedBGRA_4444_8u_IgnoreAlpha_PS( QuadVertexOutput inVertexInfo) : COLOR { float4 texturePixel = tex2D(ImageSampler, inVertexInfo.UV); texturePixel.a = 1.0; return texturePixel; } /* ** YUV -> premultiplied RGB conversion */ float4 CopyVUYA_4444_8u_PS( QuadVertexOutput inVertexInfo) : COLOR { float4 texturePixel = tex2D(ImageSampler, inVertexInfo.UV); float Y = texturePixel.r; float Cr = texturePixel.g; float Cb = texturePixel.b; return YCbCrA601ToPremultipliedRGBA(float4(Y, Cr, Cb, texturePixel.a)); } static const float YHeightScaleFactorInYUV420 = 2.0f/3.0f; static const float UVHeightScaleFactorInYUV420 = 1.0f/3.0f; /* ** YUV420 ->RGB Conversion */ float4 CopyYUV_420_8u_PS( QuadVertexOutput inVertexInfo) : COLOR { float2 texCoord; // Get the Y channel texCoord.x = inVertexInfo.UV.x; texCoord.y = inVertexInfo.UV.y * YHeightScaleFactorInYUV420; float Y = tex2D(ImageSampler, texCoord); // Get the U channel texCoord.x *= 0.5f; texCoord.y = YHeightScaleFactorInYUV420 + inVertexInfo.UV.y * UVHeightScaleFactorInYUV420; float U = tex2D(ImageSampler, texCoord); // Get the V channel // Add an offset of 0.5 to the 'u' texture coord used for the U channel // Use the same 'v' texture coord as for the U channel texCoord.x += 0.5; float V = tex2D(ImageSampler, texCoord); return YCbCrA601ToPremultipliedRGBA(float4(Y, U, V, 1.0f)); } static const float YHeightScaleFactorInYUV420Interlaced = 1.0f/3.0f; static const float UVHeightScaleFactorInYUV420Interlaced = 0.5f/3.0f; /* ** YUV420 Interlaced ->RGB Conversion */ float4 CopyYUV_420_Interlaced_8u_PS( QuadVertexOutput inVertexInfo) : COLOR { // Normalized GPU Texture: // //Base Address of Y upper plane ----> ________________________________ // | Y upper | // | Width = 1 and Height = 0.3333 | // | | //Base Address of Y lower plane ----> |_______________________________| // | Y lower | // | Width = 1 and Height = 0.3333 | // | .---------------|---- Base Address of V upper plane //Base Address of U upper plane ----> |_______________v_______________| _ // | U upper | V upper | | Height = 0.1666 //Base Address of U lower plane ----> |_______________ _______________| _| // | U lower ^ V lower | | Height = 0.1666 // |_______________|_______________| _| // | // '.___________________ Base Address of V lower plane // \______________/ // Width = 0.5 // float2 texCoord; float isLowerField; isLowerField = floor(frac((inVertexInfo.UV.y * QuadScreenSize.y) * 0.5) * 2); // Get the Y channel texCoord.x = inVertexInfo.UV.x; texCoord.y = inVertexInfo.UV.y * YHeightScaleFactorInYUV420Interlaced; if (isLowerField) { texCoord.y += YHeightScaleFactorInYUV420Interlaced; } float Y = tex2D(ImageSampler, texCoord); // Get the U channel texCoord.x *= 0.5f; texCoord.y = YHeightScaleFactorInYUV420 + inVertexInfo.UV.y * UVHeightScaleFactorInYUV420Interlaced; if (isLowerField) { texCoord.y += UVHeightScaleFactorInYUV420Interlaced; } float U = tex2D(ImageSampler, texCoord); // Get the V channel // Add an offset of 0.5 to the 'u' texture coord used for the U channel // Use the same 'v' texture coord as for the U channel texCoord.x += 0.5; float V = tex2D(ImageSampler, texCoord); return YCbCrA601ToPremultipliedRGBA(float4(Y, U, V, 1.0f)); } /* ** YUYV422 - 601 -> premultiplied RGB Conversion */ float4 CopyYUYV_422_8u_601_PS( QuadVertexOutput inVertexInfo) : COLOR { float isOddUV, texelWidth; isOddUV = frac(floor(inVertexInfo.UV.x * QuadScreenSize.x) * 0.5) * 2; texelWidth = 1.0 / (QuadScreenSize.x); // We need two adjacent A8L8 pixels in order to compute two output pixels, // out of which we need to pick one. To determine whether to look for the adjacent A8L8 // pixel on the left or on the right of the current UV location, we determine if the current UV // location is odd or even. // Assuming [Even Odd Even Odd .......] UV addressing: // If UV location addresses an even pixel, we need the texel on the right. // If UV location addresses an odd pixel, we need the texel on the left. float2 texCoord0, texCoord1; texCoord0.x = inVertexInfo.UV.x - (isOddUV * texelWidth); texCoord0.y = inVertexInfo.UV.y; texCoord1.x = texCoord0.x + texelWidth; texCoord1.y = texCoord0.y; float4 texColor0, texColor1; // Sample two adjacent pixels texColor0 = tex2D( ImageSampler, texCoord0 ); texColor1 = tex2D( ImageSampler, texCoord1 ); texColor0.r = texColor0.r; // Y0 texColor0.g = texColor0.a; // U0 texColor0.b = texColor1.a; // V0 texColor1.r = texColor1.r; // Y1 texColor1.g = texColor0.a; // U0 texColor1.b = texColor1.a; // V0 texColor0 *= (1.0-isOddUV); texColor1 *= (isOddUV); // Choose one of the two pixels texColor0 = texColor0 + texColor1; return YCbCrA601ToPremultipliedRGBA(float4(texColor0.r, texColor0.g, texColor0.b, 1.0f)); } /* ** UYVY422 - 601 -> premultiplied RGB Conversion */ float4 CopyUYVY_422_8u_601_PS( QuadVertexOutput inVertexInfo) : COLOR { float isOddUV, texelWidth; isOddUV = floor(frac((inVertexInfo.UV.x * QuadScreenSize.x) * 0.5) * 2); texelWidth = 1.0 / QuadScreenSize.x; // We need two adjacent A8L8 pixels in order to compute two output pixels, // out of which we need to pick one. To determine whether to look for the adjacent A8L8 // pixel on the left or on the right of the current UV location, we determine if the current UV // location is odd or even. // Assuming [Even Odd Even Odd .......] UV addressing: // If UV location addresses an even pixel, we need the texel on the right. // If UV location addresses an odd pixel, we need the texel on the left. float2 texCoord0, texCoord1; texCoord0.x = inVertexInfo.UV.x - (isOddUV * texelWidth); texCoord0.y = inVertexInfo.UV.y; texCoord1.x = texCoord0.x + texelWidth; texCoord1.y = texCoord0.y; float4 texColor0, texColor1; // Sample two adjacent pixels texColor0 = tex2D( ImageSampler, texCoord0 ); texColor1 = tex2D( ImageSampler, texCoord1 ); texColor0.r = texColor0.a; // Y0 texColor0.g = texColor0.g; // U0 texColor0.b = texColor1.b; // V0 texColor1.r = texColor1.a; // Y1 texColor1.g = texColor0.g; // U0 texColor1.b = texColor1.b; // V0 texColor0 *= (1-isOddUV); texColor1 *= (isOddUV); // Choose one of the two pixels texColor0 = texColor0 + texColor1; return YCbCrA601ToPremultipliedRGBA(float4(texColor0.r, texColor0.g, texColor0.b, 1.0f)); } /* ** YUYV422 - 709 -> premultiplied RGB Conversion */ float4 CopyYUYV_422_8u_709_PS( QuadVertexOutput inVertexInfo) : COLOR { float isOddUV, texelWidth; isOddUV = frac(floor(inVertexInfo.UV.x * QuadScreenSize.x) * 0.5) * 2; texelWidth = 1.0 / (QuadScreenSize.x); // We need two adjacent A8L8 pixels in order to compute two output pixels, // out of which we need to pick one. To determine whether to look for the adjacent A8L8 // pixel on the left or on the right of the current UV location, we determine if the current UV // location is odd or even. // Assuming [Even Odd Even Odd .......] UV addressing: // If UV location addresses an even pixel, we need the texel on the right. // If UV location addresses an odd pixel, we need the texel on the left. float2 texCoord0, texCoord1; texCoord0.x = inVertexInfo.UV.x - (isOddUV * texelWidth); texCoord0.y = inVertexInfo.UV.y; texCoord1.x = texCoord0.x + texelWidth; texCoord1.y = texCoord0.y; float4 texColor0, texColor1; // Sample two adjacent pixels texColor0 = tex2D( ImageSampler, texCoord0 ); texColor1 = tex2D( ImageSampler, texCoord1 ); texColor0.r = texColor0.r; // Y0 texColor0.g = texColor0.a; // U0 texColor0.b = texColor1.a; // V0 texColor1.r = texColor1.r; // Y1 texColor1.g = texColor0.a; // U0 texColor1.b = texColor1.a; // V0 texColor0 *= (1.0-isOddUV); texColor1 *= (isOddUV); // Choose one of the two pixels texColor0 = texColor0 + texColor1; float Y = texColor0.r; float Cr = texColor0.g; float Cb = texColor0.b; return YCbCrA709ToPremultipliedRGBA(float4(Y, Cr, Cb, 1.0f)); } /* ** UYVY422 - 709 -> premultiplied RGB Conversion */ float4 CopyUYVY_422_8u_709_PS( QuadVertexOutput inVertexInfo) : COLOR { float isOddUV, texelWidth; isOddUV = floor(frac((inVertexInfo.UV.x * QuadScreenSize.x) * 0.5) * 2); texelWidth = 1.0 / QuadScreenSize.x; // We need two adjacent A8L8 pixels in order to compute two output pixels, // out of which we need to pick one. To determine whether to look for the adjacent A8L8 // pixel on the left or on the right of the current UV location, we determine if the current UV // location is odd or even. // Assuming [Even Odd Even Odd .......] UV addressing: // If UV location addresses an even pixel, we need the texel on the right. // If UV location addresses an odd pixel, we need the texel on the left. float2 texCoord0, texCoord1; texCoord0.x = inVertexInfo.UV.x - (isOddUV * texelWidth); texCoord0.y = inVertexInfo.UV.y; texCoord1.x = texCoord0.x + texelWidth; texCoord1.y = texCoord0.y; float4 texColor0, texColor1; // Sample two adjacent pixels texColor0 = tex2D( ImageSampler, texCoord0 ); texColor1 = tex2D( ImageSampler, texCoord1 ); texColor0.r = texColor0.a; // Y0 texColor0.g = texColor0.g; // U0 texColor0.b = texColor1.b; // V0 texColor1.r = texColor1.a; // Y1 texColor1.g = texColor0.g; // U0 texColor1.b = texColor1.b; // V0 texColor0 *= (1-isOddUV); texColor1 *= (isOddUV); // Choose one of the two pixels texColor0 = texColor0 + texColor1; float Y = texColor0.r; float Cr = texColor0.g; float Cb = texColor0.b; return YCbCrA709ToPremultipliedRGBA(float4(Y, Cr, Cb, 1.0f)); } /* ** Techniques */ /* ** Uses a Straight copy pixel shader */ technique LoadTextureBGRA_4444_8u { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_1_1 CopyBGRA_4444_8u_PS(); } } /* ** Uses a Premultiplied copy pixel shader */ technique LoadTexturePremultipliedBGRA_4444_8u { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_1_1 CopyPremultipliedBGRA_4444_8u_PS(); } } technique LoadTexturePremultipliedBGRA_4444_8u_InvertAlpha { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_1_1 CopyPremultipliedBGRA_4444_8u_InvertAlpha_PS(); } } technique LoadTexturePremultipliedBGRA_4444_8u_IgnoreAlpha { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_1_1 CopyPremultipliedBGRA_4444_8u_IgnoreAlpha_PS(); } } technique LoadTextureVUYA_4444_8u { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_2_0 CopyVUYA_4444_8u_PS(); } } technique LoadTextureYUV_420_8u { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS420(); PixelShader = compile ps_2_0 CopyYUV_420_8u_PS(); } } technique LoadTextureYUV_420_Interlaced_8u { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS420Interlaced(); PixelShader = compile ps_2_0 CopyYUV_420_Interlaced_8u_PS(); } } technique LoadTextureYUYV_422_8u_601 { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_2_0 CopyYUYV_422_8u_601_PS(); } } technique LoadTextureUYVY_422_8u_601 { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_2_0 CopyUYVY_422_8u_601_PS(); } } technique LoadTextureYUYV_422_8u_709 { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_2_0 CopyYUYV_422_8u_709_PS(); } } technique LoadTextureUYVY_422_8u_709 { pass P0 { // shaders VertexShader = compile vs_1_1 ScreenQuadVS(); PixelShader = compile ps_2_0 CopyUYVY_422_8u_709_PS(); } }