summaryrefslogtreecommitdiff
path: root/ARMFCaptureD3D/device.cpp
diff options
context:
space:
mode:
authorfcolin2011-11-18 12:14:12 +0000
committerfcolin2011-11-18 12:14:12 +0000
commit6bcf419d2e8f739b432d4790d1ba9d48ab65365b (patch)
tree92815e16f189c8e328dff4fcfa38ebe1d0217fdd /ARMFCaptureD3D/device.cpp
parent487e963b081d7ffe2ddf489e11d927982c9101a6 (diff)
downloadamilis-6bcf419d2e8f739b432d4790d1ba9d48ab65365b.zip
amilis-6bcf419d2e8f739b432d4790d1ba9d48ab65365b.tar.gz
amilis-6bcf419d2e8f739b432d4790d1ba9d48ab65365b.tar.bz2
amilis-6bcf419d2e8f739b432d4790d1ba9d48ab65365b.tar.xz
Diffstat (limited to 'ARMFCaptureD3D/device.cpp')
-rw-r--r--ARMFCaptureD3D/device.cpp1280
1 files changed, 1280 insertions, 0 deletions
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<void**>(&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;
+}
+