Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
6th August 2012, 03:24 | #20021 | Link | |||
Registered User
Join Date: Jul 2012
Posts: 7
|
Quote:
Quote:
Quote:
It looks like, if maintaining the aspect ratio, causes the black bars to be inserted on the sides or the top and bottom of the texture, the destRect values are used as offsets to where the source video data ended up, withing the m_TemporaryScreenSpaceTextureSize values. I have some examples of screen shots and OutputDebugStrings near the end of this post, that show the situations that cause the destRect values to become necessary. Knowing where the source video data ended up is crucial to properly interleaving the pixels. For SBS 3D images, the destRect.top value doesn't come into play. But the offset to the source video data and the width in destRect.left and destRect.right are needed to keep me from interleaving the valid video source pixels into the black surrounding pixels. At some point I may end up doing a shader to handle top and bottom split 3D images (I'm pretty sure top and bottom split 3D images are what 3D BlueRay disks use). When I do that, I will probably also have to pass in the destRect.top and (destRect.bottom+1 - destRect.top) values. This is the code I am currently using. It appears to be working. I can move the window around and resize the and the left and right sides don't transpose themselves. Code:
RECT sWndRect; GetWindowRect( m_hWnd, &sWndRect ); POINT sWindowOrigin = { sWndRect.left, sWndRect.top }; MONITORINFO sMonitorInfo; sMonitorInfo.cbSize = sizeof(sMonitorInfo); GetMonitorInfo(MonitorFromPoint( sWindowOrigin, MONITOR_DEFAULTTONEAREST), &sMonitorInfo); POINT sMonitorAdjustedWindOrigin = { sWndRect.left - sMonitorInfo.rcWork.left, sWndRect.top - sMonitorInfo.rcWork.top }; float fConstData[][4] = { { (float)m_TemporaryScreenSpaceTextureSize.cx, (float)m_TemporaryScreenSpaceTextureSize.cy, (float)(counter++), (float)diff / CLOCKS_PER_SEC}, { 1.0f / m_TemporaryScreenSpaceTextureSize.cx, 1.0f / m_TemporaryScreenSpaceTextureSize.cy, (float)destRect.left, (float)( destRect.right + 1 ) - destRect.left }, { (float)sMonitorAdjustedWindOrigin.y, (float)sMonitorAdjustedWindOrigin.x, (float)0, (float)0 }, }; This is an image capture taken when destRect.top was 0, destRect.left was 57, and destRect.right was 526. This is an image capture taken when destRect.top was 23, destRect.left was 0, and destRect.right was 380. Here is what those images look like when my 3D shader isn't running... This next image is a good example of why I need the destRect.left and right values. If I pull one of the pixels, just to the right of the center and move it all the way to the left edge, it will be surrounded by black pixels, not the pixels from the other eye's image. The values I am getting in my OutputDebugString statements seem to be valid. And the 3D output seems to be solid. But I'm definitely open to making changes that would make it more efficient. Here are some of the values output by the OutputDebugStrings. The first 4 groups are checking the destRect values for 2 different window sizes on primary and secondary monitors. Within the groups, the small group containing the sPlace and sWindowInfo values are just there for comparison. The next small group with sWndRect and sMonitorInfo values are there just for information, some of the values are used to calculate the final values that become the parameters to the Pixel Shader. MPC-HC-destrect.top=23,left=0,bottom=228,right=380.jpg on primary monitor ------------------------------------------------------ sPlace.rcNormalPosition.top=490,left=1038,bottom=872,right=1434 sWindowInfo.cyWindowBorders=0,cxWindowBorders=0 sWndRect.top=540,left=1046,bottom=792,right=1426 sMonitorInfo.rcMonitor.top=0,left=0,bottom=1004,right=1824 sMonitorInfo.rcWork.top=0,left=0,bottom=922,right=1824 sMonitorAdjustedWindOrigin.y=540,x=1046, m_TemporaryScreenSpaceTextureSize.cx=1824,cy=1038 destrect.top=23,left=0,bottom=228,right=380 MPC-HC-destrect.top=23,left=0,bottom=228,right=380.jpg on secondary 2D monitor, to the right of the primary monitor ------------------------------------------------------ sPlace.rcNormalPosition.top=338,left=2349,bottom=720,right=2745 sWindowInfo.cyWindowBorders=0,cxWindowBorders=0 sWndRect.top=388,left=2357,bottom=640,right=2737 sMonitorInfo.rcMonitor.top=0,left=1824,bottom=1200,right=3744 sMonitorInfo.rcWork.top=0,left=1824,bottom=1200,right=3744 sMonitorAdjustedWindOrigin.y=388,x=533 m_TemporaryScreenSpaceTextureSize.cx=1920,cy=1200 destrect.top=23,left=0,bottom=228,right=380 MPC-HC-destrect.top=0,left=57,bottom=254,right=526.jpg on primary monitor ------------------------------------------------------ sPlace.rcNormalPosition.top=503,left=868,bottom=887,right=1468 sWindowInfo.cyWindowBorders=0,cxWindowBorders=0 sWndRect.top=553,left=876,bottom=807,right=1460 sMonitorInfo.rcMonitor.top=0,left=0,bottom=1004,right=1824 sMonitorInfo.rcWork.top=0,left=0,bottom=922,right=1824 sMonitorAdjustedWindOrigin.y=553,x=876 m_TemporaryScreenSpaceTextureSize.cx=1824,cy=1038 destrect.top=0,left=57,bottom=254,right=526 MPC-HC-destrect.top=0,left=57,bottom=254,right=526.jpg on secondary monitor, to the right of the primary monitor ------------------------------------------------------ sPlace.rcNormalPosition.top=237,left=2027,bottom=621,right=2627 sWindowInfo.cyWindowBorders=0,cxWindowBorders=0 sWndRect.top=287,left=2035,bottom=541,right=2619 sMonitorInfo.rcMonitor.top=0,left=1824,bottom=1200,right=3744 sMonitorInfo.rcWork.top=0,left=1824,bottom=1200,right=3744 sMonitorAdjustedWindOrigin.y=287,x=211 m_TemporaryScreenSpaceTextureSize.cx=1920,cy=1200 destrect.top=0,left=57,bottom=254,right=526 These next 2 groups are testing negative monitor coordinates, by changing the 2D monitor on the right to the primary monitor and the 3D monitor on the left to the secondary monitor. Full Screen, Video displayed on the Secondary 3D monitor, on the left of the primary 2d monitor -------------------------------------------- sPlace.rcNormalPosition.top=0,left=-1824,bottom=1004,right=0 WndRect.top=0,left=-1824,bottom=1004,right=0 sMonitorInfo.rcMonitor.top=0,left=-1824,bottom=1004,right=0 sMonitorInfo.rcWork.top=0,left=-1824,bottom=1004,right=0 sMonitorAdjustedWindOrigin.y=0,x=0 m_TemporaryScreenSpaceTextureSize.cx=1824,cy=1038 destrect.top=8,left=0,bottom=994,right=1824 Windowed, displayed on the Secondary 3D monitor, on the left of the primary 2d monitor -------------------------------------------- sPlace.rcNormalPosition.top=191,left=-1654,bottom=909,right=-591 sWndRect.top=241,left=-1646,bottom=829,right=-599 sMonitorInfo.rcMonitor.top=0,left=-1824,bottom=1004,right=0 sMonitorInfo.rcWork.top=0,left=-1824,bottom=1004,right=0 sMonitorAdjustedWindOrigin.y=241,x=178 m_TemporaryScreenSpaceTextureSize.cx=1824,cy=1038 destrect.top=10,left=0,bottom=576,right=1047 |
|||
6th August 2012, 08:00 | #20022 | Link |
Fantasy Codecs writer
Join Date: Nov 2007
Location: Yang Zhou,Jiang Su,China
Posts: 392
|
S.Chinese update
http://www.mediafire.com/?ccx5kgxaugmpj7n |
6th August 2012, 14:29 | #20024 | Link |
Registered User
Join Date: Jul 2012
Posts: 7
|
After my last post, I decided to add a couple more shaders to support Top and Bottom encoded 3D video streams.
So that I can determine where the lower half of the video data starts, I've changed the parameters I am sending to the Post-Resize Pixel shader to include the destRect.top and ((destRect.bottom+1)-destRect.top) values. From: Code:
float fConstData[][4] = { { (float)m_TemporaryScreenSpaceTextureSize.cx, (float)m_TemporaryScreenSpaceTextureSize.cy, (float)(counter++), (float)diff / CLOCKS_PER_SEC}, { 1.0f / m_TemporaryScreenSpaceTextureSize.cx, 1.0f / m_TemporaryScreenSpaceTextureSize.cy, (float)destRect.left, (float)( destRect.right + 1 ) - destRect.left }, { (float)sMonitorAdjustedWindOrigin.y, (float)sMonitorAdjustedWindOrigin.x, (float)0, (float)0 }, }; Code:
float fConstData[][4] = { { (float)m_TemporaryScreenSpaceTextureSize.cx, (float)m_TemporaryScreenSpaceTextureSize.cy, (float)(counter++), (float)diff / CLOCKS_PER_SEC}, { 1.0f / m_TemporaryScreenSpaceTextureSize.cx, 1.0f / m_TemporaryScreenSpaceTextureSize.cy, (float)sMonitorAdjustedWindOrigin.y, (float)sMonitorAdjustedWindOrigin.x }, { (float)destRect.left, (float)( destRect.right + 1 ) - destRect.left, (float)destRect.top, (float)( destRect.bottom + 1 ) - destRect.top }, }; Last edited by TheCatcher; 6th August 2012 at 14:31. |
6th August 2012, 16:30 | #20025 | Link | |
Registered User
Join Date: Oct 2010
Location: The Netherlands
Posts: 1,083
|
Quote:
__________________
development folder, containing MPC-HC experimental tester builds, pixel shaders and more: http://www.mediafire.com/?xwsoo403c53hv Last edited by JanWillem32; 6th August 2012 at 19:56. Reason: missed the per-pixel interleave part... |
|
6th August 2012, 20:37 | #20026 | Link | |||
Registered User
Join Date: Jul 2012
Posts: 7
|
Quote:
Quote:
Quote:
I haven't tested the TAB Shaders yet, I will test them, today, after work. There is a possibility the TAB Shaders might end up using more storage variables than DX9 allows. So I might have to make them DX10, ps_3_0 shaders. When I modified the SBS Shaders, to make sure they pulled the source pixels from dead center of the pixel (so the color wouldn't be muddied by the surrounding pixels), I ended up having to do a lot of optimizing to get the storage variable count back down, to be DX9 compatible. Last edited by TheCatcher; 6th August 2012 at 20:39. |
|||
6th August 2012, 22:54 | #20027 | Link | ||||
Registered User
Join Date: Oct 2010
Location: The Netherlands
Posts: 1,083
|
Quote:
Quote:
Quote:
Quote:
I thought you were trying to transform to a different interleaved format at first... Oh well, it's still a good example: Code:
// (C) 2012 Jan-Willem Krans (janwillem32 <at> hotmail.com) // This file is part of Video pixel shader pack. // This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. // You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // Prototype // This shader should be run as a screen space pixel shader. // This shader requires compiling with ps_2_0, but higher is better, see http://en.wikipedia.org/wiki/Pixel_shader to look up what PS version your video card supports. // Use this shader to convert a SBS 3D image to interleave per scan line 3D format, while doubling the width of the image by Mitchell-Netravali cubic5 interpolation. // This shader requires the source image (split halves) to span the full width of the screen space and have the top pixel row aligned to even. sampler s0; float2 c0; float2 c1; // average two pixels per sample, as the output is half-height #define sp(a, b) float4 a = tex2D(s0, float2(coord+b*fx*c1.x, tex.y))+tex2D(s0, float2(coord+b*fx*c1.x, tex.y+c1.y)); float4 main(float2 tex : TEXCOORD0) : COLOR { float offset = 0; float n = frac(tex.y*c0.y/2.); if(n > .5) offset = .5+.5*c1.x;// even y top, odd y bottom // double the width float coord = (tex.x/2.+offset)*c0.x;// assign the output position, normalized to texture width in pixels float t = frac(coord);// calculate the difference between the output pixel and the original surrounding two pixels // adjust sampling matrix to put the ouput pixel on Q2+.25 float fx; if(t > .5) {coord = (coord-t+1.5)*c1.x; fx = -1;} else {coord = (coord-t+.5)*c1.x; fx = 1;} sp(Q0, -2) sp(Q1, -1) sp(Q2, 0) sp(Q3, 1) sp(Q4, 2)// original pixels return Q0*25/20736.*.5+Q2*16632/20736.*.5+Q3*5234/20736.*.5-Q1*770/20736.*.5-Q4*385/20736.*.5;// output interpolated value }
__________________
development folder, containing MPC-HC experimental tester builds, pixel shaders and more: http://www.mediafire.com/?xwsoo403c53hv |
||||
7th August 2012, 07:52 | #20029 | Link |
Registered User
Join Date: Jul 2012
Posts: 7
|
I am far from a DirectX or video programming expert. I'm probably not even novice level. Before last week, I'd never seen any shader code. The last time I did any video code was probably close to 25 years ago on the old Amiga computers.
When I started this I was writing the shader code in the shader assembly langauge. My son told me about the C-style shader code that was available for it... Though I tend to prefer assembly languages, the C-style code sure makes the shaders easy. Here are the shader routines for the SBS file formats. I called the first one "3D-SBS-DLP-CheckerBoard-Normal". It is for the case when the image on the left of the video frame is for the left eye, and the image on the right of the video frame is for the right eye. If the destination pixel calculation is even, we are placing a pixel that will be displayed to the left eye. For this one, if the destination pixel calculation is odd, we pull the source pixel from the right side. Code:
// 3D-SBS-DLP-CheckerBoard-Normal // Normal - The video image on the left is displayed to the left eye, on even offset pixels // The video image on the right is displayed to the right eye, on odd offset pixels // Instructions: // "View" Menu -> "Shader Editor" Item // Enter "3D-SBS-DLP-CheckerBoard-Normal" in the top left box, and press the "Enter" key. // Select "ps_2_0" from the smaller top (on the middle / right) // Paste in the code for th "3D-SBS-DLP-CheckerBoard-Normal" shader. // Close the Shaders Editor (x in upper left, next to name) // "Play" Menu -> "Shaders" Sub-Menu Item -> "Select Shaders..." Item // Check the "Enable post-resize pixel shaders" checkbox // Click once in the window under the "Enable post-resize pixel shaders" // select the "3D-SBS-DLP-CheckerBoard-Normal" shader from the drop down list on the top // Click the "Add" button // Click the "OK" button // ps_2_0 sampler s0 : register(s0); float4 p0 : register(c0); float4 p1 : register(c1); float4 p2 : register(c2); #define width (p0[0]) // These 2 values are used in combination with the monitor_* values #define height (p0[1]) // to determine if the destination pixel is on an odd or even offset #define counter (p0[2]) // These 2 values are not used in this shader #define clock (p0[3]) #define one_over_width (p1[0]) // These 2 values are used to calculate integer pixel offsets and #define one_over_height (p1[1]) // to reposition the pixel offsets to the center of the source pixel #define monitor_top (p1[2]) // These 2 values are used to determine if the output pixel #define monitor_left (p1[3]) // is displayed to the right or left eye #define video_left (p2[0]) // These 2 values are used for SBS, to calculate where #define video_width (p2[1]) // to pull the source pixel from... #define video_top (p2[2]) // These 2 values are used for TAB, to calculate where #define video_height (p2[3]) // to pull the source pixel from... #define PI acos(-1) float4 main(float2 tex : TEXCOORD0) : COLOR { // Default the output color to the color of the pixel at the current coordinate float4 output = tex2D(s0, tex); // Integer math will be slower on a VPU but it will eliminate any possiblity of round off errors int iCurPixel = tex.x / one_over_width; // This value is used in combination with the video_left value, to be sure we don't change any of // pixels that don't contain actual video data int iVideoRight = video_left + video_width; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from if( ( iCurPixel > video_left ) && ( iCurPixel <= iVideoRight ) ) { // Calculate a pixel offset into the frame on the left side of the video data int iPixelOffset = ( ( iCurPixel - video_left ) / 2 ) + video_left; // Don't round up! // Check to see if we need to be using data from the frame on the right side of the video data if( (monitor_top+monitor_left+(int)(tex.y * height)+(int)(tex.x * width)) % 2 == 1 ) { // Adjust the pixel offset, in to the video frame on the right side of the video data iPixelOffset += (int)(video_width / 2); } // Use this 1/2 pixel width value to center our X coordinate over the pixel data, // so we don't get color bleed float fHalfPixelWidth = one_over_width / 2; // Adjust the X coordinate of the source color to the correct side of the video image // using the pixel offset we just calculated, and apply 1/2 pixel offset, so we don't // get color bleed // Since we didn't modify the Y coordinate, we can hopefully assume it is already at the center // of the pixel float2 Color = tex; Color.x = clamp( ( iPixelOffset * one_over_width ) + fHalfPixelWidth, 0.0f,1.0f) ; // Replace the default pixel color with the pixel color from the location we just calculated output = tex2D(s0, Color); } return output; } Code:
// 3D-SBS-DLP-CheckerBoard-Reversed // Reversed - The video image on the right is displayed to the left eye, on even offset pixels // The video image on the left is displayed to the right eye, on odd offset pixels // Instructions: // "View" Menu -> "Shader Editor" Item // Enter "3D-SBS-DLP-CheckerBoard-Reversed" in the top left box, and press the "Enter" key. // Select "ps_2_0" from the smaller top (on the middle / right) // Paste in the code for th "3D-SBS-DLP-CheckerBoard-Reversed" shader. // Close the Shaders Editor (x in upper left, next to name) // "Play" Menu -> "Shaders" Sub-Menu Item -> "Select Shaders..." Item // Check the "Enable post-resize pixel shaders" checkbox // Click once in the window under the "Enable post-resize pixel shaders" // select the "3D-SBS-DLP-CheckerBoard-Reversed" shader from the drop down list on the top // Click the "Add" button // Click the "OK" button // ps_2_0 sampler s0 : register(s0); float4 p0 : register(c0); float4 p1 : register(c1); float4 p2 : register(c2); #define width (p0[0]) // These 2 values are used in combination with the monitor_* values #define height (p0[1]) // to determine if the destination pixel is on an odd or even offset #define counter (p0[2]) // These 2 values are not used in this shader #define clock (p0[3]) #define one_over_width (p1[0]) // These 2 values are used to calculate integer pixel offsets and #define one_over_height (p1[1]) // to reposition the pixel offsets to the center of the source pixel #define monitor_top (p1[2]) // These 2 values are used to determine if the output pixel #define monitor_left (p1[3]) // is displayed to the right or left eye #define video_left (p2[0]) // These 2 values are used for SBS, to calculate where #define video_width (p2[1]) // to pull the source pixel from... #define video_top (p2[2]) // These 2 values are used for TAB, to calculate where #define video_height (p2[3]) // to pull the source pixel from... #define PI acos(-1) float4 main(float2 tex : TEXCOORD0) : COLOR { // Default the output color to the color of the pixel at the current coordinate float4 output = tex2D(s0, tex); // Integer math will be slower on a VPU but it will eliminate any possiblity of round off errors int iCurPixel = tex.x / one_over_width; // This value is used in combination with the video_left value, to be sure we don't change any of // pixels that don't contain actual video data int iVideoRight = video_left + video_width; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from if( ( iCurPixel > video_left ) && ( iCurPixel <= iVideoRight ) ) { // Calculate a pixel offset into the frame on the left side of the video data int iPixelOffset = ( ( iCurPixel - video_left ) / 2 ) + video_left; // Don't round up! // Check to see if we need to be using data from the frame on the right side of the video data if( (monitor_top+monitor_left+(int)(tex.y * height)+(int)(tex.x * width)) % 2 == 0 ) { // Adjust the pixel offset, in to the video frame on the right side of the video data iPixelOffset += (int)(video_width / 2); } // Use this 1/2 pixel width value to center our X coordinate over the pixel data, // so we don't get color bleed float fHalfPixelWidth = one_over_width / 2; // Adjust the X coordinate of the source color to the correct side of the video image // using the pixel offset we just calculated, and apply 1/2 pixel offset, so we don't // get color bleed // Since we didn't modify the Y coordinate, we can hopefully assume it is already at the center // of the pixel float2 Color = tex; Color.x = clamp( ( iPixelOffset * one_over_width ) + fHalfPixelWidth, 0.0f,1.0f) ; // Replace the default pixel color with the pixel color from the location we just calculated output = tex2D(s0, Color); } return output; } Last edited by TheCatcher; 7th August 2012 at 08:26. |
7th August 2012, 13:15 | #20030 | Link | ||
Registered User
Join Date: May 2008
Posts: 1,840
|
Quote:
Quote:
will restrict hotkeys to MPC-HC |
||
7th August 2012, 18:08 | #20031 | Link |
Registered User
Join Date: Oct 2010
Location: The Netherlands
Posts: 1,083
|
@TheCatcher: DirectX 9 only allows integers for the loop counter register, the rest are always floats: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx . The HLSL compiler in DirectX 9 mode can generate operations for floating-point that are usually integer-only. (You can check the output assembly of the compiler.)
Even under DirectX 10 rules, the hardware is required to support all integer operands, but may emulate the arithmetic operations using the floating-point units. I used your code as a template. This is probably not a fully optimized version yet, but may help you further: (It only works in full screen for the trunk build. For my builds, it needs a window aligned on even pixel offsets, and video filling the width of the visible window.) Code:
sampler s0; float2 c0; float2 pc1;// temp, remove on final // prototyped, resolve for final //float4 c1; //float4 c2; /* c0.x These 2 values are used in combination with the monitor_* values c0.y to determine if the destination pixel is on an odd or even offset c1.x These 2 values are used to calculate integer pixel offsets and c1.y to reposition the pixel offsets to the center of the source pixel c1.z These 2 values are used to determine if the output pixel c1.w is displayed to the right or left eye c2.x These 2 values are used for SBS, to calculate where c2.y to pull the source pixel from... c2.z These 2 values are used for TAB, to calculate where c2.w to pull the source pixel from... */ float4 main(float2 tex : TEXCOORD0) : COLOR { float4 c1 = {pc1, 0, 0};// temp, remove on final float4 c2 = {0, c0.x, 0, c0.y};// temp, remove on final float2 CurPixel = tex * c0; float VideoRight = c2.x + c2.y; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from // these compares probably could use an epsilon, else using VPOS would make it easier if((CurPixel.x >= c2.x) && (CurPixel.x <= VideoRight)) { float ox = tex.x-c1.x*c2.x;// normalized video-relative x position float PixelOffset = -.5*ox;// the two images are half-width, compensate for that float2 MonitorPos = CurPixel+c2.xz;// to monitor-relative coordinates // Check to see if we need to be using data from the frame on the right side of the video data float2 n = frac(MonitorPos*.5); // Adjust the pixel offset, in to the video frame on the right side of the video data where required if(n.x >= .5) { PixelOffset -= c1.x*.5;// round half-pixel offsets down if(n.y < .5) PixelOffset += c1.x*.5*c2.y;} else if(n.y >= .5) PixelOffset += c1.x*.5*c2.y; // Adjust the X coordinate of the source color to the correct side of the video image // using the pixel offset we just calculated tex.x += PixelOffset;} return tex2D(s0, tex); }
__________________
development folder, containing MPC-HC experimental tester builds, pixel shaders and more: http://www.mediafire.com/?xwsoo403c53hv |
7th August 2012, 20:03 | #20032 | Link |
Registered User
Join Date: Nov 2005
Posts: 693
|
Unless you can append MPC-HC's build number on Github (1.6.3.5757 (8701ded349) for instance would be a lot better), I would very much welcome that.
__________________
My hobby website |
8th August 2012, 07:07 | #20033 | Link | |
Registered User
Join Date: Jul 2012
Posts: 7
|
Quote:
I got the Pixel Shaders for Top And Bottom (TAB) 3D file format to 3D DLP Checkerboard working today. And while I was doing it, I identified a problem with my SBS Pixel Shaders. The only code byte different between the two SBS shaders, is backwards. The SBS Normal Shader's modulo 2 compare should be to 0, not 1. And the SBS Reversed Shader's modulo 2 compare should be to 1, not 0. Logically this change doesn't make sense to me. But it turned out the source SBS video I was using was reversed. So, though logically it doesn't make sense. The reality of it is that it works correctly after making this change. And the TAB 3D file format works this way also. So the only conclusions I can come up with are... 1. One of the four variables that I am adding up to perform the modulo 2 on, must contain a relative 1 value, instead of a relative 0 value. 2. Somehow one of the (int) conversion on the tex.x and tex.y multiplies by the width and height of the textures are ending up one number higher than they should be... Or 3. My video card settings are offset from the HDTV by one pixel... Which doesn't make sense, because the NVidia software required me to use its reversed mode for this reversed SBS file also... I haven't seen the source code to other 3D SBS and TAB video players... maybe this is just the way it is - modulo 0 when it seems like it should be modulo 1, and vice versa... None of these options makes sense to me. I will look into this later in the week, when I get another chance to play with the code. Here is the working Pixel Shader code for the Normal Top and Bottom conversion to DLP Checkerboard format (Normal being left eye's image on top). Code:
// 3D-TAB-DLP-CheckerBoard-Normal // Normal - The video image on the top is displayed to the left eye, on even offset pixels // The video image on the bottom is displayed to the right eye, on odd offset pixels // Instructions: // "View" Menu -> "Shader Editor" Item // Enter "3D-TAB-DLP-CheckerBoard-Normal" in the top left box, and press the "Enter" key. // Select "ps_2_0" from the smaller top (on the middle / right) // Paste in the code for th "3D-TAB-DLP-CheckerBoard-Normal" shader. // Close the Shaders Editor (x in upper left, next to name) // "Play" Menu -> "Shaders" Sub-Menu Item -> "Select Shaders..." Item // Check the "Enable post-resize pixel shaders" checkbox // Click once in the window under the "Enable post-resize pixel shaders" // select the "3D-TAB-DLP-CheckerBoard-Normal" shader from the drop down list on the top // Click the "Add" button // Click the "OK" button // ps_2_0 sampler s0 : register(s0); float4 p0 : register(c0); float4 p1 : register(c1); float4 p2 : register(c2); #define width (p0[0]) // These 2 values are used in combination with the monitor_* values #define height (p0[1]) // to determine if the destination pixel is on an odd or even offset #define counter (p0[2]) // These 2 values are not used in this shader #define clock (p0[3]) #define one_over_width (p1[0]) // These 2 values are used to calculate integer pixel offsets and #define one_over_height (p1[1]) // to reposition the pixel offsets to the center of the source pixel #define monitor_top (p1[2]) // These 2 values are used to determine if the output pixel #define monitor_left (p1[3]) // is displayed to the right SBS, to calculate where #define video_width (p2[1]) // to pull the source pixel from... #define video_top (p2[2]) // These 2 values are used for TAB, to calculate where #define video_height (p2[3]) // to pull the source pixel from... #define PI acos(-1) float4 main(float2 tex : TEXCOORD0) : COLOR { // Default the output color to the color of the pixel at the current coordinate float4 output = tex2D(s0, tex); // Integer math will be slower on a VPU but it will eliminate any possiblity of round off errors int iCurPixel = tex.y / one_over_height; // This value is used in combination with the video_top value, to be sure we don't change any of // pixels that don't contain actual video data int iVideoBottom = video_top + video_height; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from if( ( iCurPixel > video_top ) && ( iCurPixel <= iVideoBottom ) ) { // Calculate a pixel offset into the frame on the top half of the video data int iPixelOffset = ( ( iCurPixel - video_top ) / 2 ) + video_top; // Don't round up! // Check to see if we need to be using data from the frame on the bottom half of the video data if( (monitor_top+monitor_left+(int)(tex.y * height)+(int)(tex.x * width)) % 2 == 0 ) { // Adjust the pixel offset, in to the video frame on the bottom half of the video data iPixelOffset += (int)(video_height / 2); } // Use this 1/2 pixel width value to center our X coordinate over the pixel data, // so we don't get color bleed float fHalfPixelheight = one_over_height / 2; // Adjust the Y coordinate of the source color to the correct half of the video image // using the pixel offset we just calculated, and apply 1/2 pixel offset, so we don't // get color bleed // Since we didn't modify the X coordinate, we can hopefully assume it is already at the center // of the pixel float2 Color = tex; Color.y = clamp( ( iPixelOffset * one_over_height ) + fHalfPixelheight, 0.0f,1.0f) ; // Replace the default pixel color with the pixel color from the location we just calculated output = tex2D(s0, Color); } return output; } Code:
// 3D-TAB-DLP-CheckerBoard-Reversed // Reversed - The video image on the right is displayed to the left eye, on even offset pixels // The video image on the left is displayed to the right eye, on odd offset pixels // Instructions: // "View" Menu -> "Shader Editor" Item // Enter "3D-TAB-DLP-CheckerBoard-Reversed" in the top left box, and press the "Enter" key. // Select "ps_2_0" from the smaller top (on the middle / right) // Paste in the code for th "3D-TAB-DLP-CheckerBoard-Reversed" shader. // Close the Shaders Editor (x in upper left, next to name) // "Play" Menu -> "Shaders" Sub-Menu Item -> "Select Shaders..." Item // Check the "Enable post-resize pixel shaders" checkbox // Click once in the window under the "Enable post-resize pixel shaders" // select the "3D-TAB-DLP-CheckerBoard-Reversed" shader from the drop down list on the top // Click the "Add" button // Click the "OK" button // ps_2_0 sampler s0 : register(s0); float4 p0 : register(c0); float4 p1 : register(c1); float4 p2 : register(c2); #define width (p0[0]) // These 2 values are used in combination with the monitor_* values #define height (p0[1]) // to determine if the destination pixel is on an odd or even offset #define counter (p0[2]) // These 2 values are not used in this shader #define clock (p0[3]) #define one_over_width (p1[0]) // These 2 values are used to calculate integer pixel offsets and #define one_over_height (p1[1]) // to reposition the pixel offsets to the center of the source pixel #define monitor_top (p1[2]) // These 2 values are used to determine if the output pixel #define monitor_left (p1[3]) // is displayed to the right SBS, to calculate where #define video_width (p2[1]) // to pull the source pixel from... #define video_top (p2[2]) // These 2 values are used for TAB, to calculate where #define video_height (p2[3]) // to pull the source pixel from... #define PI acos(-1) float4 main(float2 tex : TEXCOORD0) : COLOR { // Default the output color to the color of the pixel at the current coordinate float4 output = tex2D(s0, tex); // Integer math will be slower on a VPU but it will eliminate any possiblity of round off errors int iCurPixel = tex.y / one_over_height; // This value is used in combination with the video_top value, to be sure we don't change any of // pixels that don't contain actual video data int iVideoBottom = video_top + video_height; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from if( ( iCurPixel > video_top ) && ( iCurPixel <= iVideoBottom ) ) { // Calculate a pixel offset into the frame on the top half of the video data int iPixelOffset = ( ( iCurPixel - video_top ) / 2 ) + video_top; // Don't round up! // Check to see if we need to be using data from the frame on the bottom half of the video data if( (monitor_top+monitor_left+(int)(tex.y * height)+(int)(tex.x * width)) % 2 == 1 ) { // Adjust the pixel offset, in to the video frame on the bottom half of the video data iPixelOffset += (int)(video_height / 2); } // Use this 1/2 pixel width value to center our X coordinate over the pixel data, // so we don't get color bleed float fHalfPixelheight = one_over_height / 2; // Adjust the Y coordinate of the source color to the correct half of the video image // using the pixel offset we just calculated, and apply 1/2 pixel offset, so we don't // get color bleed // Since we didn't modify the X coordinate, we can hopefully assume it is already at the center // of the pixel float2 Color = tex; Color.y = clamp( ( iPixelOffset * one_over_height ) + fHalfPixelheight, 0.0f,1.0f) ; // Replace the default pixel color with the pixel color from the location we just calculated output = tex2D(s0, Color); } return output; } |
|
8th August 2012, 21:38 | #20034 | Link |
Registered User
Join Date: Oct 2010
Location: The Netherlands
Posts: 1,083
|
I think you missed the thing I noted before; DirectX 9 has no support for integers other than the loop counter. Not a single integer is used in the output assembly of your shaders. The integer modulo you put in the shader is approximated by doing many floating-point operations (most notable arithmetic saturation and extraction of the fractional component). The prototpe I posted has "float2 n = frac(MonitorPos*.5);", to only calculate a floating-point fractional part once, and use that directly. The FRC instruction is native to the assembly under PS 2.0 and onward rules: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx .
Integer modulo is expensive even on systems that do support it. For an x86 CPU, IDIV (signed) and DIV (unsigned) instructions are used to perform division (to the RAX[64-bit], EAX[32-bit], AX[16-bit] or AL[8-bit] register) and modulo (to the RDX, EDX, DX or AH register) simultaneously. It can take up to 197 clocks to perform. For calculating modulo of x with a right-hand operand of 2, 4, 8 and 16, we optimize using the single-clock AND/TEST instruction: x & 1, x & 3, x & 7, x & 15. I haven't seen a compiler do this optimization yet. So, the standard tests for odd and even are: "if(x&1) {" (TEST reg 1, JZ label) and "if(!(x&1)) {" (TEST reg 1, JNZ label).
__________________
development folder, containing MPC-HC experimental tester builds, pixel shaders and more: http://www.mediafire.com/?xwsoo403c53hv |
9th August 2012, 00:43 | #20035 | Link |
Fantasy Codecs writer
Join Date: Nov 2007
Location: Yang Zhou,Jiang Su,China
Posts: 392
|
S.Chinese update
http://www.mediafire.com/?j2grwjyp6ivy4jj |
9th August 2012, 16:45 | #20036 | Link |
Registered User
Join Date: Jul 2012
Posts: 7
|
Yep, I missed that point... I've made the changes, switched all the artificial ints over to floats, modified the modulo 2 code to be a
if (value - float(value) < 0.5f) for normal and if (value - float(value) >= 0.5f) for reversed. Also changed the passed in offsets to the video to be left-top-width-height. The size went from over 60 slots / instructions to around 30. It still seems to be backwards. I will figure out what is up with that later this week. |
9th August 2012, 20:02 | #20037 | Link |
Registered User
Join Date: Oct 2010
Location: The Netherlands
Posts: 1,083
|
I optimized the primary SBS to checkerboard pixel shader:
Code:
sampler s0; float2 c0; float4 c1; float4 c2; /* c0.x screen width These 2 values are used in combination with the monitor-relative values to determine if the destination pixel is on an odd or even offset c0.y screen height c1.x 1/screen width These 2 values are used to calculate whole pixel offsets relative to the normalized space c1.y 1/screen height c1.z window left to monitor These 2 values are used to determine if the output pixel is displayed to the right or left eye c1.w window top to monitor c2.x video left to window These 2 values are used for SBS, to calculate where to pull the source pixel from... c2.z video width c2.y video top to window These 2 values are used for TAB, to calculate where to pull the source pixel from... c2.w video height For this shader to work correctly, the video width on screen has to be an even amount.*/ float4 main(float2 tex : TEXCOORD0) : COLOR { float2 CurPixel = tex*c0; float VideoRight = c2.x+c2.z; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from // these compares probably could use an epsilon, else using VPOS would make it easier if((CurPixel.x >= c2.x) && (CurPixel.x <= VideoRight)) { float ox = CurPixel.x-c2.x;// video-relative x position float PixelOffset = floor(-.5*ox);// the two images are half-width, compensate for that, round half-pixel offsets down float2 MonitorPos = CurPixel-c2.xy;// to monitor-relative coordinates // Check to see if we need to be using data from the frame on the right side of the video data float n = frac(dot(1, MonitorPos)*.5-.25); // Adjust the pixel offset, in to the video frame on the right side of the video data where required if(n >= .5) PixelOffset += .5*c2.z; // Adjust the X coordinate of the source position to the correct side of the video image using the pixel offset we just calculated tex.x += PixelOffset*c1.x;} return tex2D(s0, tex); } Code:
sampler s0; float2 c0; float2 pc1;// temp, remove on final // prototyped, resolve for final //float4 c1; //float4 c2; /* c0.x screen width These 2 values are used in combination with the monitor-relative values to determine if the destination pixel is on an odd or even offset c0.y screen height c1.x 1/screen width These 2 values are used to calculate whole pixel offsets relative to the normalized space c1.y 1/screen height c1.z window left to monitor These 2 values are used to determine if the output pixel is displayed to the right or left eye c1.w window top to monitor c2.x video left to window These 2 values are used for SBS, to calculate where to pull the source pixel from... c2.z video width c2.y video top to window These 2 values are used for TAB, to calculate where to pull the source pixel from... c2.w video height For this shader to work correctly, the video width on screen has to be an even amount.*/ float4 main(float2 tex : TEXCOORD0) : COLOR { float4 c1 = {pc1, 0, 0};// temp, remove on final float4 c2 = {0, 0, c0};// temp, remove on final float2 CurPixel = tex*c0; float VideoRight = c2.x+c2.z; // If we are currently putting a pixel on the screen, that contains video image data // Then figure out where we need to get the pixel from // these compares probably could use an epsilon, else using VPOS would make it easier if((CurPixel.x >= c2.x) && (CurPixel.x <= VideoRight)) { float ox = CurPixel.x-c2.x;// video-relative x position float PixelOffset = floor(-.5*ox);// the two images are half-width, compensate for that, round half-pixel offsets down float2 MonitorPos = CurPixel-c2.xy;// to monitor-relative coordinates // Check to see if we need to be using data from the frame on the right side of the video data float n = frac(dot(1, MonitorPos)*.5-.25); // Adjust the pixel offset, in to the video frame on the right side of the video data where required if(n >= .5) PixelOffset += .5*c2.z; // Adjust the X coordinate of the source position to the correct side of the video image using the pixel offset we just calculated tex.x += PixelOffset*c1.x;} return tex2D(s0, tex); }
__________________
development folder, containing MPC-HC experimental tester builds, pixel shaders and more: http://www.mediafire.com/?xwsoo403c53hv |
10th August 2012, 21:20 | #20038 | Link |
Registered User
Join Date: Aug 2006
Posts: 21
|
Have some misunderstanding of the DXVA support for WMV3 (VC-1) in MPC-HC after about 5000 builds. With one video DXVA in MPC Video Decoder with all checks skipped is not in use:
MediaInfo: Code:
ID : 2 Format : VC-1 Format profile : MP@ML Codec ID : WMV3 Codec ID/Info : Windows Media Video 9 Codec ID/Hint : WMV3 Description of the codec : Windows Media Video 9 Duration : 4mn 25s Bit rate mode : Variable Bit rate : 1 500 Kbps Width : 696 pixels Height : 412 pixels Display aspect ratio : 16:9 Frame rate : 25.000 fps Bit depth : 8 bits Scan type : Progressive Compression mode : Lossy Bits/(Pixel*Frame) : 0.209 Stream size : 47.5 MiB (84%) Code:
DXVA2_ProcessDeviceDestroyed, 1800, 00:00:03.1345956 DXVA2_ProcessDeviceDestroyed, 1800, 00:00:03.1347092 DXVA2_ProcessDeviceCreated, mpc-hc64, 00:00:08.6857561 DXVA2_ProcessDeviceCreated, mpc-hc64, 00:00:08.6858225 DXVA2_ProcessDeviceDestroyed, mpc-hc64, 00:00:08.7013206 DXVA2_ProcessDeviceDestroyed, mpc-hc64, 00:00:08.7013597 DXVA2_ProcessDeviceCreated, mpc-hc64, 00:00:08.7521071 DXVA2_ProcessDeviceCreated, mpc-hc64, 00:00:08.7521567 DXVA2_ProcessBlt, mpc-hc64, 00:00:08.7534609 DXVA2_ProcessBlt, mpc-hc64, 00:00:08.7574633 DXVA2_ProcessBlt, mpc-hc64, 00:00:08.7604663 DXVA2_ProcessBlt, mpc-hc64, 00:00:08.7624646 DXVA2_ProcessBlt, mpc-hc64, 00:00:08.7644756 Here is another video, with working DXVA: Code:
ID : 2 Format : VC-1 Format profile : MP@HL Codec ID : WMV3 Codec ID/Info : Windows Media Video 9 Codec ID/Hint : WMV3 Description of the codec : Windows Media Video 9 - Professional Duration : 1mn 3s Bit rate mode : Constant Bit rate : 11.0 Mbps Width : 1 280 pixels Height : 720 pixels Display aspect ratio : 16:9 Frame rate : 29.970 fps Bit depth : 8 bits Scan type : Progressive Compression mode : Lossy Bits/(Pixel*Frame) : 0.398 Stream size : 83.6 MiB Code:
DXVA2_ProcessDeviceCreated, mpc-hc64, 00:00:03.8030614 DXVA2_ProcessDeviceCreated, mpc-hc64, 00:00:03.8031243 DXVA2_DecodeDeviceCreated, mpc-hc64, 00:00:03.8093286 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8334641 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8370296 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8370321 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8370349 DXVA2_DecodeDeviceExecute, mpc-hc64, 00:00:03.8370383 DXVA2_DecodeDeviceEndFrame, mpc-hc64, 00:00:03.8370771 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8387586 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8387688 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8387716 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8387775 DXVA2_DecodeDeviceExecute, mpc-hc64, 00:00:03.8387788 DXVA2_DecodeDeviceEndFrame, mpc-hc64, 00:00:03.8387936 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8389860 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8389922 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8389932 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8389950 DXVA2_DecodeDeviceExecute, mpc-hc64, 00:00:03.8389956 DXVA2_DecodeDeviceEndFrame, mpc-hc64, 00:00:03.8390025 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8392582 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8392650 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8392662 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8392678 DXVA2_DecodeDeviceExecute, mpc-hc64, 00:00:03.8392687 DXVA2_DecodeDeviceEndFrame, mpc-hc64, 00:00:03.8392762 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8395024 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8427427 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8467446 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8507470 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8507579 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8507597 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8507666 DXVA2_DecodeDeviceExecute, mpc-hc64, 00:00:03.8507678 DXVA2_DecodeDeviceEndFrame, mpc-hc64, 00:00:03.8507815 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8508879 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8547464 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8547554 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8547563 DXVA2_DecodeDeviceGetBuffer, mpc-hc64, 00:00:03.8547728 DXVA2_DecodeDeviceExecute, mpc-hc64, 00:00:03.8547740 DXVA2_DecodeDeviceEndFrame, mpc-hc64, 00:00:03.8547914 DXVA2_DecodeDeviceBeginFrame, mpc-hc64, 00:00:03.8549084 DXVA2_ProcessBlt, mpc-hc64, 00:00:03.8557654 With both videos DXVA Checker 'Check Decoders' button results with this: Code:
[DS] WMVideo Decoder DMO [DXVA1] [WMV3 696x412] - [MF] WMVideo Decoder MFT [DXVA2] [WMV3 696x412] ModeVC1_VLD2010: DXVA2 ModeVC1_VLD: DXVA2 ModeVC1_IDCT: DXVA2 ModeWMV9_IDCT: DXVA2 ModeVC1_MoComp: DXVA2 ModeWMV9_MoComp: DXVA2 ModeVC1_PostProc: DXVA2 ModeWMV9_PostProc: DXVA2 System is Win7 Pro x64, video board is a NVIDIA GTX 590 with 304.79 Driver. Is videos with resolutions below 1280 is just banned from DXVA in MPC-HC after https://github.com/mpc-hc/mpc-hc/commit/ad48e5edf7eb5674f888a51f53bd3e866ce93fc1 commit? Cause the 4992 build from http://www.xvidvideo.ru/media-player-classic-home-cinema-x86-x64/media-player-classic-homecinema-x86-x64-1-6-3-4992.html use DXVA with both files. |
11th August 2012, 08:08 | #20039 | Link |
Registered User
Join Date: Dec 2008
Posts: 1,968
|
@jffulcrum
Most of WMV3 videos has problems when playing in DXVA mode, if the frame width is less or equal than 720. Here runs a simple rule, if the format is WMV3, and frame width is less or equal than 720, then DXVA is not used. This rule is constant, it will not be optional. MPC-HC v5349 or later. Last edited by v0lt; 12th August 2012 at 04:12. |
Tags |
dxva, h264, home cinema, media player classic, mpc-hc |
Thread Tools | Search this Thread |
Display Modes | |
|
|