vlc | branch: master | Steve Lhomme <[email protected]> | Fri Sep 13 14:32:18 2019 +0200| [fc8b0c8d0b53c3b1fb77a76a40b0345f28284a3f] | committer: Steve Lhomme
dxva: balance the surface API and avoid dirty casts d3d11va/dxva2 only get a va_surface from the API and deal with the references. They need to create a copy of the internal picture context so it's not released when the picture is finished in the display. A copy also increments the surface refcount, so we need to release one after the copy. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=fc8b0c8d0b53c3b1fb77a76a40b0345f28284a3f --- modules/codec/avcodec/d3d11va.c | 29 +++++++++++++++++------------ modules/codec/avcodec/dxva2.c | 29 +++++++++++++++++------------ modules/codec/avcodec/va_surface.c | 22 +++++++++++++--------- modules/codec/avcodec/va_surface_internal.h | 4 +++- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c index 3b4e89c6c0..532a03fa00 100644 --- a/modules/codec/avcodec/d3d11va.c +++ b/modules/codec/avcodec/d3d11va.c @@ -154,12 +154,10 @@ static void SetupAVCodecContext(vlc_va_sys_t *sys, unsigned surfaces) static void d3d11va_pic_context_destroy(picture_context_t *opaque) { struct d3d11va_pic_context *pic_ctx = D3D11VA_PICCONTEXT_FROM_PICCTX(opaque); - if (pic_ctx->va_surface) - { - ReleaseD3D11PictureSys(&pic_ctx->ctx.picsys); - va_surface_Release(pic_ctx->va_surface); - free(pic_ctx); - } + struct vlc_va_surface_t *va_surface = pic_ctx->va_surface; + d3d11_pic_context_destroy(&pic_ctx->ctx.s); + if (va_surface) + va_surface_Release(va_surface); } static struct d3d11va_pic_context *CreatePicContext(ID3D11VideoDecoderOutputView *, @@ -176,10 +174,9 @@ static picture_context_t *d3d11va_pic_context_copy(picture_context_t *ctx) src_ctx->ctx.picsys.slice_index, src_ctx->ctx.picsys.renderSrc); if (unlikely(pic_ctx==NULL)) return NULL; - if (src_ctx->va_surface) { - pic_ctx->va_surface = src_ctx->va_surface; + pic_ctx->va_surface = src_ctx->va_surface; + if (pic_ctx->va_surface) va_surface_AddRef(pic_ctx->va_surface); - } return &pic_ctx->ctx.s; } @@ -288,10 +285,18 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data) else #endif { - picture_context_t *pic_ctx = va_pool_Get(&sys->va_pool); - if (unlikely(pic_ctx == NULL)) + vlc_va_surface_t *va_surface = va_pool_Get(&sys->va_pool); + if (unlikely(va_surface == NULL)) + return VLC_ENOITEM; + picture_context_t *pic_ctx = va_surface_GetContext(va_surface); + pic->context = pic_ctx->copy(pic_ctx); + if (unlikely(pic->context == NULL)) + { + va_surface_Release(va_surface); return VLC_ENOITEM; - pic->context = pic_ctx; + } + // the internal copy adds an extra reference we already had with va_pool_Get() + va_surface_Release(va_surface); } *data = (uint8_t*)D3D11VA_PICCONTEXT_FROM_PICCTX(pic->context)->ctx.picsys.decoder; return VLC_SUCCESS; diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c index 350e7f08a0..325a5fb64a 100644 --- a/modules/codec/avcodec/dxva2.c +++ b/modules/codec/avcodec/dxva2.c @@ -161,20 +161,17 @@ static void SetupAVCodecContext(vlc_va_sys_t *sys, unsigned surfaces) static void dxva2_pic_context_destroy(picture_context_t *opaque) { - struct dxva2_pic_context *pic_ctx = (struct dxva2_pic_context*)opaque; - if (pic_ctx->va_surface) - { - ReleaseD3D9PictureSys(&pic_ctx->ctx.picsys); - va_surface_Release(pic_ctx->va_surface); - free(pic_ctx); - } + struct dxva2_pic_context *pic_ctx = DXVA2_PICCONTEXT_FROM_PICCTX(opaque); + struct vlc_va_surface_t *va_surface = pic_ctx->va_surface; + d3d9_pic_context_destroy(&pic_ctx->ctx.s); + va_surface_Release(va_surface); } static struct dxva2_pic_context *CreatePicContext(IDirect3DSurface9 *, IDirectXVideoDecoder *); static picture_context_t *dxva2_pic_context_copy(picture_context_t *ctx) { - struct dxva2_pic_context *src_ctx = (struct dxva2_pic_context*)ctx; + struct dxva2_pic_context *src_ctx = DXVA2_PICCONTEXT_FROM_PICCTX(ctx); struct dxva2_pic_context *pic_ctx = CreatePicContext(src_ctx->ctx.picsys.surface, src_ctx->ctx.picsys.decoder); if (unlikely(pic_ctx==NULL)) return NULL; @@ -225,12 +222,20 @@ static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data) return VLC_EGENERIC; } - picture_context_t *pic_ctx = va_pool_Get(&sys->va_pool); - if (likely(pic_ctx==NULL)) + vlc_va_surface_t *va_surface = va_pool_Get(&sys->va_pool); + if (unlikely(va_surface==NULL)) return VLC_ENOITEM; - pic->context = pic_ctx; - *data = (uint8_t*)DXVA2_PICCONTEXT_FROM_PICCTX(pic->context)->ctx.picsys.surface; + picture_context_t *pic_ctx = va_surface_GetContext(va_surface); + pic->context = pic_ctx->copy(pic_ctx); + if (unlikely(pic->context == NULL)) + { + va_surface_Release(va_surface); + return VLC_ENOITEM; + } + // the internal copy adds an extra reference we already had with va_pool_Get() + va_surface_Release(va_surface); + *data = (uint8_t*)DXVA2_PICCONTEXT_FROM_PICCTX(pic_ctx)->ctx.picsys.surface; return VLC_SUCCESS; } diff --git a/modules/codec/avcodec/va_surface.c b/modules/codec/avcodec/va_surface.c index 05617b0ddc..e055ee0120 100644 --- a/modules/codec/avcodec/va_surface.c +++ b/modules/codec/avcodec/va_surface.c @@ -39,7 +39,7 @@ #include "avcodec.h" struct vlc_va_surface_t { - atomic_uintptr_t refcount; + atomic_uintptr_t refcount; // 1 ref for the surface existance, 1 per surface/clone in-flight picture_context_t *pic_va_ctx; }; @@ -118,7 +118,7 @@ done: return err; } -static picture_context_t *GetSurface(va_pool_t *va_pool) +static vlc_va_surface_t *GetSurface(va_pool_t *va_pool) { for (unsigned i = 0; i < va_pool->surface_count; i++) { vlc_va_surface_t *surface = va_pool->surface[i]; @@ -126,25 +126,24 @@ static picture_context_t *GetSurface(va_pool_t *va_pool) if (atomic_compare_exchange_strong(&surface->refcount, &expected, 2)) { - picture_context_t *pic_ctx = surface->pic_va_ctx; - picture_context_t *field = pic_ctx->copy(pic_ctx); /* the copy should have added an extra reference */ atomic_fetch_sub(&surface->refcount, 1); - return field; + va_surface_AddRef(surface); + return surface; } } return NULL; } -picture_context_t *va_pool_Get(va_pool_t *va_pool) +vlc_va_surface_t *va_pool_Get(va_pool_t *va_pool) { unsigned tries = (VLC_TICK_FROM_SEC(1) + VOUT_OUTMEM_SLEEP) / VOUT_OUTMEM_SLEEP; - picture_context_t *field; + vlc_va_surface_t *surface; if (va_pool->surface_count == 0) return NULL; - while ((field = GetSurface(va_pool)) == NULL) + while ((surface = GetSurface(va_pool)) == NULL) { if (--tries == 0) return NULL; @@ -152,7 +151,12 @@ picture_context_t *va_pool_Get(va_pool_t *va_pool) * XXX: Both this and the core should use a semaphore or a CV. */ vlc_tick_sleep(VOUT_OUTMEM_SLEEP); } - return field; + return surface; +} + +picture_context_t *va_surface_GetContext(vlc_va_surface_t *surface) +{ + return surface->pic_va_ctx; } 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 6d451e233a..040a1bff53 100644 --- a/modules/codec/avcodec/va_surface_internal.h +++ b/modules/codec/avcodec/va_surface_internal.h @@ -77,7 +77,9 @@ struct va_pool_cfg { int va_pool_Open(vlc_va_t *, const struct va_pool_cfg *, va_pool_t *); void va_pool_Close(vlc_va_t *va, va_pool_t *); int va_pool_SetupDecoder(vlc_va_t *, va_pool_t *, const AVCodecContext *, const video_format_t *, unsigned count); -picture_context_t *va_pool_Get(va_pool_t *); +vlc_va_surface_t *va_pool_Get(va_pool_t *); + +picture_context_t *va_surface_GetContext(vlc_va_surface_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
