[vlc-devel] [PATCH] DXVA2: output D3D9 GPU surfaces
Steve Lhomme
robUx4 at videolabs.io
Wed Apr 29 09:39:45 CEST 2015
---
modules/codec/Makefile.am | 2 +-
modules/codec/avcodec/dxva2.c | 128 +++++++++++++-----------------------------
modules/codec/avcodec/va.c | 2 +-
3 files changed, 40 insertions(+), 92 deletions(-)
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index bd89326..b4d6340 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -341,8 +341,8 @@ endif
endif
libdxva2_plugin_la_SOURCES = \
- video_chroma/copy.c video_chroma/copy.h \
codec/avcodec/dxva2.c packetizer/h264_nal.c packetizer/h264_nal.h
+ ../src/win32/direct3d9_pool.c ../src/win32/direct3d9_pool.h
libdxva2_plugin_la_LIBADD = -lole32 -lshlwapi -luuid
if HAVE_AVCODEC_DXVA2
codec_LTLIBRARIES += libdxva2_plugin.la
diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index 52b40bd..9ad9e9f 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -39,7 +39,6 @@
#include <vlc_common.h>
#include <vlc_picture.h>
#include <vlc_fourcc.h>
-#include <vlc_cpu.h>
#include <vlc_plugin.h>
#include <vlc_codecs.h>
@@ -50,7 +49,6 @@
#include "avcodec.h"
#include "va.h"
-#include "../../video_chroma/copy.h"
#include "../../packetizer/h264_nal.h"
static int Open(vlc_va_t *, AVCodecContext *, enum PixelFormat,
@@ -346,10 +344,6 @@ struct vlc_va_sys_t
DXVA2_ConfigPictureDecode cfg;
IDirectXVideoDecoder *decoder;
- /* Option conversion */
- D3DFORMAT output;
- copy_cache_t surface_cache;
-
/* */
struct dxva_context hw;
@@ -366,6 +360,11 @@ struct vlc_va_sys_t
LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
};
+struct picture_sys_t
+{
+ LPDIRECT3DSURFACE9 surface;
+};
+
/* */
static int D3dCreateDevice(vlc_va_t *);
static void D3dDestroyDevice(vlc_va_sys_t *);
@@ -385,9 +384,6 @@ static int DxResetVideoDecoder(vlc_va_t *);
static bool profile_supported(const dxva2_mode_t *mode, const es_format_t *fmt);
-static void DxCreateVideoConversion(vlc_va_sys_t *);
-static void DxDestroyVideoConversion(vlc_va_sys_t *);
-
/* */
static int Setup(vlc_va_t *va, AVCodecContext *avctx, vlc_fourcc_t *chroma)
{
@@ -398,7 +394,6 @@ static int Setup(vlc_va_t *va, AVCodecContext *avctx, vlc_fourcc_t *chroma)
goto ok;
/* */
- DxDestroyVideoConversion(sys);
DxDestroyVideoDecoder(sys);
avctx->hwaccel_context = NULL;
@@ -421,13 +416,9 @@ static int Setup(vlc_va_t *va, AVCodecContext *avctx, vlc_fourcc_t *chroma)
sys->hw.surface = sys->hw_surface;
/* */
- DxCreateVideoConversion(sys);
-
- /* */
ok:
avctx->hwaccel_context = &sys->hw;
- const d3d_format_t *output = D3dFindFormat(sys->output);
- *chroma = output->codec;
+ *chroma = VLC_CODEC_D3D9_OPAQUE;
return VLC_SUCCESS;
}
@@ -436,61 +427,29 @@ static int Extract(vlc_va_t *va, picture_t *picture, uint8_t *data)
{
vlc_va_sys_t *sys = va->sys;
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data;
+ picture_sys_t *p_sys = picture->p_sys;
+ LPDIRECT3DSURFACE9 output = p_sys->surface;
+
+ assert(d3d != output);
+#ifndef NDEBUG
+ LPDIRECT3DDEVICE9 srcDevice, dstDevice;
+ IDirect3DSurface9_GetDevice(d3d, &srcDevice);
+ IDirect3DSurface9_GetDevice(output, &dstDevice);
+ assert(srcDevice == dstDevice);
+#endif
- if (!sys->surface_cache.buffer)
- return VLC_EGENERIC;
-
- /* */
- assert(sys->output == MAKEFOURCC('Y','V','1','2'));
-
- /* */
- D3DLOCKED_RECT lock;
- if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY))) {
- msg_Err(va, "Failed to lock surface");
+ HRESULT hr;
+ RECT visibleSource;
+ visibleSource.left = 0;
+ visibleSource.top = 0;
+ visibleSource.right = picture->format.i_visible_width;
+ visibleSource.bottom = picture->format.i_visible_height;
+ hr = IDirect3DDevice9_StretchRect( sys->d3ddev, d3d, &visibleSource, output, &visibleSource, D3DTEXF_NONE);
+ if (FAILED(hr)) {
+ msg_Err(va, "Failed to copy the hw surface to the decoder surface (hr=0x%0lx)", hr );
return VLC_EGENERIC;
}
- if (sys->render == MAKEFOURCC('Y','V','1','2') ||
- sys->render == MAKEFOURCC('I','M','C','3')) {
- bool imc3 = sys->render == MAKEFOURCC('I','M','C','3');
- size_t chroma_pitch = imc3 ? lock.Pitch : (lock.Pitch / 2);
-
- size_t pitch[3] = {
- lock.Pitch,
- chroma_pitch,
- chroma_pitch,
- };
-
- uint8_t *plane[3] = {
- (uint8_t*)lock.pBits,
- (uint8_t*)lock.pBits + pitch[0] * sys->surface_height,
- (uint8_t*)lock.pBits + pitch[0] * sys->surface_height
- + pitch[1] * sys->surface_height / 2,
- };
-
- if (imc3) {
- uint8_t *V = plane[1];
- plane[1] = plane[2];
- plane[2] = V;
- }
- CopyFromYv12(picture, plane, pitch, sys->width, sys->height,
- &sys->surface_cache);
- } else {
- assert(sys->render == MAKEFOURCC('N','V','1','2'));
- uint8_t *plane[2] = {
- lock.pBits,
- (uint8_t*)lock.pBits + lock.Pitch * sys->surface_height
- };
- size_t pitch[2] = {
- lock.Pitch,
- lock.Pitch,
- };
- CopyFromNv12(picture, plane, pitch, sys->width, sys->height,
- &sys->surface_cache);
- }
-
- /* */
- IDirect3DSurface9_UnlockRect(d3d);
return VLC_SUCCESS;
}
@@ -557,7 +516,6 @@ static void Close(vlc_va_t *va, AVCodecContext *ctx)
vlc_va_sys_t *sys = va->sys;
(void) ctx;
- DxDestroyVideoConversion(sys);
DxDestroyVideoDecoder(sys);
DxDestroyVideoService(sys);
D3dDestroyDeviceManager(sys);
@@ -603,12 +561,20 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
}
msg_Dbg(va, "DLLs loaded");
- /* */
- if (D3dCreateDevice(va)) {
- msg_Err(va, "Failed to create Direct3D device");
- goto error;
+ sys->d3ddev = NULL;
+ if (p_sys!=NULL)
+ IDirect3DSurface9_GetDevice(p_sys->surface, &sys->d3ddev);
+
+ if (sys->d3ddev) {
+ msg_Dbg(va, "Reusing D3D9 device");
+ } else {
+ /* */
+ if (D3dCreateDevice(va)) {
+ msg_Err(va, "Failed to create Direct3D device");
+ goto error;
+ }
+ msg_Dbg(va, "D3dCreateDevice succeed");
}
- msg_Dbg(va, "D3dCreateDevice succeed");
if (D3dCreateDeviceManager(va)) {
msg_Err(va, "D3dCreateDeviceManager failed");
@@ -1148,21 +1114,3 @@ static int DxResetVideoDecoder(vlc_va_t *va)
return VLC_EGENERIC;
}
-static void DxCreateVideoConversion(vlc_va_sys_t *va)
-{
- switch (va->render) {
- case MAKEFOURCC('N','V','1','2'):
- case MAKEFOURCC('I','M','C','3'):
- va->output = MAKEFOURCC('Y','V','1','2');
- break;
- default:
- va->output = va->render;
- break;
- }
- CopyInitCache(&va->surface_cache, va->surface_width);
-}
-
-static void DxDestroyVideoConversion(vlc_va_sys_t *va)
-{
- CopyCleanCache(&va->surface_cache);
-}
diff --git a/modules/codec/avcodec/va.c b/modules/codec/avcodec/va.c
index 413574d..f9e94e6 100644
--- a/modules/codec/avcodec/va.c
+++ b/modules/codec/avcodec/va.c
@@ -41,7 +41,7 @@ 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_YV12;
+ return VLC_CODEC_D3D9_OPAQUE;
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(53, 14, 0))
case AV_PIX_FMT_VDA_VLD:
return VLC_CODEC_UYVY;
--
2.3.2
More information about the vlc-devel
mailing list