obs-qsv11: Use d3d9 allocator on Win7
Use a d3d9 device and allocator to encode in QSV. This fixes a random crash that could only happen on Windows 7. The QSV Deviced returned a DEVICE_FAILURE after a random amount of time with the old method. This fix is totally based on Shinck's QSVHelper.exe patch for OBS Classic (see https://obsproject.com/forum/threads/0-633b-qsvhelper-exe-was-killed-encode-failed.19230/page-3#post-161984 for more information) This is more like a proof of concept, but that fix is currently stable and tested more than 50 hours, with a single session of +14 hours. That commit doesn't respect all OBS Guidelines. It is currently recommended to wait for a more "cleaner" implementation.master
parent
2278782c19
commit
b276b1633e
|
@ -48,9 +48,11 @@ set(obs-qsv11_libmfx_HEADERS
|
|||
)
|
||||
|
||||
set(obs-qsv11_SOURCES
|
||||
common_directx9.cpp
|
||||
common_directx11.cpp
|
||||
common_utils.cpp
|
||||
common_utils_windows.cpp
|
||||
device_directx9.cpp
|
||||
QSV_Encoder.cpp
|
||||
QSV_Encoder_Internal.cpp
|
||||
obs-qsv11.c
|
||||
|
@ -59,7 +61,9 @@ set(obs-qsv11_SOURCES
|
|||
set(obs-qsv11_HEADERS
|
||||
bits/linux_defs.h
|
||||
bits/windows_defs.h
|
||||
common_directx9.h
|
||||
common_directx11.h
|
||||
device_directx9.h
|
||||
common_utils.h
|
||||
QSV_Encoder.h
|
||||
QSV_Encoder_Internal.h)
|
||||
|
@ -72,7 +76,9 @@ add_library(obs-qsv11 MODULE
|
|||
)
|
||||
target_link_libraries(obs-qsv11
|
||||
libobs
|
||||
d3d9
|
||||
d3d11
|
||||
dxva2
|
||||
dxgi
|
||||
)
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ QSV_Encoder_Internal::QSV_Encoder_Internal(mfxIMPL& impl, mfxVersion& version) :
|
|||
|
||||
m_bIsWindows8OrGreater = IsWindows8OrGreater();
|
||||
m_bUseD3D11 = false;
|
||||
m_bD3D9HACK = true;
|
||||
|
||||
if (m_bIsWindows8OrGreater) {
|
||||
tempImpl = impl | MFX_IMPL_VIA_D3D11;
|
||||
|
@ -107,6 +108,21 @@ QSV_Encoder_Internal::QSV_Encoder_Internal(mfxIMPL& impl, mfxVersion& version) :
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (m_bD3D9HACK) {
|
||||
tempImpl = impl | MFX_IMPL_VIA_D3D9;
|
||||
sts = m_session.Init(tempImpl, &version);
|
||||
if (sts == MFX_ERR_NONE) {
|
||||
m_session.QueryVersion(&version);
|
||||
m_session.Close();
|
||||
|
||||
blog(LOG_INFO, "\timpl: D3D09\n"
|
||||
"\tsurf: Hack");
|
||||
|
||||
m_impl = tempImpl;
|
||||
m_ver = version;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Either windows 7 or D3D11 failed at this point.
|
||||
tempImpl = impl | MFX_IMPL_VIA_D3D9;
|
||||
|
@ -136,11 +152,14 @@ mfxStatus QSV_Encoder_Internal::Open(qsv_param_t * pParams)
|
|||
|
||||
if (m_bUseD3D11)
|
||||
// Use D3D11 surface
|
||||
sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator);
|
||||
sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, false, false);
|
||||
else if (m_bD3D9HACK)
|
||||
// Use hack
|
||||
sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator, false, true);
|
||||
else
|
||||
// Use system memory
|
||||
sts = Initialize(m_impl, m_ver, &m_session, NULL);
|
||||
|
||||
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
m_pmfxENC = new MFXVideoENCODE(m_session);
|
||||
|
@ -260,7 +279,7 @@ bool QSV_Encoder_Internal::InitParams(qsv_param_t * pParams)
|
|||
m_mfxEncParams.mfx.FrameInfo.Width = MSDK_ALIGN16(pParams->nWidth);
|
||||
m_mfxEncParams.mfx.FrameInfo.Height = MSDK_ALIGN16(pParams->nHeight);
|
||||
|
||||
if (m_bUseD3D11)
|
||||
if (m_bUseD3D11 || m_bD3D9HACK)
|
||||
m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
|
||||
else
|
||||
m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
|
||||
|
@ -282,7 +301,7 @@ mfxStatus QSV_Encoder_Internal::AllocateSurfaces()
|
|||
EncRequest.NumFrameSuggested += m_mfxEncParams.AsyncDepth;
|
||||
|
||||
// Allocate required surfaces
|
||||
if (m_bUseD3D11) {
|
||||
if (m_bUseD3D11 || m_bD3D9HACK) {
|
||||
sts = m_mfxAllocator.Alloc(m_mfxAllocator.pthis, &EncRequest,
|
||||
&m_mfxResponse);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
@ -498,14 +517,14 @@ mfxStatus QSV_Encoder_Internal::Encode(uint64_t ts, uint8_t *pDataY,
|
|||
}
|
||||
|
||||
mfxFrameSurface1 *pSurface = m_pmfxSurfaces[nSurfIdx];
|
||||
if (m_bUseD3D11)
|
||||
if (m_bUseD3D11 || m_bD3D9HACK)
|
||||
sts = m_mfxAllocator.Lock(m_mfxAllocator.pthis,
|
||||
pSurface->Data.MemId, &(pSurface->Data));
|
||||
|
||||
sts = LoadNV12(pSurface, pDataY, pDataUV, strideY, strideUV);
|
||||
pSurface->Data.TimeStamp = ts;
|
||||
|
||||
if (m_bUseD3D11)
|
||||
if (m_bUseD3D11 || m_bD3D9HACK)
|
||||
sts = m_mfxAllocator.Unlock(m_mfxAllocator.pthis,
|
||||
pSurface->Data.MemId, &(pSurface->Data));
|
||||
|
||||
|
@ -538,7 +557,7 @@ mfxStatus QSV_Encoder_Internal::Drain()
|
|||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
while (m_pTaskPool[m_nFirstSyncTask].syncp) {
|
||||
while (m_pTaskPool && m_pTaskPool[m_nFirstSyncTask].syncp) {
|
||||
sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, 60000);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
|
@ -556,11 +575,11 @@ mfxStatus QSV_Encoder_Internal::ClearData()
|
|||
|
||||
sts = m_pmfxENC->Close();
|
||||
|
||||
if (m_bUseD3D11)
|
||||
if (m_bUseD3D11 || m_bD3D9HACK)
|
||||
m_mfxAllocator.Free(m_mfxAllocator.pthis, &m_mfxResponse);
|
||||
|
||||
for (int i = 0; i < m_nSurfNum; i++) {
|
||||
if (!m_bUseD3D11)
|
||||
if (!m_bUseD3D11 && !m_bD3D9HACK)
|
||||
delete m_pmfxSurfaces[i]->Data.Y;
|
||||
|
||||
delete m_pmfxSurfaces[i];
|
||||
|
@ -578,7 +597,7 @@ mfxStatus QSV_Encoder_Internal::ClearData()
|
|||
m_pmfxENC = NULL;
|
||||
}
|
||||
|
||||
if (m_bUseD3D11)
|
||||
if (m_bUseD3D11 || m_bD3D9HACK)
|
||||
Release();
|
||||
|
||||
m_session.Close();
|
||||
|
|
|
@ -108,5 +108,6 @@ private:
|
|||
mfxBitstream m_outBitstream;
|
||||
bool m_bIsWindows8OrGreater;
|
||||
bool m_bUseD3D11;
|
||||
bool m_bD3D9HACK;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,457 @@
|
|||
#include "common_directx9.h"
|
||||
#include "device_directx9.h"
|
||||
|
||||
#include <objbase.h>
|
||||
#include <initguid.h>
|
||||
#include <d3d9.h>
|
||||
#include <map>
|
||||
#include <atlbase.h>
|
||||
|
||||
|
||||
#define D3DFMT_NV12 (D3DFORMAT)MAKEFOURCC('N','V','1','2')
|
||||
#define D3DFMT_YV12 (D3DFORMAT)MAKEFOURCC('Y','V','1','2')
|
||||
#define D3DFMT_P010 (D3DFORMAT)MAKEFOURCC('P','0','1','0')
|
||||
#define MSDK_SAFE_FREE(X) {if (X) { free(X); X = NULL; }}
|
||||
|
||||
std::map<mfxMemId*, mfxHDL> dx9_allocResponses;
|
||||
std::map<mfxHDL, mfxFrameAllocResponse> dx9_allocDecodeResponses;
|
||||
std::map<mfxHDL, int> dx9_allocDecodeRefCount;
|
||||
|
||||
CComPtr<IDirect3DDeviceManager9> m_manager;
|
||||
CComPtr<IDirectXVideoDecoderService> m_decoderService;
|
||||
CComPtr<IDirectXVideoProcessorService> m_processorService;
|
||||
HANDLE m_hDecoder;
|
||||
HANDLE m_hProcessor;
|
||||
DWORD m_surfaceUsage;
|
||||
|
||||
CD3D9Device* g_hwdevice;
|
||||
|
||||
const struct {
|
||||
mfxIMPL impl; // actual implementation
|
||||
mfxU32 adapterID; // device adapter number
|
||||
} implTypes[] = {
|
||||
{ MFX_IMPL_HARDWARE, 0 },
|
||||
{ MFX_IMPL_HARDWARE2, 1 },
|
||||
{ MFX_IMPL_HARDWARE3, 2 },
|
||||
{ MFX_IMPL_HARDWARE4, 3 }
|
||||
};
|
||||
|
||||
struct mfxAllocatorParams
|
||||
{
|
||||
virtual ~mfxAllocatorParams(){};
|
||||
};
|
||||
|
||||
struct D3DAllocatorParams : mfxAllocatorParams
|
||||
{
|
||||
IDirect3DDeviceManager9 *pManager;
|
||||
DWORD surfaceUsage;
|
||||
|
||||
D3DAllocatorParams()
|
||||
: pManager()
|
||||
, surfaceUsage()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
mfxStatus DX9_Alloc_Init(D3DAllocatorParams *pParams)
|
||||
{
|
||||
D3DAllocatorParams *pd3dParams = 0;
|
||||
pd3dParams = dynamic_cast<D3DAllocatorParams *>(pParams);
|
||||
if (!pd3dParams)
|
||||
return MFX_ERR_NOT_INITIALIZED;
|
||||
|
||||
m_manager = pd3dParams->pManager;
|
||||
m_surfaceUsage = pd3dParams->surfaceUsage;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus DX9_CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND, bool)
|
||||
{
|
||||
mfxStatus result;
|
||||
|
||||
g_hwdevice = new CD3D9Device;
|
||||
mfxU32 adapterNum = 0;
|
||||
mfxIMPL impl;
|
||||
|
||||
MFXQueryIMPL(session, &impl);
|
||||
|
||||
mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type
|
||||
|
||||
// get corresponding adapter number
|
||||
for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) {
|
||||
if (implTypes[i].impl == baseImpl) {
|
||||
adapterNum = implTypes[i].adapterID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
POINT point = { 0, 0 };
|
||||
HWND window = WindowFromPoint(point);
|
||||
|
||||
result = g_hwdevice->Init(window, 0, adapterNum);
|
||||
if (result != MFX_ERR_NONE) {
|
||||
return result;
|
||||
}
|
||||
|
||||
g_hwdevice->GetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle);
|
||||
|
||||
|
||||
D3DAllocatorParams dx9_allocParam;
|
||||
dx9_allocParam.pManager = reinterpret_cast<IDirect3DDeviceManager9 *>(*deviceHandle);
|
||||
DX9_Alloc_Init(&dx9_allocParam);
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
void DX9_CleanupHWDevice()
|
||||
{
|
||||
if (g_hwdevice) {
|
||||
// g_hwdevice->Close();
|
||||
delete g_hwdevice;
|
||||
g_hwdevice = NULL;
|
||||
}
|
||||
if (m_manager && m_hDecoder) {
|
||||
m_manager->CloseDeviceHandle(m_hDecoder);
|
||||
m_manager = NULL;
|
||||
m_hDecoder = NULL;
|
||||
}
|
||||
|
||||
if (m_manager && m_hProcessor) {
|
||||
m_manager->CloseDeviceHandle(m_hProcessor);
|
||||
m_manager = NULL;
|
||||
m_hProcessor = NULL;
|
||||
}
|
||||
|
||||
if (m_decoderService) {
|
||||
// delete m_decoderService;
|
||||
m_decoderService = NULL;
|
||||
}
|
||||
|
||||
if (m_processorService) {
|
||||
// delete m_processorService;
|
||||
m_processorService = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3DFORMAT ConvertMfxFourccToD3dFormat(mfxU32 fourcc)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case MFX_FOURCC_NV12:
|
||||
return D3DFMT_NV12;
|
||||
case MFX_FOURCC_YV12:
|
||||
return D3DFMT_YV12;
|
||||
case MFX_FOURCC_YUY2:
|
||||
return D3DFMT_YUY2;
|
||||
case MFX_FOURCC_RGB3:
|
||||
return D3DFMT_R8G8B8;
|
||||
case MFX_FOURCC_RGB4:
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case MFX_FOURCC_P8:
|
||||
return D3DFMT_P8;
|
||||
case MFX_FOURCC_P010:
|
||||
return D3DFMT_P010;
|
||||
case MFX_FOURCC_A2RGB10:
|
||||
return D3DFMT_A2R10G10B10;
|
||||
default:
|
||||
return D3DFMT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
mfxStatus dx9_simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
pthis; // To suppress warning for this unused parameter
|
||||
|
||||
if (!ptr || !mid)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
mfxHDLPair *dxmid = (mfxHDLPair*)mid;
|
||||
IDirect3DSurface9 *pSurface = static_cast<IDirect3DSurface9*>(dxmid->first);
|
||||
if (pSurface == 0)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
HRESULT hr = pSurface->GetDesc(&desc);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_LOCK_MEMORY;
|
||||
|
||||
if (desc.Format != D3DFMT_NV12 &&
|
||||
desc.Format != D3DFMT_YV12 &&
|
||||
desc.Format != D3DFMT_YUY2 &&
|
||||
desc.Format != D3DFMT_R8G8B8 &&
|
||||
desc.Format != D3DFMT_A8R8G8B8 &&
|
||||
desc.Format != D3DFMT_P8 &&
|
||||
desc.Format != D3DFMT_P010 &&
|
||||
desc.Format != D3DFMT_A2R10G10B10)
|
||||
return MFX_ERR_LOCK_MEMORY;
|
||||
|
||||
D3DLOCKED_RECT locked;
|
||||
|
||||
hr = pSurface->LockRect(&locked, 0, D3DLOCK_NOSYSLOCK);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_LOCK_MEMORY;
|
||||
|
||||
switch ((DWORD)desc.Format)
|
||||
{
|
||||
case D3DFMT_NV12:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8 *)locked.pBits;
|
||||
ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
|
||||
ptr->V = ptr->U + 1;
|
||||
break;
|
||||
case D3DFMT_YV12:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8 *)locked.pBits;
|
||||
ptr->V = ptr->Y + desc.Height * locked.Pitch;
|
||||
ptr->U = ptr->V + (desc.Height * locked.Pitch) / 4;
|
||||
break;
|
||||
case D3DFMT_YUY2:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8 *)locked.pBits;
|
||||
ptr->U = ptr->Y + 1;
|
||||
ptr->V = ptr->Y + 3;
|
||||
break;
|
||||
case D3DFMT_R8G8B8:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->B = (mfxU8 *)locked.pBits;
|
||||
ptr->G = ptr->B + 1;
|
||||
ptr->R = ptr->B + 2;
|
||||
break;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_A2R10G10B10:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->B = (mfxU8 *)locked.pBits;
|
||||
ptr->G = ptr->B + 1;
|
||||
ptr->R = ptr->B + 2;
|
||||
ptr->A = ptr->B + 3;
|
||||
break;
|
||||
case D3DFMT_P8:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8 *)locked.pBits;
|
||||
ptr->U = 0;
|
||||
ptr->V = 0;
|
||||
break;
|
||||
case D3DFMT_P010:
|
||||
ptr->PitchHigh = (mfxU16)(locked.Pitch / (1 << 16));
|
||||
ptr->PitchLow = (mfxU16)(locked.Pitch % (1 << 16));
|
||||
ptr->Y = (mfxU8 *)locked.pBits;
|
||||
ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
|
||||
ptr->V = ptr->U + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus dx9_simple_unlock(mfxHDL, mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
if (!mid)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
mfxHDLPair *dxmid = (mfxHDLPair*)mid;
|
||||
IDirect3DSurface9 *pSurface = static_cast<IDirect3DSurface9*>(dxmid->first);
|
||||
if (pSurface == 0)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
pSurface->UnlockRect();
|
||||
|
||||
if (NULL != ptr)
|
||||
{
|
||||
ptr->Pitch = 0;
|
||||
ptr->Y = 0;
|
||||
ptr->U = 0;
|
||||
ptr->V = 0;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus dx9_simple_gethdl(mfxHDL, mfxMemId mid, mfxHDL* handle)
|
||||
{
|
||||
if (!mid || !handle)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
mfxHDLPair *dxMid = (mfxHDLPair*)mid;
|
||||
*handle = dxMid->first;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus _dx9_simple_free(mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (!response)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
if (response->mids) {
|
||||
for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
|
||||
if (response->mids[i]) {
|
||||
mfxHDLPair *dxMids = (mfxHDLPair*)response->mids[i];
|
||||
static_cast<IDirect3DSurface9*>(dxMids->first)->Release();
|
||||
}
|
||||
}
|
||||
MSDK_SAFE_FREE(response->mids[0]);
|
||||
}
|
||||
MSDK_SAFE_FREE(response->mids);
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus dx9_simple_free(mfxHDL pthis, mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (NULL == response)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
if (dx9_allocResponses.find(response->mids) == dx9_allocResponses.end()) {
|
||||
// Decode free response handling
|
||||
if (--dx9_allocDecodeRefCount[pthis] == 0) {
|
||||
_dx9_simple_free(response);
|
||||
dx9_allocDecodeResponses.erase(pthis);
|
||||
dx9_allocDecodeRefCount.erase(pthis);
|
||||
}
|
||||
} else {
|
||||
// Encode and VPP free response handling
|
||||
dx9_allocResponses.erase(response->mids);
|
||||
_dx9_simple_free(response);
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus _dx9_simple_alloc(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
MSDK_CHECK_POINTER(request, MFX_ERR_NULL_PTR);
|
||||
if (request->NumFrameSuggested == 0)
|
||||
return MFX_ERR_UNKNOWN;
|
||||
|
||||
D3DFORMAT format = ConvertMfxFourccToD3dFormat(request->Info.FourCC);
|
||||
|
||||
if (format == D3DFMT_UNKNOWN)
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
DWORD target;
|
||||
|
||||
if (MFX_MEMTYPE_DXVA2_DECODER_TARGET & request->Type)
|
||||
{
|
||||
target = DXVA2_VideoDecoderRenderTarget;
|
||||
}
|
||||
else if (MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET & request->Type)
|
||||
{
|
||||
target = DXVA2_VideoProcessorRenderTarget;
|
||||
}
|
||||
else
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
IDirectXVideoAccelerationService* videoService = NULL;
|
||||
|
||||
if (target == DXVA2_VideoProcessorRenderTarget) {
|
||||
if (!m_hProcessor) {
|
||||
hr = m_manager->OpenDeviceHandle(&m_hProcessor);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
hr = m_manager->GetVideoService(m_hProcessor, IID_IDirectXVideoProcessorService, (void**)&m_processorService);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
videoService = m_processorService;
|
||||
}
|
||||
else {
|
||||
if (!m_hDecoder)
|
||||
{
|
||||
hr = m_manager->OpenDeviceHandle(&m_hDecoder);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
hr = m_manager->GetVideoService(m_hDecoder, IID_IDirectXVideoDecoderService, (void**)&m_decoderService);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
videoService = m_decoderService;
|
||||
}
|
||||
|
||||
mfxHDLPair *dxMids = NULL, **dxMidPtrs = NULL;
|
||||
dxMids = (mfxHDLPair*)calloc(request->NumFrameSuggested, sizeof(mfxHDLPair));
|
||||
dxMidPtrs = (mfxHDLPair**)calloc(request->NumFrameSuggested, sizeof(mfxHDLPair*));
|
||||
|
||||
if (!dxMids || !dxMidPtrs) {
|
||||
MSDK_SAFE_FREE(dxMids);
|
||||
MSDK_SAFE_FREE(dxMidPtrs);
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
|
||||
response->mids = (mfxMemId*)dxMidPtrs;
|
||||
response->NumFrameActual = request->NumFrameSuggested;
|
||||
|
||||
if (request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
|
||||
for (int i = 0; i < request->NumFrameSuggested; i++) {
|
||||
hr = videoService->CreateSurface(request->Info.Width, request->Info.Height, 0, format,
|
||||
D3DPOOL_DEFAULT, m_surfaceUsage, target, (IDirect3DSurface9**)&dxMids[i].first, &dxMids[i].second);
|
||||
if (FAILED(hr)) {
|
||||
_dx9_simple_free(response);
|
||||
MSDK_SAFE_FREE(dxMids);
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
dxMidPtrs[i] = &dxMids[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
safe_array<IDirect3DSurface9*> dxSrf(new IDirect3DSurface9*[request->NumFrameSuggested]);
|
||||
if (!dxSrf.get())
|
||||
{
|
||||
MSDK_SAFE_FREE(dxMids);
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
hr = videoService->CreateSurface(request->Info.Width, request->Info.Height, request->NumFrameSuggested - 1, format,
|
||||
D3DPOOL_DEFAULT, m_surfaceUsage, target, dxSrf.get(), NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MSDK_SAFE_FREE(dxMids);
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < request->NumFrameSuggested; i++) {
|
||||
dxMids[i].first = dxSrf.get()[i];
|
||||
dxMidPtrs[i] = &dxMids[i];
|
||||
}
|
||||
}
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus dx9_simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
|
||||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
if (request->Type & MFX_MEMTYPE_SYSTEM_MEMORY)
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
if (dx9_allocDecodeResponses.find(pthis) != dx9_allocDecodeResponses.end() &&
|
||||
MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
|
||||
MFX_MEMTYPE_FROM_DECODE & request->Type) {
|
||||
// Memory for this request was already allocated during manual allocation stage. Return saved response
|
||||
// When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
|
||||
// Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
|
||||
// (No such restriction applies to Encode or VPP)
|
||||
*response = dx9_allocDecodeResponses[pthis];
|
||||
dx9_allocDecodeRefCount[pthis]++;
|
||||
} else {
|
||||
sts = _dx9_simple_alloc(request, response);
|
||||
|
||||
if (MFX_ERR_NONE == sts) {
|
||||
if ( MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
|
||||
MFX_MEMTYPE_FROM_DECODE & request->Type) {
|
||||
// Decode alloc response handling
|
||||
dx9_allocDecodeResponses[pthis] = *response;
|
||||
dx9_allocDecodeRefCount[pthis]++;
|
||||
} else {
|
||||
// Encode and VPP alloc response handling
|
||||
dx9_allocResponses[response->mids] = pthis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*********************************************************************************
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2011-2014 Intel Corporation. All Rights Reserved.
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common_utils.h"
|
||||
#include <initguid.h>
|
||||
#include <d3d9.h>
|
||||
#include <dxva2api.h>
|
||||
#include <dxva.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define VIDEO_MAIN_FORMAT D3DFMT_YUY2
|
||||
|
||||
class IGFXS3DControl;
|
||||
|
||||
/** Direct3D 9 device implementation.
|
||||
@note Can be initilized for only 1 or two 2 views. Handle to
|
||||
MFX_HANDLE_GFXS3DCONTROL must be set prior if initializing for 2 views.
|
||||
|
||||
@note Device always set D3DPRESENT_PARAMETERS::Windowed to TRUE.
|
||||
*/
|
||||
template <class T>
|
||||
class safe_array
|
||||
{
|
||||
public:
|
||||
safe_array(T *ptr = 0):m_ptr(ptr)
|
||||
{ // construct from object pointer
|
||||
};
|
||||
~safe_array()
|
||||
{
|
||||
reset(0);
|
||||
}
|
||||
T* get()
|
||||
{ // return wrapped pointer
|
||||
return m_ptr;
|
||||
}
|
||||
T* release()
|
||||
{ // return wrapped pointer and give up ownership
|
||||
T* ptr = m_ptr;
|
||||
m_ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
void reset(T* ptr)
|
||||
{ // destroy designated object and store new pointer
|
||||
if (m_ptr)
|
||||
{
|
||||
delete[] m_ptr;
|
||||
}
|
||||
m_ptr = ptr;
|
||||
}
|
||||
protected:
|
||||
T* m_ptr; // the wrapped object pointer
|
||||
};
|
||||
|
||||
mfxStatus dx9_simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response);
|
||||
mfxStatus dx9_simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr);
|
||||
mfxStatus dx9_simple_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr);
|
||||
mfxStatus dx9_simple_gethdl(mfxHDL pthis, mfxMemId mid, mfxHDL* handle);
|
||||
mfxStatus dx9_simple_free(mfxHDL pthis, mfxFrameAllocResponse* response);
|
||||
|
||||
mfxStatus DX9_CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND hWnd, bool bCreateSharedHandles);
|
||||
void DX9_CleanupHWDevice();
|
|
@ -95,7 +95,7 @@ typedef struct {
|
|||
int GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize);
|
||||
|
||||
// Initialize Intel Media SDK Session, device/display and memory manager
|
||||
mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles = false);
|
||||
mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles = false, bool dx9hack = false);
|
||||
|
||||
// Release resources (device/display)
|
||||
void Release();
|
||||
|
|
|
@ -16,13 +16,14 @@ Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved.
|
|||
#include "common_directx.h"
|
||||
#elif DX11_D3D
|
||||
#include "common_directx11.h"
|
||||
#include "common_directx9.h"
|
||||
#endif
|
||||
|
||||
/* =======================================================
|
||||
* Windows implementation of OS-specific utility functions
|
||||
*/
|
||||
|
||||
mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles)
|
||||
mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles, bool dx9hack)
|
||||
{
|
||||
bCreateSharedHandles; // (Hugh) Currently unused
|
||||
pmfxAllocator; // (Hugh) Currently unused
|
||||
|
@ -30,10 +31,10 @@ mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mf
|
|||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
// If mfxFrameAllocator is provided it means we need to setup DirectX device and memory allocator
|
||||
if (pmfxAllocator) {
|
||||
// Initialize Intel Media SDK Session
|
||||
sts = pSession->Init(impl, &ver);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
if (pmfxAllocator && !dx9hack) {
|
||||
// Initialize Intel Media SDK Session
|
||||
sts = pSession->Init(impl, &ver);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
// Create DirectX device context
|
||||
mfxHDL deviceHandle;
|
||||
|
@ -54,13 +55,37 @@ mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mf
|
|||
// Since we are using video memory we must provide Media SDK with an external allocator
|
||||
sts = pSession->SetFrameAllocator(pmfxAllocator);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
} else if (pmfxAllocator && dx9hack) {
|
||||
// Initialize Intel Media SDK Session
|
||||
sts = pSession->Init(impl, &ver);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
// Create DirectX device context
|
||||
mfxHDL deviceHandle;
|
||||
sts = DX9_CreateHWDevice(*pSession, &deviceHandle, NULL, bCreateSharedHandles);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
// Provide device manager to Media SDK
|
||||
sts = pSession->SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
pmfxAllocator->pthis = *pSession; // We use Media SDK session ID as the allocation identifier
|
||||
pmfxAllocator->Alloc = dx9_simple_alloc;
|
||||
pmfxAllocator->Free = dx9_simple_free;
|
||||
pmfxAllocator->Lock = dx9_simple_lock;
|
||||
pmfxAllocator->Unlock = dx9_simple_unlock;
|
||||
pmfxAllocator->GetHDL = dx9_simple_gethdl;
|
||||
|
||||
// Since we are using video memory we must provide Media SDK with an external allocator
|
||||
sts = pSession->SetFrameAllocator(pmfxAllocator);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
} else {
|
||||
// Initialize Intel Media SDK Session
|
||||
sts = pSession->Init(impl, &ver);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize Intel Media SDK Session
|
||||
sts = pSession->Init(impl, &ver);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
@ -68,6 +93,7 @@ void Release()
|
|||
{
|
||||
#if defined(DX9_D3D) || defined(DX11_D3D)
|
||||
CleanupHWDevice();
|
||||
DX9_CleanupHWDevice();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
/*********************************************************************************
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2011-2015 Intel Corporation. All Rights Reserved.
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
// #include "mfx_samples_config.h"
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
|
||||
//prefast singnature used in combaseapi.h
|
||||
#ifndef _PREFAST_
|
||||
#pragma warning(disable:4068)
|
||||
#endif
|
||||
|
||||
#include "device_directx9.h"
|
||||
// #include "igfx_s3dcontrol.h"
|
||||
|
||||
#include "atlbase.h"
|
||||
|
||||
// Macros
|
||||
#define MSDK_ZERO_MEMORY(VAR) {memset(&VAR, 0, sizeof(VAR));}
|
||||
#define MSDK_MEMCPY_VAR(dstVarName, src, count) memcpy_s(&(dstVarName), sizeof(dstVarName), (src), (count))
|
||||
|
||||
CD3D9Device::CD3D9Device()
|
||||
{
|
||||
m_pD3D9 = NULL;
|
||||
m_pD3DD9 = NULL;
|
||||
m_pDeviceManager9 = NULL;
|
||||
MSDK_ZERO_MEMORY(m_D3DPP);
|
||||
m_resetToken = 0;
|
||||
|
||||
m_nViews = 0;
|
||||
m_pS3DControl = NULL;
|
||||
|
||||
MSDK_ZERO_MEMORY(m_backBufferDesc);
|
||||
m_pDXVAVPS = NULL;
|
||||
m_pDXVAVP_Left = NULL;
|
||||
m_pDXVAVP_Right = NULL;
|
||||
|
||||
MSDK_ZERO_MEMORY(m_targetRect);
|
||||
|
||||
MSDK_ZERO_MEMORY(m_VideoDesc);
|
||||
MSDK_ZERO_MEMORY(m_BltParams);
|
||||
MSDK_ZERO_MEMORY(m_Sample);
|
||||
|
||||
// Initialize DXVA structures
|
||||
|
||||
DXVA2_AYUVSample16 color = {
|
||||
0x8000, // Cr
|
||||
0x8000, // Cb
|
||||
0x1000, // Y
|
||||
0xffff // Alpha
|
||||
};
|
||||
|
||||
DXVA2_ExtendedFormat format = { // DestFormat
|
||||
DXVA2_SampleProgressiveFrame, // SampleFormat
|
||||
DXVA2_VideoChromaSubsampling_MPEG2, // VideoChromaSubsampling
|
||||
DXVA_NominalRange_0_255, // NominalRange
|
||||
DXVA2_VideoTransferMatrix_BT709, // VideoTransferMatrix
|
||||
DXVA2_VideoLighting_bright, // VideoLighting
|
||||
DXVA2_VideoPrimaries_BT709, // VideoPrimaries
|
||||
DXVA2_VideoTransFunc_709 // VideoTransferFunction
|
||||
};
|
||||
|
||||
// init m_VideoDesc structure
|
||||
MSDK_MEMCPY_VAR(m_VideoDesc.SampleFormat, &format, sizeof(DXVA2_ExtendedFormat));
|
||||
m_VideoDesc.SampleWidth = 0;
|
||||
m_VideoDesc.SampleHeight = 0;
|
||||
m_VideoDesc.InputSampleFreq.Numerator = 60;
|
||||
m_VideoDesc.InputSampleFreq.Denominator = 1;
|
||||
m_VideoDesc.OutputFrameFreq.Numerator = 60;
|
||||
m_VideoDesc.OutputFrameFreq.Denominator = 1;
|
||||
|
||||
// init m_BltParams structure
|
||||
MSDK_MEMCPY_VAR(m_BltParams.DestFormat, &format, sizeof(DXVA2_ExtendedFormat));
|
||||
MSDK_MEMCPY_VAR(m_BltParams.BackgroundColor, &color, sizeof(DXVA2_AYUVSample16));
|
||||
|
||||
// init m_Sample structure
|
||||
m_Sample.Start = 0;
|
||||
m_Sample.End = 1;
|
||||
m_Sample.SampleFormat = format;
|
||||
m_Sample.PlanarAlpha.Fraction = 0;
|
||||
m_Sample.PlanarAlpha.Value = 1;
|
||||
|
||||
m_bIsA2rgb10 = FALSE;
|
||||
}
|
||||
|
||||
bool CD3D9Device::CheckOverlaySupport()
|
||||
{
|
||||
D3DCAPS9 d3d9caps;
|
||||
D3DOVERLAYCAPS d3doverlaycaps = {0};
|
||||
IDirect3D9ExOverlayExtension *d3d9overlay = NULL;
|
||||
bool overlaySupported = false;
|
||||
|
||||
memset(&d3d9caps, 0, sizeof(d3d9caps));
|
||||
HRESULT hr = m_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3d9caps);
|
||||
if (FAILED(hr) || !(d3d9caps.Caps & D3DCAPS_OVERLAY))
|
||||
{
|
||||
overlaySupported = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = m_pD3D9->QueryInterface(IID_PPV_ARGS(&d3d9overlay));
|
||||
if (FAILED(hr) || (d3d9overlay == NULL))
|
||||
{
|
||||
overlaySupported = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = d3d9overlay->CheckDeviceOverlayType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
|
||||
m_D3DPP.BackBufferWidth,
|
||||
m_D3DPP.BackBufferHeight,
|
||||
m_D3DPP.BackBufferFormat, NULL,
|
||||
D3DDISPLAYROTATION_IDENTITY, &d3doverlaycaps);
|
||||
MSDK_SAFE_RELEASE(d3d9overlay);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
overlaySupported = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlaySupported = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return overlaySupported;
|
||||
}
|
||||
|
||||
mfxStatus CD3D9Device::FillD3DPP(mfxHDL hWindow, mfxU16 nViews, D3DPRESENT_PARAMETERS &D3DPP)
|
||||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
D3DPP.Windowed = true;
|
||||
D3DPP.hDeviceWindow = (HWND)hWindow;
|
||||
|
||||
D3DPP.Flags = D3DPRESENTFLAG_VIDEO;
|
||||
D3DPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
||||
D3DPP.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // note that this setting leads to an implicit timeBeginPeriod call
|
||||
D3DPP.BackBufferCount = 1;
|
||||
D3DPP.BackBufferFormat = (m_bIsA2rgb10) ? D3DFMT_A2R10G10B10 : D3DFMT_X8R8G8B8;
|
||||
|
||||
if (hWindow)
|
||||
{
|
||||
RECT r;
|
||||
GetClientRect((HWND)hWindow, &r);
|
||||
int x = GetSystemMetrics(SM_CXSCREEN);
|
||||
int y = GetSystemMetrics(SM_CYSCREEN);
|
||||
D3DPP.BackBufferWidth = min(r.right - r.left, x);
|
||||
D3DPP.BackBufferHeight = min(r.bottom - r.top, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3DPP.BackBufferWidth = GetSystemMetrics(SM_CYSCREEN);
|
||||
D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
//
|
||||
// Mark the back buffer lockable if software DXVA2 could be used.
|
||||
// This is because software DXVA2 device requires a lockable render target
|
||||
// for the optimal performance.
|
||||
//
|
||||
{
|
||||
D3DPP.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
|
||||
}
|
||||
|
||||
bool isOverlaySupported = CheckOverlaySupport();
|
||||
if (2 == nViews && !isOverlaySupported)
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
bool needOverlay = (2 == nViews) ? true : false;
|
||||
|
||||
D3DPP.SwapEffect = needOverlay ? D3DSWAPEFFECT_OVERLAY : D3DSWAPEFFECT_DISCARD;
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CD3D9Device::Init(
|
||||
mfxHDL hWindow,
|
||||
mfxU16 nViews,
|
||||
mfxU32 nAdapterNum)
|
||||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
if (2 < nViews)
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
m_nViews = nViews;
|
||||
|
||||
HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_pD3D9);
|
||||
if (!m_pD3D9 || FAILED(hr))
|
||||
return MFX_ERR_DEVICE_FAILED;
|
||||
|
||||
ZeroMemory(&m_D3DPP, sizeof(m_D3DPP));
|
||||
sts = FillD3DPP(hWindow, nViews, m_D3DPP);
|
||||
MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
|
||||
|
||||
hr = m_pD3D9->CreateDeviceEx(
|
||||
nAdapterNum,
|
||||
D3DDEVTYPE_HAL,
|
||||
(HWND)hWindow,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
|
||||
&m_D3DPP,
|
||||
NULL,
|
||||
&m_pD3DD9);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
if(hWindow)
|
||||
{
|
||||
hr = m_pD3DD9->ResetEx(&m_D3DPP, NULL);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
hr = m_pD3DD9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
}
|
||||
UINT resetToken = 0;
|
||||
|
||||
hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &m_pDeviceManager9);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, resetToken);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
|
||||
m_resetToken = resetToken;
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CD3D9Device::Reset()
|
||||
{
|
||||
HRESULT hr = NO_ERROR;
|
||||
MSDK_CHECK_POINTER(m_pD3DD9, MFX_ERR_NULL_PTR);
|
||||
|
||||
if (m_D3DPP.Windowed)
|
||||
{
|
||||
RECT r;
|
||||
GetClientRect((HWND)m_D3DPP.hDeviceWindow, &r);
|
||||
int x = GetSystemMetrics(SM_CXSCREEN);
|
||||
int y = GetSystemMetrics(SM_CYSCREEN);
|
||||
m_D3DPP.BackBufferWidth = min(r.right - r.left, x);
|
||||
m_D3DPP.BackBufferHeight = min(r.bottom - r.top, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_D3DPP.BackBufferWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
m_D3DPP.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
|
||||
// Reset will change the parameters, so use a copy instead.
|
||||
D3DPRESENT_PARAMETERS d3dpp = m_D3DPP;
|
||||
hr = m_pD3DD9->ResetEx(&d3dpp, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
|
||||
hr = m_pDeviceManager9->ResetDevice(m_pD3DD9, m_resetToken);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
void CD3D9Device::Close()
|
||||
{
|
||||
MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
|
||||
MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
|
||||
MSDK_SAFE_RELEASE(m_pDXVAVPS);
|
||||
|
||||
MSDK_SAFE_RELEASE(m_pDeviceManager9);
|
||||
MSDK_SAFE_RELEASE(m_pD3DD9);
|
||||
MSDK_SAFE_RELEASE(m_pD3D9);
|
||||
m_pS3DControl = NULL;
|
||||
}
|
||||
|
||||
CD3D9Device::~CD3D9Device()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
mfxStatus CD3D9Device::GetHandle(mfxHandleType type, mfxHDL *pHdl)
|
||||
{
|
||||
if (MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 == type && pHdl != NULL)
|
||||
{
|
||||
*pHdl = m_pDeviceManager9;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
else if (MFX_HANDLE_GFXS3DCONTROL == type && pHdl != NULL)
|
||||
{
|
||||
*pHdl = m_pS3DControl;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mfxStatus CD3D9Device::SetHandle(mfxHandleType type, mfxHDL hdl)
|
||||
{
|
||||
if (MFX_HANDLE_GFXS3DCONTROL == type && hdl != NULL)
|
||||
{
|
||||
m_pS3DControl = (IGFXS3DControl*)hdl;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
else if (MFX_HANDLE_DEVICEWINDOW == type && hdl != NULL) //for render window handle
|
||||
{
|
||||
m_D3DPP.hDeviceWindow = (HWND)hdl;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mfxStatus CD3D9Device::RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (!(1 == m_nViews || (2 == m_nViews && NULL != m_pS3DControl)))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
|
||||
MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(m_pDeviceManager9, MFX_ERR_NOT_INITIALIZED);
|
||||
MSDK_CHECK_POINTER(pmfxAlloc, MFX_ERR_NULL_PTR);
|
||||
|
||||
// don't try to render second view if output rect changed since first view
|
||||
if (2 == m_nViews && (0 != pSurface->Info.FrameId.ViewId))
|
||||
return MFX_ERR_NONE;
|
||||
|
||||
hr = m_pD3DD9->TestCooperativeLevel();
|
||||
|
||||
switch (hr)
|
||||
{
|
||||
case D3D_OK :
|
||||
break;
|
||||
|
||||
case D3DERR_DEVICELOST :
|
||||
{
|
||||
return MFX_ERR_DEVICE_LOST;
|
||||
}
|
||||
|
||||
case D3DERR_DEVICENOTRESET :
|
||||
{
|
||||
return MFX_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
default :
|
||||
{
|
||||
return MFX_ERR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
CComPtr<IDirect3DSurface9> pBackBuffer;
|
||||
hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
|
||||
|
||||
mfxHDLPair* dxMemId = (mfxHDLPair*)pSurface->Data.MemId;
|
||||
|
||||
hr = m_pD3DD9->StretchRect((IDirect3DSurface9*)dxMemId->first, NULL, pBackBuffer, NULL, D3DTEXF_LINEAR);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return MFX_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)&& (1 == m_nViews || pSurface->Info.FrameId.ViewId == 1))
|
||||
{
|
||||
hr = m_pD3DD9->Present(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
mfxStatus CD3D9Device::CreateVideoProcessors()
|
||||
{
|
||||
if (!(1 == m_nViews || (2 == m_nViews && NULL != m_pS3DControl)))
|
||||
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
||||
|
||||
MSDK_SAFE_RELEASE(m_pDXVAVP_Left);
|
||||
MSDK_SAFE_RELEASE(m_pDXVAVP_Right);
|
||||
|
||||
HRESULT hr ;
|
||||
|
||||
if (2 == m_nViews && NULL != m_pS3DControl)
|
||||
{
|
||||
hr = m_pS3DControl->SetDevice(m_pDeviceManager9);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ZeroMemory(&m_backBufferDesc, sizeof(m_backBufferDesc));
|
||||
IDirect3DSurface9 *backBufferTmp = NULL;
|
||||
hr = m_pD3DD9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBufferTmp);
|
||||
if (NULL != backBufferTmp)
|
||||
backBufferTmp->GetDesc(&m_backBufferDesc);
|
||||
MSDK_SAFE_RELEASE(backBufferTmp);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Create DXVA2 Video Processor Service.
|
||||
hr = DXVA2CreateVideoService(m_pD3DD9,
|
||||
IID_IDirectXVideoProcessorService,
|
||||
(void**)&m_pDXVAVPS);
|
||||
}
|
||||
|
||||
if (2 == m_nViews)
|
||||
{
|
||||
// Activate L channel
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_pS3DControl->SelectLeftView();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Create VPP device for the L channel
|
||||
hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
|
||||
&m_VideoDesc,
|
||||
m_D3DPP.BackBufferFormat,
|
||||
1,
|
||||
&m_pDXVAVP_Left);
|
||||
}
|
||||
|
||||
// Activate R channel
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_pS3DControl->SelectRightView();
|
||||
}
|
||||
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_pDXVAVPS->CreateVideoProcessor(DXVA2_VideoProcProgressiveDevice,
|
||||
&m_VideoDesc,
|
||||
m_D3DPP.BackBufferFormat,
|
||||
1,
|
||||
&m_pDXVAVP_Right);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr) ? MFX_ERR_NONE : MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // #if defined(WIN32) || defined(WIN64)
|
|
@ -0,0 +1,118 @@
|
|||
/*********************************************************************************
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2011-2014 Intel Corporation. All Rights Reserved.
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined( _WIN32 ) || defined ( _WIN64 )
|
||||
|
||||
#include "common_utils.h"
|
||||
|
||||
#pragma warning(disable : 4201)
|
||||
#include <initguid.h>
|
||||
#include <d3d9.h>
|
||||
#include <dxva2api.h>
|
||||
#include <dxva.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define VIDEO_MAIN_FORMAT D3DFMT_YUY2
|
||||
|
||||
class IGFXS3DControl;
|
||||
|
||||
|
||||
/// Base class for hw device
|
||||
class CHWDevice
|
||||
{
|
||||
public:
|
||||
virtual ~CHWDevice(){}
|
||||
/** Initializes device for requested processing.
|
||||
@param[in] hWindow Window handle to bundle device to.
|
||||
@param[in] nViews Number of views to process.
|
||||
@param[in] nAdapterNum Number of adapter to use
|
||||
*/
|
||||
virtual mfxStatus Init(
|
||||
mfxHDL hWindow,
|
||||
mfxU16 nViews,
|
||||
mfxU32 nAdapterNum) = 0;
|
||||
/// Reset device.
|
||||
virtual mfxStatus Reset() = 0;
|
||||
/// Get handle can be used for MFX session SetHandle calls
|
||||
virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *pHdl) = 0;
|
||||
/** Set handle.
|
||||
Particular device implementation may require other objects to operate.
|
||||
*/
|
||||
virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) = 0;
|
||||
virtual mfxStatus RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc) = 0;
|
||||
virtual void Close() = 0;
|
||||
};
|
||||
|
||||
enum {
|
||||
MFX_HANDLE_GFXS3DCONTROL = 0x100, /* A handle to the IGFXS3DControl instance */
|
||||
MFX_HANDLE_DEVICEWINDOW = 0x101 /* A handle to the render window */
|
||||
}; //mfxHandleType
|
||||
|
||||
/** Direct3D 9 device implementation.
|
||||
@note Can be initilized for only 1 or two 2 views. Handle to
|
||||
MFX_HANDLE_GFXS3DCONTROL must be set prior if initializing for 2 views.
|
||||
|
||||
@note Device always set D3DPRESENT_PARAMETERS::Windowed to TRUE.
|
||||
*/
|
||||
class CD3D9Device : public CHWDevice
|
||||
{
|
||||
public:
|
||||
CD3D9Device();
|
||||
virtual ~CD3D9Device();
|
||||
|
||||
virtual mfxStatus Init(
|
||||
mfxHDL hWindow,
|
||||
mfxU16 nViews,
|
||||
mfxU32 nAdapterNum);
|
||||
virtual mfxStatus Reset();
|
||||
virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *pHdl);
|
||||
virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl);
|
||||
virtual mfxStatus RenderFrame(mfxFrameSurface1 * pSurface, mfxFrameAllocator * pmfxAlloc);
|
||||
virtual void UpdateTitle(double /*fps*/) { }
|
||||
virtual void Close() ;
|
||||
void DefineFormat(bool isA2rgb10) { m_bIsA2rgb10 = (isA2rgb10) ? TRUE : FALSE; }
|
||||
protected:
|
||||
mfxStatus CreateVideoProcessors();
|
||||
bool CheckOverlaySupport();
|
||||
virtual mfxStatus FillD3DPP(mfxHDL hWindow, mfxU16 nViews, D3DPRESENT_PARAMETERS &D3DPP);
|
||||
private:
|
||||
IDirect3D9Ex* m_pD3D9;
|
||||
IDirect3DDevice9Ex* m_pD3DD9;
|
||||
IDirect3DDeviceManager9* m_pDeviceManager9;
|
||||
D3DPRESENT_PARAMETERS m_D3DPP;
|
||||
UINT m_resetToken;
|
||||
|
||||
mfxU16 m_nViews;
|
||||
IGFXS3DControl* m_pS3DControl;
|
||||
|
||||
|
||||
D3DSURFACE_DESC m_backBufferDesc;
|
||||
|
||||
// service required to create video processors
|
||||
IDirectXVideoProcessorService* m_pDXVAVPS;
|
||||
//left channel processor
|
||||
IDirectXVideoProcessor* m_pDXVAVP_Left;
|
||||
// right channel processor
|
||||
IDirectXVideoProcessor* m_pDXVAVP_Right;
|
||||
|
||||
// target rectangle
|
||||
RECT m_targetRect;
|
||||
|
||||
// various structures for DXVA2 calls
|
||||
DXVA2_VideoDesc m_VideoDesc;
|
||||
DXVA2_VideoProcessBltParams m_BltParams;
|
||||
DXVA2_VideoSample m_Sample;
|
||||
|
||||
BOOL m_bIsA2rgb10;
|
||||
};
|
||||
|
||||
#endif // #if defined( _WIN32 ) || defined ( _WIN64 )
|
Loading…
Reference in New Issue