Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/LAVFilters.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2016-02-14 18:56:52 +0300
committerHendrik Leppkes <h.leppkes@gmail.com>2016-02-14 18:56:52 +0300
commit14703100434eb2971a209f0bfe289582a40b02d1 (patch)
treedfaa6d73490b4c7fdd792a5541b27ac06b94905f /decoder
parent49fe074d3d4492bb0070f7fdfc0fb32263a82771 (diff)
Add options to select the GPU for DXVA2-CopyBack
Diffstat (limited to 'decoder')
-rw-r--r--decoder/LAVVideo/DecodeThread.cpp24
-rw-r--r--decoder/LAVVideo/DecodeThread.h3
-rw-r--r--decoder/LAVVideo/LAVVideo.cpp109
-rw-r--r--decoder/LAVVideo/LAVVideo.h9
-rw-r--r--decoder/LAVVideo/LAVVideo.rc9
-rw-r--r--decoder/LAVVideo/LAVVideoSettings.h19
-rw-r--r--decoder/LAVVideo/VideoSettingsProp.cpp58
-rw-r--r--decoder/LAVVideo/VideoSettingsProp.h1
-rw-r--r--decoder/LAVVideo/decoders/DecBase.h4
-rw-r--r--decoder/LAVVideo/decoders/ILAVDecoder.h17
-rw-r--r--decoder/LAVVideo/decoders/dxva2dec.cpp92
-rw-r--r--decoder/LAVVideo/decoders/dxva2dec.h4
-rw-r--r--decoder/LAVVideo/decoders/quicksync.h2
-rw-r--r--decoder/LAVVideo/resource.h7
14 files changed, 330 insertions, 28 deletions
diff --git a/decoder/LAVVideo/DecodeThread.cpp b/decoder/LAVVideo/DecodeThread.cpp
index e3ff7a90..ffda97e0 100644
--- a/decoder/LAVVideo/DecodeThread.cpp
+++ b/decoder/LAVVideo/DecodeThread.cpp
@@ -405,6 +405,21 @@ DWORD CDecodeThread::ThreadProc()
|| ((pBMI->biHeight > 576 || pBMI->biWidth > 1024) && pBMI->biHeight <= 1200 && pBMI->biWidth <= 1920 && m_pLAVVideo->GetHWAccelResolutionFlags() & LAVHWResFlag_HD) \
|| ((pBMI->biHeight > 1200 || pBMI->biWidth > 1920) && m_pLAVVideo->GetHWAccelResolutionFlags() & LAVHWResFlag_UHD))
+ILAVDecoder * CDecodeThread::CreateHWAccelDecoder(LAVHWAccel hwAccel)
+{
+ ILAVDecoder * pDecoder = nullptr;
+ if (hwAccel == HWAccel_CUDA)
+ pDecoder = CreateDecoderCUVID();
+ else if (hwAccel == HWAccel_QuickSync)
+ pDecoder = CreateDecoderQuickSync();
+ else if (hwAccel == HWAccel_DXVA2CopyBack)
+ pDecoder = CreateDecoderDXVA2();
+ else if (hwAccel == HWAccel_DXVA2Native)
+ pDecoder = CreateDecoderDXVA2Native();
+
+ return pDecoder;
+}
+
STDMETHODIMP CDecodeThread::CreateDecoderInternal(const CMediaType *pmt, AVCodecID codec)
{
DbgLog((LOG_TRACE, 10, L"CDecodeThread::CreateDecoderInternal(): Creating new decoder for codec %S", avcodec_get_name(codec)));
@@ -429,14 +444,7 @@ STDMETHODIMP CDecodeThread::CreateDecoderInternal(const CMediaType *pmt, AVCodec
if (!bHWDecBlackList && hwAccel != HWAccel_None && !m_bHWDecoderFailed && HWFORMAT_ENABLED && HWRESOLUTION_ENABLED)
{
DbgLog((LOG_TRACE, 10, L"-> Trying Hardware Codec %d", hwAccel));
- if (hwAccel == HWAccel_CUDA)
- m_pDecoder = CreateDecoderCUVID();
- else if (hwAccel == HWAccel_QuickSync)
- m_pDecoder = CreateDecoderQuickSync();
- else if (hwAccel == HWAccel_DXVA2CopyBack)
- m_pDecoder = CreateDecoderDXVA2();
- else if (hwAccel == HWAccel_DXVA2Native)
- m_pDecoder = CreateDecoderDXVA2Native();
+ m_pDecoder = CreateHWAccelDecoder(hwAccel);
m_bHWDecoder = TRUE;
}
diff --git a/decoder/LAVVideo/DecodeThread.h b/decoder/LAVVideo/DecodeThread.h
index 53fee896..96801745 100644
--- a/decoder/LAVVideo/DecodeThread.h
+++ b/decoder/LAVVideo/DecodeThread.h
@@ -30,6 +30,8 @@ public:
CDecodeThread(CLAVVideo *pLAVVideo);
~CDecodeThread();
+ static ILAVDecoder * CreateHWAccelDecoder(LAVHWAccel hwAccel);
+
// Parts of ILAVDecoder
STDMETHODIMP_(const WCHAR*) GetDecoderName() { return m_pDecoder ? m_pDecoder->GetDecoderName() : nullptr; }
STDMETHODIMP_(long) GetBufferCount() { return m_pDecoder ? m_pDecoder->GetBufferCount() : 4; }
@@ -51,6 +53,7 @@ public:
STDMETHODIMP PostConnect(IPin *pPin);
STDMETHODIMP_(BOOL) IsHWDecoderActive() { return m_bHWDecoder; }
+ STDMETHODIMP GetHWAccelActiveDevice(BSTR *pstrDeviceName) { return m_pDecoder ? m_pDecoder->GetHWAccelActiveDevice(pstrDeviceName) : E_UNEXPECTED; }
// ILAVVideoCallback
STDMETHODIMP AllocateFrame(LAVFrame **ppFrame);
diff --git a/decoder/LAVVideo/LAVVideo.cpp b/decoder/LAVVideo/LAVVideo.cpp
index 4eff4f0b..ee300574 100644
--- a/decoder/LAVVideo/LAVVideo.cpp
+++ b/decoder/LAVVideo/LAVVideo.cpp
@@ -174,6 +174,10 @@ HRESULT CLAVVideo::LoadDefaults()
m_settings.DitherMode = LAVDither_Random;
+
+ m_settings.HWAccelDeviceDXVA2 = LAVHWACCEL_DEVICE_DEFAULT;
+ m_settings.HWAccelDeviceDXVA2Desc = 0;
+
return S_OK;
}
@@ -297,6 +301,12 @@ HRESULT CLAVVideo::ReadSettings(HKEY rootKey)
dwVal = regHW.ReadDWORD(L"HWDeintOutput", hr);
if (SUCCEEDED(hr)) m_settings.HWDeintOutput = dwVal;
+
+ dwVal = regHW.ReadDWORD(L"HWAccelDeviceDXVA2", hr);
+ if (SUCCEEDED(hr)) m_settings.HWAccelDeviceDXVA2 = dwVal;
+
+ dwVal = regHW.ReadDWORD(L"HWAccelDeviceDXVA2Desc", hr);
+ if (SUCCEEDED(hr)) m_settings.HWAccelDeviceDXVA2Desc = dwVal;
}
return S_OK;
@@ -351,6 +361,9 @@ HRESULT CLAVVideo::SaveSettings()
regHW.WriteDWORD(L"HWDeintMode", m_settings.HWDeintMode);
regHW.WriteDWORD(L"HWDeintOutput", m_settings.HWDeintOutput);
+ regHW.WriteDWORD(L"HWAccelDeviceDXVA2", m_settings.HWAccelDeviceDXVA2);
+ regHW.WriteDWORD(L"HWAccelDeviceDXVA2Desc", m_settings.HWAccelDeviceDXVA2Desc);
+
reg.WriteDWORD(L"SWDeintMode", m_settings.SWDeintMode);
reg.WriteDWORD(L"SWDeintOutput", m_settings.SWDeintOutput);
reg.WriteDWORD(L"DitherMode", m_settings.DitherMode);
@@ -2016,21 +2029,7 @@ STDMETHODIMP_(DWORD) CLAVVideo::CheckHWAccelSupport(LAVHWAccel hwAccel)
return 2;
HRESULT hr = E_FAIL;
- ILAVDecoder *pDecoder = nullptr;
- switch(hwAccel) {
- case HWAccel_CUDA:
- pDecoder = CreateDecoderCUVID();
- break;
- case HWAccel_QuickSync:
- pDecoder = CreateDecoderQuickSync();
- break;
- case HWAccel_DXVA2CopyBack:
- pDecoder = CreateDecoderDXVA2();
- break;
- case HWAccel_DXVA2Native:
- pDecoder = CreateDecoderDXVA2Native();
- break;
- }
+ ILAVDecoder *pDecoder = CDecodeThread::CreateHWAccelDecoder(hwAccel);
if (pDecoder) {
hr = pDecoder->InitInterfaces(this, this);
@@ -2212,3 +2211,83 @@ STDMETHODIMP CLAVVideo::SetGPUDeviceIndex(DWORD dwDevice)
m_dwGPUDeviceIndex = dwDevice;
return S_OK;
}
+
+STDMETHODIMP_(DWORD) CLAVVideo::GetHWAccelNumDevices(LAVHWAccel hwAccel)
+{
+ HRESULT hr = S_OK;
+ ILAVDecoder *pDecoder = CDecodeThread::CreateHWAccelDecoder(hwAccel);
+ DWORD dwDevices = 0;
+ if (pDecoder) {
+ hr = pDecoder->InitInterfaces(this, this);
+ if (SUCCEEDED(hr)) {
+ dwDevices = pDecoder->GetHWAccelNumDevices();
+ }
+ SAFE_DELETE(pDecoder);
+ }
+ return dwDevices;
+}
+
+STDMETHODIMP CLAVVideo::GetHWAccelDeviceInfo(LAVHWAccel hwAccel, DWORD dwIndex, BSTR *pstrDeviceName, DWORD *pdwDeviceIdentifier)
+{
+ HRESULT hr = E_NOINTERFACE;
+ ILAVDecoder *pDecoder = CDecodeThread::CreateHWAccelDecoder(hwAccel);
+ if (pDecoder) {
+ hr = pDecoder->InitInterfaces(this, this);
+ if (SUCCEEDED(hr)) {
+ hr = pDecoder->GetHWAccelDeviceInfo(dwIndex, pstrDeviceName, pdwDeviceIdentifier);
+ }
+ SAFE_DELETE(pDecoder);
+ }
+ return hr;
+}
+
+STDMETHODIMP_(DWORD) CLAVVideo::GetHWAccelDeviceIndex(LAVHWAccel hwAccel, DWORD *pdwDeviceIdentifier)
+{
+ HRESULT hr = S_OK;
+ if (hwAccel == HWAccel_DXVA2CopyBack) {
+ DWORD dwDeviceIndex = m_settings.HWAccelDeviceDXVA2;
+ DWORD dwDeviceId = m_settings.HWAccelDeviceDXVA2Desc;
+
+ // verify the values and re-match them to adapters appropriately
+ if (dwDeviceIndex != LAVHWACCEL_DEVICE_DEFAULT && dwDeviceId != 0) {
+ hr = VerifyD3D9Device(dwDeviceIndex, dwDeviceId);
+ if (FAILED(hr)) {
+ dwDeviceIndex = LAVHWACCEL_DEVICE_DEFAULT;
+ dwDeviceId = 0;
+ }
+ }
+
+ if (pdwDeviceIdentifier)
+ *pdwDeviceIdentifier = dwDeviceId;
+
+ return dwDeviceIndex;
+ }
+
+ if (pdwDeviceIdentifier)
+ *pdwDeviceIdentifier = 0;
+ return LAVHWACCEL_DEVICE_DEFAULT;
+}
+
+STDMETHODIMP CLAVVideo::SetHWAccelDeviceIndex(LAVHWAccel hwAccel, DWORD dwIndex, DWORD dwDeviceIdentifier)
+{
+ HRESULT hr = S_OK;
+
+ if (dwIndex != LAVHWACCEL_DEVICE_DEFAULT && dwDeviceIdentifier == 0)
+ hr = GetHWAccelDeviceInfo(hwAccel, dwIndex, nullptr, &dwDeviceIdentifier);
+
+ if (SUCCEEDED(hr)) {
+ if (hwAccel == HWAccel_DXVA2CopyBack) {
+ m_settings.HWAccelDeviceDXVA2 = dwIndex;
+ m_settings.HWAccelDeviceDXVA2Desc = dwDeviceIdentifier;
+ }
+ return SaveSettings();
+ }
+ else {
+ return E_INVALIDARG;
+ }
+}
+
+STDMETHODIMP CLAVVideo::GetHWAccelActiveDevice(BSTR *pstrDeviceName)
+{
+ return m_Decoder.GetHWAccelActiveDevice(pstrDeviceName);
+}
diff --git a/decoder/LAVVideo/LAVVideo.h b/decoder/LAVVideo/LAVVideo.h
index b353db81..9089d6a4 100644
--- a/decoder/LAVVideo/LAVVideo.h
+++ b/decoder/LAVVideo/LAVVideo.h
@@ -127,8 +127,15 @@ public:
STDMETHODIMP SetGPUDeviceIndex(DWORD dwDevice);
+ STDMETHODIMP_(DWORD) GetHWAccelNumDevices(LAVHWAccel hwAccel);
+ STDMETHODIMP GetHWAccelDeviceInfo(LAVHWAccel hwAccel, DWORD dwIndex, BSTR *pstrDeviceName, DWORD *pdwDeviceIdentifier);
+
+ STDMETHODIMP_(DWORD) GetHWAccelDeviceIndex(LAVHWAccel hwAccel, DWORD *pdwDeviceIdentifier);
+ STDMETHODIMP SetHWAccelDeviceIndex(LAVHWAccel hwAccel, DWORD dwIndex, DWORD dwDeviceIdentifier);
+
// ILAVVideoStatus
STDMETHODIMP_(const WCHAR *) GetActiveDecoderName() { return m_Decoder.GetDecoderName(); }
+ STDMETHODIMP GetHWAccelActiveDevice(BSTR *pstrDeviceName);
// CTransformFilter
HRESULT CheckInputType(const CMediaType* mtIn);
@@ -281,6 +288,8 @@ private:
DWORD SWDeintOutput;
DWORD DitherMode;
BOOL bDVDVideo;
+ DWORD HWAccelDeviceDXVA2;
+ DWORD HWAccelDeviceDXVA2Desc;
} m_settings;
DWORD m_dwGPUDeviceIndex = DWORD_MAX;
diff --git a/decoder/LAVVideo/LAVVideo.rc b/decoder/LAVVideo/LAVVideo.rc
index f5bdd676..fa1117dd 100644
--- a/decoder/LAVVideo/LAVVideo.rc
+++ b/decoder/LAVVideo/LAVVideo.rc
@@ -113,7 +113,7 @@ BEGIN
LTEXT "Hardware Decoder to use:",IDC_LBL_HWACCEL,157,17,107,8
COMBOBOX IDC_HWACCEL,160,28,85,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Active",IDC_HWACCEL_AVAIL,247,31,30,8
- LTEXT "Active Decoder: ",IDC_STATIC,160,46,57,8
+ LTEXT "Active Decoder: ",IDC_STATIC,157,46,57,8
LTEXT "<inactive>",IDC_ACTIVE_DECODER,220,46,55,8
LTEXT "Resolutions",IDC_LBL_HWRESOLUTIONS,280,17,47,8
CONTROL "SD",IDC_HWRES_SD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,283,27,32,10
@@ -127,6 +127,11 @@ BEGIN
CONTROL "DVD",IDC_HWACCEL_MPEG2_DVD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,321,67,35,10
CONTROL "MPEG-4",IDC_HWACCEL_MPEG4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,359,67,35,10
CONTROL "VP9",IDC_HWACCEL_VP9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,283,81,35,10
+ LTEXT "Active Hardware Accelerator:",IDC_LBL_HWACCEL_DEVICE,157,62,110,8
+ LTEXT "<none>",IDC_HWACCEL_DEVICE,160,72,110,8
+ LTEXT "Hardware Device to use:",IDC_LBL_HWACCEL_DEVICE_SELECT,157,87,105,8
+ COMBOBOX IDC_HWACCEL_DEVICE_SELECT,160,98,235,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "The selected Hardware Decoder does not support using a specific device.", IDC_LBL_HWACCEL_DEVICE_HINT, 160, 115, 235, 18
GROUPBOX "Hardware/GPU Deinterlacing (CUVID/QS only)",IDC_GROUP_HWDEINT,237,143,167,52
CONTROL "Enable Adaptive HW Deinterlacing",IDC_HWDEINT_ENABLE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,244,155,139,10
@@ -134,7 +139,7 @@ BEGIN
CONTROL "25p/30p (Film)",IDC_HWDEINT_OUT_FILM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,247,180,58,10
CONTROL "50p/60p (Video)",IDC_HWDEINT_OUT_VIDEO,"Button",BS_AUTORADIOBUTTON,315,180,62,10
GROUPBOX "Software Deinterlacing",IDC_SWDEINT,237,197,167,67
- LTEXT "Algorithm", IDC_LBL_SWDEINT_ALGO, 243, 208, 100, 11
+ LTEXT "Algorithm",IDC_LBL_SWDEINT_ALGO,243,208,100,11
COMBOBOX IDC_SWDEINT_MODE,246,220,140,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Output Mode (YADIF only)",IDC_LBL_SWDEINT_MODE,243,237,100,11
CONTROL "25p/30p (Film)",IDC_SWDEINT_OUT_FILM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,247,248,58,10
diff --git a/decoder/LAVVideo/LAVVideoSettings.h b/decoder/LAVVideo/LAVVideoSettings.h
index 68daa5a4..6a8a7518 100644
--- a/decoder/LAVVideo/LAVVideoSettings.h
+++ b/decoder/LAVVideo/LAVVideoSettings.h
@@ -116,7 +116,8 @@ typedef enum LAVHWAccel {
HWAccel_QuickSync,
HWAccel_DXVA2,
HWAccel_DXVA2CopyBack = HWAccel_DXVA2,
- HWAccel_DXVA2Native
+ HWAccel_DXVA2Native,
+ HWAccel_NB, // Number of HWAccels
} LAVHWAccel;
// Deinterlace algorithms offered by the hardware decoders
@@ -361,6 +362,19 @@ interface ILAVVideoSettings : public IUnknown
// Must be called before an input is connected to LAV Video, and the setting is non-persistent
// NOTE: For CUVID, the index defines the index of the CUDA capable device, while for DXVA2, the list includes all D3D9 devices
STDMETHOD(SetGPUDeviceIndex)(DWORD dwDevice) = 0;
+
+ // Get the number of available devices for the specified HWAccel
+ STDMETHOD_(DWORD, GetHWAccelNumDevices)(LAVHWAccel hwAccel) = 0;
+
+ // Get a list of available HWAccel devices for the specified HWAccel
+ STDMETHOD(GetHWAccelDeviceInfo)(LAVHWAccel hwAccel, DWORD dwIndex, BSTR *pstrDeviceName, DWORD *pdwDeviceIdentifier) = 0;
+
+ // Get/Set the device for a specified HWAccel
+ // In contrast to SetGPUDeviceIndex, this setting is hwaccel-specific and persistent
+ // dwDeviceIdentifier is an optional parameter that identifies the selected device (ie. its device id), set to 0 if not used
+#define LAVHWACCEL_DEVICE_DEFAULT ((DWORD)-1)
+ STDMETHOD_(DWORD, GetHWAccelDeviceIndex)(LAVHWAccel hwAccel, DWORD *pdwDeviceIdentifier) = 0;
+ STDMETHOD(SetHWAccelDeviceIndex)(LAVHWAccel hwAccel, DWORD dwIndex, DWORD dwDeviceIdentifier) = 0;
};
// LAV Video status interface
@@ -369,4 +383,7 @@ interface ILAVVideoStatus : public IUnknown
{
// Get the name of the active decoder (can return NULL if none is active)
STDMETHOD_(LPCWSTR, GetActiveDecoderName)() = 0;
+
+ // Get the name of the currently active hwaccel device
+ STDMETHOD(GetHWAccelActiveDevice)(BSTR *pstrDeviceName) = 0;
};
diff --git a/decoder/LAVVideo/VideoSettingsProp.cpp b/decoder/LAVVideo/VideoSettingsProp.cpp
index 08fea475..b4b2584d 100644
--- a/decoder/LAVVideo/VideoSettingsProp.cpp
+++ b/decoder/LAVVideo/VideoSettingsProp.cpp
@@ -141,6 +141,13 @@ HRESULT CLAVVideoSettingsProp::OnApplyChanges()
m_pVideoSettings->SetHWAccelResolutionFlags(dwHWResFlags);
+ dwVal = (DWORD)SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE_SELECT, CB_GETCURSEL, 0, 0);
+ if (dwVal == 0)
+ dwVal = LAVHWACCEL_DEVICE_DEFAULT;
+ else
+ dwVal--;
+ m_pVideoSettings->SetHWAccelDeviceIndex(m_pVideoSettings->GetHWAccel(), dwVal, 0);
+
BOOL bHWDeint = (BOOL)SendDlgItemMessage(m_Dlg, IDC_HWDEINT_ENABLE, BM_GETCHECK, 0, 0);
m_pVideoSettings->SetHWAccelDeintMode(bHWDeint ? HWDeintMode_Hardware : HWDeintMode_Weave);
@@ -318,6 +325,15 @@ HRESULT CLAVVideoSettingsProp::OnActivate()
const WCHAR *decoder = m_pVideoStatus->GetActiveDecoderName();
SendDlgItemMessage(m_Dlg, IDC_ACTIVE_DECODER, WM_SETTEXT, 0, (LPARAM)(decoder ? decoder : L"<inactive>"));
+ BSTR bstrHWDevice = nullptr;
+ if (SUCCEEDED(m_pVideoStatus->GetHWAccelActiveDevice(&bstrHWDevice))) {
+ SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE, WM_SETTEXT, 0, (LPARAM)bstrHWDevice);
+ SysFreeString(bstrHWDevice);
+ }
+ else {
+ SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE, WM_SETTEXT, 0, (LPARAM)L"<none>");
+ }
+
return hr;
}
@@ -359,6 +375,43 @@ HRESULT CLAVVideoSettingsProp::UpdateHWOptions()
SendDlgItemMessage(m_Dlg, IDC_HWACCEL_AVAIL, WM_SETTEXT, 0, (LPARAM)(hwAccel == HWAccel_None ? hwAccelEmpty : dwSupport == 0 ? hwAccelUnavailable : dwSupport == 1 ? hwAccelAvailable : hwAccelActive));
+ EnableWindow(GetDlgItem(m_Dlg, IDC_LBL_HWACCEL_DEVICE_SELECT), hwAccel == HWAccel_DXVA2CopyBack);
+ EnableWindow(GetDlgItem(m_Dlg, IDC_HWACCEL_DEVICE_SELECT), hwAccel == HWAccel_DXVA2CopyBack);
+
+ const WCHAR hwHintNoDeviceChoice[] = L"The selected Hardware Decoder does not support using a specific device.";
+ const WCHAR hwHintDXVA2Display[] = L"DXVA2 requires an active display for GPUs to be available.\nNote that GPUs are listed once for each connected display.";
+
+
+ SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE_SELECT, CB_RESETCONTENT, 0, 0);
+ SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE_SELECT, CB_ADDSTRING, 0, (LPARAM)L"Automatic");
+
+ DWORD dwnDevices = m_pVideoSettings->GetHWAccelNumDevices(hwAccel);
+ for (DWORD dwDevice = 0; dwDevice < dwnDevices; dwDevice++)
+ {
+ BSTR bstrDeviceName = nullptr;
+ HRESULT hr = m_pVideoSettings->GetHWAccelDeviceInfo(hwAccel, dwDevice, &bstrDeviceName, NULL);
+ if (SUCCEEDED(hr)) {
+ SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE_SELECT, CB_ADDSTRING, 0, (LPARAM)bstrDeviceName);
+ SysFreeString(bstrDeviceName);
+ }
+ }
+
+ if (dwnDevices == 0) {
+ m_HWDeviceIndex = 0;
+ SendDlgItemMessage(m_Dlg, IDC_LBL_HWACCEL_DEVICE_HINT, WM_SETTEXT, 0, (LPARAM)hwHintNoDeviceChoice);
+ }
+ else {
+ DWORD dwDeviceId = 0;
+ m_HWDeviceIndex = m_pVideoSettings->GetHWAccelDeviceIndex(hwAccel, &dwDeviceId);
+ if (m_HWDeviceIndex == LAVHWACCEL_DEVICE_DEFAULT)
+ m_HWDeviceIndex = 0;
+ else
+ m_HWDeviceIndex++;
+ SendDlgItemMessage(m_Dlg, IDC_LBL_HWACCEL_DEVICE_HINT, WM_SETTEXT, 0, (LPARAM)(hwAccel == HWAccel_DXVA2CopyBack ? hwHintDXVA2Display : L""));
+ }
+
+ SendDlgItemMessage(m_Dlg, IDC_HWACCEL_DEVICE_SELECT, CB_SETCURSEL, m_HWDeviceIndex, 0);
+
return S_OK;
}
@@ -577,6 +630,11 @@ INT_PTR CLAVVideoSettingsProp::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wPa
if (bValue != m_HWAccelCodecs[HWCodec_VP9]) {
SetDirty();
}
+ } else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_HWACCEL_DEVICE_SELECT) {
+ lValue = SendDlgItemMessage(m_Dlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
+ if (lValue != m_HWDeviceIndex) {
+ SetDirty();
+ }
} else if (LOWORD(wParam) == IDC_HWDEINT_ENABLE && HIWORD(wParam) == BN_CLICKED) {
bValue = (BOOL)SendDlgItemMessage(m_Dlg, LOWORD(wParam), BM_GETCHECK, 0, 0);
if (bValue != (m_HWDeintAlgo == HWDeintMode_Hardware)) {
diff --git a/decoder/LAVVideo/VideoSettingsProp.h b/decoder/LAVVideo/VideoSettingsProp.h
index dbec6f01..8bf34eac 100644
--- a/decoder/LAVVideo/VideoSettingsProp.h
+++ b/decoder/LAVVideo/VideoSettingsProp.h
@@ -72,6 +72,7 @@ private:
BOOL m_HWAccelCodecs[HWCodec_NB];
DWORD m_HWRes;
+ DWORD m_HWDeviceIndex;
DWORD m_HWDeintAlgo;
DWORD m_HWDeintOutMode;
diff --git a/decoder/LAVVideo/decoders/DecBase.h b/decoder/LAVVideo/decoders/DecBase.h
index 8b88b442..e5cc1536 100644
--- a/decoder/LAVVideo/decoders/DecBase.h
+++ b/decoder/LAVVideo/decoders/DecBase.h
@@ -45,6 +45,10 @@ public:
STDMETHODIMP SetDirectOutput(BOOL bDirect) { return S_FALSE; }
+ STDMETHODIMP_(DWORD) GetHWAccelNumDevices() { return 0; }
+ STDMETHODIMP GetHWAccelDeviceInfo(DWORD dwIndex, BSTR *pstrDeviceName, DWORD *dwDeviceIdentifier) { return E_UNEXPECTED; }
+ STDMETHODIMP GetHWAccelActiveDevice(BSTR *pstrDeviceName) { return E_UNEXPECTED; }
+
STDMETHODIMP Decode(IMediaSample *pSample) {
HRESULT hr;
diff --git a/decoder/LAVVideo/decoders/ILAVDecoder.h b/decoder/LAVVideo/decoders/ILAVDecoder.h
index 5e77a561..6ec64dff 100644
--- a/decoder/LAVVideo/decoders/ILAVDecoder.h
+++ b/decoder/LAVVideo/decoders/ILAVDecoder.h
@@ -402,6 +402,21 @@ interface ILAVDecoder
* Toggle direct frame output mode for hardware decoders
*/
STDMETHOD(SetDirectOutput)(BOOL bDirect) PURE;
+
+ /**
+ * Get the number of available hw accel devices
+ */
+ STDMETHOD_(DWORD, GetHWAccelNumDevices)() PURE;
+
+ /**
+ * Get information about a hwaccel device
+ */
+ STDMETHOD(GetHWAccelDeviceInfo)(DWORD dwIndex, BSTR *pstrDeviceName, DWORD *dwDeviceIdentifier) PURE;
+
+ /**
+ * Get the description of the currently active hwaccel device
+ */
+ STDMETHOD(GetHWAccelActiveDevice)(BSTR *pstrDeviceName) PURE;
};
/**
@@ -417,3 +432,5 @@ ILAVDecoder *CreateDecoderQuickSync();
ILAVDecoder *CreateDecoderDXVA2();
ILAVDecoder *CreateDecoderDXVA2Native();
ILAVDecoder *CreateDecoderMSDKMVC();
+
+HRESULT VerifyD3D9Device(DWORD & dwIndex, DWORD dwDeviceId);
diff --git a/decoder/LAVVideo/decoders/dxva2dec.cpp b/decoder/LAVVideo/decoders/dxva2dec.cpp
index 473264b2..aa537bd4 100644
--- a/decoder/LAVVideo/decoders/dxva2dec.cpp
+++ b/decoder/LAVVideo/decoders/dxva2dec.cpp
@@ -49,6 +49,38 @@ ILAVDecoder *CreateDecoderDXVA2Native() {
return dec;
}
+HRESULT VerifyD3D9Device(DWORD & dwIndex, DWORD dwDeviceId)
+{
+ HRESULT hr = S_OK;
+
+ IDirect3D9 * pD3D = Direct3DCreate9(D3D_SDK_VERSION);
+ if (!pD3D)
+ return E_FAIL;
+
+ D3DADAPTER_IDENTIFIER9 d3dai = { 0 };
+
+ // Check the combination of adapter and device id
+ hr = pD3D->GetAdapterIdentifier(dwIndex, 0, &d3dai);
+ if (hr == D3D_OK && d3dai.DeviceId == dwDeviceId)
+ goto done;
+
+ // find an adapter with the specified device id
+ for (UINT i = 0; i < pD3D->GetAdapterCount(); i++) {
+ hr = pD3D->GetAdapterIdentifier(i, 0, &d3dai);
+ if (hr == D3D_OK && d3dai.DeviceId == dwDeviceId) {
+ dwIndex = i;
+ goto done;
+ }
+ }
+
+ // fail otherwise
+ hr = E_FAIL;
+
+done:
+ SafeRelease(&pD3D);
+ return hr;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Codec Maps
////////////////////////////////////////////////////////////////////////////////
@@ -589,7 +621,9 @@ HRESULT CDecDXVA2::InitD3D()
return E_FAIL;
}
- UINT lAdapter = D3DADAPTER_DEFAULT;
+ UINT lAdapter = m_pSettings->GetHWAccelDeviceIndex(HWAccel_DXVA2CopyBack, nullptr);
+ if (lAdapter == LAVHWACCEL_DEVICE_DEFAULT)
+ lAdapter = D3DADAPTER_DEFAULT;
DWORD dwDeviceIndex = m_pCallback->GetGPUDeviceIndex();
if (dwDeviceIndex != DWORD_MAX) {
@@ -696,6 +730,7 @@ HRESULT CDecDXVA2::RetrieveVendorId(IDirect3DDeviceManager9 *pDevManager)
m_dwVendorId = adIdentifier.VendorId;
m_dwDeviceId = adIdentifier.DeviceId;
+ memcpy(m_cDeviceName, adIdentifier.Description, sizeof(m_cDeviceName));
done:
SafeRelease(&pD3D);
@@ -1573,3 +1608,58 @@ bool CDecDXVA2::DeliverDirect(LAVFrame *pFrame)
return true;
}
+
+STDMETHODIMP_(DWORD) CDecDXVA2::GetHWAccelNumDevices()
+{
+ if (m_bNative)
+ return 0;
+
+ if (!m_pD3D)
+ return 0;
+
+ return m_pD3D->GetAdapterCount();
+}
+
+STDMETHODIMP CDecDXVA2::GetHWAccelDeviceInfo(DWORD dwIndex, BSTR *pstrDeviceName, DWORD *dwDeviceIdentifier)
+{
+ if (m_bNative)
+ return E_UNEXPECTED;
+
+ if (!m_pD3D)
+ return E_NOINTERFACE;
+
+ D3DADAPTER_IDENTIFIER9 d3dai = { 0 };
+ HRESULT err = m_pD3D->GetAdapterIdentifier(dwIndex, 0, &d3dai);
+ if (err != D3D_OK)
+ return E_INVALIDARG;
+
+ if (pstrDeviceName) {
+ int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, d3dai.Description, -1, nullptr, 0);
+ if (len == 0)
+ return E_FAIL;
+
+ *pstrDeviceName = SysAllocStringLen(nullptr, len);
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, d3dai.Description, -1, *pstrDeviceName, len);
+ }
+
+ if (dwDeviceIdentifier)
+ *dwDeviceIdentifier = d3dai.DeviceId;
+
+ return S_OK;
+}
+
+STDMETHODIMP CDecDXVA2::GetHWAccelActiveDevice(BSTR *pstrDeviceName)
+{
+ CheckPointer(pstrDeviceName, E_POINTER);
+
+ if (strlen(m_cDeviceName) == 0)
+ return E_UNEXPECTED;
+
+ int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, m_cDeviceName, -1, nullptr, 0);
+ if (len == 0)
+ return E_FAIL;
+
+ *pstrDeviceName = SysAllocStringLen(nullptr, len);
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, m_cDeviceName, -1, *pstrDeviceName, len);
+ return S_OK;
+}
diff --git a/decoder/LAVVideo/decoders/dxva2dec.h b/decoder/LAVVideo/decoders/dxva2dec.h
index d7934ae4..65322843 100644
--- a/decoder/LAVVideo/decoders/dxva2dec.h
+++ b/decoder/LAVVideo/decoders/dxva2dec.h
@@ -56,6 +56,9 @@ public:
STDMETHODIMP HasThreadSafeBuffers() { return m_bNative ? S_FALSE : S_OK; }
STDMETHODIMP SyncToProcessThread() { return S_OK; }
STDMETHODIMP SetDirectOutput(BOOL bDirect) { m_bDirect = bDirect; return S_OK; }
+ STDMETHODIMP_(DWORD) GetHWAccelNumDevices();
+ STDMETHODIMP GetHWAccelDeviceInfo(DWORD dwIndex, BSTR *pstrDeviceName, DWORD *dwDeviceIdentifier);
+ STDMETHODIMP GetHWAccelActiveDevice(BSTR *pstrDeviceName);
// CDecBase
STDMETHODIMP Init();
@@ -140,6 +143,7 @@ private:
D3DFORMAT m_eSurfaceFormat = D3DFMT_UNKNOWN;
DWORD m_dwVendorId = 0;
DWORD m_dwDeviceId = 0;
+ char m_cDeviceName[512] = { 0 };
GUID m_guidDecoderDevice = GUID_NULL;
int m_DisplayDelay = DXVA2_QUEUE_SURFACES;
diff --git a/decoder/LAVVideo/decoders/quicksync.h b/decoder/LAVVideo/decoders/quicksync.h
index f9126eb9..9b94d2bc 100644
--- a/decoder/LAVVideo/decoders/quicksync.h
+++ b/decoder/LAVVideo/decoders/quicksync.h
@@ -47,6 +47,8 @@ public:
STDMETHODIMP PostConnect(IPin *pPin);
+ STDMETHODIMP GetHWAccelActiveDevice(BSTR *pstrDeviceName) { CheckPointer(pstrDeviceName, E_POINTER); *pstrDeviceName = SysAllocString(L"Intel\xae QuickSync"); if (!*pstrDeviceName) return E_OUTOFMEMORY; return S_OK; }
+
// CDecBase
STDMETHODIMP Init();
diff --git a/decoder/LAVVideo/resource.h b/decoder/LAVVideo/resource.h
index cebc6ab6..ec7e5977 100644
--- a/decoder/LAVVideo/resource.h
+++ b/decoder/LAVVideo/resource.h
@@ -89,6 +89,11 @@
#define IDC_HWACCEL_HEVC 1080
#define IDC_HWACCEL_VP9 1081
#define IDC_LBL_SWDEINT_ALGO 1082
+#define IDC_LBL_HWACCEL_DEVICE 1083
+#define IDC_HWACCEL_DEVICE 1084
+#define IDC_HWACCEL_DEVICE_SELECT 1085
+#define IDC_LBL_HWACCEL_DEVICE_SELECT 1086
+#define IDC_LBL_HWACCEL_DEVICE_HINT 1087
// Next default values for new objects
//
@@ -96,7 +101,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 111
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1083
+#define _APS_NEXT_CONTROL_VALUE 1088
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif