Added patch for MPEG2/H264 DXVA2 video decoding through vaapi.

This commit is contained in:
Michael Müller 2015-02-22 04:08:15 +01:00
parent 8f19269b34
commit 44ea94f633
13 changed files with 6016 additions and 459 deletions

View File

@ -38,7 +38,7 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [16]:**
**Bugfixes and features included in the next upcoming release [18]:**
* Add semi-stub for GetFileVersionInfoExA/W ([Wine Bug #38098](https://bugs.winehq.org/show_bug.cgi?id=38098))
* Add semi-stub for GetFileVersionInfoSizeExA/W ([Wine Bug #38090](https://bugs.winehq.org/show_bug.cgi?id=38090))
@ -55,6 +55,8 @@ Included bug fixes and improvements
* Implement ntoskrnl.KeInitializeMutex
* Improve stubs for AEV_{Get,Set}MasterVolumeLevel
* Improve stubs for AEV_{Get,Set}Mute
* Support for H264 DXVA2 GPU video decoding through vaapi
* Support for MPEG2 DXVA2 GPU video decoding through vaapi
* Support for non-blocking SIO_ADDRESS_LIST_CHANGE requests ([Wine Bug #38062](https://bugs.winehq.org/show_bug.cgi?id=38062))

1
debian/changelog vendored
View File

@ -20,6 +20,7 @@ wine-staging (1.7.37) UNRELEASED; urgency=low
* Added patch to add stub for ntoskrnl.Mm{Map,Unmap}LockedPages.
* Added patch to implement ntoskrnl.KeInitializeMutex.
* Added patch for support of non-blocking SIO_ADDRESS_LIST_CHANGE requests.
* Added patch for MPEG2/H264 DXVA2 video decoding through vaapi.
* Removed patches for UTF7 support (accepted upstream).
* Removed patches for SIO_ADDRESS_LIST_CHANGE ioctl (accepted upstream).
* Removed patch for IApplicationAssociationRegistration::QueryCurrentDefault (accepted upstream).

View File

@ -0,0 +1,302 @@
From 65f573c73dbb07f534c66fa7a6738576872cf322 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 10 Feb 2015 16:34:05 +0100
Subject: dxva2: Implement semi-stub for Direct3DDeviceManager9 interface.
---
dlls/dxva2/Makefile.in | 4 +-
dlls/dxva2/devicemanager.c | 212 +++++++++++++++++++++++++++++++++++++++++++++
dlls/dxva2/dxva2_private.h | 21 +++++
dlls/dxva2/main.c | 7 +-
4 files changed, 241 insertions(+), 3 deletions(-)
create mode 100644 dlls/dxva2/devicemanager.c
create mode 100644 dlls/dxva2/dxva2_private.h
diff --git a/dlls/dxva2/Makefile.in b/dlls/dxva2/Makefile.in
index 7b9ef6f..ffa7fe8 100644
--- a/dlls/dxva2/Makefile.in
+++ b/dlls/dxva2/Makefile.in
@@ -1,4 +1,6 @@
MODULE = dxva2.dll
+IMPORTS = ole32
C_SRCS = \
- main.c
+ main.c \
+ devicemanager.c
diff --git a/dlls/dxva2/devicemanager.c b/dlls/dxva2/devicemanager.c
new file mode 100644
index 0000000..15d78aa
--- /dev/null
+++ b/dlls/dxva2/devicemanager.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2014 Sebastian Lackner for Pipelight
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+
+#define COBJMACROS
+#include "d3d9.h"
+#include "dxva2api.h"
+#include "dxva2_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+
+typedef struct
+{
+ IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface;
+ LONG refCount;
+ UINT token;
+ IDirect3DDevice9 *device;
+} Direct3DDeviceManager9Impl;
+
+static inline Direct3DDeviceManager9Impl *impl_from_Direct3DDeviceManager9( IDirect3DDeviceManager9 *iface )
+{
+ return CONTAINING_RECORD(iface, Direct3DDeviceManager9Impl, IDirect3DDeviceManager9_iface);
+}
+
+/*****************************************************************************
+ * IDirect3DDeviceManager9 interface
+ */
+
+static HRESULT WINAPI Direct3DDeviceManager9_QueryInterface( IDirect3DDeviceManager9 *iface, REFIID riid, LPVOID *ppv )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+ TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirect3DDeviceManager9))
+ *ppv = &This->IDirect3DDeviceManager9_iface;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Direct3DDeviceManager9_AddRef( IDirect3DDeviceManager9 *iface )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+ ULONG refCount = InterlockedIncrement(&This->refCount);
+
+ TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI Direct3DDeviceManager9_Release( IDirect3DDeviceManager9 *iface )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+ ULONG refCount = InterlockedDecrement(&This->refCount);
+
+ TRACE("(%p)->() Release from %d\n", This, refCount + 1);
+
+ if (!refCount)
+ {
+ TRACE("Destroying\n");
+
+ if (This->device)
+ IDirect3DDevice9_Release(This->device);
+
+ CoTaskMemFree(This);
+ }
+
+ return refCount;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_ResetDevice( IDirect3DDeviceManager9 *iface, IDirect3DDevice9 *pDevice, UINT resetToken )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+
+ FIXME("(%p)->(%p, %u): semi-stub\n", This, pDevice, resetToken);
+
+ if (This->device)
+ return E_FAIL;
+
+ if (resetToken != This->token)
+ return E_INVALIDARG;
+
+ This->device = pDevice;
+ IDirect3DDevice9_AddRef(This->device);
+
+ /* TODO: Reset the device, verify token ... */
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_OpenDeviceHandle( IDirect3DDeviceManager9 *iface, HANDLE *phDevice )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+
+ FIXME("(%p)->(%p): semi-stub\n", This, phDevice);
+
+ *phDevice = (HANDLE)This->device;
+ return S_OK;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_CloseDeviceHandle( IDirect3DDeviceManager9 *iface, HANDLE hDevice )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, hDevice);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_TestDevice( IDirect3DDeviceManager9 *iface, HANDLE hDevice )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+ static int once = 0;
+
+ if (!once++)
+ FIXME("(%p)->(%p): stub\n", This, hDevice);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_LockDevice( IDirect3DDeviceManager9 *iface, HANDLE hDevice, IDirect3DDevice9 **ppDevice, BOOL fBlock )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+
+ FIXME("(%p)->(%p, %p, %d): semi-stub\n", This, hDevice, ppDevice, fBlock);
+
+ *ppDevice = (IDirect3DDevice9 *)hDevice;
+ return S_OK;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_UnlockDevice( IDirect3DDeviceManager9 *iface, HANDLE hDevice, BOOL fSaveState )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+
+ FIXME("(%p)->(%p, %d): stub\n", This, hDevice, fSaveState);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Direct3DDeviceManager9_GetVideoService( IDirect3DDeviceManager9 *iface, HANDLE hDevice, REFIID riid, void **ppService )
+{
+ Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
+
+ FIXME("(%p)->(%p, %p, %p): stub\n", This, hDevice, riid, ppService);
+
+ return E_NOTIMPL;
+}
+
+static const IDirect3DDeviceManager9Vtbl Direct3DDeviceManager9_VTable =
+{
+ Direct3DDeviceManager9_QueryInterface,
+ Direct3DDeviceManager9_AddRef,
+ Direct3DDeviceManager9_Release,
+ Direct3DDeviceManager9_ResetDevice,
+ Direct3DDeviceManager9_OpenDeviceHandle,
+ Direct3DDeviceManager9_CloseDeviceHandle,
+ Direct3DDeviceManager9_TestDevice,
+ Direct3DDeviceManager9_LockDevice,
+ Direct3DDeviceManager9_UnlockDevice,
+ Direct3DDeviceManager9_GetVideoService
+};
+
+HRESULT devicemanager_create( UINT *resetToken, void **ppv )
+{
+ Direct3DDeviceManager9Impl *devicemanager;
+
+ if (!resetToken || !ppv)
+ return E_INVALIDARG;
+
+ *ppv = NULL;
+
+ devicemanager = CoTaskMemAlloc(sizeof(Direct3DDeviceManager9Impl));
+ if (!devicemanager)
+ return E_OUTOFMEMORY;
+
+ devicemanager->IDirect3DDeviceManager9_iface.lpVtbl = &Direct3DDeviceManager9_VTable;
+ devicemanager->refCount = 1;
+ devicemanager->token = 0xdeadbeef; /* FIXME: provide some better value? */
+ devicemanager->device = NULL;
+
+ *resetToken = devicemanager->token;
+ *ppv = devicemanager;
+ return S_OK;
+}
diff --git a/dlls/dxva2/dxva2_private.h b/dlls/dxva2/dxva2_private.h
new file mode 100644
index 0000000..d6e59fc
--- /dev/null
+++ b/dlls/dxva2/dxva2_private.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 Michael Müller for Pipelight
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "dxva2api.h"
+
+extern HRESULT devicemanager_create( UINT *resetToken, void **ppv ) DECLSPEC_HIDDEN;
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c
index b4704f0..e9d43d3 100644
--- a/dlls/dxva2/main.c
+++ b/dlls/dxva2/main.c
@@ -19,8 +19,11 @@
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
+
+#define INITGUID
#include "d3d9.h"
#include "dxva2api.h"
+#include "dxva2_private.h"
#include "physicalmonitorenumerationapi.h"
#include "lowlevelmonitorconfigurationapi.h"
#include "highlevelmonitorconfigurationapi.h"
@@ -39,9 +42,9 @@ BOOL WINAPI CapabilitiesRequestAndCapabilitiesReply( HMONITOR monitor, LPSTR buf
HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9( UINT *resetToken, IDirect3DDeviceManager9 **dxvManager )
{
- FIXME("(%p, %p): stub\n", resetToken, dxvManager);
+ TRACE("(%p, %p)\n", resetToken, dxvManager);
- return E_NOTIMPL;
+ return devicemanager_create( resetToken, (void **)dxvManager );
}
HRESULT WINAPI DXVA2CreateVideoService( IDirect3DDevice9 *device, REFIID riid, void **ppv )
--
2.1.0

View File

@ -0,0 +1,543 @@
From 1b237c190789f62c00be35e5b3916b1bfb6283df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Tue, 10 Feb 2015 16:54:21 +0100
Subject: dxva2: Implement stubbed interfaces for
IDirectXVideo{Acceleration,Decoder,Processor}Service.
---
dlls/dxva2/Makefile.in | 1 +
dlls/dxva2/devicemanager.c | 4 +-
dlls/dxva2/dxva2_private.h | 1 +
dlls/dxva2/main.c | 4 +-
dlls/dxva2/videoservices.c | 467 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 473 insertions(+), 4 deletions(-)
create mode 100644 dlls/dxva2/videoservices.c
diff --git a/dlls/dxva2/Makefile.in b/dlls/dxva2/Makefile.in
index ffa7fe8..02c9758 100644
--- a/dlls/dxva2/Makefile.in
+++ b/dlls/dxva2/Makefile.in
@@ -3,4 +3,5 @@ IMPORTS = ole32
C_SRCS = \
main.c \
+ videoservices.c \
devicemanager.c
diff --git a/dlls/dxva2/devicemanager.c b/dlls/dxva2/devicemanager.c
index 15d78aa..b9ed76c 100644
--- a/dlls/dxva2/devicemanager.c
+++ b/dlls/dxva2/devicemanager.c
@@ -169,9 +169,9 @@ static HRESULT WINAPI Direct3DDeviceManager9_GetVideoService( IDirect3DDeviceMan
{
Direct3DDeviceManager9Impl *This = impl_from_Direct3DDeviceManager9(iface);
- FIXME("(%p)->(%p, %p, %p): stub\n", This, hDevice, riid, ppService);
+ FIXME("(%p)->(%p, %p, %p): semi-stub\n", This, hDevice, riid, ppService);
- return E_NOTIMPL;
+ return videoservice_create( (IDirect3DDevice9 *)hDevice, riid, ppService );
}
static const IDirect3DDeviceManager9Vtbl Direct3DDeviceManager9_VTable =
diff --git a/dlls/dxva2/dxva2_private.h b/dlls/dxva2/dxva2_private.h
index d6e59fc..a88809c 100644
--- a/dlls/dxva2/dxva2_private.h
+++ b/dlls/dxva2/dxva2_private.h
@@ -18,4 +18,5 @@
#include "dxva2api.h"
+extern HRESULT videoservice_create( IDirect3DDevice9 *device, REFIID riid, void **ppv ) DECLSPEC_HIDDEN;
extern HRESULT devicemanager_create( UINT *resetToken, void **ppv ) DECLSPEC_HIDDEN;
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c
index e9d43d3..355e11f 100644
--- a/dlls/dxva2/main.c
+++ b/dlls/dxva2/main.c
@@ -49,9 +49,9 @@ HRESULT WINAPI DXVA2CreateDirect3DDeviceManager9( UINT *resetToken, IDirect3DDev
HRESULT WINAPI DXVA2CreateVideoService( IDirect3DDevice9 *device, REFIID riid, void **ppv )
{
- FIXME("(%p, %s, %p): stub\n", device, debugstr_guid(riid), ppv);
+ TRACE("(%p, %s, %p)\n", device, debugstr_guid(riid), ppv);
- return E_NOTIMPL;
+ return videoservice_create( device, riid, ppv );
}
BOOL WINAPI DegaussMonitor( HMONITOR monitor )
diff --git a/dlls/dxva2/videoservices.c b/dlls/dxva2/videoservices.c
new file mode 100644
index 0000000..936aa37
--- /dev/null
+++ b/dlls/dxva2/videoservices.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2014 Michael Müller for Pipelight
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+
+#define COBJMACROS
+#include "d3d9.h"
+#include "dxva2api.h"
+#include "dxva2_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+
+typedef struct
+{
+ IDirectXVideoAccelerationService IDirectXVideoAccelerationService_iface;
+ IDirectXVideoDecoderService IDirectXVideoDecoderService_iface;
+ IDirectXVideoProcessorService IDirectXVideoProcessorService_iface;
+
+ LONG refCount;
+ IDirect3DDevice9 *device;
+} DirectXVideoAccelerationServiceImpl;
+
+static BOOL is_h264_codec( REFGUID guid )
+{
+ return (IsEqualGUID(guid, &DXVA2_ModeH264_A) ||
+ IsEqualGUID(guid, &DXVA2_ModeH264_B) ||
+ IsEqualGUID(guid, &DXVA2_ModeH264_C) ||
+ IsEqualGUID(guid, &DXVA2_ModeH264_D) ||
+ IsEqualGUID(guid, &DXVA2_ModeH264_E) ||
+ IsEqualGUID(guid, &DXVA2_ModeH264_F));
+}
+
+static inline DirectXVideoAccelerationServiceImpl *impl_from_IDirectXVideoAccelerationService( IDirectXVideoAccelerationService *iface )
+{
+ return CONTAINING_RECORD(iface, DirectXVideoAccelerationServiceImpl, IDirectXVideoAccelerationService_iface);
+}
+
+static inline DirectXVideoAccelerationServiceImpl *impl_from_IDirectXVideoDecoderService( IDirectXVideoDecoderService *iface )
+{
+ return CONTAINING_RECORD(iface, DirectXVideoAccelerationServiceImpl, IDirectXVideoDecoderService_iface);
+}
+
+static inline DirectXVideoAccelerationServiceImpl *impl_from_IDirectXVideoProcessorService( IDirectXVideoProcessorService *iface )
+{
+ return CONTAINING_RECORD(iface, DirectXVideoAccelerationServiceImpl, IDirectXVideoProcessorService_iface);
+}
+
+/*****************************************************************************
+ * IDirectXVideoAccelerationService interface
+ */
+
+static HRESULT WINAPI DirectXVideoAccelerationService_QueryInterface( IDirectXVideoAccelerationService *iface, REFIID riid, LPVOID *ppv )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoAccelerationService(iface);
+ TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = &This->IDirectXVideoAccelerationService_iface;
+ else if (IsEqualIID(riid, &IID_IDirectXVideoAccelerationService))
+ *ppv = &This->IDirectXVideoAccelerationService_iface;
+ else if (IsEqualIID(riid, &IID_IDirectXVideoDecoderService))
+ *ppv = &This->IDirectXVideoDecoderService_iface;
+ else if (IsEqualIID(riid, &IID_IDirectXVideoProcessorService))
+ *ppv = &This->IDirectXVideoProcessorService_iface;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DirectXVideoAccelerationService_AddRef( IDirectXVideoAccelerationService *iface )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoAccelerationService(iface);
+ ULONG refCount = InterlockedIncrement(&This->refCount);
+
+ TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI DirectXVideoAccelerationService_Release( IDirectXVideoAccelerationService *iface )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoAccelerationService(iface);
+ ULONG refCount = InterlockedDecrement(&This->refCount);
+
+ TRACE("(%p)->() Release from %d\n", This, refCount + 1);
+
+ if (!refCount)
+ {
+ TRACE("Destroying\n");
+ IDirect3DDevice9_Release(This->device);
+ CoTaskMemFree(This);
+ }
+
+ return refCount;
+}
+
+static HRESULT WINAPI DirectXVideoAccelerationService_CreateSurface( IDirectXVideoAccelerationService *iface, UINT width, UINT height,
+ UINT backBuffers, D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoAccelerationService(iface);
+ HRESULT hr = S_OK;
+ int i;
+
+ FIXME("(%p)->(%u, %u, %u, %#x, 0x%x, 0x%x, 0x%x, %p, %p): semi-stub\n",
+ This, width, height, backBuffers, format, pool, usage, dxvaType, ppSurface, pSharedHandle);
+
+ /* We create only backbuffers as the front buffer usually does not support this format */
+ for (i = 0; i < backBuffers + 1; i++)
+ {
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->device, width, height, format,
+ pool, &ppSurface[i], pSharedHandle);
+ if (FAILED(hr))
+ {
+ while (i-- > 0)
+ IDirect3DSurface9_Release(ppSurface[i]);
+ return hr;
+ }
+ }
+
+ return S_OK;
+}
+
+static const IDirectXVideoAccelerationServiceVtbl DirectXVideoAccelerationService_VTable =
+{
+ DirectXVideoAccelerationService_QueryInterface,
+ DirectXVideoAccelerationService_AddRef,
+ DirectXVideoAccelerationService_Release,
+ DirectXVideoAccelerationService_CreateSurface
+};
+
+
+/*****************************************************************************
+ * IDirectXVideoDecoderService interface
+ */
+
+static HRESULT WINAPI DirectXVideoDecoderService_QueryInterface( IDirectXVideoDecoderService *iface, REFIID riid, LPVOID *ppv )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+ return DirectXVideoAccelerationService_QueryInterface(&This->IDirectXVideoAccelerationService_iface, riid, ppv);
+}
+
+static ULONG WINAPI DirectXVideoDecoderService_AddRef( IDirectXVideoDecoderService *iface )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ return DirectXVideoAccelerationService_AddRef(&This->IDirectXVideoAccelerationService_iface);
+}
+
+static ULONG WINAPI DirectXVideoDecoderService_Release( IDirectXVideoDecoderService *iface )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ return DirectXVideoAccelerationService_Release(&This->IDirectXVideoAccelerationService_iface);
+}
+
+static HRESULT WINAPI DirectXVideoDecoderService_CreateSurface( IDirectXVideoDecoderService *iface, UINT width, UINT height, UINT backBuffers,
+ D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ FIXME("(%p/%p)->(%u, %u, %u, %#x, 0x%x, 0x%x, 0x%x, %p, %p): stub\n",
+ iface, This, width, height, backBuffers, format, pool, usage, dxvaType, ppSurface, pSharedHandle);
+
+ return DirectXVideoAccelerationService_CreateSurface(&This->IDirectXVideoAccelerationService_iface,
+ width, height, backBuffers, format, pool, usage, dxvaType, ppSurface, pSharedHandle);
+}
+
+static HRESULT WINAPI DirectXVideoDecoderService_CreateVideoDecoder( IDirectXVideoDecoderService *iface, REFGUID guid,
+ const DXVA2_VideoDesc *pVideoDesc, DXVA2_ConfigPictureDecode *pConfig, IDirect3DSurface9 **ppDecoderRenderTargets, UINT NumSurfaces,
+ IDirectXVideoDecoder **ppDecode )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %p, %p, %u, %p): stub\n",
+ iface, This, debugstr_guid(guid), pVideoDesc, pConfig, ppDecoderRenderTargets, NumSurfaces, ppDecode);
+
+ if (!guid || !pVideoDesc || !pConfig || !ppDecoderRenderTargets || !NumSurfaces || !ppDecode)
+ return E_INVALIDARG;
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoDecoderService_GetDecoderConfigurations( IDirectXVideoDecoderService *iface, REFGUID guid,
+ const DXVA2_VideoDesc *pVideoDesc, IUnknown *pReserved, UINT *pCount, DXVA2_ConfigPictureDecode **ppConfigs )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+ DXVA2_ConfigPictureDecode *config;
+
+ FIXME("(%p/%p)->(%s, %p, %p, %p, %p): semi-stub\n",
+ iface, This, debugstr_guid(guid), pVideoDesc, pReserved, pCount, ppConfigs);
+
+ if (!guid || !pVideoDesc || !pCount || !ppConfigs)
+ return E_INVALIDARG;
+
+ config = CoTaskMemAlloc(sizeof(*config));
+ if (!config)
+ return E_OUTOFMEMORY;
+
+ /* TODO: Query decoder instead of using hardcoded values */
+
+ memcpy(&config->guidConfigBitstreamEncryption, &DXVA_NoEncrypt, sizeof(GUID));
+ memcpy(&config->guidConfigMBcontrolEncryption, &DXVA_NoEncrypt, sizeof(GUID));
+ memcpy(&config->guidConfigResidDiffEncryption, &DXVA_NoEncrypt, sizeof(GUID));
+
+ config->ConfigBitstreamRaw = 1;
+ config->ConfigMBcontrolRasterOrder = is_h264_codec(guid) ? 0 : 1;
+ config->ConfigResidDiffHost = 0; /* FIXME */
+ config->ConfigSpatialResid8 = 0; /* FIXME */
+ config->ConfigResid8Subtraction = 0; /* FIXME */
+ config->ConfigSpatialHost8or9Clipping = 0; /* FIXME */
+ config->ConfigSpatialResidInterleaved = 0; /* FIXME */
+ config->ConfigIntraResidUnsigned = 0; /* FIXME */
+ config->ConfigResidDiffAccelerator = 0;
+ config->ConfigHostInverseScan = 0;
+ config->ConfigSpecificIDCT = 1;
+ config->Config4GroupedCoefs = 0;
+ config->ConfigMinRenderTargetBuffCount = 3;
+ config->ConfigDecoderSpecific = 0;
+
+ *pCount = 1;
+ *ppConfigs = config;
+ return S_OK;
+}
+
+static HRESULT WINAPI DirectXVideoDecoderService_GetDecoderDeviceGuids( IDirectXVideoDecoderService *iface, UINT *count, GUID **pGuids )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ FIXME("(%p/%p)->(%p, %p): stub\n", iface, This, count, pGuids);
+
+ if (!count || !pGuids)
+ return E_INVALIDARG;
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoDecoderService_GetDecoderRenderTargets( IDirectXVideoDecoderService *iface, REFGUID guid,
+ UINT *pCount, D3DFORMAT **pFormats )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoDecoderService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %p): stub\n", iface, This, debugstr_guid(guid), pCount, pFormats);
+
+ if (!guid || !pCount || !pFormats)
+ return E_INVALIDARG;
+
+ return E_NOTIMPL;
+}
+
+static const IDirectXVideoDecoderServiceVtbl DirectXVideoDecoderService_VTable =
+{
+ DirectXVideoDecoderService_QueryInterface,
+ DirectXVideoDecoderService_AddRef,
+ DirectXVideoDecoderService_Release,
+ DirectXVideoDecoderService_CreateSurface,
+ DirectXVideoDecoderService_GetDecoderDeviceGuids,
+ DirectXVideoDecoderService_GetDecoderRenderTargets,
+ DirectXVideoDecoderService_GetDecoderConfigurations,
+ DirectXVideoDecoderService_CreateVideoDecoder
+};
+
+/*****************************************************************************
+ * IDirectXVideoProcessorService interface
+ */
+
+static HRESULT WINAPI DirectXVideoProcessorService_QueryInterface( IDirectXVideoProcessorService *iface, REFIID riid, LPVOID *ppv )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+ return DirectXVideoAccelerationService_QueryInterface(&This->IDirectXVideoAccelerationService_iface, riid, ppv);
+}
+
+static ULONG WINAPI DirectXVideoProcessorService_AddRef( IDirectXVideoProcessorService *iface )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ return DirectXVideoAccelerationService_AddRef(&This->IDirectXVideoAccelerationService_iface);
+}
+
+static ULONG WINAPI DirectXVideoProcessorService_Release( IDirectXVideoProcessorService *iface )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ return DirectXVideoAccelerationService_Release(&This->IDirectXVideoAccelerationService_iface);
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_CreateSurface( IDirectXVideoProcessorService *iface, UINT width, UINT height,
+ UINT backBuffers, D3DFORMAT format, D3DPOOL pool, DWORD usage, DWORD dxvaType, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%u, %u, %u, %#x, 0x%x, 0x%x, 0x%x, %p, %p): stub\n",
+ iface, This, width, height, backBuffers, format, pool, usage, dxvaType, ppSurface, pSharedHandle);
+
+ return DirectXVideoAccelerationService_CreateSurface(&This->IDirectXVideoAccelerationService_iface,
+ width, height, backBuffers, format, pool, usage, dxvaType, ppSurface, pSharedHandle);
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_RegisterVideoProcessorSoftwareDevice( IDirectXVideoProcessorService *iface, void *pCallbacks)
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%p): stub\n", iface, This, pCallbacks);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorDeviceGuids( IDirectXVideoProcessorService *iface,
+ const DXVA2_VideoDesc *pVideoDesc, UINT *pCount, GUID **pGuids )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%p, %p, %p): stub\n", iface, This, pVideoDesc, pCount, pGuids);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorRenderTargets( IDirectXVideoProcessorService *iface,
+ REFGUID VideoProcDeviceGuid, const DXVA2_VideoDesc *pVideoDesc, UINT *pCount, D3DFORMAT **pFormats )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %p, %p): stub\n",
+ iface, This, debugstr_guid(VideoProcDeviceGuid), pVideoDesc, pCount, pFormats);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorSubStreamFormats( IDirectXVideoProcessorService *iface,
+ REFGUID VideoProcDeviceGuid, const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat, UINT *pCount, D3DFORMAT **pFormats )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %#x, %p, %p): stub\n",
+ iface, This, debugstr_guid(VideoProcDeviceGuid), pVideoDesc, RenderTargetFormat, pCount, pFormats);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorCaps( IDirectXVideoProcessorService *iface, REFGUID VideoProcDeviceGuid,
+ const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat, DXVA2_VideoProcessorCaps *pCaps)
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %#x, %p): stub\n",
+ iface, This, debugstr_guid(VideoProcDeviceGuid), pVideoDesc, RenderTargetFormat, pCaps);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_GetProcAmpRange( IDirectXVideoProcessorService *iface, REFGUID VideoProcDeviceGuid,
+ const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat, UINT ProcAmpCap, DXVA2_ValueRange *pRange )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %#x, %u, %p): stub\n",
+ iface, This, debugstr_guid(VideoProcDeviceGuid), pVideoDesc, RenderTargetFormat, ProcAmpCap, pRange);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_GetFilterPropertyRange( IDirectXVideoProcessorService *iface, REFGUID VideoProcDeviceGuid,
+ const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat, UINT FilterSetting, DXVA2_ValueRange *pRange )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%s, %p, %#x, %u, %p): stub\n",
+ iface, This, debugstr_guid(VideoProcDeviceGuid), pVideoDesc, RenderTargetFormat, FilterSetting, pRange);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessorService_CreateVideoProcessor( IDirectXVideoProcessorService *iface, REFGUID VideoProcDeviceGuid,
+ const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat, UINT MaxNumSubStreams, IDirectXVideoProcessor **ppVidProcess )
+{
+ DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+
+ FIXME("(%p/%p)->(%s, %#x, %u, %p): stub\n",
+ iface, This, debugstr_guid(VideoProcDeviceGuid), RenderTargetFormat, MaxNumSubStreams, ppVidProcess);
+
+ return E_NOTIMPL;
+}
+
+static const IDirectXVideoProcessorServiceVtbl DirectXVideoProcessorService_VTable =
+{
+ DirectXVideoProcessorService_QueryInterface,
+ DirectXVideoProcessorService_AddRef,
+ DirectXVideoProcessorService_Release,
+ DirectXVideoProcessorService_CreateSurface,
+ DirectXVideoProcessorService_RegisterVideoProcessorSoftwareDevice,
+ DirectXVideoProcessorService_GetVideoProcessorDeviceGuids,
+ DirectXVideoProcessorService_GetVideoProcessorRenderTargets,
+ DirectXVideoProcessorService_GetVideoProcessorSubStreamFormats,
+ DirectXVideoProcessorService_GetVideoProcessorCaps,
+ DirectXVideoProcessorService_GetProcAmpRange,
+ DirectXVideoProcessorService_GetFilterPropertyRange,
+ DirectXVideoProcessorService_CreateVideoProcessor
+};
+
+HRESULT videoservice_create( IDirect3DDevice9 *device, REFIID riid, void **ppv )
+{
+ DirectXVideoAccelerationServiceImpl *videoservice;
+
+ if (!device || !riid || !ppv)
+ return E_INVALIDARG;
+
+ *ppv = NULL;
+
+ videoservice = CoTaskMemAlloc(sizeof(DirectXVideoAccelerationServiceImpl));
+ if (!videoservice)
+ return E_OUTOFMEMORY;
+
+ videoservice->IDirectXVideoAccelerationService_iface.lpVtbl = &DirectXVideoAccelerationService_VTable;
+ videoservice->IDirectXVideoDecoderService_iface.lpVtbl = &DirectXVideoDecoderService_VTable;
+ videoservice->IDirectXVideoProcessorService_iface.lpVtbl = &DirectXVideoProcessorService_VTable;
+ videoservice->refCount = 1;
+ videoservice->device = device;
+
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = &videoservice->IDirectXVideoAccelerationService_iface;
+ else if (IsEqualIID(riid, &IID_IDirectXVideoAccelerationService))
+ *ppv = &videoservice->IDirectXVideoAccelerationService_iface;
+ else if (IsEqualIID(riid, &IID_IDirectXVideoDecoderService))
+ *ppv = &videoservice->IDirectXVideoDecoderService_iface;
+ else if (IsEqualIID(riid, &IID_IDirectXVideoProcessorService))
+ *ppv = &videoservice->IDirectXVideoProcessorService_iface;
+ else
+ {
+ CoTaskMemFree(videoservice);
+ return E_NOINTERFACE;
+ }
+
+ IDirect3DDevice9_AddRef(device);
+ return S_OK;
+}
--
2.1.0

View File

@ -0,0 +1,25 @@
From 7fda9638073cbf136c87bfcac507a067c2159b3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 21 Feb 2015 14:49:30 +0100
Subject: include: Fix an invalid UUID in dxva2api.idl.
---
include/dxva2api.idl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/dxva2api.idl b/include/dxva2api.idl
index ebd508b..7a29157 100644
--- a/include/dxva2api.idl
+++ b/include/dxva2api.idl
@@ -434,7 +434,7 @@ interface IDirectXVideoDecoder : IUnknown
*/
[
object,
- uuid(fc51a551-d5e7-11d9-af55-00054e43ff02),
+ uuid(fc51a552-d5e7-11d9-af55-00054e43ff02),
local
]
interface IDirectXVideoProcessorService : IDirectXVideoAccelerationService
--
2.1.0

View File

@ -0,0 +1,310 @@
From 7cc3c032cb2c18e5adf1f4cb6da3c2f731a092c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 21 Feb 2015 15:06:03 +0100
Subject: dxva2: Implement stubbed DirectX Software VideoProcessor interface.
---
dlls/dxva2/Makefile.in | 3 +-
dlls/dxva2/dxva2_private.h | 3 +
dlls/dxva2/softwareprocessor.c | 209 +++++++++++++++++++++++++++++++++++++++++
dlls/dxva2/videoservices.c | 17 +++-
include/dxva2api.idl | 5 +
5 files changed, 234 insertions(+), 3 deletions(-)
create mode 100644 dlls/dxva2/softwareprocessor.c
diff --git a/dlls/dxva2/Makefile.in b/dlls/dxva2/Makefile.in
index 02c9758..4af9dc0 100644
--- a/dlls/dxva2/Makefile.in
+++ b/dlls/dxva2/Makefile.in
@@ -4,4 +4,5 @@ IMPORTS = ole32
C_SRCS = \
main.c \
videoservices.c \
- devicemanager.c
+ devicemanager.c \
+ softwareprocessor.c
diff --git a/dlls/dxva2/dxva2_private.h b/dlls/dxva2/dxva2_private.h
index a88809c..f0068b6 100644
--- a/dlls/dxva2/dxva2_private.h
+++ b/dlls/dxva2/dxva2_private.h
@@ -20,3 +20,6 @@
extern HRESULT videoservice_create( IDirect3DDevice9 *device, REFIID riid, void **ppv ) DECLSPEC_HIDDEN;
extern HRESULT devicemanager_create( UINT *resetToken, void **ppv ) DECLSPEC_HIDDEN;
+extern HRESULT processor_software_create( IDirectXVideoProcessorService *processor_service, IDirect3DDevice9 *device,
+ const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat,
+ UINT MaxNumSubStreams, IDirectXVideoProcessor **processor ) DECLSPEC_HIDDEN;
diff --git a/dlls/dxva2/softwareprocessor.c b/dlls/dxva2/softwareprocessor.c
new file mode 100644
index 0000000..d396248
--- /dev/null
+++ b/dlls/dxva2/softwareprocessor.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2015 Michael Müller for Pipelight
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+
+#define COBJMACROS
+#include "d3d9.h"
+#include "dxva2api.h"
+#include "dxva2_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+
+typedef struct
+{
+ IDirectXVideoProcessor IDirectXVideoProcessor_iface;
+ LONG refCount;
+
+ IDirectXVideoProcessorService *service;
+ IDirect3DDevice9 *device;
+} DirectXVideoProcessorImpl;
+
+static inline DirectXVideoProcessorImpl *impl_from_IDirectXVideoProcessor( IDirectXVideoProcessor *iface )
+{
+ return CONTAINING_RECORD(iface, DirectXVideoProcessorImpl, IDirectXVideoProcessor_iface);
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_QueryInterface( IDirectXVideoProcessor *iface, REFIID riid, LPVOID *ppv )
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+ TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectXVideoProcessor))
+ *ppv = (LPVOID)iface;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DirectXVideoProcessor_AddRef( IDirectXVideoProcessor *iface )
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+ ULONG refCount = InterlockedIncrement(&This->refCount);
+
+ TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI DirectXVideoProcessor_Release( IDirectXVideoProcessor *iface )
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+ ULONG refCount = InterlockedDecrement(&This->refCount);
+
+ TRACE("(%p)->() Release from %d\n", This, refCount + 1);
+
+ if (!refCount)
+ {
+ TRACE("Destroying\n");
+
+ IDirectXVideoProcessorService_Release(This->service);
+ IDirect3DDevice9_Release(This->device);
+
+ CoTaskMemFree(This);
+ }
+
+ return refCount;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetVideoProcessorService(IDirectXVideoProcessor *iface,
+ IDirectXVideoProcessorService** ppService)
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, ppService);
+
+ if (!ppService)
+ return E_INVALIDARG;
+
+ IDirectXVideoProcessorService_AddRef(This->service);
+ *ppService = This->service;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetCreationParameters(IDirectXVideoProcessor *iface,
+ GUID* pDeviceGuid, DXVA2_VideoDesc* pVideoDesc,
+ D3DFORMAT* pRenderTargetFormat,
+ UINT* pMaxNumSubStreams)
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+ FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pDeviceGuid, pVideoDesc, pRenderTargetFormat, pMaxNumSubStreams);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetVideoProcessorCaps(IDirectXVideoProcessor *iface,
+ DXVA2_VideoProcessorCaps* pCaps)
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, pCaps);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetProcAmpRange(IDirectXVideoProcessor *iface, UINT ProcAmpCap,
+ DXVA2_ValueRange* pRange)
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+ FIXME("(%p)->(%u, %p): stub\n", This, ProcAmpCap, pRange);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetFilterPropertyRange(IDirectXVideoProcessor *iface,
+ UINT FilterSetting, DXVA2_ValueRange* pRange)
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+ FIXME("(%p)->(%u, %p): stub\n", This, FilterSetting, pRange);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_VideoProcessBlt(IDirectXVideoProcessor *iface, IDirect3DSurface9* pRenderTarget,
+ const DXVA2_VideoProcessBltParams* pBltParams,
+ const DXVA2_VideoSample* pSamples, UINT NumSamples,
+ HANDLE* complete)
+{
+ DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+ TRACE("(%p)->(%p, %p, %p, %u, %p)\n", This, pRenderTarget, pBltParams, pSamples, NumSamples, complete);
+
+ if (!pRenderTarget || !pBltParams || !pSamples)
+ return E_INVALIDARG;
+
+ if (NumSamples > 1)
+ FIXME("Deinterlacing not implemented, expect horrible video output!\n");
+
+ return IDirect3DDevice9_StretchRect(This->device, pSamples[0].SrcSurface, &pSamples[0].SrcRect,
+ pRenderTarget, &pSamples[0].DstRect, D3DTEXF_LINEAR);
+}
+
+static const IDirectXVideoProcessorVtbl DirectXVideoProcessor_VTable =
+{
+ DirectXVideoProcessor_QueryInterface,
+ DirectXVideoProcessor_AddRef,
+ DirectXVideoProcessor_Release,
+ DirectXVideoProcessor_GetVideoProcessorService,
+ DirectXVideoProcessor_GetCreationParameters,
+ DirectXVideoProcessor_GetVideoProcessorCaps,
+ DirectXVideoProcessor_GetProcAmpRange,
+ DirectXVideoProcessor_GetFilterPropertyRange,
+ DirectXVideoProcessor_VideoProcessBlt
+};
+
+HRESULT processor_software_create( IDirectXVideoProcessorService *processor_service, IDirect3DDevice9 *device,
+ const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat,
+ UINT MaxNumSubStreams, IDirectXVideoProcessor **processor )
+{
+ DirectXVideoProcessorImpl *software_processor;
+
+ if (!processor_service || !pVideoDesc)
+ return E_INVALIDARG;
+
+ software_processor = CoTaskMemAlloc(sizeof(*software_processor));
+ if (!software_processor)
+ return E_OUTOFMEMORY;
+
+ software_processor->IDirectXVideoProcessor_iface.lpVtbl = &DirectXVideoProcessor_VTable;
+ software_processor->refCount = 1;
+ software_processor->service = processor_service;
+ software_processor->device = device;
+
+ IDirectXVideoProcessorService_AddRef(processor_service);
+ IDirect3DDevice9_AddRef(device);
+
+ *processor = &software_processor->IDirectXVideoProcessor_iface;
+ return S_OK;
+}
diff --git a/dlls/dxva2/videoservices.c b/dlls/dxva2/videoservices.c
index 936aa37..46e431a 100644
--- a/dlls/dxva2/videoservices.c
+++ b/dlls/dxva2/videoservices.c
@@ -341,10 +341,20 @@ static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorDeviceGuids(
const DXVA2_VideoDesc *pVideoDesc, UINT *pCount, GUID **pGuids )
{
DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+ GUID *guids;
FIXME("(%p/%p)->(%p, %p, %p): stub\n", iface, This, pVideoDesc, pCount, pGuids);
- return E_NOTIMPL;
+ guids = CoTaskMemAlloc(sizeof(GUID));
+ if(!guids)
+ return E_OUTOFMEMORY;
+
+ memcpy(guids, &DXVA2_VideoProcSoftwareDevice, sizeof(GUID));
+
+ *pGuids = guids;
+ *pCount = 1;
+
+ return S_OK;
}
static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorRenderTargets( IDirectXVideoProcessorService *iface,
@@ -407,9 +417,12 @@ static HRESULT WINAPI DirectXVideoProcessorService_CreateVideoProcessor( IDirect
{
DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
- FIXME("(%p/%p)->(%s, %#x, %u, %p): stub\n",
+ FIXME("(%p/%p)->(%s, %#x, %u, %p): semi-stub\n",
iface, This, debugstr_guid(VideoProcDeviceGuid), RenderTargetFormat, MaxNumSubStreams, ppVidProcess);
+ if (IsEqualIID(VideoProcDeviceGuid, &DXVA2_VideoProcSoftwareDevice))
+ return processor_software_create(iface, This->device, pVideoDesc, RenderTargetFormat, MaxNumSubStreams, ppVidProcess);
+
return E_NOTIMPL;
}
diff --git a/include/dxva2api.idl b/include/dxva2api.idl
index 7a29157..7388b37 100644
--- a/include/dxva2api.idl
+++ b/include/dxva2api.idl
@@ -86,6 +86,11 @@ cpp_quote("#define DXVA2_ModeVC1_VLD DXVA2_ModeVC1_D")
/* Encryption */
cpp_quote("DEFINE_GUID(DXVA_NoEncrypt, 0x1b81bed0, 0xa0c7,0x11d3, 0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);")
+/* Video Processor */
+cpp_quote("DEFINE_GUID(DXVA2_VideoProcProgressiveDevice, 0x5a54a0c9, 0xc7ec,0x4bd9, 0x8e, 0xde, 0xf3, 0xc7, 0x5d, 0xc4, 0x39, 0x3b);")
+cpp_quote("DEFINE_GUID(DXVA2_VideoProcBobDevice, 0x335aa36e, 0x7884,0x43a4, 0x9c, 0x91, 0x7f, 0x87, 0xfa, 0xf3, 0xe3, 0x7e);")
+cpp_quote("DEFINE_GUID(DXVA2_VideoProcSoftwareDevice, 0x4553d47f, 0xee7e,0x4e3f, 0x94, 0x75, 0xdb, 0xf1, 0x37, 0x6c, 0x48, 0x10);")
+
typedef LONGLONG REFERENCE_TIME;
enum
--
2.1.0

View File

@ -0,0 +1,247 @@
From a871b5881c5e01ec46f49cb181d504c61765558d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 22 Feb 2015 01:10:21 +0100
Subject: include: Add dxva.h header file.
---
include/Makefile.in | 1 +
include/dxva.h | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 216 insertions(+)
create mode 100644 include/dxva.h
diff --git a/include/Makefile.in b/include/Makefile.in
index 02d5d88..2b7943a 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -314,6 +314,7 @@ SRCDIR_INCLUDES = \
dxfile.h \
dxgiformat.h \
dxgitype.h \
+ dxva.h \
dyngraph.idl \
errorrep.h \
errors.h \
diff --git a/include/dxva.h b/include/dxva.h
new file mode 100644
index 0000000..e311488
--- /dev/null
+++ b/include/dxva.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2015 Michael Müller for Pipelight
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_DXVA_H
+#define __WINE_DXVA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DXVA_USUAL_BLOCK_WIDTH 8
+#define DXVA_USUAL_BLOCK_HEIGHT 8
+#define DXVA_USUAL_BLOCK_SIZE (DXVA_USUAL_BLOCK_WIDTH * DXVA_USUAL_BLOCK_HEIGHT)
+
+#include <pshpack1.h>
+
+typedef struct _DXVA_PictureParameters
+{
+ WORD wDecodedPictureIndex;
+ WORD wDeblockedPictureIndex;
+ WORD wForwardRefPictureIndex;
+ WORD wBackwardRefPictureIndex;
+ WORD wPicWidthInMBminus1;
+ WORD wPicHeightInMBminus1;
+ BYTE bMacroblockWidthMinus1;
+ BYTE bMacroblockHeightMinus1;
+ BYTE bBlockWidthMinus1;
+ BYTE bBlockHeightMinus1;
+ BYTE bBPPminus1;
+ BYTE bPicStructure;
+ BYTE bSecondField;
+ BYTE bPicIntra;
+ BYTE bPicBackwardPrediction;
+ BYTE bBidirectionalAveragingMode;
+ BYTE bMVprecisionAndChromaRelation;
+ BYTE bChromaFormat;
+ BYTE bPicScanFixed;
+ BYTE bPicScanMethod;
+ BYTE bPicReadbackRequests;
+ BYTE bRcontrol;
+ BYTE bPicSpatialResid8;
+ BYTE bPicOverflowBlocks;
+ BYTE bPicExtrapolation;
+ BYTE bPicDeblocked;
+ BYTE bPicDeblockConfined;
+ BYTE bPic4MVallowed;
+ BYTE bPicOBMC;
+ BYTE bPicBinPB;
+ BYTE bMV_RPS;
+ BYTE bReservedBits;
+ WORD wBitstreamFcodes;
+ WORD wBitstreamPCEelements;
+ BYTE bBitstreamConcealmentNeed;
+ BYTE bBitstreamConcealmentMethod;
+} DXVA_PictureParameters, *LPDXVA_PictureParameters;
+
+typedef struct _DXVA_SliceInfo
+{
+ WORD wHorizontalPosition;
+ WORD wVerticalPosition;
+ DWORD dwSliceBitsInBuffer;
+ DWORD dwSliceDataLocation;
+ BYTE bStartCodeBitOffset;
+ BYTE bReservedBits;
+ WORD wMBbitOffset;
+ WORD wNumberMBsInSlice;
+ WORD wQuantizerScaleCode;
+ WORD wBadSliceChopping;
+} DXVA_SliceInfo, *LPDXVA_SliceInfo;
+
+typedef struct _DXVA_QmatrixData
+{
+ BYTE bNewQmatrix[4];
+ WORD Qmatrix[4][DXVA_USUAL_BLOCK_WIDTH * DXVA_USUAL_BLOCK_HEIGHT];
+} DXVA_QmatrixData, *LPDXVA_QmatrixData;
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ UCHAR Index7Bits : 7;
+ UCHAR AssociatedFlag : 1;
+ };
+ UCHAR bPicEntry;
+ };
+} DXVA_PicEntry_H264;
+
+typedef struct
+{
+ USHORT wFrameWidthInMbsMinus1;
+ USHORT wFrameHeightInMbsMinus1;
+ DXVA_PicEntry_H264 CurrPic;
+ UCHAR num_ref_frames;
+ union
+ {
+ struct
+ {
+ USHORT field_pic_flag : 1;
+ USHORT MbaffFrameFlag : 1;
+ USHORT residual_colour_transform_flag : 1;
+ USHORT sp_for_switch_flag : 1;
+ USHORT chroma_format_idc : 2;
+ USHORT RefPicFlag : 1;
+ USHORT constrained_intra_pred_flag : 1;
+ USHORT weighted_pred_flag : 1;
+ USHORT weighted_bipred_idc : 2;
+ USHORT MbsConsecutiveFlag : 1;
+ USHORT frame_mbs_only_flag : 1;
+ USHORT transform_8x8_mode_flag : 1;
+ USHORT MinLumaBipredSize8x8Flag : 1;
+ USHORT IntraPicFlag : 1;
+ };
+ USHORT wBitFields;
+ };
+ UCHAR bit_depth_luma_minus8;
+ UCHAR bit_depth_chroma_minus8;
+ USHORT Reserved16Bits;
+ UINT StatusReportFeedbackNumber;
+ DXVA_PicEntry_H264 RefFrameList[16];
+ INT CurrFieldOrderCnt[2];
+ INT FieldOrderCntList[16][2];
+ CHAR pic_init_qs_minus26;
+ CHAR chroma_qp_index_offset;
+ CHAR second_chroma_qp_index_offset;
+ UCHAR ContinuationFlag;
+ CHAR pic_init_qp_minus26;
+ UCHAR num_ref_idx_l0_active_minus1;
+ UCHAR num_ref_idx_l1_active_minus1;
+ UCHAR Reserved8BitsA;
+ USHORT FrameNumList[16];
+
+ UINT UsedForReferenceFlags;
+ USHORT NonExistingFrameFlags;
+ USHORT frame_num;
+ UCHAR log2_max_frame_num_minus4;
+ UCHAR pic_order_cnt_type;
+ UCHAR log2_max_pic_order_cnt_lsb_minus4;
+ UCHAR delta_pic_order_always_zero_flag;
+ UCHAR direct_8x8_inference_flag;
+ UCHAR entropy_coding_mode_flag;
+ UCHAR pic_order_present_flag;
+ UCHAR num_slice_groups_minus1;
+ UCHAR slice_group_map_type;
+ UCHAR deblocking_filter_control_present_flag;
+ UCHAR redundant_pic_cnt_present_flag;
+ UCHAR Reserved8BitsB;
+ USHORT slice_group_change_rate_minus1;
+ UCHAR SliceGroupMap[810];
+} DXVA_PicParams_H264;
+
+typedef struct
+{
+ UCHAR bScalingLists4x4[6][16];
+ UCHAR bScalingLists8x8[2][64];
+} DXVA_Qmatrix_H264;
+
+typedef struct
+{
+ UINT BSNALunitDataLocation;
+ UINT SliceBytesInBuffer;
+ USHORT wBadSliceChopping;
+ USHORT first_mb_in_slice;
+ USHORT NumMbsForSlice;
+ USHORT BitOffsetToSliceData;
+ UCHAR slice_type;
+ UCHAR luma_log2_weight_denom;
+ UCHAR chroma_log2_weight_denom;
+
+ UCHAR num_ref_idx_l0_active_minus1;
+ UCHAR num_ref_idx_l1_active_minus1;
+ CHAR slice_alpha_c0_offset_div2;
+ CHAR slice_beta_offset_div2;
+ UCHAR Reserved8Bits;
+ DXVA_PicEntry_H264 RefPicList[2][32];
+ SHORT Weights[2][32][3][2];
+ CHAR slice_qs_delta;
+ CHAR slice_qp_delta;
+ UCHAR redundant_pic_cnt;
+ UCHAR direct_spatial_mv_pred_flag;
+ UCHAR cabac_init_idc;
+ UCHAR disable_deblocking_filter_idc;
+ USHORT slice_id;
+} DXVA_Slice_H264_Long;
+
+typedef struct
+{
+ UINT BSNALunitDataLocation;
+ UINT SliceBytesInBuffer;
+ USHORT wBadSliceChopping;
+} DXVA_Slice_H264_Short;
+
+#include <poppack.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WINE_DXVA_H */
--
2.1.0

View File

@ -0,0 +1,416 @@
From d8850f844e13d73a850219a12b330bdbe3e995fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 22 Feb 2015 01:21:18 +0100
Subject: dxva2/tests: Add tests for dxva2 decoder.
---
configure.ac | 1 +
dlls/dxva2/tests/Makefile.in | 5 +
dlls/dxva2/tests/dxva2.c | 371 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 377 insertions(+)
create mode 100644 dlls/dxva2/tests/Makefile.in
create mode 100644 dlls/dxva2/tests/dxva2.c
diff --git a/configure.ac b/configure.ac
index f611fa5..22b46ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2941,6 +2941,7 @@ WINE_CONFIG_DLL(dxgi,,[implib])
WINE_CONFIG_TEST(dlls/dxgi/tests)
WINE_CONFIG_LIB(dxguid)
WINE_CONFIG_DLL(dxva2)
+WINE_CONFIG_TEST(dlls/dxva2/tests)
WINE_CONFIG_DLL(evr)
WINE_CONFIG_DLL(explorerframe,,[clean])
WINE_CONFIG_TEST(dlls/explorerframe/tests)
diff --git a/dlls/dxva2/tests/Makefile.in b/dlls/dxva2/tests/Makefile.in
new file mode 100644
index 0000000..10d6af5
--- /dev/null
+++ b/dlls/dxva2/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL = dxva2.dll
+IMPORTS = d3d9 user32 ole32
+
+C_SRCS = \
+ dxva2.c
diff --git a/dlls/dxva2/tests/dxva2.c b/dlls/dxva2/tests/dxva2.c
new file mode 100644
index 0000000..dcbb990
--- /dev/null
+++ b/dlls/dxva2/tests/dxva2.c
@@ -0,0 +1,371 @@
+/*
+ * Unit tests for dxva2 functions
+ *
+ * Copyright 2015 Michael Müller
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+
+#define COBJMACROS
+#define INITGUID
+#include "d3d9.h"
+#include "dxva2api.h"
+#include "dxva.h"
+
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
+struct decoder_name
+{
+ const GUID *guid;
+ const char *name;
+};
+
+struct decoder_name decoder_names[] =
+{
+ /* H.264 */
+ {&DXVA2_ModeH264_A, "H.264 MoComp"},
+ {&DXVA2_ModeH264_B, "H.264 MoComp, FGT"},
+ {&DXVA2_ModeH264_C, "H.264 IDCT"},
+ {&DXVA2_ModeH264_D, "H.264 IDCT, FGT"},
+ {&DXVA2_ModeH264_E, "H.264 VLD, no FGT"},
+ {&DXVA2_ModeH264_F, "H.264 VLD, FGT"},
+
+ /* MPEG 2 */
+ {&DXVA2_ModeMPEG2_IDCT, "MPEG-2 IDCT"},
+ {&DXVA2_ModeMPEG2_MoComp, "MPEG-2 MoComp"},
+ {&DXVA2_ModeMPEG2_VLD, "MPEG-2 VLD"},
+
+ /* VC-1 */
+ {&DXVA2_ModeVC1_A, "VC-1 post processing"},
+ {&DXVA2_ModeVC1_B, "VC-1 MoComp"},
+ {&DXVA2_ModeVC1_C, "VC-1 IDCT"},
+ {&DXVA2_ModeVC1_D, "VC-1 VLD"},
+
+ /* WMV8 */
+ {&DXVA2_ModeWMV8_A, "WMV 8 post processing"},
+ {&DXVA2_ModeWMV8_B, "WMV 8 MoComp"},
+
+ /* WMV9 */
+ {&DXVA2_ModeWMV9_A, "WMV 9 post processing"},
+ {&DXVA2_ModeWMV9_B, "WMV 9 MoComp"},
+ {&DXVA2_ModeWMV9_C, "WMV 9 IDCT"},
+};
+
+struct decoder_test
+{
+ const GUID *guid;
+ UINT width;
+ UINT height;
+ UINT surface_count;
+ BOOL supported;
+};
+
+struct decoder_test decoder_tests[] =
+{
+ {&DXVA2_ModeMPEG2_VLD, 720, 576, 3, FALSE},
+ {&DXVA2_ModeH264_E, 720, 576, 17, FALSE},
+};
+
+static const char* convert_decoderguid_to_str(const GUID *guid)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(decoder_names) / sizeof(decoder_names[0]); i++)
+ {
+ if (IsEqualGUID(guid, decoder_names[i].guid))
+ return decoder_names[i].name;
+ }
+
+ return wine_dbgstr_guid(guid);
+}
+
+HRESULT (WINAPI* pDXVA2CreateVideoService)(IDirect3DDevice9 *device, REFIID riid, void **ppv);
+
+static BOOL init_dxva2(void)
+{
+ HMODULE dxva2 = LoadLibraryA("dxva2.dll");
+ if (!dxva2)
+ {
+ win_skip("dxva2.dll not available\n");
+ return FALSE;
+ }
+
+ pDXVA2CreateVideoService = (void *)GetProcAddress(dxva2, "DXVA2CreateVideoService");
+ return TRUE;
+}
+
+static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window)
+{
+ D3DPRESENT_PARAMETERS present_parameters = {0};
+ IDirect3DDevice9 *device;
+ DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
+
+ present_parameters.BackBufferWidth = 640;
+ present_parameters.BackBufferHeight = 480;
+ present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+ present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ present_parameters.hDeviceWindow = focus_window;
+ present_parameters.Windowed = TRUE;
+ present_parameters.EnableAutoDepthStencil = FALSE;
+
+ if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
+ behavior_flags, &present_parameters, &device)))
+ return device;
+
+ return NULL;
+}
+
+static BOOL create_video_service(HWND focus_window, REFIID riid, void **service)
+{
+ IDirect3DDevice9 *device;
+ IDirect3D9 *d3d9;
+ HRESULT hr;
+
+ d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ if (!d3d9) return FALSE;
+
+ device = create_device(d3d9, focus_window);
+ IDirect3D9_Release(d3d9);
+ if(!device)
+ return FALSE;
+
+ hr = pDXVA2CreateVideoService(device, riid, service);
+ IDirect3DDevice9_Release(device);
+ if (hr) return FALSE;
+
+ return TRUE;
+}
+
+static inline void test_buffer(IDirectXVideoDecoder *decoder, UINT type, const char *name)
+{
+ void *buffer;
+ UINT size;
+ HRESULT hr;
+
+ hr = IDirectXVideoDecoder_GetBuffer(decoder, type, &buffer, &size);
+ ok(!hr, "Failed to get buffer %s: %x\n", name, hr);
+ if (!hr) IDirectXVideoDecoder_ReleaseBuffer(decoder, type);
+}
+
+static void test_decoding(IDirectXVideoDecoder *decoder, REFGUID const guid, IDirect3DSurface9 **surfaces)
+{
+ HRESULT hr;
+
+ hr = IDirectXVideoDecoder_BeginFrame(decoder, surfaces[0], NULL);
+ ok(!hr, "Failed to begin frame for: %s\n", convert_decoderguid_to_str(guid));
+ if (hr) return;
+
+ test_buffer(decoder, DXVA2_PictureParametersBufferType, "DXVA2_PictureParametersBuffer");
+ test_buffer(decoder, DXVA2_InverseQuantizationMatrixBufferType, "DXVA2_InverseQuantizationMatrixBuffer");
+ test_buffer(decoder, DXVA2_SliceControlBufferType, "DXVA2_SliceControlBuffer");
+ test_buffer(decoder, DXVA2_BitStreamDateBufferType, "DXVA2_BitStreamDateBuffer");
+
+ IDirectXVideoDecoder_EndFrame(decoder, NULL);
+}
+
+static void test_decoder_resolution(IDirectXVideoDecoderService *service, REFGUID const guid, D3DFORMAT format,
+ UINT width, UINT height, UINT surface_count)
+{
+ HRESULT hr;
+ DXVA2_VideoDesc desc;
+ UINT count;
+ DXVA2_ConfigPictureDecode *configs;
+ DXVA2_ConfigPictureDecode config;
+ IDirect3DSurface9 **surfaces;
+ IDirectXVideoDecoder *decoder;
+ unsigned int i;
+
+ trace("Analysing buffer sizes for: %s (%u x %u)\n", convert_decoderguid_to_str(guid), width, height);
+
+ memset(&desc, 0, sizeof(desc));
+
+ desc.SampleWidth = width;
+ desc.SampleHeight = height;
+ desc.Format = format;
+ desc.InputSampleFreq.Numerator = 25;
+ desc.InputSampleFreq.Denominator = 1;
+ desc.OutputFrameFreq.Numerator = 25;
+ desc.OutputFrameFreq.Denominator = 1;
+
+ if (0) /* crashes on windows */
+ {
+ hr = IDirectXVideoDecoderService_GetDecoderConfigurations(service, guid, &desc, NULL, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", hr);
+
+ hr = IDirectXVideoDecoderService_GetDecoderConfigurations(service, guid, &desc, NULL, &count, NULL);
+ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", hr);
+
+ hr = IDirectXVideoDecoderService_GetDecoderConfigurations(service, guid, &desc, NULL, NULL, &configs);
+ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", hr);
+ }
+
+ hr = IDirectXVideoDecoderService_GetDecoderConfigurations(service, &GUID_NULL, &desc, NULL, &count, &configs);
+ ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %x\n", hr);
+
+ hr = IDirectXVideoDecoderService_GetDecoderConfigurations(service, guid, &desc, NULL, &count, &configs);
+ ok(!hr, "Failed to get decoder configuration for: %s\n", convert_decoderguid_to_str(guid));
+ if (hr) return;
+
+ if (!count)
+ {
+ skip("Decoder for %s does not support a single decoder configuration? Skipping test\n",
+ convert_decoderguid_to_str(guid));
+ return;
+ }
+
+ memcpy(&config, &configs[0], sizeof(config));
+ CoTaskMemFree(configs);
+
+ surfaces = (void*)HeapAlloc(GetProcessHeap(), 0, surface_count * sizeof(IDirect3DSurface9));
+ if (!surfaces)
+ {
+ skip("Failed to allocate memory for surfaces\n");
+ return;
+ }
+
+ hr = IDirectXVideoDecoderService_CreateSurface(service, width, height, surface_count-1, format, D3DPOOL_DEFAULT, 0,
+ DXVA2_VideoDecoderRenderTarget, surfaces, NULL);
+ ok(!hr, "Failed to create surfaces: %x\n", hr);
+ if (hr)
+ {
+ HeapFree(GetProcessHeap(), 0, surfaces);
+ return;
+ }
+
+ hr = IDirectXVideoDecoderService_CreateVideoDecoder(service, guid, &desc, &configs[0], surfaces, surface_count, &decoder);
+ ok(!hr, "Failed to create decoder for %s: %x\n", convert_decoderguid_to_str(guid), hr);
+ if (!hr)
+ {
+ test_decoding(decoder, guid, surfaces);
+ IDirectXVideoDecoder_Release(decoder);
+ }
+
+ for (i = 0; i < surface_count; i++)
+ IDirect3DSurface9_Release(surfaces[i]);
+
+ HeapFree(GetProcessHeap(), 0, surfaces);
+}
+
+static void test_decoder(IDirectXVideoDecoderService *service, REFGUID const guid, UINT width, UINT height,
+ UINT surface_count)
+{
+ HRESULT hr;
+ D3DFORMAT *formats;
+ D3DFORMAT test_format;
+ UINT count;
+
+ if (0) /* crashes on windows */
+ {
+ hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(service, guid, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", hr);
+
+ hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(service, guid, &count, NULL);
+ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", hr);
+
+ hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(service, guid, NULL, &formats);
+ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %x\n", hr);
+ }
+
+ hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(service, &GUID_NULL, &count, &formats);
+ ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %x\n", hr);
+
+ hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(service, guid, &count, &formats);
+ ok(!hr, "Failed to get formats for codec %s\n", convert_decoderguid_to_str(guid));
+ if (hr) return;
+
+ if (!count)
+ {
+ skip("Decoder for %s does not support a single output format? Skipping test\n",
+ convert_decoderguid_to_str(guid));
+ return;
+ }
+
+ test_format = formats[0];
+ CoTaskMemFree(formats);
+
+ test_decoder_resolution(service, guid, test_format, width, height, surface_count);
+}
+
+static void test_decoder_service(HWND focus_window)
+{
+ IDirectXVideoDecoderService *service;
+ unsigned int i, j;
+ HRESULT hr;
+ UINT count;
+ GUID *guids;
+
+ if (!create_video_service(focus_window, &IID_IDirectXVideoDecoderService, (void**)&service))
+ {
+ skip("Failed to create video decoder service, skipping decoder service tests\n");
+ return;
+ }
+
+ hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(service, &count, &guids);
+ if (hr)
+ {
+ skip("Failed to get decoder guids: %x\n", hr);
+ return;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ trace("supported codec: %s\n", convert_decoderguid_to_str(&guids[i]));
+
+ for (j = 0; j < sizeof(decoder_tests) / sizeof(decoder_tests[0]); j++)
+ {
+ if (IsEqualGUID(&guids[i], decoder_tests[j].guid))
+ decoder_tests[j].supported = TRUE;
+ }
+ }
+
+ CoTaskMemFree(guids);
+
+ for (i = 0; i < sizeof(decoder_tests) / sizeof(decoder_tests[0]); i++)
+ {
+ if (!decoder_tests[i].supported)
+ {
+ skip("Decoder %s not supported, skipping test\n", convert_decoderguid_to_str(decoder_tests[i].guid));
+ continue;
+ }
+
+ test_decoder(service, decoder_tests[i].guid, decoder_tests[i].width,
+ decoder_tests[i].height, decoder_tests[i].surface_count);
+ }
+
+ IDirectXVideoDecoderService_Release(service);
+}
+
+START_TEST(dxva2)
+{
+ HWND window;
+
+ if (!init_dxva2())
+ return;
+
+ window = CreateWindowA("static", "dxva2_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, NULL, NULL, NULL, NULL);
+
+ ok(window != NULL, "couldn't create window\n");
+ if (!window) return;
+
+ test_decoder_service(window);
+}
--
2.1.0

View File

@ -0,0 +1,949 @@
From b4de3e81cdf0ba928d75455c871742d86920de13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 22 Feb 2015 01:43:36 +0100
Subject: dxva2: Implement h264 decoder.
---
dlls/dxva2/Makefile.in | 1 +
dlls/dxva2/dxva2_private.h | 3 +
dlls/dxva2/vaapi-h264.c | 890 +++++++++++++++++++++++++++++++++++++++++++++
dlls/dxva2/vaapi.c | 2 +
4 files changed, 896 insertions(+)
create mode 100644 dlls/dxva2/vaapi-h264.c
diff --git a/dlls/dxva2/Makefile.in b/dlls/dxva2/Makefile.in
index 808173c..69ce4c8 100644
--- a/dlls/dxva2/Makefile.in
+++ b/dlls/dxva2/Makefile.in
@@ -10,5 +10,6 @@ C_SRCS = \
main.c \
softwareprocessor.c \
vaapi.c \
+ vaapi-h264.c \
vaapi-mpeg2.c \
videoservices.c \
diff --git a/dlls/dxva2/dxva2_private.h b/dlls/dxva2/dxva2_private.h
index f518637..5df59bd 100644
--- a/dlls/dxva2/dxva2_private.h
+++ b/dlls/dxva2/dxva2_private.h
@@ -134,5 +134,8 @@ extern BOOL vaapi_create_surfaces( VADisplay va_display, const struct vaapi_form
extern HRESULT vaapi_mpeg2decoder_create( IWineVideoService *backend, const DXVA2_VideoDesc *videoDesc,
DXVA2_ConfigPictureDecode *config, UINT numSurfaces,
IWineVideoDecoder **decoder ) DECLSPEC_HIDDEN;
+extern HRESULT vaapi_h264decoder_create( IWineVideoService *service, const DXVA2_VideoDesc *videoDesc,
+ DXVA2_ConfigPictureDecode *config, UINT numSurfaces,
+ IWineVideoDecoder **decoder ) DECLSPEC_HIDDEN;
#endif /* HAVE_VAAPI */
diff --git a/dlls/dxva2/vaapi-h264.c b/dlls/dxva2/vaapi-h264.c
new file mode 100644
index 0000000..1a5817e
--- /dev/null
+++ b/dlls/dxva2/vaapi-h264.c
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2014-2015 Michael Müller for Pipelight
+ * Copyright 2014-2015 Sebastian Lackner for Pipelight
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include <stdarg.h>
+#include <assert.h>
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+
+#define COBJMACROS
+#include "d3d9.h"
+#include "dxva2api.h"
+#include "dxva.h"
+#include "dxva2_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+
+#ifdef HAVE_VAAPI
+
+#define MAX_SLICES 4096
+
+#define SLICE_TYPE_P 0
+#define SLICE_TYPE_B 1
+#define SLICE_TYPE_I 2
+#define SLICE_TYPE_SP 3
+#define SLICE_TYPE_SI 4
+
+static inline UINT estimate_maximum_slice_size( UINT width, UINT height )
+{
+ return (2 * width * height * min(width, height)) / max(width, height);
+}
+
+typedef struct
+{
+ IWineVideoDecoder IWineVideoDecoder_iface;
+ LONG refCount;
+ IWineVideoService *service;
+
+ /* video attributes */
+ UINT width;
+ UINT height;
+ D3DFORMAT format;
+ DWORD maxSliceSize;
+ VAImage vaImage;
+
+ /* surfaces used by this decoder */
+ UINT surfaceCount;
+ VASurfaceID *surfaces;
+ UINT currentSurface;
+
+ /* configuration and context of the decoder */
+ VAConfigID config;
+ VAContextID context;
+
+ /* slice buffer id */
+ VABufferID vaBitstream;
+ DXVA_PicParams_H264 d3dPictureParam;
+ DXVA_Qmatrix_H264 d3dQMatrix;
+ DXVA_Slice_H264_Long d3dSliceInfo[MAX_SLICES];
+} WineVideoDecoderH264Impl;
+
+/* caller has to hold the vaapi_lock */
+static HRESULT process_picture_parameters( WineVideoDecoderH264Impl *This, const DXVA2_DecodeBufferDesc *desc )
+{
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAPictureParameterBufferH264 params;
+ VABufferID vaPictureParam;
+ VAStatus status;
+ unsigned int i;
+
+ if (desc->DataSize != sizeof(This->d3dPictureParam))
+ FIXME("unexpected picture parameter buffer size %u\n", desc->DataSize);
+
+ /* check for valid parameters */
+ if (This->d3dPictureParam.CurrPic.Index7Bits > This->surfaceCount)
+ {
+ ERR("invalid picture reference index\n");
+ return E_FAIL;
+ }
+
+ if (!This->d3dPictureParam.ContinuationFlag)
+ FIXME("ContinuationFlag = 0 unsupported, decoding may fail\n");
+
+
+ memset(&params, 0, sizeof(params));
+
+ params.CurrPic.picture_id = This->surfaces[This->d3dPictureParam.CurrPic.Index7Bits];
+ params.CurrPic.frame_idx = This->d3dPictureParam.frame_num; /* FIXME - guessed */
+
+ if (This->d3dPictureParam.field_pic_flag)
+ params.CurrPic.flags = This->d3dPictureParam.CurrPic.AssociatedFlag ? VA_PICTURE_H264_BOTTOM_FIELD : VA_PICTURE_H264_TOP_FIELD;
+
+ if (This->d3dPictureParam.RefPicFlag)
+ params.CurrPic.flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+ /* FIXME: Distinguish between short term and longterm references */
+
+ params.CurrPic.TopFieldOrderCnt = This->d3dPictureParam.CurrFieldOrderCnt[0] & 0xffff;
+ params.CurrPic.BottomFieldOrderCnt = This->d3dPictureParam.CurrFieldOrderCnt[1] & 0xffff;
+
+ for (i = 0; i < 16; i++)
+ {
+ unsigned int flags = 0;
+
+ if (This->d3dPictureParam.RefFrameList[i].Index7Bits == 127)
+ {
+ params.ReferenceFrames[i].picture_id = VA_INVALID_ID;
+ params.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
+ continue;
+ }
+
+ if (This->d3dPictureParam.RefFrameList[i].Index7Bits >= This->surfaceCount)
+ {
+ FIXME("Out of range reference picture!\n");
+ params.ReferenceFrames[i].picture_id = VA_INVALID_ID;
+ params.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
+ continue;
+ }
+
+ params.ReferenceFrames[i].picture_id = This->surfaces[This->d3dPictureParam.RefFrameList[i].Index7Bits];
+ params.ReferenceFrames[i].frame_idx = This->d3dPictureParam.FrameNumList[i];
+
+ /* TODO: check flag conversion again */
+ if (This->d3dPictureParam.UsedForReferenceFlags & (1 << (2 * i + 0)))
+ flags |= VA_PICTURE_H264_TOP_FIELD;
+
+ if (This->d3dPictureParam.UsedForReferenceFlags & (1 << (2 * i + 1)))
+ flags |= VA_PICTURE_H264_BOTTOM_FIELD;
+
+ if (flags & VA_PICTURE_H264_TOP_FIELD || flags & VA_PICTURE_H264_BOTTOM_FIELD)
+ {
+ if (This->d3dPictureParam.RefFrameList[i].AssociatedFlag)
+ flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
+ else
+ flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+ }
+
+ /* remove top and bottom field flag if we got a full frame */
+ if ((flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) ==
+ (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD))
+ {
+ flags &= ~(VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD);
+ }
+
+ params.ReferenceFrames[i].flags = flags;
+
+ params.ReferenceFrames[i].TopFieldOrderCnt = This->d3dPictureParam.FieldOrderCntList[i][0] & 0xFFFF;
+ params.ReferenceFrames[i].BottomFieldOrderCnt = This->d3dPictureParam.FieldOrderCntList[i][1] & 0xFFFF;
+ }
+
+ params.picture_width_in_mbs_minus1 = This->d3dPictureParam.wFrameWidthInMbsMinus1;
+ params.picture_height_in_mbs_minus1 = This->d3dPictureParam.wFrameHeightInMbsMinus1;
+ params.bit_depth_luma_minus8 = This->d3dPictureParam.bit_depth_luma_minus8;
+ params.bit_depth_chroma_minus8 = This->d3dPictureParam.bit_depth_chroma_minus8;
+ params.num_ref_frames = This->d3dPictureParam.num_ref_frames;
+
+ params.seq_fields.bits.chroma_format_idc = This->d3dPictureParam.chroma_format_idc;
+ params.seq_fields.bits.residual_colour_transform_flag = This->d3dPictureParam.residual_colour_transform_flag;
+ params.seq_fields.bits.gaps_in_frame_num_value_allowed_flag = FALSE; /* FIXME */
+ params.seq_fields.bits.frame_mbs_only_flag = This->d3dPictureParam.frame_mbs_only_flag;
+ params.seq_fields.bits.mb_adaptive_frame_field_flag = This->d3dPictureParam.MbaffFrameFlag;
+ params.seq_fields.bits.direct_8x8_inference_flag = This->d3dPictureParam.direct_8x8_inference_flag;
+ params.seq_fields.bits.MinLumaBiPredSize8x8 = This->d3dPictureParam.MinLumaBipredSize8x8Flag;
+ params.seq_fields.bits.log2_max_frame_num_minus4 = This->d3dPictureParam.log2_max_frame_num_minus4;
+ params.seq_fields.bits.pic_order_cnt_type = This->d3dPictureParam.pic_order_cnt_type;
+ params.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = This->d3dPictureParam.log2_max_pic_order_cnt_lsb_minus4;
+ params.seq_fields.bits.delta_pic_order_always_zero_flag = This->d3dPictureParam.delta_pic_order_always_zero_flag;
+
+ params.num_slice_groups_minus1 = This->d3dPictureParam.num_slice_groups_minus1;
+ params.slice_group_map_type = This->d3dPictureParam.slice_group_map_type;
+ params.slice_group_change_rate_minus1 = This->d3dPictureParam.slice_group_change_rate_minus1;
+ params.pic_init_qp_minus26 = This->d3dPictureParam.pic_init_qp_minus26;
+ params.pic_init_qs_minus26 = This->d3dPictureParam.pic_init_qs_minus26;
+ params.chroma_qp_index_offset = This->d3dPictureParam.chroma_qp_index_offset;
+ params.second_chroma_qp_index_offset = This->d3dPictureParam.second_chroma_qp_index_offset;
+ params.pic_fields.bits.entropy_coding_mode_flag = This->d3dPictureParam.entropy_coding_mode_flag;
+
+ params.pic_fields.bits.weighted_pred_flag = This->d3dPictureParam.weighted_pred_flag;
+ params.pic_fields.bits.weighted_bipred_idc = This->d3dPictureParam.weighted_bipred_idc;
+ params.pic_fields.bits.transform_8x8_mode_flag = This->d3dPictureParam.transform_8x8_mode_flag;
+ params.pic_fields.bits.field_pic_flag = This->d3dPictureParam.field_pic_flag;
+ params.pic_fields.bits.constrained_intra_pred_flag = This->d3dPictureParam.constrained_intra_pred_flag;
+ params.pic_fields.bits.pic_order_present_flag = This->d3dPictureParam.pic_order_present_flag;
+ params.pic_fields.bits.deblocking_filter_control_present_flag = This->d3dPictureParam.deblocking_filter_control_present_flag;
+ params.pic_fields.bits.redundant_pic_cnt_present_flag = This->d3dPictureParam.redundant_pic_cnt_present_flag;
+ params.pic_fields.bits.reference_pic_flag = This->d3dPictureParam.RefPicFlag;
+
+ params.frame_num = This->d3dPictureParam.frame_num;
+
+ status = pvaCreateBuffer(va_display, This->context, VAPictureParameterBufferType,
+ sizeof(params), 1, &params, &vaPictureParam);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to create picture parameter buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ return E_FAIL;
+ }
+
+ /* vaRenderPicture is supposed to destroy the buffer */
+ status = pvaRenderPicture(va_display, This->context, &vaPictureParam, 1);
+ if (status == VA_STATUS_SUCCESS)
+ return S_OK;
+
+ ERR("failed to process picture parameter buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ pvaDestroyBuffer(va_display, vaPictureParam);
+ return E_FAIL;
+}
+
+/* caller has to hold the vaapi_lock */
+static HRESULT process_quantization_matrix( WineVideoDecoderH264Impl *This, const DXVA2_DecodeBufferDesc *desc )
+{
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAIQMatrixBufferH264 matrix;
+ VABufferID vaIQMatrix;
+ VAStatus status;
+
+ if (desc->DataSize != sizeof(This->d3dQMatrix))
+ FIXME("unexpected quantization matrix buffer size %u\n", desc->DataSize);
+
+ memcpy(&matrix.ScalingList4x4, &This->d3dQMatrix.bScalingLists4x4, sizeof(matrix.ScalingList4x4));
+ memcpy(&matrix.ScalingList8x8, &This->d3dQMatrix.bScalingLists8x8, sizeof(matrix.ScalingList8x8));
+
+ status = pvaCreateBuffer(va_display, This->context, VAIQMatrixBufferType,
+ sizeof(matrix), 1, &matrix, &vaIQMatrix);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to create quantization matrix buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ return E_FAIL;
+ }
+
+ /* vaRenderPicture is supposed to destroy the buffer */
+ status = pvaRenderPicture(va_display, This->context, &vaIQMatrix, 1);
+ if (status == VA_STATUS_SUCCESS)
+ return S_OK;
+
+ ERR("failed to process quantization matrix buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ pvaDestroyBuffer(va_display, vaIQMatrix);
+ return E_FAIL;
+}
+
+static void fill_reference_picture( WineVideoDecoderH264Impl *This, VAPictureH264 *pic, DXVA_PicEntry_H264 *dxva_pic )
+{
+ unsigned int i;
+
+ pic->picture_id = dxva_pic->Index7Bits < This->surfaceCount ? This->surfaces[dxva_pic->Index7Bits] : VA_INVALID_ID;
+ pic->frame_idx = 0;
+
+ if (This->d3dPictureParam.field_pic_flag)
+ pic->flags = dxva_pic->AssociatedFlag ? VA_PICTURE_H264_BOTTOM_FIELD : VA_PICTURE_H264_TOP_FIELD;
+ else
+ pic->flags = 0;
+
+ pic->TopFieldOrderCnt = 0;
+ pic->BottomFieldOrderCnt = 0;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (This->d3dPictureParam.RefFrameList[i].Index7Bits != dxva_pic->Index7Bits)
+ continue;
+
+ if ((This->d3dPictureParam.UsedForReferenceFlags & (1 << (2 * i + 0))) ||
+ (This->d3dPictureParam.UsedForReferenceFlags & (1 << (2 * i + 1))))
+ {
+ if (This->d3dPictureParam.RefFrameList[i].AssociatedFlag)
+ pic->flags |= VA_PICTURE_H264_LONG_TERM_REFERENCE;
+ else
+ pic->flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+ }
+
+ pic->frame_idx = This->d3dPictureParam.FrameNumList[i];
+ pic->TopFieldOrderCnt = This->d3dPictureParam.FieldOrderCntList[i][0] & 0xFFFF;
+ pic->BottomFieldOrderCnt = This->d3dPictureParam.FieldOrderCntList[i][1] & 0xFFFF;
+
+ return;
+ }
+
+ WARN("Reference not found!\n");
+}
+
+/* caller has to hold the vaapi_lock */
+static HRESULT process_slice_control_buffer( WineVideoDecoderH264Impl *This, const DXVA2_DecodeBufferDesc *desc )
+{
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VASliceParameterBufferH264 *slice = NULL;
+ VABufferID vaSliceInfo;
+ VAStatus status;
+ unsigned int sliceCount, i, j;
+
+ /* check for valid parameters */
+ if (!desc->DataSize || desc->DataSize % sizeof(DXVA_Slice_H264_Long) != 0)
+ {
+ ERR("slice control buffer size is invalid (got %u, expected multiple of %lu)\n",
+ desc->DataSize, (SIZE_T)sizeof(DXVA_Slice_H264_Long));
+ return E_FAIL;
+ }
+
+ sliceCount = desc->DataSize / sizeof(DXVA_Slice_H264_Long);
+
+ status = pvaCreateBuffer(va_display, This->context, VASliceParameterBufferType,
+ sizeof(VASliceParameterBufferH264), sliceCount, NULL, &vaSliceInfo);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to create slice control buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ return E_FAIL;
+ }
+
+ status = pvaMapBuffer(va_display, vaSliceInfo, (void **)&slice);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to map slice control buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ goto err;
+ }
+
+ for (i = 0; i < sliceCount; i++)
+ {
+ slice[i].slice_data_offset = This->d3dSliceInfo[i].BSNALunitDataLocation + 3;
+ slice[i].slice_data_size = This->d3dSliceInfo[i].SliceBytesInBuffer - 3;
+ slice[i].slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
+ slice[i].slice_data_bit_offset = This->d3dSliceInfo[i].BitOffsetToSliceData + 8;
+ slice[i].first_mb_in_slice = This->d3dSliceInfo[i].first_mb_in_slice;
+ slice[i].slice_type = This->d3dSliceInfo[i].slice_type % 5;
+ slice[i].direct_spatial_mv_pred_flag = This->d3dSliceInfo[i].direct_spatial_mv_pred_flag;
+ if (slice[i].slice_type == SLICE_TYPE_I)
+ {
+ slice[i].num_ref_idx_l0_active_minus1 = 0;
+ slice[i].num_ref_idx_l1_active_minus1 = 0;
+ }
+ else
+ {
+ slice[i].num_ref_idx_l0_active_minus1 = This->d3dSliceInfo[i].num_ref_idx_l0_active_minus1;
+ slice[i].num_ref_idx_l1_active_minus1 = This->d3dSliceInfo[i].num_ref_idx_l1_active_minus1;
+ }
+ slice[i].cabac_init_idc = This->d3dSliceInfo[i].cabac_init_idc;
+ slice[i].slice_qp_delta = This->d3dSliceInfo[i].slice_qp_delta;
+ slice[i].disable_deblocking_filter_idc = This->d3dSliceInfo[i].disable_deblocking_filter_idc;
+ slice[i].slice_alpha_c0_offset_div2 = This->d3dSliceInfo[i].slice_alpha_c0_offset_div2;
+ slice[i].slice_beta_offset_div2 = This->d3dSliceInfo[i].slice_beta_offset_div2;
+
+ for (j = 0; j < 32; j++)
+ {
+ if (This->d3dSliceInfo[i].RefPicList[0][j].Index7Bits < This->surfaceCount)
+ fill_reference_picture(This, &slice[i].RefPicList0[j], &This->d3dSliceInfo[i].RefPicList[0][j]);
+ else
+ {
+ slice[i].RefPicList0[j].picture_id = VA_INVALID_ID;
+ slice[i].RefPicList0[j].flags = VA_PICTURE_H264_INVALID;
+ }
+
+ if (This->d3dSliceInfo[i].RefPicList[1][j].Index7Bits < This->surfaceCount)
+ fill_reference_picture(This, &slice[i].RefPicList1[j], &This->d3dSliceInfo[i].RefPicList[1][j]);
+ else
+ {
+ slice[i].RefPicList1[j].picture_id = VA_INVALID_ID;
+ slice[i].RefPicList1[j].flags = VA_PICTURE_H264_INVALID;
+ }
+
+ }
+
+ slice[i].luma_log2_weight_denom = This->d3dSliceInfo[i].luma_log2_weight_denom;
+ slice[i].chroma_log2_weight_denom = This->d3dSliceInfo[i].chroma_log2_weight_denom;
+
+ slice[i].luma_weight_l0_flag = TRUE; /* FIXME */
+ slice[i].chroma_weight_l0_flag = TRUE; /* FIXME */
+ slice[i].luma_weight_l1_flag = TRUE; /* FIXME */
+ slice[i].chroma_weight_l1_flag = TRUE; /* FIXME */
+
+ for (j = 0; j < 32; j++)
+ {
+ slice[i].luma_weight_l0[j] = This->d3dSliceInfo[i].Weights[0][j][0][0];
+ slice[i].luma_offset_l0[j] = This->d3dSliceInfo[i].Weights[0][j][0][1];
+
+ slice[i].chroma_weight_l0[j][0] = This->d3dSliceInfo[i].Weights[0][j][1][0];
+ slice[i].chroma_offset_l0[j][0] = This->d3dSliceInfo[i].Weights[0][j][1][1];
+ slice[i].chroma_weight_l0[j][1] = This->d3dSliceInfo[i].Weights[0][j][2][0];
+ slice[i].chroma_offset_l0[j][1] = This->d3dSliceInfo[i].Weights[0][j][2][1];
+
+ slice[i].luma_weight_l1[j] = This->d3dSliceInfo[i].Weights[1][j][0][0];
+ slice[i].luma_offset_l1[j] = This->d3dSliceInfo[i].Weights[1][j][0][1];
+
+ slice[i].chroma_weight_l1[j][0] = This->d3dSliceInfo[i].Weights[1][j][1][0];
+ slice[i].chroma_offset_l1[j][0] = This->d3dSliceInfo[i].Weights[1][j][1][1];
+ slice[i].chroma_weight_l1[j][1] = This->d3dSliceInfo[i].Weights[1][j][2][0];
+ slice[i].chroma_offset_l1[j][1] = This->d3dSliceInfo[i].Weights[1][j][2][1];
+ }
+ }
+
+ if (pvaUnmapBuffer(va_display, vaSliceInfo) != VA_STATUS_SUCCESS)
+ goto err;
+
+ /* vaRenderPicture is supposed to destroy the buffer */
+ status = pvaRenderPicture(va_display, This->context, &vaSliceInfo, 1);
+ if (status == VA_STATUS_SUCCESS)
+ return S_OK;
+
+ ERR("failed to process slice control buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+
+err:
+ pvaDestroyBuffer(va_display, vaSliceInfo);
+ return E_FAIL;
+}
+
+/* caller has to hold the vaapi_lock */
+static HRESULT process_data_buffer( WineVideoDecoderH264Impl *This, const DXVA2_DecodeBufferDesc *desc )
+{
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+
+ if (This->vaBitstream == VA_INVALID_ID)
+ return E_FAIL;
+
+ /* vaRenderPicture is supposed to destroy the buffer */
+ status = pvaRenderPicture(va_display, This->context, &This->vaBitstream, 1);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to process slice buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ pvaDestroyBuffer(va_display, This->vaBitstream);
+ }
+ else hr = S_OK;
+
+ This->vaBitstream = VA_INVALID_ID;
+ return hr;
+}
+
+static inline WineVideoDecoderH264Impl *impl_from_IWineVideoDecoder( IWineVideoDecoder *iface )
+{
+ return CONTAINING_RECORD(iface, WineVideoDecoderH264Impl, IWineVideoDecoder_iface);
+}
+
+/*****************************************************************************
+ * IWineVideoDecoder interface
+ */
+
+static HRESULT WINAPI WineVideoDecoderH264_QueryInterface( IWineVideoDecoder *iface, REFIID riid, void **ppv )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineVideoDecoder))
+ *ppv = &This->IWineVideoDecoder_iface;
+
+ if (*ppv)
+ {
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
+ }
+
+ FIXME("No interface for %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI WineVideoDecoderH264_AddRef( IWineVideoDecoder *iface )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ ULONG refCount = InterlockedIncrement(&This->refCount);
+
+ TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI WineVideoDecoderH264_Release( IWineVideoDecoder *iface )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ ULONG refCount = InterlockedDecrement(&This->refCount);
+
+ TRACE("(%p)->() Release from %d\n", This, refCount + 1);
+
+ if (!refCount)
+ {
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ TRACE("Destroying\n");
+
+ vaapi_lock();
+
+ if (This->vaBitstream != VA_INVALID_ID)
+ pvaDestroyBuffer(va_display, This->vaBitstream);
+
+ pvaDestroySurfaces(va_display, This->surfaces, This->surfaceCount);
+ HeapFree(GetProcessHeap(), 0, This->surfaces);
+
+ pvaDestroyImage(va_display, This->vaImage.image_id);
+
+ pvaDestroyContext(va_display, This->context);
+ pvaDestroyConfig(va_display, This->config);
+
+ vaapi_unlock();
+
+ IWineVideoService_Release(This->service);
+ CoTaskMemFree(This);
+ }
+
+ return refCount;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_LockBuffer( IWineVideoDecoder *iface, UINT type, void **buffer,
+ UINT *size )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+ void *buf;
+
+ TRACE("(%p, %u, %p, %p)\n", This, type, buffer, size);
+
+ if (type == DXVA2_PictureParametersBufferType)
+ {
+ *buffer = &This->d3dPictureParam;
+ *size = sizeof(This->d3dPictureParam);
+ return S_OK;
+ }
+ else if(type == DXVA2_InverseQuantizationMatrixBufferType)
+ {
+ *buffer = &This->d3dQMatrix;
+ *size = sizeof(This->d3dQMatrix);
+ return S_OK;
+ }
+ else if (type == DXVA2_SliceControlBufferType)
+ {
+ *buffer = &This->d3dSliceInfo;
+ *size = sizeof(This->d3dSliceInfo);
+ return S_OK;
+ }
+ else if (type != DXVA2_BitStreamDateBufferType)
+ return E_INVALIDARG;
+
+ vaapi_lock();
+
+ /* reuse existing vaSlice buffer if any */
+ if (This->vaBitstream == VA_INVALID_ID)
+ {
+ status = pvaCreateBuffer(va_display, This->context, VASliceDataBufferType,
+ This->maxSliceSize, 1, NULL, &This->vaBitstream);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to create slice buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ goto out;
+ }
+ }
+
+ status = pvaMapBuffer(va_display, This->vaBitstream, &buf);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to map slice buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ }
+ else
+ {
+ memset(buf, 0, This->maxSliceSize);
+ *buffer = buf;
+ *size = This->maxSliceSize;
+ hr = S_OK;
+ }
+
+out:
+ vaapi_unlock();
+ return hr;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_UnlockBuffer( IWineVideoDecoder *iface, UINT type )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+
+ TRACE("(%p, %u,)\n", This, type);
+
+ if (type == DXVA2_PictureParametersBufferType ||
+ type == DXVA2_InverseQuantizationMatrixBufferType ||
+ type == DXVA2_SliceControlBufferType)
+ {
+ return S_OK;
+ }
+ else if (type != DXVA2_BitStreamDateBufferType)
+ return E_INVALIDARG;
+
+ vaapi_lock();
+
+ if (This->vaBitstream == VA_INVALID_ID)
+ {
+ ERR("no slice buffer allocated\n");
+ goto out;
+ }
+
+ status = pvaUnmapBuffer(va_display, This->vaBitstream);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to unmap slice buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ }
+ else hr = S_OK;
+
+out:
+ vaapi_unlock();
+ return hr;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_ExecuteBuffer( IWineVideoDecoder *iface, DXVA2_DecodeBufferDesc *pictureParam,
+ DXVA2_DecodeBufferDesc *qMatrix, DXVA2_DecodeBufferDesc *sliceInfo, DXVA2_DecodeBufferDesc *bitStream )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ HRESULT hr;
+
+ TRACE("(%p, %p, %p, %p, %p)\n", This, pictureParam, qMatrix, sliceInfo, bitStream);
+
+ if (!pictureParam || !qMatrix || !sliceInfo || !bitStream)
+ {
+ FIXME("not enough buffers to decode picture\n");
+ return E_FAIL;
+ }
+
+ vaapi_lock();
+
+ hr = process_picture_parameters(This, pictureParam);
+
+ if (SUCCEEDED(hr))
+ hr = process_quantization_matrix(This, qMatrix);
+
+ if (SUCCEEDED(hr))
+ hr = process_slice_control_buffer(This, sliceInfo);
+
+ if (SUCCEEDED(hr))
+ hr = process_data_buffer(This, bitStream);
+
+ vaapi_unlock();
+ return hr;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_BeginFrame( IWineVideoDecoder *iface, UINT surfaceIndex )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+
+ TRACE("(%p, %d)\n", This, surfaceIndex);
+
+ if (surfaceIndex >= This->surfaceCount)
+ return E_INVALIDARG;
+
+ vaapi_lock();
+
+ status = pvaBeginPicture(va_display, This->context, This->surfaces[surfaceIndex]);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to begin picture: %s (0x%x)\n", pvaErrorStr(status), status);
+ }
+ else
+ {
+ This->currentSurface = surfaceIndex;
+ hr = S_OK;
+ }
+
+ vaapi_unlock();
+ return hr;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_EndFrame( IWineVideoDecoder *iface )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+
+ TRACE("(%p)\n", This);
+
+ vaapi_lock();
+
+ status = pvaEndPicture(va_display, This->context);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("ending picture failed: %s (0x%x)\n", pvaErrorStr(status), status);
+ }
+ else hr = S_OK;
+
+ vaapi_unlock();
+ return hr;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_LockImage( IWineVideoDecoder *iface, WineVideoImage *image )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+
+ TRACE("(%p, %p)\n", This, image);
+
+ vaapi_lock();
+
+ pvaSyncSurface(va_display, This->surfaces[This->currentSurface]);
+
+ status = pvaGetImage(va_display, This->surfaces[This->currentSurface], 0, 0,
+ This->width, This->height, This->vaImage.image_id);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to get image: %s (0x%x)\n", pvaErrorStr(status), status);
+ goto out;
+ }
+
+ status = pvaMapBuffer(va_display, This->vaImage.buf, &image->buffer);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to map image buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ }
+ else
+ {
+ image->format = This->format;
+ image->width = This->vaImage.width;
+ image->height = This->vaImage.height;
+ image->planeCount = This->vaImage.num_planes;
+ image->offsets = This->vaImage.offsets;
+ image->pitches = This->vaImage.pitches;
+ hr = S_OK;
+ }
+
+out:
+ vaapi_unlock();
+ return hr;
+}
+
+static HRESULT WINAPI WineVideoDecoderH264_UnlockImage( IWineVideoDecoder *iface )
+{
+ WineVideoDecoderH264Impl *This = impl_from_IWineVideoDecoder(iface);
+ VADisplay va_display = IWineVideoService_VADisplay(This->service);
+ VAStatus status;
+ HRESULT hr = E_FAIL;
+
+ TRACE("(%p)\n", This);
+
+ vaapi_lock();
+
+ status = pvaUnmapBuffer(va_display, This->vaImage.buf);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to unmap image buffer: %s (0x%x)\n", pvaErrorStr(status), status);
+ }
+ else hr = S_OK;
+
+ vaapi_unlock();
+ return hr;
+}
+
+static const IWineVideoDecoderVtbl WineVideoDecoderH264_VTable =
+{
+ WineVideoDecoderH264_QueryInterface,
+ WineVideoDecoderH264_AddRef,
+ WineVideoDecoderH264_Release,
+ WineVideoDecoderH264_LockBuffer,
+ WineVideoDecoderH264_UnlockBuffer,
+ WineVideoDecoderH264_ExecuteBuffer,
+ WineVideoDecoderH264_BeginFrame,
+ WineVideoDecoderH264_EndFrame,
+ WineVideoDecoderH264_LockImage,
+ WineVideoDecoderH264_UnlockImage
+};
+
+HRESULT vaapi_h264decoder_create( IWineVideoService *service, const DXVA2_VideoDesc *videoDesc,
+ DXVA2_ConfigPictureDecode *config, UINT numSurfaces, IWineVideoDecoder **decoder )
+{
+ struct vaapi_format *format;
+ struct vaapi_profile *profile;
+ WineVideoDecoderH264Impl *h264decoder;
+ VAConfigAttrib codecAttrib;
+ VADisplay va_display;
+ VAStatus status;
+
+ if (!service || !videoDesc || !config || !decoder)
+ return E_INVALIDARG;
+
+ va_display = IWineVideoService_VADisplay(service);
+ *decoder = NULL;
+
+ /* H264 requires at least 17 frames - 16 reference frames + 1 target */
+ if (numSurfaces < 17)
+ WARN("decoder initialized with less than 16 + 1 frames\n");
+
+ format = vaapi_lookup_d3dformat(videoDesc->Format);
+ profile = vaapi_lookup_guid(&DXVA2_ModeH264_E);
+ if (!format || !profile)
+ return E_INVALIDARG;
+
+ if (!vaapi_is_format_supported(va_display, profile, format))
+ return E_INVALIDARG;
+
+ if (videoDesc->InputSampleFreq.Numerator * videoDesc->OutputFrameFreq.Denominator !=
+ videoDesc->OutputFrameFreq.Numerator * videoDesc->InputSampleFreq.Denominator)
+ {
+ FIXME("Changing the framerate is not supported.\n");
+ return E_INVALIDARG;
+ }
+
+ h264decoder = CoTaskMemAlloc(sizeof(*h264decoder));
+ if (!h264decoder)
+ return E_OUTOFMEMORY;
+
+ memset(h264decoder, 0, sizeof(*h264decoder));
+
+ h264decoder->IWineVideoDecoder_iface.lpVtbl = &WineVideoDecoderH264_VTable;
+ h264decoder->refCount = 1;
+ h264decoder->service = service;
+
+ h264decoder->width = videoDesc->SampleWidth;
+ h264decoder->height = videoDesc->SampleHeight;
+ h264decoder->format = videoDesc->Format;
+ h264decoder->maxSliceSize = estimate_maximum_slice_size(videoDesc->SampleWidth, videoDesc->SampleHeight);
+ memset(&h264decoder->vaImage, 0, sizeof(h264decoder->vaImage));
+ h264decoder->vaImage.image_id = VA_INVALID_ID;
+
+ h264decoder->surfaceCount = numSurfaces;
+ h264decoder->surfaces = NULL;
+ h264decoder->currentSurface = 0;
+
+ h264decoder->config = 0;
+ h264decoder->context = 0;
+
+ h264decoder->vaBitstream = VA_INVALID_ID;
+
+ vaapi_lock();
+
+ codecAttrib.type = VAConfigAttribRTFormat;
+ codecAttrib.value = format->vaformat;
+
+ status = pvaCreateConfig(va_display, profile->profile, profile->entryPoint,
+ &codecAttrib, 1, &h264decoder->config);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to create decoder config: %s (0x%x)\n", pvaErrorStr(status), status);
+ goto err;
+ }
+
+ if (!vaapi_create_surfaces(va_display, format, h264decoder->width, h264decoder->height,
+ &h264decoder->vaImage, numSurfaces, &h264decoder->surfaces))
+ {
+ ERR("Failed to create image or surfaces\n");
+ goto err;
+ }
+
+ status = pvaCreateContext(va_display, h264decoder->config, h264decoder->width, h264decoder->height,
+ VA_PROGRESSIVE, h264decoder->surfaces, numSurfaces, &h264decoder->context);
+ if (status != VA_STATUS_SUCCESS)
+ {
+ ERR("failed to create context: %s (0x%x)\n", pvaErrorStr(status), status);
+ goto err;
+ }
+
+ vaapi_unlock();
+
+ IWineVideoService_AddRef(service);
+
+ *decoder = &h264decoder->IWineVideoDecoder_iface;
+ return S_OK;
+
+err:
+ if (h264decoder->surfaces)
+ {
+ pvaDestroySurfaces(va_display, h264decoder->surfaces, h264decoder->surfaceCount);
+ HeapFree(GetProcessHeap(), 0, h264decoder->surfaces);
+ }
+
+ if (h264decoder->vaImage.image_id != VA_INVALID_ID)
+ pvaDestroyImage(va_display, h264decoder->vaImage.image_id);
+
+ if (h264decoder->config)
+ pvaDestroyConfig(va_display, h264decoder->config);
+
+ vaapi_unlock();
+ CoTaskMemFree(h264decoder);
+ return E_FAIL;
+}
+
+#endif /* HAVE_VAAPI */
diff --git a/dlls/dxva2/vaapi.c b/dlls/dxva2/vaapi.c
index 3369a03..404f1ab 100644
--- a/dlls/dxva2/vaapi.c
+++ b/dlls/dxva2/vaapi.c
@@ -655,6 +655,8 @@ static HRESULT WINAPI WineVideoService_CreateVideoDecoder( IWineVideoService *if
if (IsEqualGUID(guid, &DXVA2_ModeMPEG2_VLD))
return vaapi_mpeg2decoder_create(iface, videoDesc, config, numSurfaces, decoder);
+ if (IsEqualGUID(guid, &DXVA2_ModeH264_E))
+ return vaapi_h264decoder_create(iface, videoDesc, config, numSurfaces, decoder);
return E_FAIL;
}
--
2.1.0

View File

@ -0,0 +1,4 @@
Fixes: Support for MPEG2 DXVA2 GPU video decoding through vaapi
Fixes: Support for H264 DXVA2 GPU video decoding through vaapi
Depends: winecfg-Staging

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
From 9741c7941627cf4a0aba5e6dcd02bc1d991cea7f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 21 Feb 2015 23:37:26 +0100
Subject: winecfg: Add checkbox to enable/disable vaapi GPU decoder.
---
programs/winecfg/resource.h | 1 +
programs/winecfg/staging.c | 20 ++++++++++++++++++++
programs/winecfg/winecfg.rc | 1 +
3 files changed, 22 insertions(+)
diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h
index 02d90fd..4b21d16 100644
--- a/programs/winecfg/resource.h
+++ b/programs/winecfg/resource.h
@@ -212,6 +212,7 @@
/* Staging tab */
#define IDC_ENABLE_CSMT 9001
+#define IDC_ENABLE_VAAPI 9002
/* About tab */
#define IDC_ABT_OWNER 8432
diff --git a/programs/winecfg/staging.c b/programs/winecfg/staging.c
index 09c0d3f..bda2e6e 100644
--- a/programs/winecfg/staging.c
+++ b/programs/winecfg/staging.c
@@ -49,10 +49,26 @@ static void csmt_set(BOOL status)
set_reg_key(config_key, keypath("DllRedirects"), "wined3d", status ? "wined3d-csmt.dll" : NULL);
}
+/*
+ * DXVA2
+ */
+static BOOL vaapi_get(void)
+{
+ BOOL ret;
+ char *value = get_reg_key(config_key, keypath("DXVA2"), "backend", NULL);
+ ret = (value && !strcmp(value, "va"));
+ HeapFree(GetProcessHeap(), 0, value);
+ return ret;
+}
+static void vaapi_set(BOOL status)
+{
+ set_reg_key(config_key, keypath("DXVA2"), "backend", status ? "va" : NULL);
+}
static void load_staging_settings(HWND dialog)
{
CheckDlgButton(dialog, IDC_ENABLE_CSMT, csmt_get() ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(dialog, IDC_ENABLE_VAAPI, vaapi_get() ? BST_CHECKED : BST_UNCHECKED);
}
INT_PTR CALLBACK StagingDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -82,6 +98,10 @@ INT_PTR CALLBACK StagingDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
csmt_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_CSMT) == BST_CHECKED);
SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
return TRUE;
+ case IDC_ENABLE_VAAPI:
+ vaapi_set(IsDlgButtonChecked(hDlg, IDC_ENABLE_VAAPI) == BST_CHECKED);
+ SendMessageW(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
}
break;
}
diff --git a/programs/winecfg/winecfg.rc b/programs/winecfg/winecfg.rc
index a723880..694bd73 100644
--- a/programs/winecfg/winecfg.rc
+++ b/programs/winecfg/winecfg.rc
@@ -314,6 +314,7 @@ BEGIN
GROUPBOX "Staging settings",IDC_STATIC,8,4,244,210
LTEXT "The following settings are experimental and may break stuff!\nMake sure to reset them again in case of a problem.",IDC_STATIC,16,16,230,16
CONTROL "Enable &CSMT for better graphic performance",IDC_ENABLE_CSMT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,40,230,8
+ CONTROL "Enable &VAAPI as backend for DXVA2 GPU decoding",IDC_ENABLE_VAAPI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,55,230,8
END
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
--
2.1.0