I have read presentation from NVidio about NVidia 3D Vision.
I have got monitor, video board, glasses.
I use the render video filter to display video in full screen with the simple video player.
In this filter the image is drawing using Direct3D surfaces.
I load it from IMediaSample to two surfaces.
After that i stretch images to final two images 3D surface with NVidia signatures.
Finally, i put this surface to back buffer surface and do Present.
As it is written in the presentetion.
But i get only right inage in the fullscreen NVidia 3D Vision glasses mode.
The question is: "Why is there only right image?"
The answer is: "Surface rectangle in last StretchRect!"
I do two images from source image using the shift, as if it was two eyes.
Here is the function code (left some code from previos variant using video cashing):
HRESULT CTransform::Transform( IMediaSample *pMediaSample, AM_MEDIA_TYPE* media_type, LPDIRECT3DDEVICE9 direct_3D_device )
{
if (
pMediaSample==NULL || media_type==NULL || direct_3D_device == NULL
)
{
return E_POINTER;
}
AM_MEDIA_TYPE* pType = media_type;
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
BYTE *pData;
long lDataLen;
RGBTRIPLE *prgb;
pMediaSample->GetPointer(&pData);
lDataLen = pMediaSample->GetSize();
int iPixelSize = pvi->bmiHeader.biBitCount / 8;
int cxImage = pvi->bmiHeader.biWidth;
int cyImage = pvi->bmiHeader.biHeight;
int cbImage = cyImage * cxImage * iPixelSize;
int numPixels = cxImage * cyImage;
iPixelSize = pvi->bmiHeader.biBitCount / 8;
cxImage = pvi->bmiHeader.biWidth;
cyImage = pvi->bmiHeader.biHeight;
cbImage = cyImage * cxImage * iPixelSize;
numPixels = cxImage * cyImage;
prgb = (RGBTRIPLE*) pData;
int pixels_shift = 2*cxImage/100;
REFERENCE_TIME rtStart, rtEnd;
pMediaSample->GetTime(&rtStart, &rtEnd);
{
if(buffers_size!=cxImage*cyImage)
{
buffers_size = cxImage*cyImage;
delete []member_cash_buffer;
delete []member_buffer;
delete []local_member_buffer_1;
delete []local_member_buffer_2;
delete []local_member_entered_buffer;
member_cash_buffer = new RGBTRIPLE[buffers_size];
member_buffer = new RGBTRIPLE[buffers_size];
local_member_buffer_1 = new RGBTRIPLE[buffers_size];
local_member_buffer_2 = new RGBTRIPLE[buffers_size];
local_member_entered_buffer = new RGBTRIPLE[buffers_size];
member_valid_cash = 0;
}
}
#define RGB_BYTE_ORDER(r, g ,b) ((DWORD) (((BYTE) (b) | ((WORD) (g) << 8)) | (((DWORD) (BYTE) (r)) << 16)))
HRESULT local_handle_result = S_OK;
{
IDirect3DSurface9* gImageSrcLeft = NULL;
IDirect3DSurface9* gImageSrcRight = NULL;
{
local_handle_result = direct_3D_device->CreateOffscreenPlainSurface(
cxImage-pixels_shift,
cyImage,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
&gImageSrcLeft, NULL);
if(local_handle_result!=S_OK)
{
return local_handle_result;
}
local_handle_result = direct_3D_device->CreateOffscreenPlainSurface(
cxImage-pixels_shift,
cyImage,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
&gImageSrcRight, NULL);
if(local_handle_result!=S_OK)
{
gImageSrcLeft->Release();
return local_handle_result;
}
{
DWORD *local_bit_map_buffer;
local_bit_map_buffer = new DWORD[(cxImage-pixels_shift)*cyImage];
for(int local_counter_width=pixels_shift;local_counter_width<cxImage;local_counter_width++)
{
for(int local_counter_height=0;local_counter_height<cyImage;local_counter_height++)
{
int local_couter = local_counter_width+local_counter_height*cxImage;
int local_bit_map_couter = local_counter_width-pixels_shift+(cyImage-(local_counter_height+1))*(cxImage-pixels_shift);
local_bit_map_buffer[local_bit_map_couter] = RGB_BYTE_ORDER(prgb[local_couter].rgbtRed,prgb[local_couter].rgbtGreen,prgb[local_couter].rgbtBlue);
}
}
HBITMAP handle_bit_map = NULL;
handle_bit_map = CreateBitmap(
cxImage-pixels_shift,
cyImage,
1,
32,
local_bit_map_buffer);
delete []local_bit_map_buffer;
HRESULT local_handle_result;
HDC hdc;
gImageSrcLeft->GetDC(&hdc);
HDC hdc_compatible = CreateCompatibleDC(hdc);
SelectObject(hdc_compatible,handle_bit_map);
BitBlt(hdc, 0 ,0 ,cxImage-pixels_shift , cyImage , hdc_compatible, 0, 0, SRCCOPY);
gImageSrcLeft->ReleaseDC(hdc);
DeleteDC(hdc_compatible);
bool local_result = DeleteObject(handle_bit_map);
}
{
DWORD *local_bit_map_buffer;
local_bit_map_buffer = new DWORD[(cxImage-pixels_shift)*cyImage];
for(int local_counter_width=0;local_counter_width<cxImage-pixels_shift;local_counter_width++)
{
for(int local_counter_height=0;local_counter_height<cyImage;local_counter_height++)
{
int local_couter = local_counter_width+local_counter_height*cxImage;
int local_bit_map_couter = local_counter_width+(cyImage-(local_counter_height+1))*(cxImage-pixels_shift);
local_bit_map_buffer[local_bit_map_couter] = RGB_BYTE_ORDER(prgb[local_couter].rgbtRed,prgb[local_couter].rgbtGreen,prgb[local_couter].rgbtBlue);
}
}
HBITMAP handle_bit_map = NULL;
handle_bit_map = CreateBitmap(
cxImage-pixels_shift,
cyImage,
1,
32,
local_bit_map_buffer);
delete []local_bit_map_buffer;
HRESULT local_handle_result;
HDC hdc;
gImageSrcRight->GetDC(&hdc);
HDC hdc_compatible = CreateCompatibleDC(hdc);
SelectObject(hdc_compatible,handle_bit_map);
BitBlt(hdc, 0 ,0 ,cxImage-pixels_shift , cyImage , hdc_compatible, 0, 0, SRCCOPY);
gImageSrcRight->ReleaseDC(hdc);
DeleteDC(hdc_compatible);
bool local_result = DeleteObject(handle_bit_map);
}
int gImageWidth= cxImage-pixels_shift;
int gImageHeight= cyImage;
IDirect3DSurface9* gImageSrc= NULL;
local_handle_result = direct_3D_device->CreateOffscreenPlainSurface(
gImageWidth* 2,
gImageHeight+ 1,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
&gImageSrc, NULL);
if(local_handle_result!=S_OK)
{
gImageSrcLeft->Release();
gImageSrcRight->Release();
return local_handle_result;
}
RECT srcRect= { 0, 0, gImageWidth, gImageHeight};
RECT dstRect= { 0, 0, gImageWidth, gImageHeight};
direct_3D_device->StretchRect(gImageSrcLeft, &srcRect, gImageSrc, &dstRect, D3DTEXF_LINEAR);
RECT srcRect2= { 0, 0, 2*gImageWidth, gImageHeight+1};
RECT dstRect2= {gImageWidth, 0, 2*gImageWidth, gImageHeight};
direct_3D_device->StretchRect(gImageSrcRight, &srcRect, gImageSrc, &dstRect2, D3DTEXF_LINEAR);
#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e //NV3D
typedef struct _Nv_Stereo_Image_Header
{
unsigned int dwSignature;
unsigned int dwWidth;
unsigned int dwHeight;
unsigned int dwBPP;
unsigned int dwFlags;
} NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER;
#define SIH_SWAP_EYES 0x00000001
#define SIH_SCALE_TO_FIT 0x00000002
D3DLOCKED_RECT lr;
gImageSrc->LockRect(&lr,NULL,0);
LPNVSTEREOIMAGEHEADER pSIH=
(LPNVSTEREOIMAGEHEADER)(((unsigned char *) lr.pBits) + (lr.Pitch* gImageHeight));
pSIH->dwSignature= NVSTEREO_IMAGE_SIGNATURE;
pSIH->dwBPP= 32;
pSIH->dwFlags= SIH_SWAP_EYES;
pSIH->dwWidth= gImageWidth*2;
pSIH->dwHeight= gImageHeight;
gImageSrc->UnlockRect();
D3DVIEWPORT9 local_view_port;
direct_3D_device->GetViewport(&local_view_port);
RECT local_view_port_rect = {0,0,local_view_port.Width,local_view_port.Height};
{
gImageSrcLeft->Release();
gImageSrcRight->Release();
}
{
direct_3D_device->Clear (0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB (0, 0, 0), 0.0f, 0);
direct_3D_device->BeginScene ();
IDirect3DSurface9* pDestSurface;
direct_3D_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pDestSurface);
if(pDestSurface)
{
direct_3D_device->StretchRect(gImageSrc, &srcRect2, pDestSurface, &local_view_port_rect, D3DTEXF_LINEAR);
}
direct_3D_device->EndScene ();
if(pDestSurface)
{
pDestSurface->Release();
}
if(gImageSrc)
{
gImageSrc->Release();
}
}
}
}
return S_OK;
}