[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