[vlc-devel] [PATCH] direct3d9: add VLC_CODEC_D3D9_OPAQUE_10B to decode 4:2:0 10 bits with DVXA2
Steve Lhomme
robux4 at videolabs.io
Fri Jul 29 17:09:03 CEST 2016
---
include/vlc_fourcc.h | 3 ++-
modules/codec/avcodec/dxva2.c | 42 +++++++++++++++++++++++++++++-----
modules/codec/avcodec/va.c | 9 +++++++-
modules/video_output/win32/direct3d9.c | 29 +++++++++++++++++------
src/misc/fourcc.c | 2 +-
5 files changed, 69 insertions(+), 16 deletions(-)
diff --git a/include/vlc_fourcc.h b/include/vlc_fourcc.h
index 9a7a95c..06e0bba 100644
--- a/include/vlc_fourcc.h
+++ b/include/vlc_fourcc.h
@@ -346,7 +346,8 @@
#define VLC_CODEC_MMAL_OPAQUE VLC_FOURCC('M','M','A','L')
/* DXVA2 opaque video surface for use with D3D9 */
-#define VLC_CODEC_D3D9_OPAQUE VLC_FOURCC('D','X','A','9')
+#define VLC_CODEC_D3D9_OPAQUE VLC_FOURCC('D','X','A','9') /* 4:2:0 8 bpc */
+#define VLC_CODEC_D3D9_OPAQUE_10B VLC_FOURCC('D','X','A','0') /* 4:2:0 10 bpc */
/* D3D11VA opaque video surface for use with D3D11 */
#define VLC_CODEC_D3D11_OPAQUE VLC_FOURCC('D','X','1','1') /* 4:2:0 8 bpc */
diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index ff05db0..936e1df 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -91,6 +91,7 @@ static const d3d_format_t d3d_formats[] = {
{ "YV12", MAKEFOURCC('Y','V','1','2'), VLC_CODEC_YV12 },
{ "NV12", MAKEFOURCC('N','V','1','2'), VLC_CODEC_NV12 },
{ "IMC3", MAKEFOURCC('I','M','C','3'), VLC_CODEC_YV12 },
+ { "P010", MAKEFOURCC('P','0','1','0'), VLC_CODEC_P010 },
{ NULL, 0, 0 }
};
@@ -107,6 +108,7 @@ static const d3d_format_t *D3dFindFormat(D3DFORMAT format)
struct vlc_va_sys_t
{
directx_sys_t dx_sys;
+ vlc_fourcc_t i_chroma;
/* DLL */
HINSTANCE hd3d9_dll;
@@ -176,7 +178,7 @@ static picture_t *video_new_buffer(filter_t *p_filter)
}
static filter_t *CreateFilter( vlc_object_t *p_this, const es_format_t *p_fmt_in,
- vlc_fourcc_t fmt_out )
+ vlc_fourcc_t src_chroma )
{
filter_t *p_filter;
@@ -186,9 +188,20 @@ static filter_t *CreateFilter( vlc_object_t *p_this, const es_format_t *p_fmt_in
p_filter->owner.video.buffer_new = (picture_t *(*)(filter_t *))video_new_buffer;
+ vlc_fourcc_t fmt_out;
+ switch (src_chroma)
+ {
+ case VLC_CODEC_D3D9_OPAQUE_10B:
+ fmt_out = VLC_CODEC_P010;
+ break;
+ case VLC_CODEC_D3D9_OPAQUE:
+ fmt_out = VLC_CODEC_YV12;
+ break;
+ }
+
es_format_InitFromVideo( &p_filter->fmt_in, &p_fmt_in->video );
es_format_InitFromVideo( &p_filter->fmt_out, &p_fmt_in->video );
- p_filter->fmt_in.i_codec = p_filter->fmt_in.video.i_chroma = VLC_CODEC_D3D9_OPAQUE;
+ p_filter->fmt_in.i_codec = p_filter->fmt_in.video.i_chroma = src_chroma;
p_filter->fmt_out.i_codec = p_filter->fmt_out.video.i_chroma = fmt_out;
p_filter->p_module = module_need( p_filter, "video filter2", NULL, false );
@@ -207,7 +220,7 @@ static void Setup(vlc_va_t *va, vlc_fourcc_t *chroma)
{
vlc_va_sys_t *sys = va->sys;
- *chroma = sys->filter == NULL ? VLC_CODEC_D3D9_OPAQUE : VLC_CODEC_YV12;
+ *chroma = sys->filter == NULL ? sys->i_chroma : VLC_CODEC_YV12;
}
void SetupAVCodecContext(vlc_va_t *va)
@@ -228,7 +241,8 @@ static int Extract(vlc_va_t *va, picture_t *picture, uint8_t *data)
{
directx_sys_t *dx_sys = &va->sys->dx_sys;
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data;
- if (picture->format.i_chroma == VLC_CODEC_D3D9_OPAQUE)
+ if ( picture->format.i_chroma == VLC_CODEC_D3D9_OPAQUE ||
+ picture->format.i_chroma == VLC_CODEC_D3D9_OPAQUE_10B )
{
picture_sys_t *p_sys = picture->p_sys;
LPDIRECT3DSURFACE9 output = p_sys->surface;
@@ -308,6 +322,20 @@ static void Close(vlc_va_t *va, AVCodecContext *ctx)
free(sys);
}
+vlc_fourcc_t d3d9va_fourcc(enum PixelFormat swfmt)
+{
+ switch (swfmt)
+ {
+ case AV_PIX_FMT_YUV420P10LE:
+ return VLC_CODEC_D3D9_OPAQUE_10B;
+ case AV_PIX_FMT_YUVJ420P:
+ case AV_PIX_FMT_YUV420P:
+ return VLC_CODEC_D3D9_OPAQUE;
+ default:
+ return VLC_CODEC_D3D9_OPAQUE;
+ }
+}
+
static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
const es_format_t *fmt, picture_sys_t *p_sys)
{
@@ -351,13 +379,15 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
if (p_sys!=NULL)
IDirect3DSurface9_GetDevice(p_sys->surface, (IDirect3DDevice9**) &dx_sys->d3ddev );
+ sys->i_chroma = d3d9va_fourcc(ctx->sw_pix_fmt);
+
err = directx_va_Open(va, &sys->dx_sys, ctx, fmt, true);
if (err!=VLC_SUCCESS)
goto error;
if (p_sys == NULL)
{
- sys->filter = CreateFilter( VLC_OBJECT(va), fmt, VLC_CODEC_YV12);
+ sys->filter = CreateFilter( VLC_OBJECT(va), fmt, sys->i_chroma);
if (sys->filter == NULL)
goto error;
}
@@ -790,7 +820,7 @@ static int DxResetVideoDecoder(vlc_va_t *va)
static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsigned index)
{
video_format_t src_fmt = *fmt;
- src_fmt.i_chroma = VLC_CODEC_D3D9_OPAQUE;
+ src_fmt.i_chroma = va->sys->i_chroma;
picture_sys_t *pic_sys = calloc(1, sizeof(*pic_sys));
if (unlikely(pic_sys == NULL))
return NULL;
diff --git a/modules/codec/avcodec/va.c b/modules/codec/avcodec/va.c
index 0ca991a..8a6b549 100644
--- a/modules/codec/avcodec/va.c
+++ b/modules/codec/avcodec/va.c
@@ -41,7 +41,14 @@ vlc_fourcc_t vlc_va_GetChroma(enum PixelFormat hwfmt, enum PixelFormat swfmt)
return VLC_CODEC_YV12;
case AV_PIX_FMT_DXVA2_VLD:
- return VLC_CODEC_D3D9_OPAQUE;
+ switch (swfmt)
+ {
+ case AV_PIX_FMT_YUV420P10LE:
+ return VLC_CODEC_D3D9_OPAQUE_10B;
+ default:
+ return VLC_CODEC_D3D9_OPAQUE;
+ }
+ break;
#if LIBAVUTIL_VERSION_CHECK(54, 13, 1, 24, 100)
case AV_PIX_FMT_D3D11VA_VLD:
diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index 9372875..1f86c70 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -153,6 +153,18 @@ static void Direct3D9RenderScene(vout_display_t *vd, d3d_region_t *, int, d3d_re
/* */
static int DesktopCallback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
+static bool is_d3d9_opaque(vlc_fourcc_t chroma)
+{
+ switch (chroma)
+ {
+ case VLC_CODEC_D3D9_OPAQUE:
+ case VLC_CODEC_D3D9_OPAQUE_10B:
+ return true;
+ default:
+ return false;
+ }
+}
+
/**
* It creates a Direct3D vout display.
*/
@@ -202,10 +214,10 @@ static int Open(vlc_object_t *object)
/* */
vout_display_info_t info = vd->info;
- info.is_slow = fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE;
+ info.is_slow = !is_d3d9_opaque(fmt.i_chroma);
info.has_double_click = true;
info.has_hide_mouse = false;
- info.has_pictures_invalid = fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE;
+ info.has_pictures_invalid = !is_d3d9_opaque(fmt.i_chroma);
info.has_event_thread = true;
if (var_InheritBool(vd, "direct3d9-hw-blending") &&
sys->d3dregion_format != D3DFMT_UNKNOWN &&
@@ -291,6 +303,8 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
pictures = calloc(count, sizeof(*pictures));
if (!pictures)
goto error;
+
+ D3DFORMAT format = vd->fmt.i_chroma == VLC_CODEC_D3D9_OPAQUE_10B ? MAKEFOURCC('P','0','1','0') : MAKEFOURCC('N','V','1','2');
for (picture_count = 0; picture_count < count; ++picture_count)
{
picture_sys_t *picsys = malloc(sizeof(*picsys));
@@ -300,7 +314,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(vd->sys->d3ddev,
vd->fmt.i_width,
vd->fmt.i_height,
- MAKEFOURCC('N','V','1','2'),
+ format,
D3DPOOL_DEFAULT,
&picsys->surface,
NULL);
@@ -352,7 +366,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
* The clean way would be to release the picture (and ensure that
* the vout doesn't keep a reference). But because of the vout
* wrapper, we can't */
- if ( picture->format.i_chroma != VLC_CODEC_D3D9_OPAQUE )
+ if ( !is_d3d9_opaque(picture->format.i_chroma) )
Direct3D9UnlockSurface(picture);
/* check if device is still available */
@@ -418,7 +432,7 @@ static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
}
/* XXX See Prepare() */
- if ( picture->format.i_chroma != VLC_CODEC_D3D9_OPAQUE )
+ if ( !is_d3d9_opaque(picture->format.i_chroma) )
Direct3D9LockSurface(picture);
picture_Release(picture);
if (subpicture)
@@ -965,6 +979,7 @@ static const d3d_format_t d3d_formats[] = {
{ "YV12", MAKEFOURCC('Y','V','1','2'), VLC_CODEC_J420, 0,0,0 },
{ "NV12", MAKEFOURCC('N','V','1','2'), VLC_CODEC_NV12, 0,0,0 },
{ "DXA9", MAKEFOURCC('N','V','1','2'), VLC_CODEC_D3D9_OPAQUE, 0,0,0 },
+ { "DXA9_10", MAKEFOURCC('P','0','1','0'), VLC_CODEC_D3D9_OPAQUE_10B, 0,0,0 },
{ "UYVY", D3DFMT_UYVY, VLC_CODEC_UYVY, 0,0,0 },
{ "YUY2", D3DFMT_YUY2, VLC_CODEC_YUYV, 0,0,0 },
{ "X8R8G8B8", D3DFMT_X8R8G8B8,VLC_CODEC_RGB32, 0xff0000, 0x00ff00, 0x0000ff },
@@ -986,7 +1001,7 @@ static const d3d_format_t *Direct3DFindFormat(vout_display_t *vd, vlc_fourcc_t c
const vlc_fourcc_t *list;
const vlc_fourcc_t dxva_chroma[] = {chroma, 0};
- if (pass == 0 && chroma == VLC_CODEC_D3D9_OPAQUE)
+ if (pass == 0 && is_d3d9_opaque(chroma))
list = dxva_chroma;
else if (pass == 0 && sys->allow_hw_yuv && vlc_fourcc_IsYUV(chroma))
list = vlc_fourcc_GetYUVFallback(chroma);
@@ -1074,7 +1089,7 @@ static int Direct3D9CreatePool(vout_display_t *vd, video_format_t *fmt)
fmt->i_gmask = d3dfmt->gmask;
fmt->i_bmask = d3dfmt->bmask;
- if ( fmt->i_chroma == VLC_CODEC_D3D9_OPAQUE )
+ if ( is_d3d9_opaque(fmt->i_chroma) )
/* a DXA9 pool will be created when needed */
return VLC_SUCCESS;
diff --git a/src/misc/fourcc.c b/src/misc/fourcc.c
index 45ac301..9e42045 100644
--- a/src/misc/fourcc.c
+++ b/src/misc/fourcc.c
@@ -664,7 +664,7 @@ static const struct
{ { VLC_CODEC_ANDROID_OPAQUE, VLC_CODEC_MMAL_OPAQUE,
VLC_CODEC_D3D9_OPAQUE, VLC_CODEC_D3D11_OPAQUE },
FAKE_FMT() },
- { { VLC_CODEC_D3D11_OPAQUE_10B },
+ { { VLC_CODEC_D3D11_OPAQUE_10B, VLC_CODEC_D3D9_OPAQUE_10B },
FAKE_FMT() },
{ { VLC_CODEC_CVPX_OPAQUE }, FAKE_FMT() },
--
2.8.2
More information about the vlc-devel
mailing list