dxva2: the decoder sets the surface in the picture->context, not picture_sys_t
authorSteve Lhomme <robux4@videolabs.io>
Mon, 29 May 2017 14:23:13 +0000 (16:23 +0200)
committerJean-Baptiste Kempf <jb@videolan.org>
Tue, 13 Jun 2017 12:44:04 +0000 (14:44 +0200)
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
modules/codec/avcodec/dxva2.c
modules/video_chroma/d3d9_fmt.h
modules/video_chroma/dxa9.c
modules/video_output/win32/direct3d9.c

index 46e8c6b..e549743 100644 (file)
@@ -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 = (struct va_pic_context*)picture->context;
+    directx_va_AddRef(pic_ctx->va_surface);
     return VLC_SUCCESS;
 }
 
@@ -222,13 +200,49 @@ static int CheckDevice(vlc_va_t *va)
     return VLC_SUCCESS;
 }
 
+static void d3d9_pic_context_destroy(struct picture_context_t *opaque)
+{
+    struct va_pic_context *pic_ctx = (struct va_pic_context*)opaque;
+    if (pic_ctx->va_surface)
+    {
+        ReleasePictureSys(&pic_ctx->picsys);
+        directx_va_Release(pic_ctx->va_surface);
+        free(pic_ctx);
+    }
+}
+
+static struct picture_context_t *CreatePicContext(vlc_va_surface_t *);
+
+static struct picture_context_t *d3d9_pic_context_copy(struct picture_context_t *ctx)
+{
+    struct va_pic_context *src_ctx = (struct va_pic_context*)ctx;
+    return CreatePicContext(src_ctx->va_surface);
+}
+
+static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
+{
+    struct va_pic_context *pic_ctx = calloc(1, sizeof(*pic_ctx));
+    if (unlikely(pic_ctx==NULL))
+        return NULL;
+    pic_ctx->va_surface = va_surface;
+    directx_va_AddRef(pic_ctx->va_surface);
+    pic_ctx->s.destroy = d3d9_pic_context_destroy;
+    pic_ctx->s.copy    = d3d9_pic_context_copy;
+    pic_ctx->picsys.surface = va_surface->decoderSurface;
+    IDirect3DSurface9_AddRef(pic_ctx->picsys.surface);
+    return &pic_ctx->s;
+}
+
 static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
 {
     vlc_va_surface_t *va_surface = directx_va_Get(va, &va->sys->dx_sys);
     if (unlikely(va_surface==NULL))
         return VLC_EGENERIC;
+    pic->context = CreatePicContext(va_surface);
+    directx_va_Release(va_surface);
+    if (unlikely(pic->context==NULL))
+        return VLC_EGENERIC;
     *data = (uint8_t*)va_surface->decoderSurface;
-    pic->p_sys->va_surface = va_surface;
     return VLC_SUCCESS;
 }
 
@@ -265,8 +279,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 = (struct va_pic_context*)pic->context;
+    directx_va_Release(pic_ctx->va_surface);
     picture_Release(pic);
 }
 
index fdf778d..fe96099 100644 (file)
 #ifndef VLC_VIDEOCHROMA_D3D9_FMT_H_
 #define VLC_VIDEOCHROMA_D3D9_FMT_H_
 
+#include <vlc_picture.h>
+
 typedef struct vlc_va_surface_t vlc_va_surface_t;
 
 /* owned by the vout for VLC_CODEC_D3D9_OPAQUE */
 struct picture_sys_t
 {
     LPDIRECT3DSURFACE9 surface;
-    vlc_va_surface_t              *va_surface;
+};
+
+/* owned by the hardware decoder */
+struct va_pic_context
+{
+    picture_context_t          s;
+    struct picture_sys_t       picsys;
+    vlc_va_surface_t           *va_surface;
 };
 
 static inline void ReleasePictureSys(picture_sys_t *p_sys)
index afd8fc4..ca30f93 100644 (file)
@@ -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')) {
@@ -157,7 +159,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)
index 22e4259..a41c0b8 100644 (file)
@@ -465,6 +465,23 @@ 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 = (struct va_pic_context*)picture->context;
+        if (picture->p_sys && pic_ctx->picsys.surface != picture->p_sys->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, 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);