diff options
author | Alex Marsev <alex.marsev@gmail.com> | 2015-08-25 17:08:36 +0300 |
---|---|---|
committer | Underground78 <underground78@users.sourceforge.net> | 2015-09-24 22:57:37 +0300 |
commit | adca201f0b6fe9a437f32e7285d93e03b7759e7d (patch) | |
tree | fa51ba0b7b1f7e15ff8cb8388e3a3723124c0af5 | |
parent | 41c6940cc34572922f412fc6b7d795bb8092cd0f (diff) |
Tweak 10bit IPin hook
Delegate rejection to LAV Video Decoder in order to support 10bit DXVA decoding.
Resolves #151.
-rw-r--r-- | src/filters/renderer/VideoRenderers/IPinHook.cpp | 42 | ||||
-rw-r--r-- | src/filters/renderer/VideoRenderers/IPinHook.h | 4 | ||||
-rw-r--r-- | src/mpc-hc/FGFilter.cpp | 10 | ||||
-rw-r--r-- | src/mpc-hc/FGFilter.h | 2 |
4 files changed, 28 insertions, 30 deletions
diff --git a/src/filters/renderer/VideoRenderers/IPinHook.cpp b/src/filters/renderer/VideoRenderers/IPinHook.cpp index f01efeca5..2e85648a9 100644 --- a/src/filters/renderer/VideoRenderers/IPinHook.cpp +++ b/src/filters/renderer/VideoRenderers/IPinHook.cpp @@ -29,6 +29,8 @@ #include "IPinHook.h"
#include "AllocatorCommon.h"
+#include "../../../mpc-hc/FGFilterLAV.h"
+
#define DXVA_LOGFILE_A 0 // set to 1 for logging DXVA data to a file
#define LOG_BITSTREAM 0 // set to 1 for logging DXVA bitstream data to a file
#define LOG_MATRIX 0 // set to 1 for logging DXVA matrix data to a file
@@ -47,7 +49,7 @@ GUID g_guidDXVADecoder = GUID_NULL; int g_nDXVAVersion = 0;
IPinCVtbl* g_pPinCVtbl = nullptr;
-IPinCVtbl* g_pPinCVtblVideoDriverWorkAround = nullptr;
+IPinCVtbl* g_pPinCVtbl10BitWorkAround = nullptr;
IMemInputPinCVtbl* g_pMemInputPinCVtbl = nullptr;
struct D3DFORMAT_TYPE {
@@ -153,12 +155,15 @@ static HRESULT(STDMETHODCALLTYPE* ReceiveConnectionOrg)(IPinC* This, /* [in] */ static HRESULT STDMETHODCALLTYPE ReceiveConnectionMine(IPinC* This, /* [in] */ IPinC* pConnector, /* [in] */ const AM_MEDIA_TYPE* pmt)
{
- // Force the renderer to always reject the P010 and P016 pixel formats
+ // Force-reject P010 and P016 pixel formats due to Microsoft bug ...
if (pmt && (pmt->subtype == MEDIASUBTYPE_P010 || pmt->subtype == MEDIASUBTYPE_P016)) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- } else {
- return ReceiveConnectionOrg(This, pConnector, pmt);
+ // ... but allow LAV Video Decoder to do that itself in order to support 10bit DXVA.
+ if (GetCLSID((IPin*)pConnector) != GUID_LAVVideo) {
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ }
}
+
+ return ReceiveConnectionOrg(This, pConnector, pmt);
}
@@ -184,15 +189,8 @@ static HRESULT STDMETHODCALLTYPE ReceiveMine(IMemInputPinC* This, IMediaSample* return ReceiveMineI(This, pSample);
}
-void HookWorkAroundVideoDriversBug(IBaseFilter* pBF)
+void HookWorkAround10BitBug(IBaseFilter* pBF)
{
- // Work-around a bug in some video drivers: some drivers mistakenly
- // accepts P010 and P016 pixel formats as input for VMR/EVR renderers
- // so use the pin hook to add our own level of verification.
-#if MPC_VERSION_MAJOR > 1 || MPC_VERSION_MINOR > 7 || MPC_VERSION_PATCH > 9
-#pragma message("WARNING: Check if this bug is fixed in currently distributed drivers")
-#endif
-
if (CComPtr<IPin> pPin = GetFirstPin(pBF)) {
IPinC* pPinC = (IPinC*)(IPin*)pPin;
@@ -204,7 +202,7 @@ void HookWorkAroundVideoDriversBug(IBaseFilter* pBF) pPinC->lpVtbl->ReceiveConnection = ReceiveConnectionMine;
FlushInstructionCache(GetCurrentProcess(), pPinC->lpVtbl, sizeof(IPinCVtbl));
VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
- g_pPinCVtblVideoDriverWorkAround = pPinC->lpVtbl;
+ g_pPinCVtbl10BitWorkAround = pPinC->lpVtbl;
} else {
TRACE(_T("HookWorkAroundVideoDriversBug: Could not hook the VTable"));
ASSERT(FALSE);
@@ -212,19 +210,19 @@ void HookWorkAroundVideoDriversBug(IBaseFilter* pBF) }
}
-void UnhookWorkAroundVideoDriversBug()
+void UnhookWorkAround10BitBug()
{
// Unhook previous VTable
- if (g_pPinCVtblVideoDriverWorkAround) {
+ if (g_pPinCVtbl10BitWorkAround) {
DWORD flOldProtect = 0;
- if (VirtualProtect(g_pPinCVtblVideoDriverWorkAround, sizeof(IPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
- if (g_pPinCVtblVideoDriverWorkAround->ReceiveConnection == ReceiveConnectionMine) {
- g_pPinCVtblVideoDriverWorkAround->ReceiveConnection = ReceiveConnectionOrg;
+ if (VirtualProtect(g_pPinCVtbl10BitWorkAround, sizeof(IPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
+ if (g_pPinCVtbl10BitWorkAround->ReceiveConnection == ReceiveConnectionMine) {
+ g_pPinCVtbl10BitWorkAround->ReceiveConnection = ReceiveConnectionOrg;
}
ReceiveConnectionOrg = nullptr;
- FlushInstructionCache(GetCurrentProcess(), g_pPinCVtblVideoDriverWorkAround, sizeof(IPinCVtbl));
- VirtualProtect(g_pPinCVtblVideoDriverWorkAround, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
- g_pPinCVtblVideoDriverWorkAround = nullptr;
+ FlushInstructionCache(GetCurrentProcess(), g_pPinCVtbl10BitWorkAround, sizeof(IPinCVtbl));
+ VirtualProtect(g_pPinCVtbl10BitWorkAround, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
+ g_pPinCVtbl10BitWorkAround = nullptr;
} else {
TRACE(_T("UnhookWorkAroundVideoDriversBug: Could not unhook previous VTable"));
ASSERT(FALSE);
diff --git a/src/filters/renderer/VideoRenderers/IPinHook.h b/src/filters/renderer/VideoRenderers/IPinHook.h index adb5f8d83..7425224a9 100644 --- a/src/filters/renderer/VideoRenderers/IPinHook.h +++ b/src/filters/renderer/VideoRenderers/IPinHook.h @@ -76,8 +76,8 @@ extern bool HookNewSegmentAndReceive(IPinC* pPinC, IMemInputPinC* pMemInputPin); extern void UnhookNewSegmentAndReceive();
extern REFERENCE_TIME g_tSegmentStart, g_tSampleStart, g_rtTimePerFrame;
-extern void HookWorkAroundVideoDriversBug(IBaseFilter* pBF);
-extern void UnhookWorkAroundVideoDriversBug();
+extern void HookWorkAround10BitBug(IBaseFilter* pBF);
+extern void UnhookWorkAround10BitBug();
//
diff --git a/src/mpc-hc/FGFilter.cpp b/src/mpc-hc/FGFilter.cpp index c52373a13..46de4918f 100644 --- a/src/mpc-hc/FGFilter.cpp +++ b/src/mpc-hc/FGFilter.cpp @@ -428,15 +428,15 @@ HRESULT CFGFilterFile::Create(IBaseFilter** ppBF, CInterfaceList<IUnknown, &IID_ CFGFilterVideoRenderer::CFGFilterVideoRenderer(HWND hWnd, const CLSID& clsid, CStringW name, UINT64 merit)
: CFGFilter(clsid, name, merit)
, m_hWnd(hWnd)
- , m_bHasVideoDriverWorkAround(false)
+ , m_bHas10BitWorkAround(false)
{
AddType(MEDIATYPE_Video, MEDIASUBTYPE_NULL);
}
CFGFilterVideoRenderer::~CFGFilterVideoRenderer()
{
- if (m_bHasVideoDriverWorkAround) {
- UnhookWorkAroundVideoDriversBug();
+ if (m_bHas10BitWorkAround) {
+ UnhookWorkAround10BitBug();
}
}
@@ -513,8 +513,8 @@ HRESULT CFGFilterVideoRenderer::Create(IBaseFilter** ppBF, CInterfaceList<IUnkno CheckPointer(*ppBF, E_FAIL);
if (m_clsid != CLSID_madVRAllocatorPresenter) {
- HookWorkAroundVideoDriversBug(*ppBF);
- m_bHasVideoDriverWorkAround = true;
+ HookWorkAround10BitBug(*ppBF);
+ m_bHas10BitWorkAround = true;
}
return hr;
diff --git a/src/mpc-hc/FGFilter.h b/src/mpc-hc/FGFilter.h index abec238fc..a0c035bab 100644 --- a/src/mpc-hc/FGFilter.h +++ b/src/mpc-hc/FGFilter.h @@ -124,7 +124,7 @@ class CFGFilterVideoRenderer : public CFGFilter {
protected:
HWND m_hWnd;
- bool m_bHasVideoDriverWorkAround;
+ bool m_bHas10BitWorkAround;
public:
CFGFilterVideoRenderer(HWND hWnd, const CLSID& clsid, CStringW name = L"", UINT64 merit = MERIT64_DO_USE);
|