[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