[vlc-devel] [PATCH 3/4] d3d11va: use the same output format order as the vout for safer compatibility
Steve Lhomme
robux4 at gmail.com
Mon Jul 20 13:33:06 CEST 2015
From: Steve Lhomme <robUx4 at gmail.com>
in debug builds log all the support DXGI output formats
---
modules/codec/Makefile.am | 1 +
modules/codec/avcodec/d3d11va.c | 64 +++++++++++++++--------
modules/video_chroma/dxgi_fmt.c | 98 +++++++++++++++++++++++++++++++++++
modules/video_chroma/dxgi_fmt.h | 43 +++++++++++++++
modules/video_output/Makefile.am | 1 +
modules/video_output/msw/direct3d11.c | 67 +++++++-----------------
6 files changed, 203 insertions(+), 71 deletions(-)
create mode 100644 modules/video_chroma/dxgi_fmt.c
create mode 100644 modules/video_chroma/dxgi_fmt.h
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index 4ae29ac..b1fdcf8 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -359,6 +359,7 @@ endif
libd3d11va_plugin_la_SOURCES = \
codec/avcodec/d3d11va.c codec/avcodec/directx_va.c codec/avcodec/directx_va.h \
+ video_chroma/dxgi_fmt.c video_chroma/dxgi_fmt.h \
packetizer/h264_nal.c packetizer/h264_nal.h
libd3d11va_plugin_la_LIBADD = -lole32 -luuid
if HAVE_AVCODEC_D3D11VA
diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index 54a30ca..d00e634 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -44,9 +44,11 @@
#include "directx_va.h"
#define COBJMACROS
+#define INITGUID
+#include <d3d11.h>
#include <libavcodec/d3d11va.h>
-#include "../../video_chroma/copy.h"
+#include "../../video_chroma/dxgi_fmt.h"
static int Open(vlc_va_t *, AVCodecContext *, enum PixelFormat,
const es_format_t *, picture_sys_t *p_sys);
@@ -618,38 +620,54 @@ static int DxSetupOutput(vlc_va_t *va, const GUID *input)
directx_sys_t *dx_sys = &va->sys->dx_sys;
HRESULT hr;
- /* */
- BOOL is_supported = false;
- hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice*) dx_sys->d3ddec, input, DXGI_FORMAT_NV12, &is_supported);
- if (SUCCEEDED(hr) && is_supported)
- msg_Dbg(va, "NV12 is supported for output");
+#ifndef NDEBUG
+ BOOL bSupported = false;
+ for (int format = 0; format < 188; format++) {
+ hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice*) dx_sys->d3ddec, input, format, &bSupported);
+ if (SUCCEEDED(hr) && bSupported)
+ msg_Dbg(va, "format %s is supported for output", DxgiFormatToStr(format));
+ }
+#endif
+ DXGI_FORMAT processorInput[4];
+ int idx = 0;
if ( va->sys->render != DXGI_FORMAT_UNKNOWN )
+ processorInput[idx++] = va->sys->render;
+ processorInput[idx++] = DXGI_FORMAT_NV12;
+ processorInput[idx++] = DXGI_FORMAT_UNKNOWN;
+
+ /* */
+ for (idx = 0; processorInput[idx] != DXGI_FORMAT_UNKNOWN; ++idx)
{
- is_supported = false;
- hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice*) dx_sys->d3ddec, input, va->sys->render, &is_supported);
+ BOOL is_supported = false;
+ hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice*) dx_sys->d3ddec, input, processorInput[idx], &is_supported);
if (SUCCEEDED(hr) && is_supported)
+ msg_Dbg(va, "%s is supported for output", DxgiFormatToStr(processorInput[idx]));
+ else
{
- /* We have our solution */
- msg_Dbg(va, "Using decoder output from picture source.");
- return VLC_SUCCESS;
+ msg_Dbg(va, "Can't get a decoder for output format %s.", DxgiFormatToStr(processorInput[idx]));
+ continue;
}
- msg_Dbg(va, "Output format from picture source not supported.");
- return VLC_EGENERIC;
- }
- else
- {
- /* */
- is_supported = false;
- hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice*) dx_sys->d3ddec, input, DXGI_FORMAT_NV12, &is_supported);
- if (SUCCEEDED(hr) && is_supported)
+
+ // check if we can create render texture of that format
+ // check the decoder can output to that format
+ const UINT i_quadSupportFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_LOAD;
+ UINT i_formatSupport;
+ bool b_needsProcessor = true;
+ if( SUCCEEDED( ID3D11Device_CheckFormatSupport((ID3D11Device*) dx_sys->d3ddev,
+ processorInput[idx],
+ &i_formatSupport)) &&
+ ( i_formatSupport & i_quadSupportFlags ) == i_quadSupportFlags )
+ b_needsProcessor = false;
+
+ if ( !b_needsProcessor )
{
- /* We have our solution */
- msg_Dbg(va, "Using decoder output NV12");
- va->sys->render = DXGI_FORMAT_NV12;
+ va->sys->render = processorInput[idx];
return VLC_SUCCESS;
}
}
+
+ msg_Dbg(va, "Output format from picture source not supported.");
return VLC_EGENERIC;
}
diff --git a/modules/video_chroma/dxgi_fmt.c b/modules/video_chroma/dxgi_fmt.c
new file mode 100644
index 0000000..9772652
--- /dev/null
+++ b/modules/video_chroma/dxgi_fmt.c
@@ -0,0 +1,98 @@
+/*****************************************************************************
+ * d3d11_surface.c : D3D11 GPU surface conversion module for vlc
+ *****************************************************************************
+ * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
+ *
+ * Authors: Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program 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 program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "dxgi_fmt.h"
+
+typedef struct
+{
+ const char *name;
+ DXGI_FORMAT format;
+} dxgi_format_t;
+
+static const dxgi_format_t dxgi_formats[] = {
+ { "NV12", DXGI_FORMAT_NV12 },
+ { "I420_OPAQUE", DXGI_FORMAT_420_OPAQUE },
+ { "RGBA", DXGI_FORMAT_R8G8B8A8_UNORM },
+ { "RGBA_SRGB", DXGI_FORMAT_R8G8B8A8_UNORM_SRGB },
+ { "BGRX", DXGI_FORMAT_B8G8R8X8_UNORM },
+ { "BGRA", DXGI_FORMAT_B8G8R8A8_UNORM },
+ { "BGRA_SRGB", DXGI_FORMAT_B8G8R8A8_UNORM_SRGB },
+ { "AYUV", DXGI_FORMAT_AYUV },
+ { "YUY2", DXGI_FORMAT_YUY2 },
+ { "AI44", DXGI_FORMAT_AI44 },
+ { "P8", DXGI_FORMAT_P8 },
+ { "A8P8", DXGI_FORMAT_A8P8 },
+ { "B5G6R5", DXGI_FORMAT_B5G6R5_UNORM },
+ { "Y416", DXGI_FORMAT_Y416 },
+ { "P010", DXGI_FORMAT_P010 },
+ { "Y210", DXGI_FORMAT_Y210 },
+ { "Y410", DXGI_FORMAT_Y410 },
+ { "NV11", DXGI_FORMAT_NV11 },
+ { "UNKNOWN", DXGI_FORMAT_UNKNOWN },
+
+ { NULL, 0,}
+};
+
+static const d3d_format_t d3d_formats[] = {
+ { "I420", DXGI_FORMAT_NV12, VLC_CODEC_I420, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
+ { "YV12", DXGI_FORMAT_NV12, VLC_CODEC_YV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
+ { "NV12", DXGI_FORMAT_NV12, VLC_CODEC_NV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
+ { "VA_NV12", DXGI_FORMAT_NV12, VLC_CODEC_D3D11_OPAQUE, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
+#ifdef BROKEN_PIXEL
+ { "YUY2", DXGI_FORMAT_YUY2, VLC_CODEC_I422, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
+ { "AYUV", DXGI_FORMAT_AYUV, VLC_CODEC_YUVA, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
+ { "Y416", DXGI_FORMAT_Y416, VLC_CODEC_I444_16L, DXGI_FORMAT_R16G16B16A16_UINT, 0 },
+#endif
+#ifdef UNTESTED
+ { "P010", DXGI_FORMAT_P010, VLC_CODEC_I420_10L, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM },
+ { "Y210", DXGI_FORMAT_Y210, VLC_CODEC_I422_10L, DXGI_FORMAT_R16G16B16A16_UNORM, 0 },
+ { "Y410", DXGI_FORMAT_Y410, VLC_CODEC_I444_10L, DXGI_FORMAT_R10G10B10A2_UNORM, 0 },
+ { "NV11", DXGI_FORMAT_NV11, VLC_CODEC_I411, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
+#endif
+ { "R8G8B8A8", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
+ { "VA_RGBA", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_D3D11_OPAQUE, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
+ { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_BGRA, DXGI_FORMAT_B8G8R8A8_UNORM, 0 },
+ { "VA_BGRA", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_D3D11_OPAQUE, DXGI_FORMAT_B8G8R8A8_UNORM, 0 },
+ { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM, VLC_CODEC_RGB32, DXGI_FORMAT_B8G8R8X8_UNORM, 0 },
+ { "B5G6R5", DXGI_FORMAT_B5G6R5_UNORM, VLC_CODEC_RGB16, DXGI_FORMAT_B5G6R5_UNORM, 0 },
+
+ { NULL, 0, 0, 0, 0}
+};
+
+const char *DxgiFormatToStr(DXGI_FORMAT format)
+{
+ for (const dxgi_format_t *f = dxgi_formats; f->name != NULL; ++f)
+ {
+ if (f->format == format)
+ return f->name;
+ }
+ return NULL;
+}
+
+const d3d_format_t *GetRenderFormatList(void)
+{
+ return d3d_formats;
+}
diff --git a/modules/video_chroma/dxgi_fmt.h b/modules/video_chroma/dxgi_fmt.h
new file mode 100644
index 0000000..4a0c03d
--- /dev/null
+++ b/modules/video_chroma/dxgi_fmt.h
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * d3d11_surface.c : DXGI helper calls
+ *****************************************************************************
+ * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
+ *
+ * Authors: Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program 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 program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef _VLC_VIDEOCHROMA_DXGI_H
+#define _VLC_VIDEOCHROMA_DXGI_H 1
+
+#include <dxgiformat.h>
+
+#include <vlc_common.h>
+#include <vlc_fourcc.h>
+
+typedef struct
+{
+ const char *name;
+ DXGI_FORMAT formatTexture;
+ vlc_fourcc_t fourcc;
+ DXGI_FORMAT formatY;
+ DXGI_FORMAT formatUV;
+} d3d_format_t;
+
+extern const char *DxgiFormatToStr(DXGI_FORMAT format);
+extern const d3d_format_t *GetRenderFormatList(void);
+
+#endif /* _VLC_VIDEOCHROMA_DXGI_H */
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index fb5b20d..be79e90 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -178,6 +178,7 @@ vout_LTLIBRARIES += $(LTLIBdirect3d9)
EXTRA_LTLIBRARIES += libdirect3d9_plugin.la
libdirect3d11_plugin_la_SOURCES = video_output/msw/direct3d11.c \
+ video_chroma/dxgi_fmt.c video_chroma/dxgi_fmt.h \
video_output/msw/common.c video_output/msw/common.h
libdirect3d11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_direct3d11
diff --git a/modules/video_output/msw/direct3d11.c b/modules/video_output/msw/direct3d11.c
index e58287f..9894a78 100644
--- a/modules/video_output/msw/direct3d11.c
+++ b/modules/video_output/msw/direct3d11.c
@@ -38,6 +38,8 @@
#include "common.h"
+#include "../../video_chroma/dxgi_fmt.h"
+
#if !VLC_WINSTORE_APP
# if USE_DXGI
# define D3D11CreateDeviceAndSwapChain(args...) sys->OurD3D11CreateDeviceAndSwapChain(args)
@@ -78,39 +80,6 @@ vlc_module_begin ()
set_callbacks(Open, Close)
vlc_module_end ()
-typedef struct
-{
- const char *name;
- DXGI_FORMAT formatTexture;
- vlc_fourcc_t fourcc;
- DXGI_FORMAT formatY;
- DXGI_FORMAT formatUV;
-} d3d_format_t;
-
-static const d3d_format_t d3d_formats[] = {
- { "I420", DXGI_FORMAT_NV12, VLC_CODEC_I420, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
- { "YV12", DXGI_FORMAT_NV12, VLC_CODEC_YV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
- { "NV12", DXGI_FORMAT_NV12, VLC_CODEC_NV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
- { "VA_NV12", DXGI_FORMAT_NV12, VLC_CODEC_D3D11_OPAQUE, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
-#ifdef BROKEN_PIXEL
- { "YUY2", DXGI_FORMAT_YUY2, VLC_CODEC_I422, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
- { "AYUV", DXGI_FORMAT_AYUV, VLC_CODEC_YUVA, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
- { "Y416", DXGI_FORMAT_Y416, VLC_CODEC_I444_16L, DXGI_FORMAT_R16G16B16A16_UINT, 0 },
-#endif
-#ifdef UNTESTED
- { "P010", DXGI_FORMAT_P010, VLC_CODEC_I420_10L, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM },
- { "Y210", DXGI_FORMAT_Y210, VLC_CODEC_I422_10L, DXGI_FORMAT_R16G16B16A16_UNORM, 0 },
- { "Y410", DXGI_FORMAT_Y410, VLC_CODEC_I444_10L, DXGI_FORMAT_R10G10B10A2_UNORM, 0 },
- { "NV11", DXGI_FORMAT_NV11, VLC_CODEC_I411, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
-#endif
- { "R8G8B8A8", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
- { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_BGRA, DXGI_FORMAT_B8G8R8A8_UNORM, 0 },
- { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM, VLC_CODEC_RGB32, DXGI_FORMAT_B8G8R8X8_UNORM, 0 },
- { "B5G6R5", DXGI_FORMAT_B5G6R5_UNORM, VLC_CODEC_RGB16, DXGI_FORMAT_B5G6R5_UNORM, 0 },
-
- { NULL, 0, 0, 0, 0}
-};
-
#ifdef HAVE_ID3D11VIDEODECODER
/* VLC_CODEC_D3D11_OPAQUE */
struct picture_sys_t
@@ -1028,20 +997,21 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
// look for the request pixel format first
UINT i_quadSupportFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_LOAD;
UINT i_formatSupport;
- for (unsigned i = 0; d3d_formats[i].name != 0; i++)
+ for (const d3d_format_t *output_format = GetRenderFormatList();
+ output_format->name != NULL; ++output_format)
{
- if( i_src_chroma == d3d_formats[i].fourcc)
+ if( i_src_chroma == output_format->fourcc)
{
if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys->d3ddevice,
- d3d_formats[i].formatTexture,
+ output_format->formatTexture,
&i_formatSupport)) &&
( i_formatSupport & i_quadSupportFlags ) == i_quadSupportFlags )
{
- msg_Dbg(vd, "Using pixel format %s", d3d_formats[i].name );
- fmt->i_chroma = d3d_formats[i].fourcc;
- sys->picQuadConfig.textureFormat = d3d_formats[i].formatTexture;
- sys->picQuadConfig.resourceFormatYRGB = d3d_formats[i].formatY;
- sys->picQuadConfig.resourceFormatUV = d3d_formats[i].formatUV;
+ msg_Dbg(vd, "Using pixel format %s", output_format->name );
+ fmt->i_chroma = output_format->fourcc;
+ sys->picQuadConfig.textureFormat = output_format->formatTexture;
+ sys->picQuadConfig.resourceFormatYRGB = output_format->formatY;
+ sys->picQuadConfig.resourceFormatUV = output_format->formatUV;
break;
}
}
@@ -1050,18 +1020,19 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
// look for any pixel format that we can handle
if ( !fmt->i_chroma )
{
- for (unsigned i = 0; d3d_formats[i].name != 0; i++)
+ for (const d3d_format_t *output_format = GetRenderFormatList();
+ output_format->name != NULL; ++output_format)
{
if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys->d3ddevice,
- d3d_formats[i].formatTexture,
+ output_format->formatTexture,
&i_formatSupport)) &&
( i_formatSupport & i_quadSupportFlags ) == i_quadSupportFlags )
{
- msg_Dbg(vd, "Using pixel format %s", d3d_formats[i].name );
- fmt->i_chroma = d3d_formats[i].fourcc;
- sys->picQuadConfig.textureFormat = d3d_formats[i].formatTexture;
- sys->picQuadConfig.resourceFormatYRGB = d3d_formats[i].formatY;
- sys->picQuadConfig.resourceFormatUV = d3d_formats[i].formatUV;
+ msg_Dbg(vd, "Using pixel format %s", output_format->name );
+ fmt->i_chroma = output_format->fourcc;
+ sys->picQuadConfig.textureFormat = output_format->formatTexture;
+ sys->picQuadConfig.resourceFormatYRGB = output_format->formatY;
+ sys->picQuadConfig.resourceFormatUV = output_format->formatUV;
break;
}
}
--
2.4.2
More information about the vlc-devel
mailing list