Commit 2d37a81d authored by Thomas Guillem's avatar 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
parent 0dece153
......@@ -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
......
......@@ -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);
......
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
......@@ -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);
......
......@@ -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);
}
......
/*****************************************************************************
* instance.c: VAAPI instance management for VLC
*****************************************************************************
* Copyright (C) 2017 VLC authors, VideoLAN and VideoLabs
*
* Author: Victorien Le Couviour--Tuffet <victorien.lecouviour.tuffet@gmail.com>
*
* 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
......@@ -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;
}
......@@ -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 */
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment