vlc | branch: master | Thomas Guillem <[email protected]> | Mon Jul 3 10:57:16 2017 +0200| [2d37a81d5146f90a565fc5d624fdde90458f9889] | committer: Thomas Guillem
hw: vaapi: remove vaapi global instance We still need a *not global* vaapi instance: struct vlc_vaapi_instance. This struct holds a VADisplay and a refcount. Every pictures of the vout pool hold a reference to this struct in order to avoid that the VADisplay is terminated while being used by pictures. Filters now get the vaapi instance via filter_NewPicture(). Static filters like the deinterlace one may not have access to a picture allocated by the vout. This is fixed by next patches. Refs #18445 > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2d37a81d5146f90a565fc5d624fdde90458f9889 --- modules/codec/Makefile.am | 6 +- modules/codec/avcodec/vaapi.c | 40 +++++----- modules/hw/vaapi/Makefile.am | 11 +-- modules/hw/vaapi/chroma.c | 31 +++----- modules/hw/vaapi/filters.c | 18 +++-- modules/hw/vaapi/instance.c | 93 ---------------------- modules/hw/vaapi/vlc_vaapi.c | 108 +++++++++++++++++++++----- modules/hw/vaapi/vlc_vaapi.h | 41 ++++++---- modules/video_output/Makefile.am | 2 +- modules/video_output/opengl/converter_vaapi.c | 29 +++---- 10 files changed, 170 insertions(+), 209 deletions(-) diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am index c3bb6d207a..91c6e257cc 100644 --- a/modules/codec/Makefile.am +++ b/modules/codec/Makefile.am @@ -379,19 +379,19 @@ libvaapi_drm_plugin_la_SOURCES = \ libvaapi_drm_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_DRM libvaapi_drm_plugin_la_CFLAGS = $(AM_CFLAGS) \ $(LIBVA_DRM_CFLAGS) $(AVCODEC_CFLAGS) -libvaapi_drm_plugin_la_LIBADD = $(LIBVA_DRM_LIBS) libvlc_vaapi_instance.la +libvaapi_drm_plugin_la_LIBADD = $(LIBVA_DRM_LIBS) libvaapi_x11_plugin_la_SOURCES = \ codec/avcodec/vaapi.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h libvaapi_x11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_XLIB libvaapi_x11_plugin_la_CFLAGS = $(AM_CFLAGS) \ $(LIBVA_X11_CFLAGS) $(X_CFLAGS) $(AVCODEC_CFLAGS) libvaapi_x11_plugin_la_LIBADD = $(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) \ - -lX11 libvlc_vaapi_instance.la + -lX11 libvaapi_dr_plugin_la_SOURCES = \ codec/avcodec/vaapi.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h libvaapi_dr_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_DR libvaapi_dr_plugin_la_CFLAGS = $(AM_CFLAGS) $(AVCODEC_CFLAGS) -libvaapi_dr_plugin_la_LIBADD = $(LIBVA_LIBS) libvlc_vaapi_instance.la +libvaapi_dr_plugin_la_LIBADD = $(LIBVA_LIBS) if HAVE_AVCODEC_VAAPI if HAVE_VAAPI_DRM codec_LTLIBRARIES += libvaapi_drm_plugin.la diff --git a/modules/codec/avcodec/vaapi.c b/modules/codec/avcodec/vaapi.c index 4f46802400..8c00f216c5 100644 --- a/modules/codec/avcodec/vaapi.c +++ b/modules/codec/avcodec/vaapi.c @@ -54,6 +54,7 @@ struct vlc_va_sys_t { + struct vlc_vaapi_instance *va_inst; #ifdef VLC_VA_BACKEND_XLIB Display *p_display_x11; #endif @@ -147,14 +148,14 @@ static void DeleteDR(vlc_va_t *va, void *hwctx) vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id); vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id); - vlc_vaapi_ReleaseInstance(sys->hw_ctx.display); + vlc_vaapi_ReleaseInstance(sys->va_inst); free(sys); } static int CreateDR(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, const es_format_t *fmt, picture_sys_t *p_sys) { - if (pix_fmt != AV_PIX_FMT_VAAPI_VLD) + if (pix_fmt != AV_PIX_FMT_VAAPI_VLD || p_sys == NULL) return VLC_EGENERIC; (void) fmt; @@ -164,9 +165,9 @@ static int CreateDR(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, vlc_va_sys_t *sys = NULL; /* The picture must be allocated by the vout */ - VADisplay *va_dpy = vlc_vaapi_GetInstance(); - if (va_dpy == NULL) - return VLC_EGENERIC; + VADisplay va_dpy; + struct vlc_vaapi_instance *va_inst = + vlc_vaapi_PicSysHoldInstance(p_sys, &va_dpy); VASurfaceID *render_targets; unsigned num_render_targets = @@ -188,6 +189,7 @@ static int CreateDR(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, memset(sys, 0, sizeof (*sys)); /* */ + sys->va_inst = va_inst; sys->hw_ctx.display = va_dpy; sys->hw_ctx.config_id = VA_INVALID_ID; sys->hw_ctx.context_id = VA_INVALID_ID; @@ -221,7 +223,7 @@ error: vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id); free(sys); } - vlc_vaapi_ReleaseInstance(va_dpy); + vlc_vaapi_ReleaseInstance(va_inst); return ret; } @@ -254,7 +256,7 @@ static void Delete(vlc_va_t *va, void **hwctx) picture_pool_Release(sys->pool); vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id); vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id); - vlc_vaapi_ReleaseInstance(sys->hw_ctx.display); + vlc_vaapi_ReleaseInstance(sys->va_inst); #ifdef VLC_VA_BACKEND_XLIB XCloseDisplay(sys->p_display_x11); #endif @@ -267,7 +269,7 @@ static void Delete(vlc_va_t *va, void **hwctx) static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, const es_format_t *fmt, picture_sys_t *p_sys) { - if (pix_fmt != AV_PIX_FMT_VAAPI_VLD) + if (pix_fmt != AV_PIX_FMT_VAAPI_VLD || p_sys) return VLC_EGENERIC; (void) fmt; @@ -299,6 +301,7 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, sys->hw_ctx.config_id = VA_INVALID_ID; sys->hw_ctx.context_id = VA_INVALID_ID; sys->pool = NULL; + sys->va_inst = NULL; /* Create a VA display */ #ifdef VLC_VA_BACKEND_XLIB @@ -337,18 +340,9 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, goto error; } - if (vlc_vaapi_Initialize(o, sys->hw_ctx.display)) - { - sys->hw_ctx.display = NULL; + sys->va_inst = vlc_vaapi_InitializeInstance(o, sys->hw_ctx.display); + if (!sys->va_inst) goto error; - } - - if (vlc_vaapi_SetInstance(sys->hw_ctx.display)) - { - msg_Err(va, "VAAPI instance already in use"); - sys->hw_ctx.display = NULL; - goto error; - } sys->hw_ctx.config_id = vlc_vaapi_CreateConfigChecked(o, sys->hw_ctx.display, i_profile, @@ -364,7 +358,7 @@ static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, .i_visible_height = ctx->coded_height }; VASurfaceID *surfaces; - sys->pool = vlc_vaapi_PoolNew(o, sys->hw_ctx.display, count, + sys->pool = vlc_vaapi_PoolNew(o, sys->va_inst, sys->hw_ctx.display, count, &surfaces, &vfmt, VA_RT_FORMAT_YUV420, 0); if (!sys->pool) @@ -391,8 +385,10 @@ error: picture_pool_Release(sys->pool); if (sys->hw_ctx.config_id != VA_INVALID_ID) vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id); - if (sys->hw_ctx.display != NULL) - vlc_vaapi_ReleaseInstance(sys->hw_ctx.display); + if (sys->va_inst != NULL) + vlc_vaapi_ReleaseInstance(sys->va_inst); + else if (sys->hw_ctx.display != NULL) + vaTerminate(sys->hw_ctx.display); #ifdef VLC_VA_BACKEND_XLIB if( sys->p_display_x11 != NULL) XCloseDisplay(sys->p_display_x11); diff --git a/modules/hw/vaapi/Makefile.am b/modules/hw/vaapi/Makefile.am index d0e595e7c6..563bad2844 100644 --- a/modules/hw/vaapi/Makefile.am +++ b/modules/hw/vaapi/Makefile.am @@ -1,23 +1,16 @@ vaapidir = $(pluginsdir)/vaapi -libvlc_vaapi_instance_la_SOURCES = hw/vaapi/instance.c hw/vaapi/vlc_vaapi.h -libvlc_vaapi_instance_la_CFLAGS = $(LIBVA_CFLAGS) -libvlc_vaapi_instance_la_LIBADD = $(LIBVA_LIBS) $(LIBPTHREAD) -libvlc_vaapi_instance_la_LDFLAGS = -no-undefined \ - -version-info 0:0:0 - libvaapi_chroma_plugin_la_SOURCES = hw/vaapi/chroma.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h \ video_chroma/copy.c video_chroma/copy.h libvaapi_chroma_plugin_la_CFLAGS = $(AM_CFLAGS) $(LIBVA_CFLAGS) -libvaapi_chroma_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) libvlc_vaapi_instance.la +libvaapi_chroma_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) libvaapi_filters_plugin_la_SOURCES = hw/vaapi/filters.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h libvaapi_filters_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) libvaapi_filters_plugin_la_CFLAGS = $(AM_CFLAGS) $(LIBVA_CFLAGS) -libvaapi_filters_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) libvlc_vaapi_instance.la +libvaapi_filters_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) if HAVE_VAAPI -pkglib_LTLIBRARIES += libvlc_vaapi_instance.la vaapi_LTLIBRARIES = libvaapi_chroma_plugin.la \ libvaapi_filters_plugin.la endif diff --git a/modules/hw/vaapi/chroma.c b/modules/hw/vaapi/chroma.c index 278ecf9e17..a202f3f8aa 100644 --- a/modules/hw/vaapi/chroma.c +++ b/modules/hw/vaapi/chroma.c @@ -39,6 +39,7 @@ struct filter_sys_t { + struct vlc_vaapi_instance *va_inst; VADisplay dpy; picture_pool_t * dest_pics; VASurfaceID * va_surface_ids; @@ -126,20 +127,10 @@ static picture_t * DownloadSurface(filter_t *filter, picture_t *src_pic) { filter_sys_t *const filter_sys = filter->p_sys; - VADisplay va_dpy; + VADisplay va_dpy = vlc_vaapi_PicGetDisplay(src_pic); VAImage src_img; void * src_buf; - if (filter_sys->dpy == NULL) - { - /* Get the instance here since the instance may be not created by the - * decoder from Open() */ - va_dpy = filter_sys->dpy = vlc_vaapi_GetInstance(); - assert(filter_sys->dpy); - } - else - va_dpy = filter->p_sys->dpy; - picture_t *dest = filter_NewPicture(filter); if (!dest) { @@ -310,24 +301,26 @@ static int Open(vlc_object_t *obj) filter_sys->derive_failed = false; filter_sys->image_fallback_failed = false; filter_sys->image_fallback.image_id = VA_INVALID_ID; + filter_sys->va_inst = vlc_vaapi_FilterHoldInstance(filter, + &filter_sys->dpy); if (is_upload) { - filter_sys->dpy = vlc_vaapi_GetInstance(); - if (filter_sys->dpy == NULL) + /* Only upload can't work without a VAAPI instance */ + if (filter_sys->va_inst == NULL) { free(filter_sys); return VLC_EGENERIC; } filter_sys->dest_pics = - vlc_vaapi_PoolNew(obj, filter_sys->dpy, DEST_PICS_POOL_SZ, - &filter_sys->va_surface_ids, + vlc_vaapi_PoolNew(obj, filter_sys->va_inst, filter_sys->dpy, + DEST_PICS_POOL_SZ, &filter_sys->va_surface_ids, &filter->fmt_out.video, VA_RT_FORMAT_YUV420, VA_FOURCC_NV12); if (!filter_sys->dest_pics) { - vlc_vaapi_ReleaseInstance(filter_sys->dpy); + vlc_vaapi_ReleaseInstance(filter_sys->va_inst); free(filter_sys); return VLC_EGENERIC; } @@ -344,7 +337,7 @@ static int Open(vlc_object_t *obj) if (is_upload) { picture_pool_Release(filter_sys->dest_pics); - vlc_vaapi_ReleaseInstance(filter_sys->dpy); + vlc_vaapi_ReleaseInstance(filter_sys->va_inst); } free(filter_sys); return VLC_EGENERIC; @@ -365,8 +358,8 @@ Close(vlc_object_t *obj) filter_sys->image_fallback.image_id); if (filter_sys->dest_pics) picture_pool_Release(filter_sys->dest_pics); - if (filter_sys->dpy != NULL) - vlc_vaapi_ReleaseInstance(filter_sys->dpy); + if (filter_sys->va_inst != NULL) + vlc_vaapi_ReleaseInstance(filter_sys->va_inst); CopyCleanCache(&filter_sys->cache); free(filter_sys); diff --git a/modules/hw/vaapi/filters.c b/modules/hw/vaapi/filters.c index 0af9c0548b..f68c28a3e5 100644 --- a/modules/hw/vaapi/filters.c +++ b/modules/hw/vaapi/filters.c @@ -38,6 +38,7 @@ struct va_filter_desc { + struct vlc_vaapi_instance *inst; VADisplay dpy; VAConfigID conf; VAContextID ctx; @@ -298,14 +299,15 @@ Open(filter_t * filter, filter_sys->va.conf = VA_INVALID_ID; filter_sys->va.ctx = VA_INVALID_ID; filter_sys->va.buf = VA_INVALID_ID; - filter_sys->va.dpy = vlc_vaapi_GetInstance(); - if (!filter_sys->va.dpy) + filter_sys->va.inst = + vlc_vaapi_FilterHoldInstance(filter, &filter_sys->va.dpy); + if (!filter_sys->va.inst) goto error; filter_sys->dest_pics = - vlc_vaapi_PoolNew(VLC_OBJECT(filter), filter_sys->va.dpy, - DEST_PICS_POOL_SZ, &filter_sys->va.surface_ids, - &filter->fmt_out.video, + vlc_vaapi_PoolNew(VLC_OBJECT(filter), filter_sys->va.inst, + filter_sys->va.dpy, DEST_PICS_POOL_SZ, + &filter_sys->va.surface_ids, &filter->fmt_out.video, VA_RT_FORMAT_YUV420, VA_FOURCC_NV12); if (!filter_sys->dest_pics) goto error; @@ -376,8 +378,8 @@ error: if (filter_sys->va.conf != VA_INVALID_ID) vlc_vaapi_DestroyConfig(VLC_OBJECT(filter), filter_sys->va.dpy, filter_sys->va.conf); - if (filter_sys->va.dpy) - vlc_vaapi_ReleaseInstance(filter_sys->va.dpy); + if (filter_sys->va.inst) + vlc_vaapi_ReleaseInstance(filter_sys->va.inst); free(filter_sys); return VLC_EGENERIC; } @@ -389,7 +391,7 @@ Close(vlc_object_t * obj, filter_sys_t * filter_sys) vlc_vaapi_DestroyBuffer(obj, filter_sys->va.dpy, filter_sys->va.buf); vlc_vaapi_DestroyContext(obj, filter_sys->va.dpy, filter_sys->va.ctx); vlc_vaapi_DestroyConfig(obj, filter_sys->va.dpy, filter_sys->va.conf); - vlc_vaapi_ReleaseInstance(filter_sys->va.dpy); + vlc_vaapi_ReleaseInstance(filter_sys->va.inst); free(filter_sys); } diff --git a/modules/hw/vaapi/instance.c b/modules/hw/vaapi/instance.c deleted file mode 100644 index 3f70fe7ebc..0000000000 --- a/modules/hw/vaapi/instance.c +++ /dev/null @@ -1,93 +0,0 @@ -/***************************************************************************** - * instance.c: VAAPI instance management for VLC - ***************************************************************************** - * Copyright (C) 2017 VLC authors, VideoLAN and VideoLabs - * - * Author: Victorien Le Couviour--Tuffet <[email protected]> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - *****************************************************************************/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <assert.h> -#include <pthread.h> -#include <stdlib.h> -#include <vlc_common.h> -#include "vlc_vaapi.h" - -#pragma GCC visibility push(default) - -static struct -{ - pthread_mutex_t lock; - VADisplay dpy; - unsigned refcount; -} va_instance = { PTHREAD_MUTEX_INITIALIZER, NULL, 0 }; - -/* Set the VA instance and sets the reference counter to 1. */ -int -vlc_vaapi_SetInstance(VADisplay dpy) -{ - pthread_mutex_lock(&va_instance.lock); - if (va_instance.refcount != 0) - { - vaTerminate(dpy); - pthread_mutex_unlock(&va_instance.lock); - return VLC_EGENERIC; - } - va_instance.refcount = 1; - va_instance.dpy = dpy; - pthread_mutex_unlock(&va_instance.lock); - return VLC_SUCCESS; -} - -/* Retrieve the VA instance and increases the reference counter by 1. */ -VADisplay -vlc_vaapi_GetInstance(void) -{ - VADisplay dpy; - pthread_mutex_lock(&va_instance.lock); - if (!va_instance.dpy) - dpy = NULL; - else - { - dpy = va_instance.dpy; - ++va_instance.refcount; - } - pthread_mutex_unlock(&va_instance.lock); - return dpy; -} - -/* Decreases the reference counter by 1 and frees the instance if that counter - reaches 0. */ -void -vlc_vaapi_ReleaseInstance(VADisplay *dpy) -{ - assert(va_instance.dpy == dpy && va_instance.refcount > 0); - (void) dpy; - - pthread_mutex_lock(&va_instance.lock); - if (--va_instance.refcount == 0) - { - vaTerminate(va_instance.dpy); - va_instance.dpy = NULL; - } - pthread_mutex_unlock(&va_instance.lock); -} - -#pragma GCC visibility pop diff --git a/modules/hw/vaapi/vlc_vaapi.c b/modules/hw/vaapi/vlc_vaapi.c index 04514eb852..7b9d9c0da2 100644 --- a/modules/hw/vaapi/vlc_vaapi.c +++ b/modules/hw/vaapi/vlc_vaapi.c @@ -38,6 +38,7 @@ #include <vlc_common.h> #include <vlc_atomic.h> #include <vlc_fourcc.h> +#include <vlc_filter.h> #include <vlc_picture_pool.h> /* This macro is designed to wrap any VA call, and in case of failure, @@ -54,19 +55,47 @@ } \ } while (0) -/***************** - * VAAPI display * - *****************/ +/************************** + * VA instance management * + **************************/ -int -vlc_vaapi_Initialize(vlc_object_t *o, VADisplay dpy) +struct vlc_vaapi_instance { + VADisplay dpy; + atomic_uint pic_refcount; +}; + +struct vlc_vaapi_instance * +vlc_vaapi_InitializeInstance(vlc_object_t *o, VADisplay dpy) { int major = 0, minor = 0; VA_CALL(o, vaInitialize, dpy, &major, &minor); - return VLC_SUCCESS; + struct vlc_vaapi_instance *inst = malloc(sizeof(*inst)); + + if (unlikely(inst == NULL)) + return NULL; + inst->dpy = dpy; + atomic_init(&inst->pic_refcount, 1); + + return inst; error: - vaTerminate(dpy); - return VLC_EGENERIC; + return NULL; +} + +VADisplay +vlc_vaapi_HoldInstance(struct vlc_vaapi_instance *inst) +{ + atomic_fetch_add(&inst->pic_refcount, 1); + return inst->dpy; +} + +void +vlc_vaapi_ReleaseInstance(struct vlc_vaapi_instance *inst) +{ + if (atomic_fetch_sub(&inst->pic_refcount, 1) == 1) + { + vaTerminate(inst->dpy); + free(inst); + } } /************************** @@ -412,8 +441,9 @@ struct vaapi_pic_ctx struct pic_sys_vaapi_instance { - atomic_int refcount; - VADisplay dpy; + atomic_int pic_refcount; + VADisplay va_dpy; + struct vlc_vaapi_instance *va_inst; unsigned num_render_targets; VASurfaceID render_targets[]; }; @@ -430,11 +460,11 @@ pool_pic_destroy_cb(picture_t *pic) picture_sys_t *p_sys = pic->p_sys; struct pic_sys_vaapi_instance *instance = p_sys->instance; - if (atomic_fetch_sub(&instance->refcount, 1) == 1) + if (atomic_fetch_sub(&instance->pic_refcount, 1) == 1) { - vaDestroySurfaces(instance->dpy, instance->render_targets, + vaDestroySurfaces(instance->va_dpy, instance->render_targets, instance->num_render_targets); - vlc_vaapi_ReleaseInstance(instance->dpy); + vlc_vaapi_ReleaseInstance(instance->va_inst); free(instance); } free(pic->p_sys); @@ -471,8 +501,8 @@ pic_sys_ctx_destroy_cb(struct picture_context_t *opaque) } picture_pool_t * -vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay dpy, unsigned count, - VASurfaceID **render_targets, +vlc_vaapi_PoolNew(vlc_object_t *o, struct vlc_vaapi_instance *va_inst, + VADisplay dpy, unsigned count, VASurfaceID **render_targets, const video_format_t *restrict fmt, unsigned va_rt_format, int va_force_fourcc) { @@ -481,7 +511,7 @@ vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay dpy, unsigned count, if (!instance) return NULL; instance->num_render_targets = count; - atomic_init(&instance->refcount, 0); + atomic_init(&instance->pic_refcount, 0); VASurfaceAttrib *attribs = NULL; unsigned num_attribs = 0; @@ -536,9 +566,9 @@ vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay dpy, unsigned count, if (!pool) goto error_pic; - atomic_store(&instance->refcount, count); - instance->dpy = vlc_vaapi_GetInstance(); /* Hold a reference on VADisplay */ - assert(instance->dpy == dpy); + atomic_store(&instance->pic_refcount, count); + instance->va_dpy = vlc_vaapi_HoldInstance(va_inst); + instance->va_inst = va_inst; *render_targets = instance->render_targets; return pool; @@ -547,7 +577,7 @@ error_pic: while (count > 0) picture_Release(pics[--count]); - VA_CALL(o, vaDestroySurfaces, instance->dpy, instance->render_targets, + VA_CALL(o, vaDestroySurfaces, instance->va_dpy, instance->render_targets, instance->num_render_targets); error: @@ -564,9 +594,37 @@ vlc_vaapi_PicSysGetRenderTargets(picture_sys_t *sys, return sys->instance->num_render_targets; } +struct vlc_vaapi_instance * +vlc_vaapi_PicSysHoldInstance(picture_sys_t *sys, VADisplay *dpy) +{ + assert(sys->instance != NULL); + *dpy = vlc_vaapi_HoldInstance(sys->instance->va_inst); + return sys->instance->va_inst; +} + +struct vlc_vaapi_instance * +vlc_vaapi_FilterHoldInstance(filter_t *filter, VADisplay *dpy) +{ + picture_t *pic = filter_NewPicture(filter); + if (!pic) + return NULL; + + struct vlc_vaapi_instance *va_inst = + pic->format.i_chroma == VLC_CODEC_VAAPI_420 && pic->p_sys ? + vlc_vaapi_PicSysHoldInstance(pic->p_sys, dpy) : NULL; + picture_Release(pic); + + return va_inst; +} + +#define ASSERT_VAAPI_CHROMA(pic) do { \ + assert(pic->format.i_chroma == VLC_CODEC_VAAPI_420); \ +} while(0) + void vlc_vaapi_PicAttachContext(picture_t *pic) { + ASSERT_VAAPI_CHROMA(pic); assert(pic->p_sys != NULL); assert(pic->context == NULL); @@ -577,7 +635,17 @@ vlc_vaapi_PicAttachContext(picture_t *pic) VASurfaceID vlc_vaapi_PicGetSurface(picture_t *pic) { + ASSERT_VAAPI_CHROMA(pic); assert(pic->context); return ((struct vaapi_pic_ctx *)pic->context)->surface; } + +VADisplay +vlc_vaapi_PicGetDisplay(picture_t *pic) +{ + ASSERT_VAAPI_CHROMA(pic); + assert(pic->context); + + return ((struct vaapi_pic_ctx *)pic->context)->picref->p_sys->instance->va_dpy; +} diff --git a/modules/hw/vaapi/vlc_vaapi.h b/modules/hw/vaapi/vlc_vaapi.h index 51dbc69a6c..fc2cfff6a8 100644 --- a/modules/hw/vaapi/vlc_vaapi.h +++ b/modules/hw/vaapi/vlc_vaapi.h @@ -35,25 +35,20 @@ * VA instance management * **************************/ -/* Allocates the VA instance and sets the reference counter to 1. */ -int -vlc_vaapi_SetInstance(VADisplay dpy); +struct vlc_vaapi_instance; + +/* Initializes the VADisplay and sets the reference counter to 1. */ +struct vlc_vaapi_instance * +vlc_vaapi_InitializeInstance(vlc_object_t *o, VADisplay dpy); -/* Retrieve the VA instance and increases the reference counter by 1. */ +/* Increments the VAAPI instance refcount */ VADisplay -vlc_vaapi_GetInstance(void); +vlc_vaapi_HoldInstance(struct vlc_vaapi_instance *inst); -/* Decreases the reference counter by 1 and frees the instance if that counter - reaches 0. */ +/* Decrements the VAAPI instance refcount, and call vaTerminate if that counter + * reaches 0 */ void -vlc_vaapi_ReleaseInstance(VADisplay *); - -/***************** - * VAAPI display * - *****************/ - -int -vlc_vaapi_Initialize(vlc_object_t *o, VADisplay va_dpy); +vlc_vaapi_ReleaseInstance(struct vlc_vaapi_instance *inst); /************************** * VAAPI create & destroy * @@ -177,8 +172,8 @@ vlc_vaapi_CreateConfigChecked(vlc_object_t *o, VADisplay dpy, /* Create a pool backed by VASurfaceID. render_targets will destroyed once * the pool and every pictures are released. */ picture_pool_t * -vlc_vaapi_PoolNew(vlc_object_t *o, VADisplay va_dpy, - unsigned count, VASurfaceID **render_targets, +vlc_vaapi_PoolNew(vlc_object_t *o, struct vlc_vaapi_instance *vainst, + VADisplay dpy, unsigned count, VASurfaceID **render_targets, const video_format_t *restrict fmt, unsigned va_rt_format, int va_force_fourcc); @@ -188,6 +183,14 @@ unsigned vlc_vaapi_PicSysGetRenderTargets(picture_sys_t *sys, VASurfaceID **render_targets); +/* Get and hold the VADisplay instance attached to the picture sys */ +struct vlc_vaapi_instance * +vlc_vaapi_PicSysHoldInstance(picture_sys_t *sys, VADisplay *dpy); + +/* Get and hold the VADisplay instance from a filter */ +struct vlc_vaapi_instance * +vlc_vaapi_FilterHoldInstance(filter_t *filter, VADisplay *dpy); + /* Attachs the VASurface to the picture context, the picture must be allocated * by a vaapi pool (see vlc_vaapi_PoolNew()) */ void @@ -197,4 +200,8 @@ vlc_vaapi_PicAttachContext(picture_t *pic); VASurfaceID vlc_vaapi_PicGetSurface(picture_t *pic); +/* Get the VADisplay attached to the pic (valid while the pic is alive) */ +VADisplay +vlc_vaapi_PicGetDisplay(picture_t *pic); + #endif /* VLC_VAAPI_H */ diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am index 8c89e0bedd..e7cf70ab66 100644 --- a/modules/video_output/Makefile.am +++ b/modules/video_output/Makefile.am @@ -24,7 +24,7 @@ OPENGL_COMMONCFLAGS += -DVLCGL_CONV_CVPX endif if HAVE_EGL if HAVE_VAAPI -OPENGL_COMMONLIBS += $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) libvlc_vaapi_instance.la +OPENGL_COMMONLIBS += $(LIBVA_LIBS) $(LIBVA_EGL_LIBS) OPENGL_COMMONSOURCES += video_output/opengl/converter_vaapi.c \ hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h OPENGL_COMMONCFLAGS += -DVLCGL_CONV_VA diff --git a/modules/video_output/opengl/converter_vaapi.c b/modules/video_output/opengl/converter_vaapi.c index 03987a8e34..1775cd0cb1 100644 --- a/modules/video_output/opengl/converter_vaapi.c +++ b/modules/video_output/opengl/converter_vaapi.c @@ -47,6 +47,7 @@ struct priv { + struct vlc_vaapi_instance *vainst; VADisplay vadpy; VASurfaceID *va_surface_ids; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; @@ -225,9 +226,9 @@ tc_vaegl_get_pool(const opengl_tex_converter_t *tc, unsigned requested_count) struct priv *priv = tc->priv; picture_pool_t *pool = - vlc_vaapi_PoolNew(VLC_OBJECT(tc->gl), priv->vadpy, requested_count, - &priv->va_surface_ids, &tc->fmt, VA_RT_FORMAT_YUV420, - VA_FOURCC_NV12); + vlc_vaapi_PoolNew(VLC_OBJECT(tc->gl), priv->vainst, priv->vadpy, + requested_count, &priv->va_surface_ids, &tc->fmt, + VA_RT_FORMAT_YUV420, VA_FOURCC_NV12); if (!pool) return NULL; @@ -252,12 +253,13 @@ tc_vaegl_release(const opengl_tex_converter_t *tc) if (priv->last.pic != NULL) vaegl_release_last_pic(tc, priv); - vlc_vaapi_ReleaseInstance(priv->vadpy); + vlc_vaapi_ReleaseInstance(priv->vainst); #ifdef HAVE_VA_X11 if (priv->x11dpy != NULL) XCloseDisplay(priv->x11dpy); #endif + free(tc->priv); } @@ -324,31 +326,24 @@ tc_vaegl_init(opengl_tex_converter_t *tc, VADisplay *vadpy) tc->pf_release = tc_vaegl_release; tc->pf_get_pool = tc_vaegl_get_pool; - if (vlc_vaapi_Initialize(VLC_OBJECT(tc->gl), priv->vadpy)) + priv->vainst = vlc_vaapi_InitializeInstance(VLC_OBJECT(tc->gl), priv->vadpy); + if (priv->vainst == NULL) goto error; if (tc_va_check_interop_blacklist(tc, priv->vadpy)) goto error; - if (vlc_vaapi_SetInstance(priv->vadpy)) - { - msg_Err(tc->gl, "VAAPI instance already in use"); - vadpy = NULL; - goto error; - } - tc->fshader = opengl_fragment_shader_init(tc, GL_TEXTURE_2D, VLC_CODEC_NV12, tc->fmt.space); if (tc->fshader == 0) - { - vlc_vaapi_ReleaseInstance(priv->vadpy); - vadpy = NULL; goto error; - } + return VLC_SUCCESS; error: - if (vadpy != NULL) + if (priv->vainst) + vlc_vaapi_ReleaseInstance(priv->vainst); + else vaTerminate(vadpy); free(tc->priv); return ret; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
