基於FFmpeg的Dxva2硬解碼及Direct3D顯示(三)


初始化Direct3D

Direct3D渲染可以通過Surface和Texture來實現,后者比較復雜,只是顯示視頻的化用Surface足以。Direct3D有幾個重要的概念需要說明以下:

Device:就是渲染設備實例

Resources:可以理解成一個參數結構體,描述怎樣渲染的細節。

Swap Chains:交換鏈,由一個或者多個緩沖區組成,可以理解成包含多個緩沖區的數組,如下圖所示。

創建Direct3D物理設備對象實例

這一步為了得到IDirect3D9* 實例 m_pD3d9;

m_hD3dDll = LoadLibrary("d3d9.dll");
pDirect3DCreate9 *createD3D = (pDirect3DCreate9 *)GetProcAddress(m_hD3dDll, "Direct3DCreate9");

m_pD3d9 = createD3D(D3D_SDK_VERSION);// 怎樣指定GPU?

創建Direct3D渲染設備實例

這一步為了得到IDirect3DDevice9* 實例 m_pD3d9Dev;

// 獲取顯示適配器參數
D3DDISPLAYMODE displayModel;
if (m_pD3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayModel) < 0)
{
    return FALSE;
}

D3DPRESENT_PARAMETERS presentParms = { 0 };
presentParms.Windowed = TRUE;			// 是否窗口顯示	
presentParms.BackBufferCount = 0;		// 后台緩沖表面數量,指定為0時會被視為1
presentParms.hDeviceWindow = m_hWnd;	// 顯示窗口句柄
presentParms.SwapEffect = D3DSWAPEFFECT_DISCARD;	// 交換鏈設置,后台緩沖使用后直接丟棄
presentParms.BackBufferFormat = displayModel.Format;// 后台緩沖表面格式
presentParms.EnableAutoDepthStencil = FALSE;		// 是否自動創建深度模板緩沖,適用於3D場景
presentParms.Flags = D3DPRESENTFLAG_VIDEO;			// 附加特性,顯示視頻
presentParms.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;	// 刷新率,窗口模式時必須為0
presentParms.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;	// 前后台緩沖區的交換頻率

// 查詢設備是否支持硬件加速渲染
DWORD behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED;
D3DDEVTYPE devType = D3DDEVTYPE_HAL;
D3DCAPS9 caps;

if (m_pD3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, devType, &caps) >= 0)
{
    if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
    {
        behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
    }
    else
    {
        behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;
    }
}
else
{
    return FALSE;
}

// 創建渲染設備實例
if (m_pD3d9->CreateDevice(D3DADAPTER_DEFAULT, devType, m_hWnd,
                          behaviorFlags, &presentParms, &m_pD3d9Dev) < 0)
{
    return FALSE;
}

創建Direct3D視頻解碼服務

這一步為了得到IDirectXVideoDecoderService* 實例 m_pDecoderService;

m_hDxva2Dll = LoadLibrary("dxva2.dll");
if (!m_hDxva2Dll)
{
    return FALSE;
}

pCreateDeviceManager9 *createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(m_hDxva2Dll, "DXVA2CreateDirect3DDeviceManager9");

// 設備管理器實例標識
unsigned resetToken = 0;
if (createDeviceManager(&resetToken, &m_pD3d9DevMgr) < 0)
{
    return FALSE;
}

// 重置渲染設備
HRESULT hr = m_pD3d9DevMgr->ResetDevice(m_pD3d9Dev, resetToken);
if (FAILED(hr))
{
    return FALSE;
}

// 打開渲染設備
hr = m_pD3d9DevMgr->OpenDeviceHandle(&m_hDev);
if (FAILED(hr))
{
    return FALSE;
}

// 獲取視頻渲染服務實例
hr = m_pD3d9DevMgr->GetVideoService(m_hDev, IID_IDirectXVideoDecoderService, (void **)&m_pDecoderService);
if (FAILED(hr))
{
    return FALSE;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM