Added headless Direct3D11 mode for QSV on Ivy Bridge or better

This commit is contained in:
palana 2013-06-26 01:43:43 +02:00
parent ae170aefbe
commit fcc8b34c57
6 changed files with 77 additions and 69 deletions

View File

@ -42,8 +42,16 @@ namespace
#define TO_STR(a) TEXT(#a)
const float baseCRF = 22.0f;
const mfxVersion version = {4, 1}; //Highest supported version on Sandy Bridge
const mfxIMPL validImpl[] = {MFX_IMPL_HARDWARE_ANY, MFX_IMPL_HARDWARE};
const struct {
mfxU32 type,
intf;
mfxVersion version;
} validImpl[] = {
{ MFX_IMPL_HARDWARE_ANY, MFX_IMPL_VIA_D3D11, {6, 1} },
{ MFX_IMPL_HARDWARE, MFX_IMPL_VIA_D3D11, {6, 1} },
{ MFX_IMPL_HARDWARE_ANY, MFX_IMPL_VIA_ANY, {4, 1} }, //Sandy Bridge
{ MFX_IMPL_HARDWARE, MFX_IMPL_VIA_ANY, {4, 1} },
};
const TCHAR* implStr[] = {
TO_STR(MFX_IMPL_AUTO),
TO_STR(MFX_IMPL_SOFTWARE),
@ -65,6 +73,19 @@ namespace
TO_STR(MFX_TARGETUSAGE_BEST_SPEED)
};
TCHAR* qsv_intf_str(const mfxU32 impl)
{
switch(impl & (-MFX_IMPL_VIA_ANY))
{
#define VIA_STR(x) case MFX_IMPL_VIA_##x: return TEXT(" | ") TO_STR(MFX_IMPL_VIA_##x)
VIA_STR(ANY);
VIA_STR(D3D9);
VIA_STR(D3D11);
#undef VIA_STR
default: return nullptr;
}
};
void ConvertFrameRate(mfxF64 dFrameRate, mfxU32& pnFrameRateExtN, mfxU32& pnFrameRateExtD)
{
mfxU32 fr;
@ -109,11 +130,10 @@ namespace
bool CheckQSVHardwareSupport(bool log=true)
{
MFXVideoSession test;
for(int i = 0; i < sizeof(validImpl)/sizeof(validImpl[0]); i++)
for(auto impl = std::begin(validImpl); impl != std::end(validImpl); impl++)
{
mfxIMPL impl = validImpl[i];
mfxVersion ver = version;
auto result = test.Init(impl, &ver);
mfxVersion ver = impl->version;
auto result = test.Init(impl->type | impl->intf, &ver);
if(result != MFX_ERR_NONE)
continue;
if(log)
@ -268,25 +288,21 @@ public:
: enc(nullptr), bFirstFrameProcessed(false), bFirstFrameQueued(false)
{
Log(TEXT("------------------------------------------"));
for(int i = 0; i < sizeof(validImpl)/sizeof(validImpl[0]); i++)
for(auto impl = std::begin(validImpl); impl != std::end(validImpl); impl++)
{
mfxIMPL impl = validImpl[i];
ver = version;
mfxStatus result = MFX_ERR_UNKNOWN;
for(ver.Minor = 6; ver.Minor >= 4; ver.Minor -= 2)
{
result = session.Init(impl, &ver);
ver = impl->version;
auto result = session.Init(impl->type | impl->intf, &ver);
if(result == MFX_ERR_NONE)
{
mfxIMPL actual;
session.QueryIMPL(&actual);
Log(TEXT("QSV version %u.%u using %s (actual: %s)"), ver.Major, ver.Minor, implStr[impl], implStr[actual]);
auto intf_str = qsv_intf_str(actual);
Log(TEXT("QSV version %u.%u using %s (actual: %s%s)"), ver.Major, ver.Minor,
implStr[impl->type], implStr[actual & (MFX_IMPL_VIA_ANY - 1)], intf_str ? intf_str : TEXT(""));
break;
}
}
if(result == MFX_ERR_NONE)
break;
}
session.SetPriority(MFX_PRIORITY_HIGH);
@ -302,7 +318,7 @@ public:
params.mfx.TargetKbps = maxBitrate;
params.mfx.MaxKbps = maxBitrate;
params.mfx.BufferSizeInKB = bufferSize/8;
params.mfx.GopOptFlag = MFX_GOP_CLOSED | MFX_GOP_STRICT;
params.mfx.GopOptFlag = MFX_GOP_CLOSED;
params.mfx.GopPicSize = 250;
params.mfx.GopRefDist = 8;
params.mfx.IdrInterval = 0;

View File

@ -58,7 +58,7 @@ public:
// Initialize device using DXGI 1.1 interface
virtual
bool Init(const mfxU32 adapterNum) = 0;
bool Init(const bool countDisplays, const mfxU32 adapterNum) = 0;
// Obtain graphic card's parameter
mfxU32 GetVendorID(void) const;
@ -113,7 +113,7 @@ public:
// Initialize device
virtual
bool Init(const mfxU32 adapterNum);
bool Init(const bool countDisplays, const mfxU32 adapterNum);
// Close the object
virtual
@ -137,7 +137,7 @@ public:
~DXVA2Device(void);
// Initialize device using DXGI 1.1 interface
bool InitDXGI1(const mfxU32 adapterNum);
bool InitDXGI1(const bool countDisplays, const mfxU32 adapterNum);
// Obtain graphic card's parameter
mfxU32 GetVendorID(void) const;

View File

@ -58,7 +58,7 @@ public:
~MFXLibraryIterator(void);
// Initialize the iterator
mfxStatus Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID);
mfxStatus Init(eMfxImplType implType, const bool countDisplays, const mfxU32 adapterNum, int storageID);
// Get the next library path
mfxStatus SelectDLLVersion(wchar_t *pPath, size_t pathSize, eMfxImplType *pImplType, mfxVersion minVersion);

View File

@ -172,6 +172,7 @@ mfxStatus DISPATCHER_EXPOSED_PREFIX(MFXInit)(mfxIMPL impl, mfxVersion *pVer, mfx
{
// initialize the library iterator
mfxRes = libIterator.Init(implTypes[curImplIdx].implType,
implInterface != MFX_IMPL_VIA_D3D11,
implTypes[curImplIdx].adapterID,
currentStorage);

View File

@ -164,7 +164,7 @@ void DXGI1Device::Close(void)
} // void DXGI1Device::Close(void)
bool DXGI1Device::Init(const mfxU32 adapterNum)
bool DXGI1Device::Init(const bool countDisplays, const mfxU32 adapterNum)
{
// release the object before initialization
Close();
@ -181,7 +181,6 @@ bool DXGI1Device::Init(const mfxU32 adapterNum)
IDXGIFactory1 *pFactory;
IDXGIAdapter1 *pAdapter;
DXGI_ADAPTER_DESC1 desc;
mfxU32 curAdapter, maxAdapters;
HRESULT hRes;
// load address of procedure to create DXGI 1.1 factory
@ -203,54 +202,46 @@ bool DXGI1Device::Init(const mfxU32 adapterNum)
}
m_pDXGIFactory1 = pFactory;
// get the number of adapters
curAdapter = 0;
maxAdapters = 0;
mfxU32 outputs = 0;
do
if(countDisplays)
{
// get the required adapted
hRes = pFactory->EnumAdapters1(curAdapter, &pAdapter);
if (FAILED(hRes))
{
break;
}
mfxU32 curOutput = 0;
HRESULT h;
do
UINT display = 0;
for(UINT adapter = 0; pFactory->EnumAdapters1(adapter, &pAdapter) != DXGI_ERROR_NOT_FOUND; adapter++)
{
IDXGIOutput *out;
h = pAdapter->EnumOutputs(curOutput, &out);
if(FAILED(h))
break;
// if it is the required adapter, save the interface
if (outputs == adapterNum)
m_pDXGIAdapter1 = pAdapter;
for(UINT start_display = display; pAdapter->EnumOutputs(display-start_display, &out) != DXGI_ERROR_NOT_FOUND; display++)
{
out->Release();
outputs += 1;
curOutput += 1;
} while(!m_pDXGIAdapter1 && SUCCEEDED(h));
if (display != adapterNum)
continue;
m_pDXGIAdapter1 = pAdapter;
break;
}
if(m_pDXGIAdapter1)
break;
if(!m_pDXGIAdapter1)
pAdapter->Release();
curAdapter += 1;
} while (!m_pDXGIAdapter1 && SUCCEEDED(hRes));
maxAdapters = curAdapter;
}
// there is no required adapter
if (adapterNum >= outputs)
{
if (adapterNum > display)
return false;
}
else
{
hRes = pFactory->EnumAdapters1(adapterNum, &pAdapter);
if(FAILED(hRes))
return false;
m_pDXGIAdapter1 = pAdapter;
}
pAdapter = (IDXGIAdapter1 *) m_pDXGIAdapter1;
if(!pAdapter)
return false;
// get the adapter's parameters
hRes = pAdapter->GetDesc1(&desc);
if (FAILED(hRes))
@ -292,7 +283,7 @@ void DXVA2Device::Close(void)
} // void DXVA2Device::Close(void)
bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum)
bool DXVA2Device::InitDXGI1(const bool countDisplays, const mfxU32 adapterNum)
{
DXGI1Device dxgi1Device;
bool bRes;
@ -301,7 +292,7 @@ bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum)
Close();
// create modern DXGI device
bRes = dxgi1Device.Init(adapterNum);
bRes = dxgi1Device.Init(countDisplays, adapterNum);
if (false == bRes)
{
return false;

View File

@ -90,7 +90,7 @@ void MFXLibraryIterator::Release(void)
} // void MFXLibraryIterator::Release(void)
mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID)
mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const bool countDisplays, const mfxU32 adapterNum, int storageID)
{
DXVA2Device dxvaDevice;
HKEY rootHKey;
@ -121,7 +121,7 @@ mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNu
m_implType = implType;
// try to open DXGI 1.1 device to get hardware ID
if (!dxvaDevice.InitDXGI1(adapterNum))
if (!dxvaDevice.InitDXGI1(countDisplays, adapterNum))
{
DISPATCHER_LOG_INFO((("dxvaDevice.InitDXGI1(%d) Failed "), adapterNum ));
return MFX_ERR_UNSUPPORTED;