Skip to content

Commit

Permalink
dxva: use d3d9 ex if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Dec 31, 2014
1 parent d538939 commit ebf7413
Showing 1 changed file with 110 additions and 29 deletions.
139 changes: 110 additions & 29 deletions src/codec/video/VideoDecoderDXVA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "utils/GPUMemCopy.h"
#include "utils/Logger.h"

// d3d9ex: http://dxr.mozilla.org/mozilla-central/source/dom/media/wmf/DXVA2Manager.cpp
// TODO: add to QtAV_Compat.h?
// FF_API_PIX_FMT
#ifdef PixelFormat
Expand Down Expand Up @@ -85,6 +86,7 @@ namespace QtAV {
// some MS_GUID are defined in mingw but some are not. move to namespace and define all is ok
MS_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
MS_GUID(IID_IDirectXVideoAccelerationService, 0xfc51a550, 0xd5e7, 0x11d9, 0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
MS_GUID(IID_IDirect3DDevice9Ex, 0xb18b10ce, 0x2649, 0x405a, 0x87, 0xf, 0x95, 0xf7, 0x77, 0xd4, 0x31, 0x3a);

MS_GUID (DXVA_NoEncrypt, 0x1b81bed0, 0xa0c7, 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);

Expand Down Expand Up @@ -297,6 +299,7 @@ class VideoDecoderDXVAPrivate : public VideoDecoderFFmpegHWPrivate
hd3d9_dll = 0;
hdxva2_dll = 0;
d3dobj = 0;
d3dobj_ex = 0;
d3ddev = 0;
token = 0;
devmng = 0;
Expand All @@ -312,6 +315,7 @@ class VideoDecoderDXVAPrivate : public VideoDecoderFFmpegHWPrivate
surface_auto = true;
surface_count = 0;
copy_uswc = true;
ZeroMemory(&d3dai, sizeof(d3dai));
}
virtual ~VideoDecoderDXVAPrivate()
{
Expand All @@ -321,6 +325,8 @@ class VideoDecoderDXVAPrivate : public VideoDecoderFFmpegHWPrivate
bool loadDll();
bool unloadDll();
bool D3dCreateDevice();
bool D3dCreateDeviceEx();
bool D3dCreateDeviceFallback();
void D3dDestroyDevice();
bool D3dCreateDeviceManager();
void D3dDestroyDeviceManager();
Expand Down Expand Up @@ -348,11 +354,10 @@ class VideoDecoderDXVAPrivate : public VideoDecoderFFmpegHWPrivate
HINSTANCE hdxva2_dll;

/* Direct3D */
D3DPRESENT_PARAMETERS d3dpp;
IDirect3D9 *d3dobj;
IDirect3D9Ex *d3dobj_ex;
D3DADAPTER_IDENTIFIER9 d3dai;
IDirect3DDevice9 *d3ddev;

IDirect3DDevice9 *d3ddev; // can be Ex
/* Device manager */
UINT token;
IDirect3DDeviceManager9 *devmng;
Expand Down Expand Up @@ -607,6 +612,76 @@ bool VideoDecoderDXVAPrivate::unloadDll() {

bool VideoDecoderDXVAPrivate::D3dCreateDevice()
{
if (D3dCreateDeviceEx())
return true;
return D3dCreateDeviceFallback();
}

bool VideoDecoderDXVAPrivate::D3dCreateDeviceEx()
{
//http://msdn.microsoft.com/en-us/library/windows/desktop/bb219676(v=vs.85).aspx
typedef HRESULT (WINAPI *Create9ExFunc)(UINT SDKVersion, IDirect3D9Ex **ppD3D); //IDirect3D9Ex: void is ok
Create9ExFunc Create9Ex = (Create9ExFunc)GetProcAddress(hd3d9_dll, "Direct3DCreate9Ex");
if (!Create9Ex) {
qWarning("Does not support Direct3DCreate9Ex");
return false;
}
if (FAILED(Create9Ex(D3D_SDK_VERSION, &d3dobj_ex))) {
d3dobj_ex = 0;
qWarning("Can not create IDirect3D9Ex");
return false;
}
if (FAILED(d3dobj_ex->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &d3dai))) {
qWarning("IDirect3D9Ex->GetAdapterIdentifier failed. Fallback to IDirect3D9->GetAdapterIdentifier");
ZeroMemory(&d3dai, sizeof(d3dai));
return false;
}
vendor = getVendorName(&d3dai);
description = QString().sprintf("DXVA2 (%.*s, vendor %lu(%s), device %lu, revision %lu)",
sizeof(d3dai.Description), d3dai.Description,
d3dai.VendorId, qPrintable(vendor), d3dai.DeviceId, d3dai.Revision);
if (copy_uswc)
copy_uswc = vendor.toLower() == "intel";
qDebug("DXVA2 description: %s", description.toUtf8().constData());

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
// use mozilla's parameters
d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
d3dpp.Windowed = TRUE;
d3dpp.hDeviceWindow = ::GetShellWindow(); //NULL;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
//d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
//d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.BackBufferCount = 1; //0; /* FIXME what to put here */
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; //D3DFMT_X8R8G8B8; /* FIXME what to put here */
d3dpp.BackBufferWidth = 1; //0;
d3dpp.BackBufferHeight = 1; //0;
//d3dpp.EnableAutoDepthStencil = FALSE;

DWORD flags = D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING;
// old: D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED
// mpv:
/* Direct3D needs a HWND to create a device, even without using ::Present
this HWND is used to alert Direct3D when there's a change of focus window.
For now, use GetDesktopWindow, as it looks harmless */
if (FAILED(d3dobj_ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, GetShellWindow(),// GetDesktopWindow(), //GetShellWindow()?
flags,
&d3dpp,
NULL,
(IDirect3DDevice9Ex**)(&d3ddev)))) {
qWarning("IDirect3D9Ex->CreateDeviceEx failed. Fallback to IDirect3D9->CreateDevice");
d3ddev = 0;
return false;
}
qDebug("IDirect3DDevice9Ex created....");
return true;
}

bool VideoDecoderDXVAPrivate::D3dCreateDeviceFallback()
{
qDebug("Fallback to d3d9");
typedef IDirect3D9* (WINAPI *Create9Func)(UINT SDKVersion);
Create9Func Create9 = (Create9Func)GetProcAddress(hd3d9_dll, "Direct3DCreate9");
if (!Create9) {
Expand All @@ -619,42 +694,42 @@ bool VideoDecoderDXVAPrivate::D3dCreateDevice()
return false;
}
if (FAILED(d3dobj->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &d3dai))) {
qWarning("IDirect3D9_GetAdapterIdentifier failed");
qWarning("IDirect3D9->GetAdapterIdentifier failed");
ZeroMemory(&d3dai, sizeof(d3dai));
} else {
vendor = getVendorName(&d3dai);
description = QString().sprintf("DXVA2 (%.*s, vendor %lu(%s), device %lu, revision %lu)",
sizeof(d3dai.Description), d3dai.Description,
d3dai.VendorId, qPrintable(vendor), d3dai.DeviceId, d3dai.Revision);
if (copy_uswc)
copy_uswc = vendor.toLower() == "intel";
qDebug("DXVA2 description: %s", description.toUtf8().constData());
return false;
}
vendor = getVendorName(&d3dai);
description = QString().sprintf("DXVA2 (%.*s, vendor %lu(%s), device %lu, revision %lu)",
sizeof(d3dai.Description), d3dai.Description,
d3dai.VendorId, qPrintable(vendor), d3dai.DeviceId, d3dai.Revision);
if (copy_uswc)
copy_uswc = vendor.toLower() == "intel";
qDebug("DXVA2 description: %s", description.toUtf8().constData());

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
// use mozilla's parameters
d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
d3dpp.Windowed = TRUE;
d3dpp.hDeviceWindow = NULL;
d3dpp.hDeviceWindow = ::GetShellWindow(); //NULL;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.BackBufferCount = 0; /* FIXME what to put here */
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; /* FIXME what to put here */
d3dpp.BackBufferWidth = 0;
d3dpp.BackBufferHeight = 0;
d3dpp.EnableAutoDepthStencil = FALSE;

/* Direct3D needs a HWND to create a device, even without using ::Present
this HWND is used to alert Direct3D when there's a change of focus window.
For now, use GetDesktopWindow, as it looks harmless */
//d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
//d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.BackBufferCount = 1; //0; /* FIXME what to put here */
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; //D3DFMT_X8R8G8B8; /* FIXME what to put here */
d3dpp.BackBufferWidth = 1; //0;
d3dpp.BackBufferHeight = 1; //0;
//d3dpp.EnableAutoDepthStencil = FALSE;
DWORD flags = D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING;
if (FAILED(d3dobj->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, GetDesktopWindow(), //GetShellWindow()?
D3DCREATE_SOFTWARE_VERTEXPROCESSING |
D3DCREATE_MULTITHREADED,
D3DDEVTYPE_HAL, GetShellWindow(),// GetDesktopWindow(), //GetShellWindow()?
flags,
&d3dpp, &d3ddev))) {
qWarning("IDirect3D9_CreateDevice failed");
qWarning("IDirect3D9->CreateDevice failed");
d3ddev = 0;
return false;
}

qDebug("IDirect3DDevice9 created....");
return true;
}

Expand All @@ -665,6 +740,8 @@ void VideoDecoderDXVAPrivate::D3dDestroyDevice()
{
SafeRelease(&d3ddev);
SafeRelease(&d3dobj);
SafeRelease(&d3dobj_ex);
ZeroMemory(&d3dai, sizeof(d3dai));
}
/**
* It creates a Direct3D device manager
Expand Down Expand Up @@ -1039,6 +1116,10 @@ bool VideoDecoderDXVAPrivate::open()
qWarning("DxFindVideoServiceConversion failed");
goto error;
}
IDirect3DDevice9Ex *devEx;
d3ddev->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&devEx);
qDebug("using D3D9Ex: %d", !!devEx);
SafeRelease(&devEx);
/* TODO print the hardware name/vendor for debugging purposes */
return true;
error:
Expand Down

0 comments on commit ebf7413

Please sign in to comment.