vlc | branch: master | Steve Lhomme <[email protected]> | Fri Jun 16 17:48:27 2017 +0200| [6c18ebc3145b0800a035a4a01c525d81d8091e14] | committer: Jean-Baptiste Kempf
dxva: create the context copy when calling va_pool_Get() via a pf_new_surface_context callback Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6c18ebc3145b0800a035a4a01c525d81d8091e14 --- 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); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
