Several improvements to make nvcuvid (CUDA video decoding) better compatible with x86_64.

This commit is contained in:
Sebastian Lackner 2015-01-15 02:21:19 +01:00
parent 60d18d4610
commit d50c673144
3 changed files with 229 additions and 28 deletions

1
debian/changelog vendored
View File

@ -2,6 +2,7 @@ wine-staging (1.7.35) UNRELEASED; urgency=low
* Add support for patchinstall.sh parameters '--no-patchlist' and '--no-autoconf'.
* Add support for Gentoo epatch backend to patchinstall.sh.
* Synchronize CSMT patchset with https://github.com/stefand/wine.
* Several improvements to make nvcuvid (CUDA video decoding) better compatible with x86_64.
* Added patch to implement support for DDS file format in D3DXSaveTextureToFileInMemory.
* Added patch to avoid appending duplicate NULL character when importing keys with regedit.
* Added patch for IConnectionPoint/INetworkListManagerEvents stub interface.

View File

@ -1,17 +1,19 @@
From 84afbf397a3e80bc5e64b5a2af75e027c667195d Mon Sep 17 00:00:00 2001
From 914b532851757f246d3e2a28a3cd64a00c94b10c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Tue, 6 Jan 2015 05:16:36 +0100
Subject: nvcuvid: First implementation.
Subject: nvcuvid: First implementation. (rev 2)
Changes by Sebastian Lackner <sebastian@fds-team.de>:
* Convert structures properly where the Windows and Linux definition differs.
---
configure.ac | 1 +
dlls/nvcuvid/Makefile.in | 4 +
dlls/nvcuvid/nvcuvid.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/nvcuvid/nvcuvid.c | 537 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/nvcuvid/nvcuvid.spec | 24 +++
include/Makefile.in | 2 +
include/cuviddec.h | 30 ++++
include/nvcuvid.h | 66 ++++++++
7 files changed, 549 insertions(+)
include/cuviddec.h | 99 +++++++++
include/nvcuvid.h | 80 +++++++
7 files changed, 747 insertions(+)
create mode 100644 dlls/nvcuvid/Makefile.in
create mode 100644 dlls/nvcuvid/nvcuvid.c
create mode 100644 dlls/nvcuvid/nvcuvid.spec
@ -19,7 +21,7 @@ Subject: nvcuvid: First implementation.
create mode 100644 include/nvcuvid.h
diff --git a/configure.ac b/configure.ac
index 13e22c5..7c40b45 100644
index 3918ab1..937b431 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3137,6 +3137,7 @@ WINE_CONFIG_TEST(dlls/nvapi/tests)
@ -42,10 +44,10 @@ index 0000000..2c2dc8c
+ nvcuvid.c
diff --git a/dlls/nvcuvid/nvcuvid.c b/dlls/nvcuvid/nvcuvid.c
new file mode 100644
index 0000000..cf6a3a4
index 0000000..05fec0f
--- /dev/null
+++ b/dlls/nvcuvid/nvcuvid.c
@@ -0,0 +1,422 @@
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2015 Michael Müller
+ *
@ -78,7 +80,7 @@ index 0000000..cf6a3a4
+
+WINE_DEFAULT_DEBUG_CHANNEL(nvcuvid);
+
+static CUresult (*pcuvidCreateDecoder)(CUvideodecoder *phDecoder, CUVIDDECODECREATEINFO *pdci);
+static CUresult (*pcuvidCreateDecoder)(CUvideodecoder *phDecoder, LINUX_CUVIDDECODECREATEINFO *pdci);
+static CUresult (*pcuvidCreateVideoParser)(CUvideoparser *pObj, CUVIDPARSERPARAMS *pParams);
+static CUresult (*pcuvidCreateVideoSource)(CUvideosource *pObj, const char *pszFileName, CUVIDSOURCEPARAMS *pParams);
+static CUresult (*pcuvidCtxLock)(CUvideoctxlock lck, unsigned int reserved_flags);
@ -94,10 +96,17 @@ index 0000000..cf6a3a4
+/* static CUresult (*pcuvidGetVideoFrameSurface)(CUvideodecoder hDecoder, int nPicIdx, void **pSrcSurface); */
+static cudaVideoState (*pcuvidGetVideoSourceState)(CUvideosource obj);
+static CUresult (*pcuvidMapVideoFrame)(CUvideodecoder hDecoder, int nPicIdx, unsigned int *pDevPtr, unsigned int *pPitch, CUVIDPROCPARAMS *pVPP);
+static CUresult (*pcuvidParseVideoData)(CUvideoparser obj, CUVIDSOURCEDATAPACKET *pPacket);
+static CUresult (*pcuvidParseVideoData)(CUvideoparser obj, LINUX_CUVIDSOURCEDATAPACKET *pPacket);
+static CUresult (*pcuvidSetVideoSourceState)(CUvideosource obj, cudaVideoState state);
+static CUresult (*pcuvidUnmapVideoFrame)(CUvideodecoder hDecoder, unsigned int DevPtr);
+
+/* x86_64 */
+#ifdef __x86_64__
+static CUresult (*pcuvidMapVideoFrame64)(CUvideodecoder hDecoder, int nPicIdx, unsigned long long *pDevPtr,
+ unsigned int *pPitch, CUVIDPROCPARAMS *pVPP);
+static CUresult (*pcuvidUnmapVideoFrame64)(CUvideodecoder hDecoder, unsigned long long DevPtr);
+#endif
+
+static void *cuvid_handle = NULL;
+
+static BOOL load_functions(void)
@ -114,6 +123,7 @@ index 0000000..cf6a3a4
+
+ LOAD_FUNCPTR(cuvidCreateDecoder);
+ LOAD_FUNCPTR(cuvidCreateVideoParser);
+ LOAD_FUNCPTR(cuvidCreateVideoSource);
+ LOAD_FUNCPTR(cuvidCtxLock);
+ LOAD_FUNCPTR(cuvidCtxLockCreate);
+ LOAD_FUNCPTR(cuvidCtxLockDestroy);
@ -130,7 +140,12 @@ index 0000000..cf6a3a4
+ LOAD_FUNCPTR(cuvidParseVideoData);
+ LOAD_FUNCPTR(cuvidSetVideoSourceState);
+ LOAD_FUNCPTR(cuvidUnmapVideoFrame);
+ LOAD_FUNCPTR(cuvidCreateVideoSource);
+
+ /* x86_64 */
+#ifdef __x86_64__
+ LOAD_FUNCPTR(cuvidMapVideoFrame64);
+ LOAD_FUNCPTR(cuvidUnmapVideoFrame64);
+#endif
+
+ #undef LOAD_FUNCPTR
+
@ -175,24 +190,84 @@ index 0000000..cf6a3a4
+ return parser->orig_DisplayPicture(parser->orig_data, info);
+}
+
+static int relay_VideoDataHandler(void *data, CUVIDSOURCEDATAPACKET *pkt)
+static int relay_VideoDataHandler(void *data, LINUX_CUVIDSOURCEDATAPACKET *pkt)
+{
+ CUVIDSOURCEDATAPACKET win_pkt;
+ struct fake_source *source = data;
+ TRACE("(%p, %p)\n", data, pkt);
+ return source->orig_VideoDataHandler(source->orig_data, pkt);
+
+ if (pkt)
+ {
+ memset(&win_pkt, 0, sizeof(win_pkt));
+ win_pkt.flags = pkt->flags;
+ win_pkt.payload_size = pkt->payload_size;
+ win_pkt.payload = pkt->payload;
+ win_pkt.timestamp = pkt->timestamp;
+ }
+
+ return source->orig_VideoDataHandler(source->orig_data, pkt ? &win_pkt : NULL);
+}
+
+static int relay_AudioDataHandler(void *data, CUVIDSOURCEDATAPACKET *pkt)
+static int relay_AudioDataHandler(void *data, LINUX_CUVIDSOURCEDATAPACKET *pkt)
+{
+ CUVIDSOURCEDATAPACKET win_pkt;
+ struct fake_source *source = data;
+ TRACE("(%p, %p)\n", data, pkt);
+ return source->orig_AudioDataHandler(source->orig_data, pkt);
+
+ if (pkt)
+ {
+ memset(&win_pkt, 0, sizeof(win_pkt));
+ win_pkt.flags = pkt->flags;
+ win_pkt.payload_size = pkt->payload_size;
+ win_pkt.payload = pkt->payload;
+ win_pkt.timestamp = pkt->timestamp;
+ }
+
+ return source->orig_AudioDataHandler(source->orig_data, pkt ? &win_pkt : NULL);
+}
+
+CUresult WINAPI wine_cuvidCreateDecoder(CUvideodecoder *phDecoder, CUVIDDECODECREATEINFO *pdci)
+{
+ LINUX_CUVIDDECODECREATEINFO linux_dci;
+
+ TRACE("(%p, %p)\n", phDecoder, pdci);
+ return pcuvidCreateDecoder(phDecoder, pdci);
+
+ if (pdci)
+ {
+ memset(&linux_dci, 0, sizeof(linux_dci));
+ linux_dci.ulWidth = pdci->ulWidth;
+ linux_dci.ulHeight = pdci->ulHeight;
+ linux_dci.ulNumDecodeSurfaces = pdci->ulNumDecodeSurfaces;
+ linux_dci.CodecType = pdci->CodecType;
+ linux_dci.ChromaFormat = pdci->ChromaFormat;
+ linux_dci.ulCreationFlags = pdci->ulCreationFlags;
+ linux_dci.Reserved1[0] = pdci->Reserved1[0];
+ linux_dci.Reserved1[1] = pdci->Reserved1[1];
+ linux_dci.Reserved1[2] = pdci->Reserved1[2];
+ linux_dci.Reserved1[3] = pdci->Reserved1[3];
+ linux_dci.Reserved1[4] = pdci->Reserved1[4];
+ linux_dci.display_area.left = pdci->display_area.left;
+ linux_dci.display_area.top = pdci->display_area.top;
+ linux_dci.display_area.right = pdci->display_area.right;
+ linux_dci.display_area.bottom = pdci->display_area.bottom;
+ linux_dci.OutputFormat = pdci->OutputFormat;
+ linux_dci.DeinterlaceMode = pdci->DeinterlaceMode;
+ linux_dci.ulTargetWidth = pdci->ulTargetWidth;
+ linux_dci.ulTargetHeight = pdci->ulTargetHeight;
+ linux_dci.ulNumOutputSurfaces = pdci->ulNumOutputSurfaces;
+ linux_dci.vidLock = pdci->vidLock;
+ linux_dci.target_rect.left = pdci->target_rect.left;
+ linux_dci.target_rect.top = pdci->target_rect.top;
+ linux_dci.target_rect.right = pdci->target_rect.right;
+ linux_dci.target_rect.bottom = pdci->target_rect.bottom;
+ linux_dci.Reserved2[0] = pdci->Reserved2[0];
+ linux_dci.Reserved2[1] = pdci->Reserved2[1];
+ linux_dci.Reserved2[2] = pdci->Reserved2[2];
+ linux_dci.Reserved2[3] = pdci->Reserved2[3];
+ linux_dci.Reserved2[4] = pdci->Reserved2[4];
+ }
+
+ return pcuvidCreateDecoder(phDecoder, pdci ? &linux_dci : NULL);
+}
+
+CUresult WINAPI wine_cuvidCreateVideoParser(CUvideoparser *pObj, CUVIDPARSERPARAMS *pParams)
@ -353,6 +428,10 @@ index 0000000..cf6a3a4
+CUresult WINAPI wine_cuvidDecodePicture(CUvideodecoder hDecoder, CUVIDPICPARAMS *pPicParams)
+{
+ TRACE("(%p, %p)\n", hDecoder, pPicParams);
+
+ /* The size of CUVIDH264PICPARAMS is actually 4 byte larger on Windows than on Linux,
+ * but, as it is contained only as a subfield in CUVIDPICPARAMS the total size matches. */
+
+ return pcuvidDecodePicture(hDecoder, pPicParams);
+}
+
@ -430,10 +509,21 @@ index 0000000..cf6a3a4
+
+CUresult WINAPI wine_cuvidParseVideoData(CUvideoparser obj, CUVIDSOURCEDATAPACKET *pPacket)
+{
+ LINUX_CUVIDSOURCEDATAPACKET linux_packet;
+ struct fake_parser *parser = (void *)obj;
+ TRACE("(%p, %p)\n", obj, pPacket);
+ if (!parser) return CUDA_ERROR_INVALID_VALUE; /* FIXME */
+ return pcuvidParseVideoData(parser->orig_parser, pPacket);
+
+ if (pPacket)
+ {
+ memset(&linux_packet, 0, sizeof(linux_packet));
+ linux_packet.flags = pPacket->flags;
+ linux_packet.payload_size = pPacket->payload_size;
+ linux_packet.payload = pPacket->payload;
+ linux_packet.timestamp = pPacket->timestamp;
+ }
+
+ return pcuvidParseVideoData(parser->orig_parser, pPacket ? &linux_packet : NULL);
+}
+
+CUresult WINAPI wine_cuvidSetVideoSourceState(CUvideosource obj, cudaVideoState state)
@ -450,6 +540,33 @@ index 0000000..cf6a3a4
+ return pcuvidUnmapVideoFrame(hDecoder, DevPtr);
+}
+
+/*
+ * On Linux those functions are only exported x86_64, but on Windows they also exist in the 32-bit version.
+ */
+
+CUresult WINAPI wine_cuvidMapVideoFrame64(CUvideodecoder hDecoder, int nPicIdx, unsigned long long *pDevPtr,
+ unsigned int *pPitch, CUVIDPROCPARAMS *pVPP)
+{
+ TRACE("(%p, %d, %p, %p, %p)\n", hDecoder, nPicIdx, pDevPtr, pPitch, pVPP);
+#ifdef __x86_64__
+ return pcuvidMapVideoFrame64(hDecoder, nPicIdx, pDevPtr, pPitch, pVPP);
+#else
+ FIXME("not supported\n");
+ return CUDA_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+CUresult WINAPI wine_cuvidUnmapVideoFrame64(CUvideodecoder hDecoder, unsigned long long DevPtr)
+{
+ TRACE("(%p, %llu)\n", hDecoder, DevPtr);
+#ifdef __x86_64__
+ return pcuvidUnmapVideoFrame64(hDecoder, DevPtr);
+#else
+ FIXME("not supported\n");
+ return CUDA_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ TRACE("(%p, %u, %p)\n", instance, reason, reserved);
@ -470,13 +587,13 @@ index 0000000..cf6a3a4
+}
diff --git a/dlls/nvcuvid/nvcuvid.spec b/dlls/nvcuvid/nvcuvid.spec
new file mode 100644
index 0000000..73e49f1
index 0000000..433e7db
--- /dev/null
+++ b/dlls/nvcuvid/nvcuvid.spec
@@ -0,0 +1,24 @@
+@ stub CreateEncoderInterface
+@ stub cuvidMapVideoFrame64
+@ stub cuvidUnmapVideoFrame64
+@ stdcall cuvidMapVideoFrame64(ptr long ptr ptr ptr) wine_cuvidMapVideoFrame64
+@ stdcall cuvidUnmapVideoFrame64(ptr int64) wine_cuvidUnmapVideoFrame64
+@ stdcall cuvidCreateDecoder(ptr ptr) wine_cuvidCreateDecoder
+@ stdcall cuvidCreateVideoParser(ptr ptr) wine_cuvidCreateVideoParser
+@ stdcall cuvidCreateVideoSource(ptr str ptr) wine_cuvidCreateVideoSource
@ -520,10 +637,10 @@ index f9eaf44..e29f3e5 100644
odbcinst.h \
diff --git a/include/cuviddec.h b/include/cuviddec.h
new file mode 100644
index 0000000..c2301f7
index 0000000..e450321
--- /dev/null
+++ b/include/cuviddec.h
@@ -0,0 +1,30 @@
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 Michael Müller
+ *
@ -550,16 +667,85 @@ index 0000000..c2301f7
+typedef void *CUvideodecoder;
+typedef void *CUvideoctxlock;
+
+typedef int cudaVideoCodec;
+typedef int cudaVideoChromaFormat;
+typedef int cudaVideoSurfaceFormat;
+typedef int cudaVideoDeinterlaceMode;
+
+/* the following structures are documented but we don't need to know the content */
+typedef struct _CUVIDPROCPARAMS CUVIDPROCPARAMS;
+
+typedef struct _LINUX_CUVIDDECODECREATEINFO
+{
+ unsigned long ulWidth;
+ unsigned long ulHeight;
+ unsigned long ulNumDecodeSurfaces;
+ cudaVideoCodec CodecType;
+ cudaVideoChromaFormat ChromaFormat;
+ unsigned long ulCreationFlags;
+ unsigned long Reserved1[5];
+ struct
+ {
+ short left;
+ short top;
+ short right;
+ short bottom;
+ } display_area;
+ cudaVideoSurfaceFormat OutputFormat;
+ cudaVideoDeinterlaceMode DeinterlaceMode;
+ unsigned long ulTargetWidth;
+ unsigned long ulTargetHeight;
+ unsigned long ulNumOutputSurfaces;
+ CUvideoctxlock vidLock;
+ struct
+ {
+ short left;
+ short top;
+ short right;
+ short bottom;
+ } target_rect;
+ unsigned long Reserved2[5];
+} LINUX_CUVIDDECODECREATEINFO;
+
+typedef struct _CUVIDDECODECREATEINFO
+{
+ ULONG ulWidth;
+ ULONG ulHeight;
+ ULONG ulNumDecodeSurfaces;
+ cudaVideoCodec CodecType;
+ cudaVideoChromaFormat ChromaFormat;
+ ULONG ulCreationFlags;
+ ULONG Reserved1[5];
+ struct
+ {
+ short left;
+ short top;
+ short right;
+ short bottom;
+ } display_area;
+ cudaVideoSurfaceFormat OutputFormat;
+ cudaVideoDeinterlaceMode DeinterlaceMode;
+ ULONG ulTargetWidth;
+ ULONG ulTargetHeight;
+ ULONG ulNumOutputSurfaces;
+ CUvideoctxlock vidLock;
+ struct
+ {
+ short left;
+ short top;
+ short right;
+ short bottom;
+ } target_rect;
+ ULONG Reserved2[5];
+} CUVIDDECODECREATEINFO;
+
+#endif /* __WINE_CUVIDDEC_H */
diff --git a/include/nvcuvid.h b/include/nvcuvid.h
new file mode 100644
index 0000000..4885e45
index 0000000..216499f
--- /dev/null
+++ b/include/nvcuvid.h
@@ -0,0 +1,66 @@
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 Michael Müller
+ *
@ -587,12 +773,10 @@ index 0000000..4885e45
+typedef void *CUvideoparser;
+typedef long long CUvideotimestamp;
+
+typedef int cudaVideoCodec;
+typedef int cudaVideoState;
+
+/* the following structures are documented but we don't need to know the details */
+typedef struct _CUAUDIOFORMAT CUAUDIOFORMAT;
+typedef struct _CUVIDDECODECREATEINFO CUVIDDECODECREATEINFO;
+typedef struct _CUVIDEOFORMAT CUVIDEOFORMAT;
+typedef struct _CUVIDEOFORMATEX CUVIDEOFORMATEX;
+typedef struct _CUVIDPARSERDISPINFO CUVIDPARSERDISPINFO;
@ -625,6 +809,22 @@ index 0000000..4885e45
+ void *pvReserved2[8];
+} CUVIDSOURCEPARAMS;
+
+typedef struct _LINUX_CUVIDSOURCEDATAPACKET
+{
+ unsigned long flags;
+ unsigned long payload_size;
+ const unsigned char *payload;
+ CUvideotimestamp timestamp;
+} LINUX_CUVIDSOURCEDATAPACKET;
+
+typedef struct _CUVIDSOURCEDATAPACKET
+{
+ ULONG flags;
+ ULONG payload_size;
+ const unsigned char *payload;
+ CUvideotimestamp timestamp DECLSPEC_ALIGN(8);
+} CUVIDSOURCEDATAPACKET;
+
+#endif /* __WINE_NVCUVID_H */
--
2.2.1

View File

@ -2224,7 +2224,7 @@ fi
if test "$enable_nvcuvid_CUDA_Video_Support" -eq 1; then
patch_apply nvcuvid-CUDA_Video_Support/0001-nvcuvid-First-implementation.patch
(
echo '+ { "Michael Müller", "nvcuvid: First implementation.", 1 },';
echo '+ { "Michael Müller", "nvcuvid: First implementation.", 2 },';
) >> "$patchlist"
fi