[vlc-devel] [PATCH 34/39] dxva2: the decoder sets the surface in the picture->context, not picture_sys_t

Steve Lhomme robux4 at videolabs.io
Fri Jun 2 16:46:37 CEST 2017


---
 modules/codec/avcodec/dxva2.c          | 55 +++++++++++++++++-----------------
 modules/video_chroma/d3d9_fmt.h        |  7 +++++
 modules/video_chroma/dxa9.c            | 10 ++++---
 modules/video_output/win32/direct3d9.c | 14 +++++++++
 4 files changed, 54 insertions(+), 32 deletions(-)

diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index 48c1027eeb..4d2a0cc1fa 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -178,31 +178,9 @@ void SetupAVCodecContext(vlc_va_t *va)
 
 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;
-    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
-
-    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( dx_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;
-    }
-
+    VLC_UNUSED(va); VLC_UNUSED(data);
+    struct va_pic_context *pic_ctx = picture->context;
+    directx_va_AddRef(pic_ctx->va_surface);
     return VLC_SUCCESS;
 }
 
@@ -222,13 +200,34 @@ static int CheckDevice(vlc_va_t *va)
     return VLC_SUCCESS;
 }
 
+static void d3d9_pic_context_destroy(void *opaque)
+{
+    struct va_pic_context *pic_ctx = opaque;
+    if (pic_ctx->va_surface)
+    {
+        ReleasePictureSys(&pic_ctx->picsys);
+        directx_va_Release(pic_ctx->va_surface);
+        free(pic_ctx);
+    }
+}
+
 static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
 {
+    struct va_pic_context *pic_ctx = calloc(1, sizeof(*pic_ctx));
+    if (unlikely(pic_ctx==NULL))
+        return VLC_ENOMEM;
+    pic_ctx->pf_destroy = d3d9_pic_context_destroy;
     vlc_va_surface_t *va_surface = directx_va_Get(va, &va->sys->dx_sys);
     if (unlikely(va_surface==NULL))
+    {
+        free(pic_ctx);
         return VLC_EGENERIC;
+    }
     *data = (uint8_t*)va_surface->decoderSurface;
-    pic->p_sys->va_surface = va_surface;
+    pic_ctx->va_surface = va_surface;
+    pic_ctx->picsys.surface = va_surface->decoderSurface;
+    IDirect3DSurface9_AddRef(va_surface->decoderSurface);
+    pic->context = pic_ctx;
     return VLC_SUCCESS;
 }
 
@@ -265,8 +264,8 @@ static void ReleasePic(void *opaque, uint8_t *data)
 {
     (void)data;
     picture_t *pic = opaque;
-    directx_va_Release(pic->p_sys->va_surface);
-    pic->p_sys->va_surface = NULL;
+    struct va_pic_context *pic_ctx = pic->context;
+    directx_va_Release(pic_ctx->va_surface);
     picture_Release(pic);
 }
 
diff --git a/modules/video_chroma/d3d9_fmt.h b/modules/video_chroma/d3d9_fmt.h
index fdf778dcd9..67e863539e 100644
--- a/modules/video_chroma/d3d9_fmt.h
+++ b/modules/video_chroma/d3d9_fmt.h
@@ -29,6 +29,13 @@ typedef struct vlc_va_surface_t vlc_va_surface_t;
 struct picture_sys_t
 {
     LPDIRECT3DSURFACE9 surface;
+};
+
+/* owned by the hardware decoder */
+struct va_pic_context
+{
+    void (*pf_destroy)(void *); /* must be first @ref picture_Release() */
+    struct picture_sys_t          picsys;
     vlc_va_surface_t              *va_surface;
 };
 
diff --git a/modules/video_chroma/dxa9.c b/modules/video_chroma/dxa9.c
index ec1e2d27fc..bc4a821c37 100644
--- a/modules/video_chroma/dxa9.c
+++ b/modules/video_chroma/dxa9.c
@@ -70,10 +70,11 @@ static bool GetLock(filter_t *p_filter, LPDIRECT3DSURFACE9 d3d,
 static void DXA9_YV12(filter_t *p_filter, picture_t *src, picture_t *dst)
 {
     copy_cache_t *p_copy_cache = (copy_cache_t*) p_filter->p_sys;
+    picture_sys_t *p_sys = &((struct va_pic_context *)src->context)->picsys;
 
     D3DSURFACE_DESC desc;
     D3DLOCKED_RECT lock;
-    if (!GetLock(p_filter, src->p_sys->surface, &lock, &desc))
+    if (!GetLock(p_filter, p_sys->surface, &lock, &desc))
         return;
 
     if (dst->format.i_chroma == VLC_CODEC_I420) {
@@ -129,16 +130,17 @@ static void DXA9_YV12(filter_t *p_filter, picture_t *src, picture_t *dst)
     }
 
     /* */
-    IDirect3DSurface9_UnlockRect(src->p_sys->surface);
+    IDirect3DSurface9_UnlockRect(p_sys->surface);
 }
 
 static void DXA9_NV12(filter_t *p_filter, picture_t *src, picture_t *dst)
 {
     copy_cache_t *p_copy_cache = (copy_cache_t*) p_filter->p_sys;
+    picture_sys_t *p_sys = &((struct va_pic_context *)src->context)->picsys;
 
     D3DSURFACE_DESC desc;
     D3DLOCKED_RECT lock;
-    if (!GetLock(p_filter, src->p_sys->surface, &lock, &desc))
+    if (!GetLock(p_filter, p_sys->surface, &lock, &desc))
         return;
 
     if (desc.Format == MAKEFOURCC('N','V','1','2')) {
@@ -156,7 +158,7 @@ static void DXA9_NV12(filter_t *p_filter, picture_t *src, picture_t *dst)
     }
 
     /* */
-    IDirect3DSurface9_UnlockRect(src->p_sys->surface);
+    IDirect3DSurface9_UnlockRect(p_sys->surface);
 }
 
 VIDEO_FILTER_WRAPPER (DXA9_YV12)
diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
index dacc850c8f..07e865c580 100644
--- a/modules/video_output/win32/direct3d9.c
+++ b/modules/video_output/win32/direct3d9.c
@@ -465,6 +465,20 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
      * wrapper, we can't */
     if ( !is_d3d9_opaque(picture->format.i_chroma) )
         Direct3D9UnlockSurface(picture);
+    else if (picture->context)
+    {
+        const struct va_pic_context *pic_ctx = picture->context;
+        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, pic_ctx->picsys.surface, &visibleSource, surface, &visibleSource, D3DTEXF_NONE);
+        if (FAILED(hr)) {
+            msg_Err(vd, "Failed to copy the hw surface to the decoder surface (hr=0x%0lx)", hr );
+        }
+    }
 
     /* check if device is still available */
     HRESULT hr = IDirect3DDevice9_TestCooperativeLevel(sys->d3ddev);
-- 
2.12.1



More information about the vlc-devel mailing list