dxva2-Video_Decoder: Various improvements to dxva2 vaapi support.

This commit is contained in:
Sebastian Lackner 2015-03-04 19:36:04 +01:00
parent 4a8df258cd
commit c02bdae45d
5 changed files with 491 additions and 0 deletions

1
debian/changelog vendored
View File

@ -1,5 +1,6 @@
wine-staging (1.7.38) UNRELEASED; urgency=low
* Various improvements to patchupdate.py.
* Various improvements to dxva2 vaapi support.
* Disabled patchset for reg.exe cleanup (partially accepted upstream).
* Disabled patchset for TransmitFile (rewrite in progress).
* Added patch to mark DllCanUnloadNow and DllGetClassObject as private (by Amine Khaldi, wine-patched/pull/3).

View File

@ -0,0 +1,244 @@
From aaacd6fc291e406f81a4739ae7f7828937a215a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Wed, 4 Mar 2015 03:57:29 +0100
Subject: dxva2: Add DRM mode for vaapi.
---
configure.ac | 9 ++---
dlls/dxva2/dxva2_private.h | 7 +++-
dlls/dxva2/main.c | 8 +++++
dlls/dxva2/vaapi.c | 89 +++++++++++++++++++++++++++++++++++++---------
4 files changed, 91 insertions(+), 22 deletions(-)
diff --git a/configure.ac b/configure.ac
index c925f6b..bdacada 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1264,17 +1264,18 @@ This probably prevents linking to OpenGL. Try deleting the file and restarting c
OpenGL and Direct3D won't be supported.])
dnl **** Check for libva ****
- AC_CHECK_HEADERS([va/va_x11.h])
- if test "$ac_cv_header_va_va_x11_h" = "yes"
+ AC_CHECK_HEADERS([va/va_x11.h va/va_drm.h])
+ if test "$ac_cv_header_va_va_x11_h" = "yes" -a "$ac_cv_header_va_va_drm_h" = "yes"
then
WINE_CHECK_SONAME(va,vaQuerySurfaceAttributes,,,[$X_LIBS])
WINE_CHECK_SONAME(va-x11,vaGetDisplay,,,[$X_LIBS -lva])
- if test "x$ac_cv_lib_soname_va" != "x" -a "x$ac_cv_lib_soname_va_x11" != "x"
+ WINE_CHECK_SONAME(va-drm,vaGetDisplayDRM,,,[$X_LIBS -lva])
+ if test "x$ac_cv_lib_soname_va" != "x" -a "x$ac_cv_lib_soname_va_x11" != "x" -a "x$ac_cv_lib_soname_va_drm" != "x"
then
AC_DEFINE(HAVE_VAAPI, 1, [Define if you have the libva development files])
fi
fi
- WINE_NOTICE_WITH(va,[test "x$ac_cv_lib_soname_va" = "x" -o "x$ac_cv_lib_soname_va_x11" = "x"],
+ WINE_NOTICE_WITH(va,[test "x$ac_cv_lib_soname_va" = "x" -o "x$ac_cv_lib_soname_va_x11" = "x" -o "x$ac_cv_lib_soname_va_drm" = "x"],
[libva ${notice_platform}development files not found, GPU video acceleration won't be supported.])
CPPFLAGS="$ac_save_CPPFLAGS"
diff --git a/dlls/dxva2/dxva2_private.h b/dlls/dxva2/dxva2_private.h
index 5df59bd..14ac586 100644
--- a/dlls/dxva2/dxva2_private.h
+++ b/dlls/dxva2/dxva2_private.h
@@ -22,6 +22,7 @@
#ifdef HAVE_VAAPI
# undef Status
# include <va/va_x11.h>
+# include <va/va_drm.h>
#endif
extern HRESULT videoservice_create( IDirect3DDevice9 *device, REFIID riid, void **ppv ) DECLSPEC_HIDDEN;
@@ -39,6 +40,8 @@ extern HRESULT genericdecoder_create( IDirectXVideoDecoderService *videodecoder,
/* public */
extern BOOL config_vaapi_enabled DECLSPEC_HIDDEN;
+BOOL config_vaapi_drm DECLSPEC_HIDDEN;
+char config_vaapi_drm_path[MAX_PATH] DECLSPEC_HIDDEN;
extern IWineVideoService *vaapi_videoservice_create( void ) DECLSPEC_HIDDEN;
/* internal */
@@ -101,11 +104,13 @@ typedef struct
/* libraries */
void *va_handle;
void *va_x11_handle;
+ void *va_drm_handle;
void *x11_handle;
- /* display */
+ /* display / drm connection */
Display *x11_display;
VADisplay va_display;
+ int drm_fd;
} WineVideoServiceImpl;
static inline WineVideoServiceImpl *impl_from_IWineVideoService( IWineVideoService *iface )
diff --git a/dlls/dxva2/main.c b/dlls/dxva2/main.c
index 758c146..0442c63 100644
--- a/dlls/dxva2/main.c
+++ b/dlls/dxva2/main.c
@@ -33,6 +33,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
BOOL config_vaapi_enabled = FALSE;
+BOOL config_vaapi_drm = FALSE;
+char config_vaapi_drm_path[MAX_PATH] = "";
BOOL WINAPI CapabilitiesRequestAndCapabilitiesReply( HMONITOR monitor, LPSTR buffer, DWORD length )
{
@@ -379,6 +381,12 @@ static void dxva2_init( void )
if (get_config_key(defkey, appkey, "backend", buffer, sizeof(buffer)))
config_vaapi_enabled = !strcmp(buffer, "va");
+ if (get_config_key(defkey, appkey, "va_mode", buffer, sizeof(buffer)))
+ config_vaapi_drm = !strcmp(buffer, "drm");
+
+ if (!get_config_key(defkey, appkey, "va_drm_device", config_vaapi_drm_path, sizeof(config_vaapi_drm_path)))
+ strcpy(config_vaapi_drm_path, "/dev/dri/card0");
+
if (defkey) RegCloseKey(defkey);
if (appkey) RegCloseKey(appkey);
}
diff --git a/dlls/dxva2/vaapi.c b/dlls/dxva2/vaapi.c
index 4c570f5..1b19684 100644
--- a/dlls/dxva2/vaapi.c
+++ b/dlls/dxva2/vaapi.c
@@ -55,6 +55,7 @@ MAKE_FUNCPTR(vaEndPicture);
MAKE_FUNCPTR(vaErrorStr);
MAKE_FUNCPTR(vaGetConfigAttributes);
MAKE_FUNCPTR(vaGetDisplay);
+MAKE_FUNCPTR(vaGetDisplayDRM);
MAKE_FUNCPTR(vaGetImage);
MAKE_FUNCPTR(vaInitialize);
MAKE_FUNCPTR(vaMapBuffer);
@@ -135,6 +136,23 @@ error:
return NULL;
}
+static void *load_libva_drm( void )
+{
+ void *handle = wine_dlopen(SONAME_LIBVA_DRM, RTLD_NOW, NULL, 0);
+ if (!handle)
+ {
+ FIXME("Wine cannot find the %s library.\n", SONAME_LIBVA_DRM);
+ return FALSE;
+ }
+
+ LOAD_FUNCPTR(vaGetDisplayDRM);
+ return handle;
+
+error:
+ wine_dlclose(handle, NULL, 0);
+ return NULL;
+}
+
static void *load_libx11( void )
{
void *handle = wine_dlopen(SONAME_LIBX11, RTLD_NOW, NULL, 0);
@@ -480,11 +498,18 @@ static ULONG WINAPI WineVideoService_Release( IWineVideoService *iface )
pvaTerminate(This->va_display);
vaapi_unlock();
- pXCloseDisplay(This->x11_display);
-
- wine_dlclose(This->x11_handle, NULL, 0);
- wine_dlclose(This->va_x11_handle, NULL, 0);
- wine_dlclose(This->va_handle, NULL, 0);
+ if (This->x11_display)
+ pXCloseDisplay(This->x11_display);
+ if (This->x11_handle)
+ wine_dlclose(This->x11_handle, NULL, 0);
+ if (This->drm_fd > 0)
+ close(This->drm_fd);
+ if (This->va_drm_handle)
+ wine_dlclose(This->va_drm_handle, NULL, 0);
+ if (This->va_x11_handle)
+ wine_dlclose(This->va_x11_handle, NULL, 0);
+ if (This->va_handle)
+ wine_dlclose(This->va_handle, NULL, 0);
CoTaskMemFree(This);
}
@@ -703,30 +728,56 @@ IWineVideoService *vaapi_videoservice_create( void )
videoservice->va_handle = NULL;
videoservice->va_x11_handle = NULL;
+ videoservice->va_drm_handle = NULL;
videoservice->x11_handle = NULL;
videoservice->x11_display = NULL;
videoservice->va_display = NULL;
+ videoservice->drm_fd = -1;
videoservice->va_handle = load_libva();
if (!videoservice->va_handle)
goto err;
- videoservice->va_x11_handle = load_libva_x11();
- if (!videoservice->va_x11_handle)
- goto err;
+ if (config_vaapi_drm)
+ {
+ TRACE("Using VAAPI in DRM mode.\n");
- videoservice->x11_handle = load_libx11();
- if (!videoservice->x11_handle)
- goto err;
+ videoservice->va_drm_handle = load_libva_drm();
+ if (!videoservice->va_drm_handle)
+ goto err;
- videoservice->x11_display = pXOpenDisplay(NULL);
- if (!videoservice->x11_display)
- goto err;
+ videoservice->drm_fd = open(config_vaapi_drm_path, O_RDWR);
+ if (videoservice->drm_fd < 0)
+ {
+ FIXME("Failed to open device %s\n", config_vaapi_drm_path);
+ goto err;
+ }
- videoservice->va_display = pvaGetDisplay(videoservice->x11_display);
- if (!videoservice->va_display)
- goto err;
+ videoservice->va_display = pvaGetDisplayDRM(videoservice->drm_fd);
+ if (!videoservice->va_display)
+ goto err;
+ }
+ else
+ {
+ TRACE("Using VAAPI in X11 mode.\n");
+
+ videoservice->va_x11_handle = load_libva_x11();
+ if (!videoservice->va_x11_handle)
+ goto err;
+
+ videoservice->x11_handle = load_libx11();
+ if (!videoservice->x11_handle)
+ goto err;
+
+ videoservice->x11_display = pXOpenDisplay(NULL);
+ if (!videoservice->x11_display)
+ goto err;
+
+ videoservice->va_display = pvaGetDisplay(videoservice->x11_display);
+ if (!videoservice->va_display)
+ goto err;
+ }
if (pvaInitialize(videoservice->va_display, &major, &minor) != VA_STATUS_SUCCESS)
goto err;
@@ -749,6 +800,10 @@ err:
pXCloseDisplay(videoservice->x11_display);
if (videoservice->x11_handle)
wine_dlclose(videoservice->x11_handle, NULL, 0);
+ if (videoservice->drm_fd > 0)
+ close(videoservice->drm_fd);
+ if (videoservice->va_drm_handle)
+ wine_dlclose(videoservice->va_drm_handle, NULL, 0);
if (videoservice->va_x11_handle)
wine_dlclose(videoservice->va_x11_handle, NULL, 0);
if (videoservice->va_handle)
--
2.3.0

View File

@ -0,0 +1,77 @@
From 012b73c2241150216d56061ecee035d8d9ee3be9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Wed, 4 Mar 2015 04:01:41 +0100
Subject: dxva2: Fill h264 luma and chroma weights / offsets with default
values in case they are not specified.
---
dlls/dxva2/vaapi-h264.c | 50 +++++++++++++++++++++++++++++++++++++------------
1 file changed, 38 insertions(+), 12 deletions(-)
diff --git a/dlls/dxva2/vaapi-h264.c b/dlls/dxva2/vaapi-h264.c
index 1a5817e..7fe145c 100644
--- a/dlls/dxva2/vaapi-h264.c
+++ b/dlls/dxva2/vaapi-h264.c
@@ -382,21 +382,47 @@ static HRESULT process_slice_control_buffer( WineVideoDecoderH264Impl *This, con
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];
+ if (This->d3dSliceInfo[i].RefPicList[0][j].bPicEntry != 0xFF)
+ {
+ 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];
+ }
+ else
+ {
+ slice[i].luma_weight_l0[j] = 1 << This->d3dSliceInfo[i].luma_log2_weight_denom;
+ slice[i].luma_offset_l0[j] = 0;
+
+ slice[i].chroma_weight_l0[j][0] = 1 << This->d3dSliceInfo[i].chroma_log2_weight_denom;
+ slice[i].chroma_offset_l0[j][0] = 0;
+ slice[i].chroma_weight_l0[j][1] = 1 << This->d3dSliceInfo[i].chroma_log2_weight_denom;
+ slice[i].chroma_offset_l0[j][1] = 0;
+ }
- 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];
+ if (This->d3dSliceInfo[i].RefPicList[1][j].bPicEntry != 0xFF)
+ {
+ 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].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];
+ }
+ else
+ {
+ slice[i].luma_weight_l1[j] = 1 << This->d3dSliceInfo[i].luma_log2_weight_denom;
+ slice[i].luma_offset_l1[j] = 0;
- 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];
+ slice[i].chroma_weight_l1[j][0] = 1 << This->d3dSliceInfo[i].chroma_log2_weight_denom;
+ slice[i].chroma_offset_l1[j][0] = 0;
+ slice[i].chroma_weight_l1[j][1] = 1 << This->d3dSliceInfo[i].chroma_log2_weight_denom;
+ slice[i].chroma_offset_l1[j][1] = 0;
+ }
}
}
--
2.3.0

View File

@ -0,0 +1,163 @@
From f69ae619e5b10a39d261af36fe9b0cb33f28c3b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Wed, 4 Mar 2015 04:04:47 +0100
Subject: dxva2: Always destroy buffers when calling vaRenderPicture.
The vaapi documentation says the opposite, but other applications do that too.
Avoids that the vaapi implementation runs out of memory/buffers sooner or later.
---
dlls/dxva2/vaapi-h264.c | 19 ++++++++++---------
dlls/dxva2/vaapi-mpeg2.c | 19 ++++++++++---------
2 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/dlls/dxva2/vaapi-h264.c b/dlls/dxva2/vaapi-h264.c
index 7fe145c..edde27e 100644
--- a/dlls/dxva2/vaapi-h264.c
+++ b/dlls/dxva2/vaapi-h264.c
@@ -212,13 +212,13 @@ static HRESULT process_picture_parameters( WineVideoDecoderH264Impl *This, const
return E_FAIL;
}
- /* vaRenderPicture is supposed to destroy the buffer */
status = pvaRenderPicture(va_display, This->context, &vaPictureParam, 1);
+ pvaDestroyBuffer(va_display, vaPictureParam);
+
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;
}
@@ -244,13 +244,13 @@ static HRESULT process_quantization_matrix( WineVideoDecoderH264Impl *This, cons
return E_FAIL;
}
- /* vaRenderPicture is supposed to destroy the buffer */
status = pvaRenderPicture(va_display, This->context, &vaIQMatrix, 1);
+ pvaDestroyBuffer(va_display, vaIQMatrix);
+
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;
}
@@ -429,10 +429,12 @@ static HRESULT process_slice_control_buffer( WineVideoDecoderH264Impl *This, con
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)
+ {
+ pvaDestroyBuffer(va_display, vaSliceInfo);
return S_OK;
+ }
ERR("failed to process slice control buffer: %s (0x%x)\n", pvaErrorStr(status), status);
@@ -446,20 +448,19 @@ static HRESULT process_data_buffer( WineVideoDecoderH264Impl *This, const DXVA2_
{
VADisplay va_display = IWineVideoService_VADisplay(This->service);
VAStatus status;
- HRESULT hr = E_FAIL;
+ HRESULT hr = S_OK;
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);
+ hr = E_FAIL;
}
- else hr = S_OK;
+ pvaDestroyBuffer(va_display, This->vaBitstream);
This->vaBitstream = VA_INVALID_ID;
return hr;
}
diff --git a/dlls/dxva2/vaapi-mpeg2.c b/dlls/dxva2/vaapi-mpeg2.c
index 7b7f61d..3b4b859 100644
--- a/dlls/dxva2/vaapi-mpeg2.c
+++ b/dlls/dxva2/vaapi-mpeg2.c
@@ -145,13 +145,13 @@ static HRESULT process_picture_parameters( WineVideoDecoderMPEG2Impl *This, cons
return E_FAIL;
}
- /* vaRenderPicture is supposed to destroy the buffer */
status = pvaRenderPicture(va_display, This->context, &vaPictureParam, 1);
+ pvaDestroyBuffer(va_display, vaPictureParam);
+
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;
}
@@ -193,13 +193,13 @@ static HRESULT process_quantization_matrix( WineVideoDecoderMPEG2Impl *This, con
return E_FAIL;
}
- /* vaRenderPicture is supposed to destroy the buffer */
status = pvaRenderPicture(va_display, This->context, &vaIQMatrix, 1);
+ pvaDestroyBuffer(va_display, vaIQMatrix);
+
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;
}
@@ -267,10 +267,12 @@ static HRESULT process_slice_control_buffer( WineVideoDecoderMPEG2Impl *This, co
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)
+ {
+ pvaDestroyBuffer(va_display, vaSliceInfo);
return S_OK;
+ }
ERR("failed to process slice control buffer: %s (0x%x)\n", pvaErrorStr(status), status);
@@ -284,20 +286,19 @@ static HRESULT process_data_buffer( WineVideoDecoderMPEG2Impl *This, const DXVA2
{
VADisplay va_display = IWineVideoService_VADisplay(This->service);
VAStatus status;
- HRESULT hr = E_FAIL;
+ HRESULT hr = S_OK;
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);
+ hr = E_FAIL;
}
- else hr = S_OK;
+ pvaDestroyBuffer(va_display, This->vaBitstream);
This->vaBitstream = VA_INVALID_ID;
return hr;
}
--
2.3.0

View File

@ -2123,6 +2123,9 @@ if test "$enable_dxva2_Video_Decoder" -eq 1; then
patch_apply dxva2-Video_Decoder/0006-dxva2-tests-Add-tests-for-dxva2-decoder.patch
patch_apply dxva2-Video_Decoder/0007-dxva2-Initial-implementation-of-MPEG2-decoder-using-.patch
patch_apply dxva2-Video_Decoder/0008-dxva2-Implement-h264-decoder.patch
patch_apply dxva2-Video_Decoder/0009-dxva2-Add-DRM-mode-for-vaapi.patch
patch_apply dxva2-Video_Decoder/0010-dxva2-Fill-h264-luma-and-chroma-weights-offsets-with.patch
patch_apply dxva2-Video_Decoder/0011-dxva2-Always-destroy-buffers-when-calling-vaRenderPi.patch
(
echo '+ { "Sebastian Lackner", "dxva2: Implement semi-stub for Direct3DDeviceManager9 interface.", 1 },';
echo '+ { "Michael Müller", "dxva2: Implement stubbed interfaces for IDirectXVideo{Acceleration,Decoder,Processor}Service.", 1 },';
@ -2132,6 +2135,9 @@ if test "$enable_dxva2_Video_Decoder" -eq 1; then
echo '+ { "Michael Müller", "dxva2/tests: Add tests for dxva2 decoder.", 1 },';
echo '+ { "Michael Müller", "dxva2: Initial implementation of MPEG2 decoder using vaapi backend.", 1 },';
echo '+ { "Michael Müller", "dxva2: Implement h264 decoder.", 1 },';
echo '+ { "Michael Müller", "dxva2: Add DRM mode for vaapi.", 1 },';
echo '+ { "Michael Müller", "dxva2: Fill h264 luma and chroma weights / offsets with default values in case they are not specified.", 1 },';
echo '+ { "Michael Müller", "dxva2: Always destroy buffers when calling vaRenderPicture.", 1 },';
) >> "$patchlist"
fi