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) #define TO_STR(a) TEXT(#a)
const float baseCRF = 22.0f; const float baseCRF = 22.0f;
const mfxVersion version = {4, 1}; //Highest supported version on Sandy Bridge const struct {
const mfxIMPL validImpl[] = {MFX_IMPL_HARDWARE_ANY, MFX_IMPL_HARDWARE}; 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[] = { const TCHAR* implStr[] = {
TO_STR(MFX_IMPL_AUTO), TO_STR(MFX_IMPL_AUTO),
TO_STR(MFX_IMPL_SOFTWARE), TO_STR(MFX_IMPL_SOFTWARE),
@ -65,6 +73,19 @@ namespace
TO_STR(MFX_TARGETUSAGE_BEST_SPEED) 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) void ConvertFrameRate(mfxF64 dFrameRate, mfxU32& pnFrameRateExtN, mfxU32& pnFrameRateExtD)
{ {
mfxU32 fr; mfxU32 fr;
@ -109,11 +130,10 @@ namespace
bool CheckQSVHardwareSupport(bool log=true) bool CheckQSVHardwareSupport(bool log=true)
{ {
MFXVideoSession test; 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 = impl->version;
mfxVersion ver = version; auto result = test.Init(impl->type | impl->intf, &ver);
auto result = test.Init(impl, &ver);
if(result != MFX_ERR_NONE) if(result != MFX_ERR_NONE)
continue; continue;
if(log) if(log)
@ -268,24 +288,20 @@ public:
: enc(nullptr), bFirstFrameProcessed(false), bFirstFrameQueued(false) : enc(nullptr), bFirstFrameProcessed(false), bFirstFrameQueued(false)
{ {
Log(TEXT("------------------------------------------")); 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 = impl->version;
ver = version; auto result = session.Init(impl->type | impl->intf, &ver);
mfxStatus result = MFX_ERR_UNKNOWN;
for(ver.Minor = 6; ver.Minor >= 4; ver.Minor -= 2)
{
result = session.Init(impl, &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]);
break;
}
}
if(result == MFX_ERR_NONE) if(result == MFX_ERR_NONE)
{
mfxIMPL actual;
session.QueryIMPL(&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; break;
}
} }
session.SetPriority(MFX_PRIORITY_HIGH); session.SetPriority(MFX_PRIORITY_HIGH);
@ -302,7 +318,7 @@ public:
params.mfx.TargetKbps = maxBitrate; params.mfx.TargetKbps = maxBitrate;
params.mfx.MaxKbps = maxBitrate; params.mfx.MaxKbps = maxBitrate;
params.mfx.BufferSizeInKB = bufferSize/8; 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.GopPicSize = 250;
params.mfx.GopRefDist = 8; params.mfx.GopRefDist = 8;
params.mfx.IdrInterval = 0; params.mfx.IdrInterval = 0;

View File

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

View File

@ -58,7 +58,7 @@ public:
~MFXLibraryIterator(void); ~MFXLibraryIterator(void);
// Initialize the iterator // 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 // Get the next library path
mfxStatus SelectDLLVersion(wchar_t *pPath, size_t pathSize, eMfxImplType *pImplType, mfxVersion minVersion); 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 // initialize the library iterator
mfxRes = libIterator.Init(implTypes[curImplIdx].implType, mfxRes = libIterator.Init(implTypes[curImplIdx].implType,
implInterface != MFX_IMPL_VIA_D3D11,
implTypes[curImplIdx].adapterID, implTypes[curImplIdx].adapterID,
currentStorage); currentStorage);

View File

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

View File

@ -90,7 +90,7 @@ void MFXLibraryIterator::Release(void)
} // 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; DXVA2Device dxvaDevice;
HKEY rootHKey; HKEY rootHKey;
@ -121,7 +121,7 @@ mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNu
m_implType = implType; m_implType = implType;
// try to open DXGI 1.1 device to get hardware ID // 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 )); DISPATCHER_LOG_INFO((("dxvaDevice.InitDXGI1(%d) Failed "), adapterNum ));
return MFX_ERR_UNSUPPORTED; return MFX_ERR_UNSUPPORTED;