[vlc-devel] [PATCH 11/23] dxva: create the context copy when calling va_pool_Get()

Steve Lhomme robux4 at videolabs.io
Wed Jun 21 14:14:56 CEST 2017


via a pf_new_surface_context callback
---
 modules/codec/avcodec/d3d11va.c             | 61 ++++++++++++++++-------------
 modules/codec/avcodec/dxva2.c               | 35 +++++++++++------
 modules/codec/avcodec/va_surface.c          | 24 +++++++-----
 modules/codec/avcodec/va_surface_internal.h |  7 +++-
 4 files changed, 76 insertions(+), 51 deletions(-)

diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c
index 1623cfb331..dc40fa98f1 100644
--- a/modules/codec/avcodec/d3d11va.c
+++ b/modules/codec/avcodec/d3d11va.c
@@ -237,6 +237,35 @@ done:
     return pic_ctx;
 }
 
+static picture_context_t* NewSurfacePicContext(vlc_va_t *va, vlc_va_surface_t *va_surface, ID3D11VideoDecoderOutputView *surface)
+{
+    ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW];
+    ID3D11Resource *p_resource;
+    ID3D11VideoDecoderOutputView_GetResource(surface, &p_resource);
+
+    D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
+    ID3D11VideoDecoderOutputView_GetDesc(surface, &viewDesc);
+
+    for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++)
+        resourceView[i] = va->sys->resourceView[viewDesc.Texture2D.ArraySlice*D3D11_MAX_SHADER_VIEW + i];
+
+    struct va_pic_context *pic_ctx = CreatePicContext(va_surface,
+                                                  surface,
+                                                  p_resource,
+                                                  va->sys->d3dctx,
+                                                  viewDesc.Texture2D.ArraySlice,
+                                                  resourceView);
+    ID3D11Resource_Release(p_resource);
+    if (unlikely(pic_ctx==NULL))
+        return NULL;
+    /* all the resources are acquired during surfaces init, and a second time in
+     * CreatePicContext(), undo one of them otherwise we need an extra release
+     * when the pool is emptied */
+    ReleasePictureSys(&pic_ctx->picsys);
+    va_surface->decoderSurface = surface;
+    return &pic_ctx->s;
+}
+
 static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
 {
 #if D3D11_DIRECT_DECODE
@@ -276,34 +305,9 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
     else
 #endif
     {
-        ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW];
-        vlc_va_surface_t *va_surface = va_pool_Get(va, &va->sys->dx_sys.va_pool);
-        if (unlikely(va_surface==NULL))
-            return VLC_EGENERIC;
-
-        ID3D11Resource *p_resource;
-        ID3D11VideoDecoderOutputView_GetResource(va_surface->decoderSurface, &p_resource);
-
-        D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc;
-        ID3D11VideoDecoderOutputView_GetDesc(va_surface->decoderSurface, &viewDesc);
-
-        for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++)
-            resourceView[i] = va->sys->resourceView[viewDesc.Texture2D.ArraySlice*D3D11_MAX_SHADER_VIEW + i];
-
-        struct va_pic_context *pic_ctx = CreatePicContext( va_surface,
-                                                              va_surface->decoderSurface,
-                                                              p_resource,
-                                                              va->sys->d3dctx,
-                                                              viewDesc.Texture2D.ArraySlice,
-                                                              resourceView );
-
-        ID3D11Resource_Release(p_resource);
-        if (unlikely(pic_ctx==NULL))
-        {
-            va_surface_Release(va_surface);
-            return VLC_ENOMEM;
-        }
-        pic->context = &pic_ctx->s;
+        int res = va_pool_Get(va, pic, &va->sys->dx_sys.va_pool);
+        if (unlikely(res != VLC_SUCCESS))
+            return res;
     }
     *data = (uint8_t*)((struct va_pic_context *)pic->context)->picsys.decoder;
     return VLC_SUCCESS;
@@ -372,6 +376,7 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
     dx_sys->va_pool.pf_create_decoder_surfaces = DxCreateDecoderSurfaces;
     dx_sys->va_pool.pf_destroy_surfaces        = DxDestroySurfaces;
     dx_sys->va_pool.pf_setup_avcodec_ctx       = SetupAVCodecContext;
+    dx_sys->va_pool.pf_new_surface_context     = NewSurfacePicContext;
     dx_sys->pf_get_input_list          = DxGetInputList;
     dx_sys->pf_setup_output            = DxSetupOutput;
     dx_sys->psz_decoder_dll            = TEXT("D3D11.DLL");
diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index 7795ec5f41..9ef29ce803 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -193,15 +193,18 @@ static void d3d9_pic_context_destroy(struct picture_context_t *opaque)
     }
 }
 
-static struct picture_context_t *CreatePicContext(vlc_va_surface_t *);
+static struct va_pic_context *CreatePicContext(vlc_va_surface_t *, IDirect3DSurface9 *);
 
 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);
+    struct va_pic_context *pic_ctx = CreatePicContext(src_ctx->va_surface, src_ctx->picsys.surface);
+    if (unlikely(pic_ctx==NULL))
+        return NULL;
+    return &pic_ctx->s;
 }
 
-static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
+static struct va_pic_context *CreatePicContext(vlc_va_surface_t *va_surface, IDirect3DSurface9 *surface)
 {
     struct va_pic_context *pic_ctx = calloc(1, sizeof(*pic_ctx));
     if (unlikely(pic_ctx==NULL))
@@ -210,8 +213,18 @@ static struct picture_context_t *CreatePicContext(vlc_va_surface_t *va_surface)
     va_surface_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;
+    pic_ctx->picsys.surface = surface;
     AcquirePictureSys(&pic_ctx->picsys);
+    return pic_ctx;
+}
+
+static picture_context_t* NewSurfacePicContext(vlc_va_t *va, vlc_va_surface_t *va_surface, IDirect3DSurface9 *surface)
+{
+    VLC_UNUSED(va);
+    struct va_pic_context *pic_ctx = CreatePicContext(va_surface, surface);
+    if (unlikely(pic_ctx==NULL))
+        return NULL;
+    va_surface->decoderSurface = surface;
     return &pic_ctx->s;
 }
 
@@ -229,15 +242,10 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
         return VLC_EGENERIC;
     }
 
-    vlc_va_surface_t *va_surface = va_pool_Get(va, &sys->dx_sys.va_pool);
-    if (unlikely(va_surface==NULL))
-        return VLC_EGENERIC;
-    pic->context = CreatePicContext(va_surface);
-    va_surface_Release(va_surface);
-    if (unlikely(pic->context==NULL))
-        return VLC_EGENERIC;
-    *data = (uint8_t*)va_surface->decoderSurface;
-    return VLC_SUCCESS;
+    int res = va_pool_Get(va, pic, &sys->dx_sys.va_pool);
+    if (likely(res==VLC_SUCCESS))
+        *data = (uint8_t*)((struct va_pic_context*)pic->context)->picsys.surface;
+    return res;
 }
 
 static void Close(vlc_va_t *va, void **ctx)
@@ -309,6 +317,7 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
     dx_sys->va_pool.pf_create_decoder_surfaces = DxCreateVideoDecoder;
     dx_sys->va_pool.pf_destroy_surfaces        = DxDestroyVideoDecoder;
     dx_sys->va_pool.pf_setup_avcodec_ctx       = SetupAVCodecContext;
+    dx_sys->va_pool.pf_new_surface_context     = NewSurfacePicContext;
     dx_sys->pf_get_input_list          = DxGetInputList;
     dx_sys->pf_setup_output            = DxSetupOutput;
     dx_sys->psz_decoder_dll            = TEXT("DXVA2.DLL");
diff --git a/modules/codec/avcodec/va_surface.c b/modules/codec/avcodec/va_surface.c
index 7652f52c5c..e7e65ab30e 100644
--- a/modules/codec/avcodec/va_surface.c
+++ b/modules/codec/avcodec/va_surface.c
@@ -32,6 +32,7 @@
 #include <vlc_common.h>
 #include <vlc_codecs.h>
 #include <vlc_codec.h>
+#include <vlc_picture.h>
 
 
 #define D3D_DecoderSurface  void
@@ -110,7 +111,7 @@ done:
     return err;
 }
 
-static vlc_va_surface_t *GetSurface(va_pool_t *va_pool)
+static picture_context_t *GetSurface(vlc_va_t *va, va_pool_t *va_pool)
 {
     for (unsigned i = 0; i < va_pool->surface_count; i++) {
         vlc_va_surface_t *surface = va_pool->surface[i];
@@ -118,28 +119,33 @@ static vlc_va_surface_t *GetSurface(va_pool_t *va_pool)
 
         if (atomic_compare_exchange_strong(&surface->refcount, &expected, 2))
         {
-            /* TODO do a copy to allow releasing locally and keep forward alive atomic_fetch_sub(&surface->refs, 1);*/
-            surface->decoderSurface = va_pool->hw_surface[i];
-            return surface;
+            picture_context_t *field = va_pool->pf_new_surface_context(va, surface, va_pool->hw_surface[i]);
+            if (!field)
+            {
+                atomic_fetch_sub(&surface->refcount, 1);
+                continue;
+            }
+            return field;
         }
     }
     return NULL;
 }
 
-vlc_va_surface_t *va_pool_Get(vlc_va_t *va, va_pool_t *va_pool)
+int va_pool_Get(vlc_va_t *va, picture_t *pic, va_pool_t *va_pool)
 {
     unsigned tries = (CLOCK_FREQ + VOUT_OUTMEM_SLEEP) / VOUT_OUTMEM_SLEEP;
-    vlc_va_surface_t *field;
+    picture_context_t *field;
 
-    while ((field = GetSurface(va_pool)) == NULL)
+    while ((field = GetSurface(va, va_pool)) == NULL)
     {
         if (--tries == 0)
-            return NULL;
+            return VLC_ENOITEM;
         /* Pool empty. Wait for some time as in src/input/decoder.c.
          * XXX: Both this and the core should use a semaphore or a CV. */
         msleep(VOUT_OUTMEM_SLEEP);
     }
-    return field;
+    pic->context = field;
+    return VLC_SUCCESS;
 }
 
 void va_surface_AddRef(vlc_va_surface_t *surface)
diff --git a/modules/codec/avcodec/va_surface_internal.h b/modules/codec/avcodec/va_surface_internal.h
index 36f8b68656..d95505e505 100644
--- a/modules/codec/avcodec/va_surface_internal.h
+++ b/modules/codec/avcodec/va_surface_internal.h
@@ -71,12 +71,17 @@ typedef struct
      */
     void (*pf_setup_avcodec_ctx)(vlc_va_t *);
 
+    /**
+     * Create a new context for the surface being acquired
+     */
+    picture_context_t* (*pf_new_surface_context)(vlc_va_t *, vlc_va_surface_t *, D3D_DecoderSurface *);
+
 } va_pool_t;
 
 int va_pool_Open(vlc_va_t *, va_pool_t *, AVCodecContext *);
 void va_pool_Close(vlc_va_t *va, va_pool_t *);
 int va_pool_Setup(vlc_va_t *, va_pool_t *, AVCodecContext *, unsigned count, int alignment);
-vlc_va_surface_t *va_pool_Get(vlc_va_t *, va_pool_t *);
+int va_pool_Get(vlc_va_t *, picture_t *, va_pool_t *);
 void va_surface_AddRef(vlc_va_surface_t *surface);
 void va_surface_Release(vlc_va_surface_t *surface);
 
-- 
2.12.1



More information about the vlc-devel mailing list