#include "convert.h" using namespace std; #if !defined(SAFE_RELEASE) #define SAFE_RELEASE(X) \ if (X) { \ X->Release(); \ X = nullptr; \ } #endif #if !defined(PRINTERR1) #define PRINTERR1(x) printf(__FUNCTION__ ": Error 0x%08x at line %d in file %s\n", x, __LINE__, __FILE__); #endif #if !defined(PRINTERR) #define PRINTERR(x, y) printf(__FUNCTION__ ": Error 0x%08x in %s at line %d in file %s\n", x, y, __LINE__, __FILE__); #endif /// Initialize Video Context HRESULT D3dConverter::Open(ID3D11Device* pDev, ID3D11DeviceContext* pCtx, const D3D11_VIDEO_PROCESSOR_COLOR_SPACE& inColorSpace, D3D11_VIDEO_PROCESSOR_COLOR_SPACE& outColorSpace) { m_pDev = pDev; m_pCtx = pCtx; m_pDev->AddRef(); m_pCtx->AddRef(); /// Obtain Video device and Video device context HRESULT hr = m_pDev->QueryInterface(__uuidof(ID3D11VideoDevice), (void**)&m_pVid); if (FAILED(hr)) { PRINTERR(hr, "QAI for ID3D11VideoDevice"); } hr = m_pCtx->QueryInterface(__uuidof(ID3D11VideoContext), (void**)&m_pVidCtx); if (FAILED(hr)) { PRINTERR(hr, "QAI for ID3D11VideoContext"); } _inColorSpace = inColorSpace; _outColorSpace = outColorSpace; return hr; } /// Release all Resources void D3dConverter::Close() { for (auto& it : viewMap) { ID3D11VideoProcessorOutputView* pVPOV = it.second; pVPOV->Release(); } SAFE_RELEASE(m_pVP); SAFE_RELEASE(m_pVPEnum); SAFE_RELEASE(m_pVidCtx); SAFE_RELEASE(m_pVid); SAFE_RELEASE(m_pCtx); SAFE_RELEASE(m_pDev); } /// Perform Colorspace conversion HRESULT D3dConverter::Convert(ID3D11Texture2D* pIn, ID3D11Texture2D* pOut) { HRESULT hr = S_OK; D3D11_TEXTURE2D_DESC inDesc = {0}; D3D11_TEXTURE2D_DESC outDesc = {0}; pIn->GetDesc(&inDesc); pOut->GetDesc(&outDesc); /// Check if VideoProcessor needs to be reconfigured /// Reconfiguration is required if input/output dimensions have changed if (m_pVP) { if (m_inDesc.Width != inDesc.Width || m_inDesc.Height != inDesc.Height || m_outDesc.Width != outDesc.Width || m_outDesc.Height != outDesc.Height) { SAFE_RELEASE(m_pVPEnum); SAFE_RELEASE(m_pVP); } } if (!m_pVP) { /// Initialize Video Processor m_inDesc = inDesc; m_outDesc = outDesc; D3D11_VIDEO_PROCESSOR_CONTENT_DESC contentDesc = { D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE, {0, 0}, inDesc.Width, inDesc.Height, {0, 0}, outDesc.Width, outDesc.Height, D3D11_VIDEO_USAGE_PLAYBACK_NORMAL}; hr = m_pVid->CreateVideoProcessorEnumerator(&contentDesc, &m_pVPEnum); if (FAILED(hr)) { PRINTERR(hr, "CreateVideoProcessorEnumerator"); } hr = m_pVid->CreateVideoProcessor(m_pVPEnum, 0, &m_pVP); if (FAILED(hr)) { PRINTERR(hr, "CreateVideoProcessor"); } m_pVidCtx->VideoProcessorSetStreamColorSpace(m_pVP, 0, &_inColorSpace); m_pVidCtx->VideoProcessorSetOutputColorSpace(m_pVP, &_outColorSpace); } /// Obtain Video Processor Input view from input texture ID3D11VideoProcessorInputView* pVPIn = nullptr; D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputVD = {0, D3D11_VPIV_DIMENSION_TEXTURE2D, {0, 0}}; hr = m_pVid->CreateVideoProcessorInputView(pIn, m_pVPEnum, &inputVD, &pVPIn); if (FAILED(hr)) { PRINTERR(hr, "CreateVideoProcessInputView"); return hr; } /// Obtain Video Processor Output view from output texture ID3D11VideoProcessorOutputView* pVPOV = nullptr; D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC ovD = {D3D11_VPOV_DIMENSION_TEXTURE2D}; hr = m_pVid->CreateVideoProcessorOutputView(pOut, m_pVPEnum, &ovD, &pVPOV); if (FAILED(hr)) { SAFE_RELEASE(pVPIn); PRINTERR(hr, "CreateVideoProcessorOutputView"); return hr; } /// Create a Video Processor Stream to run the operation D3D11_VIDEO_PROCESSOR_STREAM stream = {TRUE, 0, 0, 0, 0, nullptr, pVPIn, nullptr}; /// Perform the Colorspace conversion hr = m_pVidCtx->VideoProcessorBlt(m_pVP, pVPOV, 0, 1, &stream); if (FAILED(hr)) { SAFE_RELEASE(pVPIn); PRINTERR(hr, "VideoProcessorBlt"); return hr; } SAFE_RELEASE(pVPIn); SAFE_RELEASE(pVPOV); return hr; }