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.
This commit is contained in:
Alexandre Biny
2016-06-14 13:44:34 +02:00
committed by jp9000
parent 2278782c19
commit b276b1633e
9 changed files with 1170 additions and 22 deletions

View File

@@ -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();