You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

372 lines
9.7 KiB
C++

2 years ago
#include "D3DVidRender.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
// ʹ<><CAB9>stdio.h<><68>strsafe.h<><68><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>TRACE<43>Ĺ<EFBFBD><C4B9><EFBFBD>
/*void LogTrace(LPCTSTR pszFormat, ...)
{
va_list pArgs;
char szMessageBuffer[16380]={0};
va_start( pArgs, pszFormat );
_vsntprintf( szMessageBuffer, 16380, pszFormat, pArgs );
va_end( pArgs );
OutputDebugString(szMessageBuffer);
}*/
CD3DVidRender::CD3DVidRender(void)
{
m_pDirect3D9 = NULL;
m_pDirect3DDevice = NULL;
m_pDirect3DSurfaceRender = NULL;
m_pBackBuffer = NULL;
}
CD3DVidRender::~CD3DVidRender(void)
{
}
void CD3DVidRender::Cleanup()
{
if (m_pBackBuffer)
{
m_pBackBuffer->Release();
m_pBackBuffer = NULL;
}
if(m_pDirect3DSurfaceRender)
{
m_pDirect3DSurfaceRender->Release();
m_pDirect3DSurfaceRender = NULL;
}
if(m_pDirect3DDevice)
{
m_pDirect3DDevice->Release();
m_pDirect3DDevice = NULL;
}
if(m_pDirect3D9)
{
m_pDirect3D9->Release();
m_pDirect3D9 = NULL;
}
if (m_pD3DXFont)
{
m_pD3DXFont->Release() ;
m_pD3DXFont = NULL ;
}
}
BOOL CD3DVidRender::InitD3D_RGB32(HWND hwnd, int img_width, int img_height)
{
HRESULT lRet;
if (m_pDirect3D9)
{
m_pDirect3D9->Release();
m_pDirect3D9 = NULL;
}
m_pDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);
if(m_pDirect3D9 == NULL)
{
return FALSE;
}
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.hDeviceWindow = hwnd;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = FALSE;
d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
D3DCAPS9 caps;
DWORD BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
HRESULT hr = m_pDirect3D9->GetDeviceCaps ( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps ) ;
if ( SUCCEEDED(hr) )
{
if ( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
}
else
{
BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
}
}
if (m_pDirect3DDevice)
{
m_pDirect3DDevice->Release();
m_pDirect3DDevice = NULL;
}
lRet = m_pDirect3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, BehaviorFlags, &d3dpp, &m_pDirect3DDevice);
if(FAILED(lRet))
{
return FALSE;
}
if (m_pDirect3DSurfaceRender)
{
m_pDirect3DSurfaceRender->Release();
m_pDirect3DSurfaceRender = NULL;
}
lRet = m_pDirect3DDevice->CreateOffscreenPlainSurface(img_width, img_height, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,
&m_pDirect3DSurfaceRender, NULL);
if(FAILED(lRet))
{
return FALSE;
}
//// create the font
//ZeroMemory(&m_font_desc, sizeof(m_font_desc));
//// set font descripter
//strcpy(m_font_desc.FaceName, "<22><><EFBFBD><EFBFBD>");
//m_font_desc.Height = 32;
//// Creates a font object indirectly for both a device and a font
//D3DXCreateFontIndirect(m_pDirect3DDevice, &m_font_desc, &m_pD3DXFont);
return TRUE;
}
BOOL CD3DVidRender::InitD3D_YUV(HWND hwnd,int img_width, int img_height)
{
HRESULT lRet;
if (m_pDirect3D9)
{
m_pDirect3D9->Release();
m_pDirect3D9 = NULL;
}
m_pDirect3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if( m_pDirect3D9 == NULL )
{
return FALSE;
}
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.hDeviceWindow = hwnd;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = FALSE;
d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
D3DCAPS9 caps;
DWORD BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
HRESULT hr = m_pDirect3D9->GetDeviceCaps ( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps ) ;
if ( SUCCEEDED(hr) )
{
if ( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE ;
}
else
{
BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
}
}
if (m_pDirect3DDevice)
{
m_pDirect3DDevice->Release();
m_pDirect3DDevice = NULL;
}
lRet = m_pDirect3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, BehaviorFlags, &d3dpp, &m_pDirect3DDevice );
if(FAILED(lRet))
{
return FALSE;
}
if (m_pDirect3DSurfaceRender)
{
m_pDirect3DSurfaceRender->Release();
m_pDirect3DSurfaceRender = NULL;
}
lRet = m_pDirect3DDevice->CreateOffscreenPlainSurface( img_width, img_height, (D3DFORMAT)MAKEFOURCC('Y', 'V', '1', '2'), D3DPOOL_DEFAULT, &m_pDirect3DSurfaceRender, NULL);
if(FAILED(lRet))
{
return FALSE;
}
return TRUE;
}
BOOL CD3DVidRender::Render_RGB32(unsigned char * pdata, int img_width, int img_height)
{
if (NULL == m_pDirect3DSurfaceRender)
{
return FALSE ;
}
HRESULT lRet;
D3DLOCKED_RECT d3d_rect;
lRet = m_pDirect3DSurfaceRender->LockRect(&d3d_rect, NULL, D3DLOCK_DONOTWAIT);
if(FAILED(lRet))
{
return FALSE;
}
byte * pSrc = pdata;
byte * pDest = (BYTE *)d3d_rect.pBits;
int lPitch = d3d_rect.Pitch;
unsigned long i = 0;
for (i = 0; i < img_height; i++)
{
memmove(pDest, pSrc, img_width * 4);
pDest += lPitch;
pSrc += img_width * 4;
}
lRet = m_pDirect3DSurfaceRender->UnlockRect();
if(FAILED(lRet))
{
return FALSE;
}
if (m_pDirect3DDevice == NULL)
{
return FALSE;
}
m_pDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
m_pDirect3DDevice->BeginScene();
if (m_pBackBuffer)
{
m_pBackBuffer->Release();
m_pBackBuffer = NULL;
}
m_pDirect3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer);
GetClientRect(d3dpp.hDeviceWindow, &m_rtViewport);
calculate_display_rect(&m_rtViewport,img_width,img_height, m_rtViewport.right, m_rtViewport.bottom) ;
m_pDirect3DDevice->StretchRect(m_pDirect3DSurfaceRender, NULL, m_pBackBuffer, &m_rtViewport, D3DTEXF_LINEAR);
//if (m_pDirect3DDevice != NULL)
//{
// m_rtFont = m_rtViewport ;
// m_rtFont.top = (m_rtViewport.bottom - m_rtViewport.top) * 3 / 4 ;
// m_pD3DXFont->DrawTextW(NULL, L"Programming is fun!<21><><EFBFBD><EFBFBD>", -1, &m_rtFont, DT_CENTER | DT_VCENTER, D3DCOLOR_XRGB(255,0,0));
//}
m_pDirect3DDevice->EndScene();
m_pDirect3DDevice->Present(NULL, NULL, NULL, NULL);
RECT rcCurrentClient;
GetClientRect(d3dpp.hDeviceWindow, &rcCurrentClient);
if( ( UINT )rcCurrentClient.right != d3dpp.BackBufferWidth ||
( UINT )rcCurrentClient.bottom != d3dpp.BackBufferHeight )
{
d3dpp.BackBufferWidth = rcCurrentClient.right;
d3dpp.BackBufferHeight = rcCurrentClient.bottom;
InitD3D_RGB32(d3dpp.hDeviceWindow, img_width, img_height);
}
if (m_pDirect3DDevice && m_pDirect3DDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
InitD3D_RGB32(d3dpp.hDeviceWindow, img_width, img_height);
}
return TRUE;
}
void CD3DVidRender::calculate_display_rect(RECT *rect,int img_width, int img_height, int scr_width, int scr_height)
{
double video_W = img_width ; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
double video_H = img_height ; // <20><>Ƶ<EFBFBD>߶<EFBFBD>
double show_H = scr_height ; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
double show_W = scr_width ; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if((video_W / video_H) <= show_W / show_H)
{
int adjust_W =(int)(show_W - (video_W / video_H ) * show_H) / 2 ;
rect->left = adjust_W ;
rect->top = 0 ;
rect->right = scr_width - adjust_W ;
rect->bottom = scr_height ;
}
else if((video_W / video_H) > show_W / show_H)
{
int adjust_H = (int)(show_H - (video_H / video_W) * show_W) / 2 ;
rect->left = 0 ;
rect->top = adjust_H ;
rect->right = scr_width ;
rect->bottom = scr_height - adjust_H ;
}
}
BOOL CD3DVidRender::Render_YUV(unsigned char * pdata, int img_width, int img_height)
{
HRESULT lRet = -1;
D3DLOCKED_RECT d3d_rect;
lRet = m_pDirect3DSurfaceRender->LockRect(&d3d_rect, NULL, D3DLOCK_DONOTWAIT);
if(FAILED(lRet))
{
return FALSE;
}
byte *pSrc = pdata;
byte * pDest = (BYTE *)d3d_rect.pBits;
int stride = d3d_rect.Pitch;
unsigned long i = 0;
for(i = 0; i < img_height; i ++)
{
memmove(pDest + i * stride,pSrc + i * img_width, img_width);
}
for(i = 0; i < img_height/2; i ++)
{
memmove(pDest + stride * img_height + i * stride / 2,pSrc + img_width * img_height + img_width * img_height / 4 + i * img_width / 2, img_width / 2);
}
for(i = 0; i < img_height / 2; i ++)
{
memmove(pDest + stride * img_height + stride * img_height / 4 + i * stride / 2,pSrc + img_width * img_height + i * img_width / 2, img_width / 2);
}
lRet = m_pDirect3DSurfaceRender->UnlockRect();
if(FAILED(lRet))
{
return FALSE;
}
m_pDirect3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
m_pDirect3DDevice->BeginScene();
if (m_pBackBuffer)
{
m_pBackBuffer->Release();
m_pBackBuffer = NULL;
}
m_pDirect3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer);
GetClientRect(d3dpp.hDeviceWindow, &m_rtViewport);
m_pDirect3DDevice->StretchRect(m_pDirect3DSurfaceRender, NULL, m_pBackBuffer, &m_rtViewport, D3DTEXF_LINEAR);
m_pDirect3DDevice->EndScene();
m_pDirect3DDevice->Present( NULL, NULL, NULL, NULL );
RECT rcCurrentClient;
GetClientRect(d3dpp.hDeviceWindow, &rcCurrentClient);
if( ( UINT )rcCurrentClient.right != d3dpp.BackBufferWidth ||
( UINT )rcCurrentClient.bottom != d3dpp.BackBufferHeight )
{
d3dpp.BackBufferWidth = rcCurrentClient.right;
d3dpp.BackBufferHeight = rcCurrentClient.bottom;
InitD3D_YUV(d3dpp.hDeviceWindow, img_width, img_height);
}
if (m_pDirect3DDevice && m_pDirect3DDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
{
InitD3D_YUV(d3dpp.hDeviceWindow, img_width, img_height);
}
return TRUE;
}