From 6bcf419d2e8f739b432d4790d1ba9d48ab65365b Mon Sep 17 00:00:00 2001 From: fcolin Date: Fri, 18 Nov 2011 12:14:12 +0000 Subject: --- ARMFCaptureD3D/device.cpp | 1280 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1280 insertions(+) create mode 100644 ARMFCaptureD3D/device.cpp (limited to 'ARMFCaptureD3D/device.cpp') diff --git a/ARMFCaptureD3D/device.cpp b/ARMFCaptureD3D/device.cpp new file mode 100644 index 0000000..13ae7cc --- /dev/null +++ b/ARMFCaptureD3D/device.cpp @@ -0,0 +1,1280 @@ +////////////////////////////////////////////////////////////////////////// +// +// device.cpp: Manages the Direct3D device +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +////////////////////////////////////////////////////////////////////////// + +#include "ARMFCaptureD3D.h" +#include "BufferLock.h" +#include "debug.h" +#include "ARAnalyse.h" + +extern ARAnalyse *g_pAnalyse; + +void TransformImage_RGB24( + BYTE* pDest, + LONG lDestStride, + const BYTE* pSrc, + LONG lSrcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ); + +void TransformImage_RGB32( + BYTE* pDest, + LONG lDestStride, + const BYTE* pSrc, + LONG lSrcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ); + +void TransformImage_YUY2( + BYTE* pDest, + LONG lDestStride, + const BYTE* pSrc, + LONG lSrcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ); + +void TransformImage_NV12( + BYTE* pDst, + LONG dstStride, + const BYTE* pSrc, + LONG srcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ); + + +RECT LetterBoxRect(const RECT& rcSrc, const RECT& rcDst); +RECT CorrectAspectRatio(const RECT& src, const MFRatio& srcPAR); +HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride); + + +inline LONG Width(const RECT& r) +{ + return r.right - r.left; +} + +inline LONG Height(const RECT& r) +{ + return r.bottom - r.top; +} + + +// Static table of output formats and conversion functions. +struct ConversionFunction +{ + GUID subtype; + IMAGE_TRANSFORM_FN xform; +}; + + +ConversionFunction g_FormatConversions[] = +{ + { MFVideoFormat_RGB32, TransformImage_RGB32 }, + { MFVideoFormat_RGB24, TransformImage_RGB24 }, + { MFVideoFormat_YUY2, TransformImage_YUY2 }, + { MFVideoFormat_NV12, TransformImage_NV12 } +}; + +const DWORD g_cFormats = ARRAYSIZE(g_FormatConversions); + + +//------------------------------------------------------------------- +// Constructor +//------------------------------------------------------------------- + +DrawDevice::DrawDevice() : + m_hwnd(NULL), + m_pDevice(NULL), + m_pSwapChain(NULL), + m_pVertexBuffer(NULL), + m_pIndexBuffer(NULL), +#ifdef DX9 + m_pD3D(NULL), + m_format(D3DFMT_UNKNOWN), +#else + m_format(DXGI_FORMAT_UNKNOWN), +#endif + m_width(0), + m_height(0), + m_lDefaultStride(0), + m_interlace(MFVideoInterlace_Unknown), + m_convertFn(NULL) +{ + m_PixelAR.Denominator = m_PixelAR.Numerator = 1; + + ZeroMemory(&m_d3dpp, sizeof(m_d3dpp)); +} + + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- + +DrawDevice::~DrawDevice() +{ + DestroyDevice(); +} + +void DrawDevice::GetSize(UINT* width, UINT *height) const +{ + *width = m_width; + *height = m_height; +} +//------------------------------------------------------------------- +// GetFormat +// +// Get a supported output format by index. +//------------------------------------------------------------------- + +HRESULT DrawDevice::GetFormat(DWORD index, GUID *pSubtype) const +{ + if (index < g_cFormats) + { + *pSubtype = g_FormatConversions[index].subtype; + return S_OK; + } + return MF_E_NO_MORE_TYPES; +} + + +//------------------------------------------------------------------- +// IsFormatSupported +// +// Query if a format is supported. +//------------------------------------------------------------------- + +BOOL DrawDevice::IsFormatSupported(REFGUID subtype) const +{ + for (DWORD i = 0; i < g_cFormats; i++) + { + if (subtype == g_FormatConversions[i].subtype) + { + return TRUE; + } + } + return FALSE; +} + + + + +//------------------------------------------------------------------- +// CreateDevice +// +// Create the Direct3D device. +//------------------------------------------------------------------- + +HRESULT DrawDevice::CreateDevice(HWND hwnd) +{ + HRESULT hr = S_OK; + if (m_pDevice) + { + return S_OK; + } +#ifdef DX9 + // Create the Direct3D object. + if (m_pD3D == NULL) + { + m_pD3D = Direct3DCreate9(D3D_SDK_VERSION); + + if (m_pD3D == NULL) + { + return E_FAIL; + } + } + + + D3DPRESENT_PARAMETERS pp = { 0 }; + D3DDISPLAYMODE mode = { 0 }; + + pp.BackBufferFormat = D3DFMT_A8R8G8B8; + pp.SwapEffect = D3DSWAPEFFECT_FLIP; + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + pp.Windowed = TRUE; + pp.hDeviceWindow = hwnd; + + hr = m_pD3D->GetAdapterDisplayMode( + D3DADAPTER_DEFAULT, + &mode + ); + + if (FAILED(hr)) { goto done; } + + hr = m_pD3D->CheckDeviceType( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + mode.Format, + pp.BackBufferFormat, + TRUE // windowed + ); + + if (FAILED(hr)) { goto done; } + + + + hr = m_pD3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + hwnd, + D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, + &pp, + &m_pDevice + ); +#else + + DXGI_SWAP_CHAIN_DESC pp = { 0 }; + ZeroMemory( &pp, sizeof( pp ) ); + + + pp.BufferCount = 1; + //pp.BufferDesc.Width = width; + //pp.BufferDesc.Height = height; + pp.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + pp.BufferDesc.RefreshRate.Numerator = 0; //users =0, originally 60 + pp.BufferDesc.RefreshRate.Denominator = 0; + pp.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + + //pp.SwapEffect = D3DSWAPEFFECT_COPY; + //pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + pp.Windowed = TRUE; + pp.OutputWindow = hwnd; + + D3D_FEATURE_LEVEL FeatureLevels = D3D_FEATURE_LEVEL_11_0; + + + hr = D3D11CreateDevice( NULL,D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &FeatureLevels, 1, D3D11_SDK_VERSION, &m_pDevice, &FeatureLevels, &m_pDeviceContext ); + +#endif + + if (FAILED(hr)) { goto done; } + // Turn on Blending + m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + m_pDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + m_hwnd = hwnd; + m_d3dpp = pp; + +done: + return hr; +} + +//------------------------------------------------------------------- +// SetConversionFunction +// +// Set the conversion function for the specified video format. +//------------------------------------------------------------------- + +HRESULT DrawDevice::SetConversionFunction(REFGUID subtype) +{ + m_convertFn = NULL; + + for (DWORD i = 0; i < g_cFormats; i++) + { + if (g_FormatConversions[i].subtype == subtype) + { + m_convertFn = g_FormatConversions[i].xform; + return S_OK; + } + } + + return MF_E_INVALIDMEDIATYPE; +} + + +//------------------------------------------------------------------- +// SetVideoType +// +// Set the video format. +//------------------------------------------------------------------- + +HRESULT DrawDevice::SetVideoType(IMFMediaType *pType) +{ + HRESULT hr = S_OK; + GUID subtype = { 0 }; + MFRatio PAR = { 0 }; + + // Find the video subtype. + hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype); + + if (FAILED(hr)) { goto done; } + + // Choose a conversion function. + // (This also validates the format type.) + + hr = SetConversionFunction(subtype); + + if (FAILED(hr)) { goto done; } + + // + // Get some video attributes. + // + + // Get the frame size. + hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &m_width, &m_height); + + if (FAILED(hr)) { goto done; } + + + // Get the interlace mode. Default: assume progressive. + m_interlace = (MFVideoInterlaceMode)MFGetAttributeUINT32( + pType, + MF_MT_INTERLACE_MODE, + MFVideoInterlace_Progressive + ); + + // Get the image stride. + hr = GetDefaultStride(pType, &m_lDefaultStride); + + if (FAILED(hr)) { goto done; } + + // Get the pixel aspect ratio. Default: Assume square pixels (1:1) + hr = MFGetAttributeRatio( + pType, + MF_MT_PIXEL_ASPECT_RATIO, + (UINT32*)&PAR.Numerator, + (UINT32*)&PAR.Denominator + ); + + if (SUCCEEDED(hr)) + { + m_PixelAR = PAR; + } + else + { + m_PixelAR.Numerator = m_PixelAR.Denominator = 1; + } +#ifdef DX9 + m_format = (D3DFORMAT)subtype.Data1; +#else + m_format = (DXGI_FORMAT)subtype.Data1; +#endif + // Create Direct3D swap chains. + + hr = CreateSwapChains(); + + if (FAILED(hr)) { goto done; } + + + // Update the destination rectangle for the correct + // aspect ratio. + + UpdateDestinationRect(); + +done: + if (FAILED(hr)) + { +#ifdef DX9 + m_format = D3DFMT_UNKNOWN; +#else + m_format = DXGI_FORMAT_UNKNOWN; +#endif + m_convertFn = NULL; + } + return hr; +} + +//------------------------------------------------------------------- +// UpdateDestinationRect +// +// Update the destination rectangle for the current window size. +// The destination rectangle is letterboxed to preserve the +// aspect ratio of the video image. +//------------------------------------------------------------------- + +void DrawDevice::UpdateDestinationRect() +{ + RECT rcClient; + RECT rcSrc = { 0, 0, m_width, m_height }; + + GetClientRect(m_hwnd, &rcClient); + + rcSrc = CorrectAspectRatio(rcSrc, m_PixelAR); + + m_rcDest = LetterBoxRect(rcSrc, rcClient); +} + + +//------------------------------------------------------------------- +// CreateSwapChains +// +// Create Direct3D swap chains. +//------------------------------------------------------------------- + +HRESULT DrawDevice::CreateSwapChains() +{ + HRESULT hr = S_OK; +#ifdef DX9 + D3DPRESENT_PARAMETERS pp = { 0 }; + + SafeRelease(&m_pSwapChain); + + pp.BackBufferWidth = m_width; + pp.BackBufferHeight = m_height; + pp.Windowed = TRUE; + pp.SwapEffect = D3DSWAPEFFECT_FLIP; + pp.hDeviceWindow = m_hwnd; + pp.BackBufferFormat = D3DFMT_A8R8G8B8; + pp.Flags = + D3DPRESENTFLAG_VIDEO | D3DPRESENTFLAG_DEVICECLIP | + D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + //pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + pp.BackBufferCount = 2; + + hr = m_pDevice->CreateAdditionalSwapChain(&pp, &m_pSwapChain); +#else + DXGI_SWAP_CHAIN_DESC pp = { 0 }; + + SafeRelease(&m_pSwapChain); + pp.BufferCount = 1; + pp.BufferDesc.Width = m_width; + pp.BufferDesc.Height = m_height; + pp.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + pp.BufferDesc.RefreshRate.Numerator = 0; //users =0, originally 60 + pp.BufferDesc.RefreshRate.Denominator = 0; + pp.Windowed = TRUE; + pp.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //D3DSWAPEFFECT_FLIP; + pp.OutputWindow = m_hwnd; + + pp.Flags = DXGI_SWAP_CHAIN_FLAG_NONPREROTATED; + /* D3DPRESENTFLAG_VIDEO | D3DPRESENTFLAG_DEVICECLIP | + D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;*/ + //pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + + IDXGIDevice* m_pDXGIDevice; + IDXGIAdapter* m_pDXGIAdapter; + IDXGIFactory* m_pDXGIFactory; + + hr = m_pDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)& m_pDXGIDevice); + + if ( hr != S_OK ) + { + DBGMSG(L"cDX10Mananger::Initialise(): Unable to get DXGIDevice (hr = 0x%0X)\n", hr ); + return hr; + } + + hr = m_pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)& m_pDXGIAdapter); + + if ( hr != S_OK ) + { + DBGMSG(L"cDX10Mananger::Initialise(): Unable to get DXGIAdapter (hr = 0x%0X)\n", hr ); + return hr; + } + + hr = m_pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)& m_pDXGIFactory); + + if ( hr != S_OK ) + { + DBGMSG(L"cDX10Mananger::Initialise(): Unable to get DXGIFactory (hr = 0x%0X)\n", hr ); + return hr; + } + hr = m_pDXGIFactory->CreateSwapChain(m_pDevice, &pp, &m_pSwapChain ); +#endif + + return hr; +} + + +//------------------------------------------------------------------- +// DrawFrame +// +// Draw the video frame. +//------------------------------------------------------------------- + +HRESULT DrawDevice::DrawFrame(IMFMediaBuffer *pBuffer) +{ + if (m_convertFn == NULL) + { + return MF_E_INVALIDREQUEST; + } + + HRESULT hr = S_OK; + BYTE *pbScanline0 = NULL; + LONG lStride = 0; +#ifdef DX9 + D3DLOCKED_RECT lr; + + IDirect3DSurface9 *pSurf = NULL; + IDirect3DSurface9 *pBB = NULL; +#else + DXGI_MAPPED_RECT lr; + + IDXGISurface *pSurf = NULL; + IDXGISurface *pBB = NULL; + +#endif + if (m_pDevice == NULL || m_pSwapChain == NULL) + { + return S_OK; + } + + + VideoBufferLock buffer(pBuffer); // Helper object to lock the video buffer. + + hr = TestCooperativeLevel(); + + if (FAILED(hr)) { goto done; } + + // Lock the video buffer. This method returns a pointer to the first scan + // line in the image, and the stride in bytes. + + hr = buffer.LockBuffer(m_lDefaultStride, m_height, &pbScanline0, &lStride); + + if (FAILED(hr)) { goto done; } +#ifdef DX9 + // Get the swap-chain surface. + hr = m_pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurf); + + if (FAILED(hr)) { goto done; } + + // Lock the swap-chain surface. + hr = pSurf->LockRect(&lr, NULL, D3DLOCK_NOSYSLOCK ); +#else + // Get the swap-chain surface. + hr = m_pSwapChain->GetBuffer(0, __uuidof(pSurf), reinterpret_cast(&pSurf)); + + if (FAILED(hr)) { goto done; } + + // Lock the swap-chain surface. + hr = pSurf->Map( &lr, DXGI_MAP_WRITE ); +#endif + if (FAILED(hr)) { goto done; } + + + // Convert the frame. This also copies it to the Direct3D surface. + + m_convertFn( + (BYTE*)lr.pBits, + lr.Pitch, + pbScanline0, + lStride, + m_width, + m_height + ); +#ifdef DX9 + hr = pSurf->UnlockRect(); + + if (FAILED(hr)) { goto done; } + + + // Color fill the back buffer. + hr = m_pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBB); + + if (FAILED(hr)) { goto done; } + + hr = m_pDevice->ColorFill(pBB, NULL, D3DCOLOR_XRGB(0x80, 0x80, 0x80)); + + if (FAILED(hr)) { goto done; } + + + // Blit the frame. + + hr = m_pDevice->StretchRect(pSurf, NULL, pBB, &m_rcDest, D3DTEXF_LINEAR); + + if (FAILED(hr)) { goto done; } + + RenderObjects(); + // Present the frame. + + hr = m_pDevice->Present(NULL, NULL, NULL, NULL); + + +#else + hr = pSurf->Unmap(); + + if (FAILED(hr)) { goto done; } + + //Create a render target view + ID3D11Texture2D *pBackBuffer; + ID3D11RenderTargetView *g_pRenderTargetView; + + hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer ); + + if (FAILED(hr)) { goto done; } + + hr = m_pDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); + pBackBuffer->Release(); + if (FAILED(hr)) { goto done; } + + m_pDeviceContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL ); + + // + // Clear the backbuffer + // + float ClearColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; // RGBA + m_pDeviceContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); + + + if (FAILED(hr)) { goto done; } + + + // Blit the frame. + + //hr = m_pDeviceContext->StretchRect(pSurf, NULL, pBB, &m_rcDest, D3DTEXF_LINEAR); + + if (FAILED(hr)) { goto done; } + + + // Present the frame. + + hr = m_pSwapChain->Present(0,0); +#endif + +done: +#ifdef DX9 + SafeRelease(&pBB); + if ( pSurf) SafeRelease(&pSurf); +#endif + return hr; +} + +//------------------------------------------------------------------- +// TestCooperativeLevel +// +// Test the cooperative-level status of the Direct3D device. +//------------------------------------------------------------------- + +HRESULT DrawDevice::TestCooperativeLevel() +{ + if (m_pDevice == NULL) + { + return E_FAIL; + } + + HRESULT hr = S_OK; +#ifdef DX9 + // Check the current status of D3D9 device. + hr = m_pDevice->TestCooperativeLevel(); + + switch (hr) + { + case D3D_OK: + break; + + case D3DERR_DEVICELOST: + hr = S_OK; + + case D3DERR_DEVICENOTRESET: + hr = ResetDevice(); + break; + + default: + // Some other failure. + break; + } +#endif + return hr; +} + + +//------------------------------------------------------------------- +// ResetDevice +// +// Resets the Direct3D device. +//------------------------------------------------------------------- + +HRESULT DrawDevice::ResetDevice() +{ + + HRESULT hr = S_OK; +#ifdef DX9 + if (m_pDevice) + { + D3DPRESENT_PARAMETERS d3dpp = m_d3dpp; + + hr = m_pDevice->Reset(&d3dpp); + + if (FAILED(hr)) + { + DestroyDevice(); + } + } + + if (m_pDevice == NULL) + { + hr = CreateDevice(m_hwnd); + + if (FAILED(hr)) { goto done; } + } + + if ((m_pSwapChain == NULL) && (m_format != D3DFMT_UNKNOWN)) + { + hr = CreateSwapChains(); + + if (FAILED(hr)) { goto done; } + + UpdateDestinationRect(); + } +#else + if (m_pDevice) + { + DestroyDevice(); + } + + if (m_pDevice == NULL) + { + hr = CreateDevice(m_hwnd); + + if (FAILED(hr)) { goto done; } + } + + if ((m_pSwapChain == NULL) && (m_format != DXGI_FORMAT_UNKNOWN)) + { + hr = CreateSwapChains(); + + if (FAILED(hr)) { goto done; } + + UpdateDestinationRect(); + } +#endif +done: + + return hr; +} + + +//------------------------------------------------------------------- +// DestroyDevice +// +// Release all Direct3D resources. +//------------------------------------------------------------------- + +void DrawDevice::DestroyDevice() +{ + SafeRelease(&m_pSwapChain); + SafeRelease(&m_pDevice); +#ifdef DX9 + SafeRelease(&m_pD3D); + if ( m_pVertexBuffer ) SafeRelease(&m_pVertexBuffer); + if ( m_pIndexBuffer ) SafeRelease(&m_pIndexBuffer); +#endif +} + + +struct CUSTOMVERTEX {FLOAT X, Y, Z,RHW; DWORD COLOR;}; + +typedef struct CUSTOMVERTEX CustomVertex; + +#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) + +#define TRSF( axe, data ) (translate##axe + (scale##axe * data)); + +HRESULT DrawDevice::RenderObjects() +{ + HRESULT hr = S_OK; + //const ARFloat* nMatrix; + DWORD color = D3DCOLOR_ARGB(127, 0, 127, 0); + int count = g_pAnalyse->markers.size(); + if ( !count ) return hr; + //D3DMATRIX world_matrix; + //D3DMATRIX view_matrix; + //D3DMATRIX projection_matrix; + + //nMatrix = g_pAnalyse->getModelViewMatrix(); + // + ////OpenGL + // //m0 m4 m8 m12 + // //m1 m5 m9 m13 + // //m2 m6 m10 m14 + // //m3 m7 m11 m15 + // //WPF + // //M11 M12 M13 M14 + // //M21 M22 M23 M24 + // //M31 M32 M33 M34 + // //M41 M42 M43 M44 + // + //view_matrix._11 = nMatrix[0]; + // view_matrix._12 = nMatrix[4]; + // view_matrix._13 = nMatrix[8]; + // view_matrix._14 = nMatrix[12]; + // view_matrix._21 = nMatrix[1]; + // view_matrix._22 = nMatrix[5]; + // view_matrix._23 = nMatrix[9]; + // view_matrix._24 = nMatrix[13]; + // view_matrix._31 = nMatrix[2]; + // view_matrix._32 = nMatrix[6]; + // view_matrix._33 = nMatrix[10]; + // view_matrix._34 = nMatrix[14]; + // view_matrix._41 = nMatrix[3]; + // view_matrix._42 = nMatrix[7]; + // view_matrix._43 = nMatrix[11]; + // view_matrix._44 = nMatrix[15]; + //nMatrix = g_pAnalyse->getProjectionMatrix(); + //projection_matrix._11 = nMatrix[0]; + // projection_matrix._12 = nMatrix[4]; + // projection_matrix._13 = nMatrix[8]; + // projection_matrix._14 = nMatrix[12]; + // projection_matrix._21 = nMatrix[1]; + // projection_matrix._22 = nMatrix[5]; + // projection_matrix._23 = nMatrix[9]; + // projection_matrix._24 = nMatrix[13]; + // projection_matrix._31 = nMatrix[2]; + // projection_matrix._32 = nMatrix[6]; + // projection_matrix._33 = nMatrix[10]; + // projection_matrix._34 = nMatrix[14]; + // projection_matrix._41 = nMatrix[3]; + // projection_matrix._42 = nMatrix[7]; + // projection_matrix._43 = nMatrix[11]; + // projection_matrix._44 = nMatrix[15]; + + float scaleX = (float)(m_rcDest.right - m_rcDest.left ) / (float)m_width; + float scaleY = (float)(m_rcDest.bottom - m_rcDest.top ) / (float)m_height; + float translateX = m_rcDest.left; + float translateY = m_rcDest.top; + CustomVertex *quad = new CustomVertex[4*count]; + short *indexes = new short[6*count]; + int i =0; + for( ARAnalyse::MarkersMap::iterator iter = g_pAnalyse->markers.begin(); iter != g_pAnalyse->markers.end(); iter++) + { + int index = i*4; + ARToolKitPlus::ARMarkerInfo info = g_pAnalyse->getDetectedMarker(i++); + + quad[index].X = TRSF( X, info.vertex[0][0]) ; + quad[index].Y = TRSF( Y, (m_height - info.vertex[0][1])); + quad[index].Z = 0.0; + quad[index].RHW = 1.0f; + quad[index++].COLOR = color; + quad[index].X = TRSF( X, info.vertex[1][0]); + quad[index].Y = TRSF( Y, (m_height - info.vertex[1][1])); + quad[index].Z = 0; + quad[index].RHW = 1.0f; + quad[index++].COLOR = color; + quad[index].X = TRSF( X, info.vertex[2][0]); + quad[index].Y = TRSF( Y, (m_height - info.vertex[2][1])); + quad[index].Z = 0; + quad[index].RHW = 1.0f; + quad[index++].COLOR = color; + quad[index].X = TRSF( X, info.vertex[3][0]); + quad[index].Y = TRSF( Y, (m_height - info.vertex[3][1])); + quad[index].Z = 0; + quad[index].RHW = 1.0f; + quad[index].COLOR = color; + } + int j = 0; + for ( int i = 0; i < count; i++ ) + { + int index = i*4; + indexes[j++] = index+0; + indexes[j++] = index+2; + indexes[j++] = index+1; + indexes[j++] = index+3; + indexes[j++] = index+2; + indexes[j++] = index+0; + } + //if ( !m_pVertexBuffer ) + //{ + // // dim the vertex buffer to containt maximun markers + //hr = m_pDevice->CreateVertexBuffer(4*4096 *sizeof(CustomVertex), D3DUSAGE_WRITEONLY, CUSTOMFVF, D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL); + //if(FAILED(hr)) goto done; + //} + //if ( !m_pIndexBuffer ) + //{ + // // dim the index buffer to containt maximun markers + //hr = m_pDevice->CreateIndexBuffer(6*4096*sizeof(short), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIndexBuffer, NULL); + //if(FAILED(hr)) goto done; + //} + //// copy vertex buffer + //VOID* pVoid; + //hr = m_pVertexBuffer->Lock(0, 0, (void**)&pVoid, 0); + //if(FAILED(hr)) goto done; + // + //memcpy(pVoid, quad,4*count*sizeof(CustomVertex)); + //m_pVertexBuffer->Unlock(); + + //// copy index buffer + //hr = m_pIndexBuffer->Lock(0, 0, (void**)&pVoid, 0); + //if(FAILED(hr)) goto done; + // + //memcpy(pVoid, indexes, 6*count*sizeof(short)); + //m_pIndexBuffer->Unlock(); + //memset( (void*) &world_matrix , 0, sizeof( world_matrix )); + ////D3DMatrixIdentity( &world_matrix ); + //world_matrix._11 = scaleX; + //world_matrix._22 = scaleY; + //world_matrix._33 = 1.0; //scale Z + //world_matrix._41 = translateX; + //world_matrix._42 = translateY; + //world_matrix._43 = 0.0; // translate Z + //world_matrix._44 = 1.0; + + //m_pDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME); + //m_pDevice->SetRenderState(D3DRS_LIGHTING, true); + //m_pDevice->LightEnable( 0, TRUE ); + + m_pDevice->BeginScene(); + //m_pDevice->SetTransform(D3DTS_WORLD, &world_matrix); + //m_pDevice->SetTransform(D3DTS_VIEW, &view_matrix); + //m_pDevice->SetTransform(D3DTS_PROJECTION, &projection_matrix); + m_pDevice->SetFVF(CUSTOMFVF); + //m_pDevice->SetIndices(m_pIndexBuffer); + //m_pDevice->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(CustomVertex)); + //m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4*count, 0, 2*count); + //m_pDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 4*count, 0, 2*count); + m_pDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4*count, 2*count, indexes, D3DFMT_INDEX16,quad,sizeof(CustomVertex)); + m_pDevice->EndScene(); + + //m_pDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID); + +done: + delete quad; + delete indexes; + return hr; +} + +//------------------------------------------------------------------- +// +// Conversion functions +// +//------------------------------------------------------------------- + +__forceinline BYTE Clip(int clr) +{ + return (BYTE)(clr < 0 ? 0 : ( clr > 255 ? 255 : clr )); +} + +__forceinline RGBQUAD ConvertYCrCbToRGB( + int y, + int cr, + int cb + ) +{ + RGBQUAD rgbq; + + int c = y - 16; + int d = cb - 128; + int e = cr - 128; + + rgbq.rgbRed = Clip(( 298 * c + 409 * e + 128) >> 8); + rgbq.rgbGreen = Clip(( 298 * c - 100 * d - 208 * e + 128) >> 8); + rgbq.rgbBlue = Clip(( 298 * c + 516 * d + 128) >> 8); + + return rgbq; +} + + +//------------------------------------------------------------------- +// TransformImage_RGB24 +// +// RGB-24 to RGB-32 +//------------------------------------------------------------------- + +void TransformImage_RGB24( + BYTE* pDest, + LONG lDestStride, + const BYTE* pSrc, + LONG lSrcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ) +{ + for (DWORD y = 0; y < dwHeightInPixels; y++) + { + RGBTRIPLE *pSrcPel = (RGBTRIPLE*)pSrc; + DWORD *pDestPel = (DWORD*)pDest; + + for (DWORD x = 0; x < dwWidthInPixels; x++) + { +#ifdef DX9 + pDestPel[x] = D3DCOLOR_XRGB( + pSrcPel[x].rgbtRed, + pSrcPel[x].rgbtGreen, + pSrcPel[x].rgbtBlue + ); +#else + pDestPel[x] = pSrcPel[x].rgbtRed; +#endif + } + + pSrc += lSrcStride; + pDest += lDestStride; + } +} + +//------------------------------------------------------------------- +// TransformImage_RGB32 +// +// RGB-32 to RGB-32 +// +// Note: This function is needed to copy the image from system +// memory to the Direct3D surface. +//------------------------------------------------------------------- + +void TransformImage_RGB32( + BYTE* pDest, + LONG lDestStride, + const BYTE* pSrc, + LONG lSrcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ) +{ + MFCopyImage(pDest, lDestStride, pSrc, lSrcStride, dwWidthInPixels * 4, dwHeightInPixels); +} + +//------------------------------------------------------------------- +// TransformImage_YUY2 +// +// YUY2 to RGB-32 +//------------------------------------------------------------------- + +void TransformImage_YUY2( + BYTE* pDest, + LONG lDestStride, + const BYTE* pSrc, + LONG lSrcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ) +{ + for (DWORD y = 0; y < dwHeightInPixels; y++) + { + RGBQUAD *pDestPel = (RGBQUAD*)pDest; + WORD *pSrcPel = (WORD*)pSrc; + + for (DWORD x = 0; x < dwWidthInPixels; x += 2) + { + // Byte order is U0 Y0 V0 Y1 + + int y0 = (int)LOBYTE(pSrcPel[x]); + int u0 = (int)HIBYTE(pSrcPel[x]); + int y1 = (int)LOBYTE(pSrcPel[x + 1]); + int v0 = (int)HIBYTE(pSrcPel[x + 1]); + + pDestPel[x] = ConvertYCrCbToRGB(y0, v0, u0); + pDestPel[x + 1] = ConvertYCrCbToRGB(y1, v0, u0); + } + + pSrc += lSrcStride; + pDest += lDestStride; + } + +} + + +//------------------------------------------------------------------- +// TransformImage_NV12 +// +// NV12 to RGB-32 +//------------------------------------------------------------------- + +void TransformImage_NV12( + BYTE* pDst, + LONG dstStride, + const BYTE* pSrc, + LONG srcStride, + DWORD dwWidthInPixels, + DWORD dwHeightInPixels + ) +{ + const BYTE* lpBitsY = pSrc; + const BYTE* lpBitsCb = lpBitsY + (dwHeightInPixels * srcStride);; + const BYTE* lpBitsCr = lpBitsCb + 1; + + for (UINT y = 0; y < dwHeightInPixels; y += 2) + { + const BYTE* lpLineY1 = lpBitsY; + const BYTE* lpLineY2 = lpBitsY + srcStride; + const BYTE* lpLineCr = lpBitsCr; + const BYTE* lpLineCb = lpBitsCb; + + LPBYTE lpDibLine1 = pDst; + LPBYTE lpDibLine2 = pDst + dstStride; + + for (UINT x = 0; x < dwWidthInPixels; x += 2) + { + int y0 = (int)lpLineY1[0]; + int y1 = (int)lpLineY1[1]; + int y2 = (int)lpLineY2[0]; + int y3 = (int)lpLineY2[1]; + int cb = (int)lpLineCb[0]; + int cr = (int)lpLineCr[0]; + + RGBQUAD r = ConvertYCrCbToRGB(y0, cr, cb); + lpDibLine1[0] = r.rgbBlue; + lpDibLine1[1] = r.rgbGreen; + lpDibLine1[2] = r.rgbRed; + lpDibLine1[3] = 0; // Alpha + + r = ConvertYCrCbToRGB(y1, cr, cb); + lpDibLine1[4] = r.rgbBlue; + lpDibLine1[5] = r.rgbGreen; + lpDibLine1[6] = r.rgbRed; + lpDibLine1[7] = 0; // Alpha + + r = ConvertYCrCbToRGB(y2, cr, cb); + lpDibLine2[0] = r.rgbBlue; + lpDibLine2[1] = r.rgbGreen; + lpDibLine2[2] = r.rgbRed; + lpDibLine2[3] = 0; // Alpha + + r = ConvertYCrCbToRGB(y3, cr, cb); + lpDibLine2[4] = r.rgbBlue; + lpDibLine2[5] = r.rgbGreen; + lpDibLine2[6] = r.rgbRed; + lpDibLine2[7] = 0; // Alpha + + lpLineY1 += 2; + lpLineY2 += 2; + lpLineCr += 2; + lpLineCb += 2; + + lpDibLine1 += 8; + lpDibLine2 += 8; + } + + pDst += (2 * dstStride); + lpBitsY += (2 * srcStride); + lpBitsCr += srcStride; + lpBitsCb += srcStride; + } +} + + +//------------------------------------------------------------------- +// LetterBoxDstRect +// +// Takes a src rectangle and constructs the largest possible +// destination rectangle within the specifed destination rectangle +// such thatthe video maintains its current shape. +// +// This function assumes that pels are the same shape within both the +// source and destination rectangles. +// +//------------------------------------------------------------------- + +RECT LetterBoxRect(const RECT& rcSrc, const RECT& rcDst) +{ + // figure out src/dest scale ratios + int iSrcWidth = Width(rcSrc); + int iSrcHeight = Height(rcSrc); + + int iDstWidth = Width(rcDst); + int iDstHeight = Height(rcDst); + + int iDstLBWidth; + int iDstLBHeight; + + if (MulDiv(iSrcWidth, iDstHeight, iSrcHeight) <= iDstWidth) { + + // Column letter boxing ("pillar box") + + iDstLBWidth = MulDiv(iDstHeight, iSrcWidth, iSrcHeight); + iDstLBHeight = iDstHeight; + } + else { + + // Row letter boxing. + + iDstLBWidth = iDstWidth; + iDstLBHeight = MulDiv(iDstWidth, iSrcHeight, iSrcWidth); + } + + + // Create a centered rectangle within the current destination rect + + RECT rc; + + LONG left = rcDst.left + ((iDstWidth - iDstLBWidth) / 2); + LONG top = rcDst.top + ((iDstHeight - iDstLBHeight) / 2); + + SetRect(&rc, left, top, left + iDstLBWidth, top + iDstLBHeight); + + return rc; +} + + +//----------------------------------------------------------------------------- +// CorrectAspectRatio +// +// Converts a rectangle from the source's pixel aspect ratio (PAR) to 1:1 PAR. +// Returns the corrected rectangle. +// +// For example, a 720 x 486 rect with a PAR of 9:10, when converted to 1x1 PAR, +// is stretched to 720 x 540. +//----------------------------------------------------------------------------- + +RECT CorrectAspectRatio(const RECT& src, const MFRatio& srcPAR) +{ + // Start with a rectangle the same size as src, but offset to the origin (0,0). + RECT rc = {0, 0, src.right - src.left, src.bottom - src.top}; + + if ((srcPAR.Numerator != 1) || (srcPAR.Denominator != 1)) + { + // Correct for the source's PAR. + + if (srcPAR.Numerator > srcPAR.Denominator) + { + // The source has "wide" pixels, so stretch the width. + rc.right = MulDiv(rc.right, srcPAR.Numerator, srcPAR.Denominator); + } + else if (srcPAR.Numerator < srcPAR.Denominator) + { + // The source has "tall" pixels, so stretch the height. + rc.bottom = MulDiv(rc.bottom, srcPAR.Denominator, srcPAR.Numerator); + } + // else: PAR is 1:1, which is a no-op. + } + return rc; +} + + +//----------------------------------------------------------------------------- +// GetDefaultStride +// +// Gets the default stride for a video frame, assuming no extra padding bytes. +// +//----------------------------------------------------------------------------- + +HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride) +{ + LONG lStride = 0; + + // Try to get the default stride from the media type. + HRESULT hr = pType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&lStride); + if (FAILED(hr)) + { + // Attribute not set. Try to calculate the default stride. + GUID subtype = GUID_NULL; + + UINT32 width = 0; + UINT32 height = 0; + + // Get the subtype and the image size. + hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype); + if (SUCCEEDED(hr)) + { + hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height); + } + if (SUCCEEDED(hr)) + { + hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride); + } + + // Set the attribute for later reference. + if (SUCCEEDED(hr)) + { + (void)pType->SetUINT32(MF_MT_DEFAULT_STRIDE, UINT32(lStride)); + } + } + + if (SUCCEEDED(hr)) + { + *plStride = lStride; + } + return hr; +} + -- cgit v1.1