Commit 2b8794fe authored by Jean-Paul Saman's avatar Jean-Paul Saman

codec/avcodec/vaapi*: protect access to VAAPI connection.

Use a static mutex to protect access for libva.
parent f78f3ed3
......@@ -48,7 +48,18 @@
#ifdef HAVE_AVCODEC_VAAPI
/* Global VAAPI connection state */
static vlc_va_conn_t vlc_va_conn = { NULL, 0, 0, 0, 0 };
static vlc_va_conn_t vlc_va_conn = { NULL, 0, 0, 0, 0, NULL, NULL };
static vlc_mutex_t vlc_va_conn_lock = VLC_STATIC_MUTEX;
static void vlc_va_lock(void)
{
vlc_mutex_lock(&vlc_va_conn_lock);
}
static void vlc_va_unlock(void)
{
vlc_mutex_unlock(&vlc_va_conn_lock);
}
/* */
vlc_va_conn_t *vlc_va_get_conn( void )
......@@ -58,15 +69,20 @@ vlc_va_conn_t *vlc_va_get_conn( void )
vlc_va_conn_t *vlc_va_Initialize( const char *display_name )
{
vlc_mutex_lock(&vlc_va_conn_lock);
/* connect global to caller */
vlc_va_conn_t *conn = vlc_va_get_conn();
assert(conn);
if (conn->i_ref_count > 0)
{
conn->i_ref_count++;
vlc_mutex_unlock(&vlc_va_conn_lock);
return conn;
}
conn->lock = vlc_va_lock;
conn->unlock = vlc_va_unlock;
/* Create a VA display */
conn->p_display_x11 = XOpenDisplay(display_name);
if( !conn->p_display_x11 )
......@@ -80,9 +96,11 @@ vlc_va_conn_t *vlc_va_Initialize( const char *display_name )
goto error;
conn->i_ref_count++;
vlc_mutex_unlock(&vlc_va_conn_lock);
return conn;
error:
vlc_mutex_unlock(&vlc_va_conn_lock);
return NULL;
}
......
......@@ -130,6 +130,7 @@ static int Open( vlc_va_vaapi_t *p_va, int i_codec_id )
p_va->conn = vlc_va_Initialize(NULL);
if (!p_va->conn)
goto error;
p_va->conn->lock();
/* Create a VA configuration */
VAConfigAttrib attrib;
......@@ -155,14 +156,17 @@ static int Open( vlc_va_vaapi_t *p_va, int i_codec_id )
p_va->conn->i_version_major, p_va->conn->i_version_minor ) < 0 )
p_va->va.description = NULL;
p_va->conn->unlock();
return VLC_SUCCESS;
error:
p_va->conn->unlock();
return VLC_EGENERIC;
}
static void DestroySurfaces( vlc_va_vaapi_t *p_va )
{
p_va->conn->lock();
if( p_va->image.image_id != VA_INVALID_ID )
{
CopyCleanCache( &p_va->image_cache );
......@@ -186,6 +190,7 @@ static void DestroySurfaces( vlc_va_vaapi_t *p_va )
p_va->p_surface = NULL;
p_va->i_surface_width = 0;
p_va->i_surface_height = 0;
p_va->conn->unlock();
}
static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
int i_width, int i_height )
......@@ -199,6 +204,8 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
p_va->image.image_id = VA_INVALID_ID;
p_va->i_context_id = VA_INVALID_ID;
p_va->conn->lock();
/* Create surfaces */
VASurfaceID pi_surface_id[p_va->i_surface_count];
if( vaCreateSurfaces( p_va->conn->p_display, i_width, i_height, VA_RT_FORMAT_YUV420,
......@@ -287,9 +294,12 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
p_va->i_surface_chroma = i_chroma;
p_va->i_surface_width = i_width;
p_va->i_surface_height = i_height;
p_va->conn->unlock();
return VLC_SUCCESS;
error:
p_va->conn->unlock();
DestroySurfaces( p_va );
return VLC_EGENERIC;
}
......@@ -324,6 +334,8 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
if( !p_va->image_cache.buffer )
return VLC_EGENERIC;
p_va->conn->lock();
VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3];
#if VA_CHECK_VERSION(0,31,0)
......@@ -331,7 +343,7 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
#else
if( vaSyncSurface( p_va->conn->p_display, p_va->i_context_id, i_surface_id ) )
#endif
return VLC_EGENERIC;
goto error;
/* XXX vaDeriveImage may be better but it is not supported by
* my setup.
......@@ -340,11 +352,11 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
if( vaGetImage( p_va->conn->p_display, i_surface_id,
0, 0, p_va->i_surface_width, p_va->i_surface_height,
p_va->image.image_id) )
return VLC_EGENERIC;
goto error;
void *p_base;
if( vaMapBuffer( p_va->conn->p_display, p_va->image.buf, &p_base ) )
return VLC_EGENERIC;
goto error;
const uint32_t i_fourcc = p_va->image.format.fourcc;
if( i_fourcc == VA_FOURCC('Y','V','1','2') ||
......@@ -383,9 +395,14 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
}
if( vaUnmapBuffer( p_va->conn->p_display, p_va->image.buf ) )
return VLC_EGENERIC;
goto error;
p_va->conn->unlock();
return VLC_SUCCESS;
error:
p_va->conn->unlock();
return VLC_EGENERIC;
}
static vlc_va_surface_t *FindSurface( vlc_va_t *p_external, const VASurfaceID i_surface_id )
......@@ -413,6 +430,8 @@ static int DisplayPicture( vlc_va_t *p_external, picture_t *p_picture, AVFrame *
{
vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
p_va->conn->lock();
VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3];
#if VA_CHECK_VERSION(0,31,0)
......@@ -420,7 +439,7 @@ static int DisplayPicture( vlc_va_t *p_external, picture_t *p_picture, AVFrame *
#else
if( vaSyncSurface( p_va->conn->p_display, p_va->i_context_id, i_surface_id ) )
#endif
return VLC_EGENERIC;
goto error;
if (!p_picture->p_sys)
abort();
......@@ -430,7 +449,12 @@ static int DisplayPicture( vlc_va_t *p_external, picture_t *p_picture, AVFrame *
if( !p_picture->p_sys->surface )
abort();
p_va->conn->unlock();
return VLC_SUCCESS;
error:
p_va->conn->unlock();
return VLC_EGENERIC;
}
static int Get( vlc_va_t *p_external, AVFrame *p_ff )
......@@ -492,8 +516,10 @@ static void Close( vlc_va_vaapi_t *p_va )
if( p_va->i_surface_width || p_va->i_surface_height )
DestroySurfaces( p_va );
p_va->conn->lock();
if( p_va->i_config_id != VA_INVALID_ID )
vaDestroyConfig( p_va->conn->p_display, p_va->i_config_id );
p_va->conn->unlock();
vlc_va_Terminate( p_va->conn );
}
......
......@@ -25,6 +25,9 @@ struct vlc_va_conn_t
int i_version_major;
int i_version_minor;
int i_ref_count; /* for internal use only */
void (*lock)(void);
void (*unlock)(void);
};
typedef struct
......
......@@ -182,11 +182,12 @@ static void subpicture_cache_destroy(vasubpicture_cache_t *cache)
* release allocated VA API resources */
static void SubpictureCacheClean(vout_display_t *vd, vlc_va_conn_t *conn, subpicture_cache_t *cache)
{
vout_display_sys_t *sys = (vout_display_sys_t *)vd->sys;
#ifdef VAAPI_DEBUG
msg_Dbg(vd, "subpictureCacheClean cache %d", cache->i_id);
#else
VLC_UNUSED(vd);
#endif
sys->conn->lock();
const int num = vlc_array_count(&cache->subpictures);
for (int i = num - 1; i >= 0; i--)
{
......@@ -213,6 +214,7 @@ static void SubpictureCacheClean(vout_display_t *vd, vlc_va_conn_t *conn, subpic
subpicture_cache_destroy(subpic);
subpic = NULL;
}
sys->conn->unlock();
}
/* VA API support functions */
......@@ -220,6 +222,7 @@ static int VASubtitleFourCC(vout_display_t *vd)
{
vout_display_sys_t *sys = (vout_display_sys_t *) vd->sys;
sys->conn->lock();
int num = vaMaxNumSubpictureFormats(sys->conn->p_display);
if (num <= 0)
goto out_warning;
......@@ -244,6 +247,7 @@ static int VASubtitleFourCC(vout_display_t *vd)
memcpy((void*)&sys->sub_fmt, (void*)&format, sizeof(VAImageFormat));
free(p_fmt);
free(flags);
sys->conn->unlock();
return VLC_SUCCESS;
}
}
......@@ -254,6 +258,7 @@ out:
out_warning:
msg_Warn(vd, "VAAP-X11 does not support fourcc RGBA subtitles");
sys->conn->unlock();
return VLC_EGENERIC;
}
......@@ -261,6 +266,8 @@ static int FindVAFourCC(vout_display_t *vd)
{
vout_display_sys_t *sys = (vout_display_sys_t *) vd->sys;
sys->conn->lock();
/* Find and create a supported image chroma */
int i_fmt_count = vaMaxNumImageFormats(sys->conn->p_display);
VAImageFormat *p_fmt = calloc(i_fmt_count, sizeof(*p_fmt));
......@@ -293,23 +300,28 @@ static int FindVAFourCC(vout_display_t *vd)
vd->fmt.i_chroma = i_chroma;
vd->fmt.i_bits_per_pixel = i_bits_per_pixel;
sys->conn->unlock();
return VLC_SUCCESS;
error:
sys->conn->unlock();
return VLC_EGENERIC;
}
static vout_window_t *MakeWindow (vout_display_t *vd)
{
vout_display_sys_t *sys = (vout_display_sys_t *)vd->sys;
vout_window_cfg_t wnd_cfg;
sys->conn->lock();
/* FIXME: Correct vout_window_t display size
* looks like it assumes fullscreen for
* vout_display_PlacePicture() to work as expected. */
unsigned int width, height;
int screen = DefaultScreen(vd->sys->conn->p_display_x11);
width = DisplayWidth(vd->sys->conn->p_display_x11, screen);
height = DisplayHeight(vd->sys->conn->p_display_x11, screen);
int screen = DefaultScreen(sys->conn->p_display_x11);
width = DisplayWidth(sys->conn->p_display_x11, screen);
height = DisplayHeight(sys->conn->p_display_x11, screen);
sys->conn->unlock();
memset (&wnd_cfg, 0, sizeof (wnd_cfg));
wnd_cfg.type = VOUT_WINDOW_TYPE_XID;
......@@ -332,11 +344,15 @@ static int GetWindowSize(vout_display_t *vd, unsigned int *pi_width, unsigned in
int x, y;
unsigned int bw, depth;
sys->conn->lock();
status = XGetGeometry(sys->conn->p_display_x11,
sys->embed->handle.xid,
&root_window,
&x, &y, pi_width, pi_height,
&bw, &depth);
sys->conn->unlock();
if (status == 0)
{
msg_Err(vd, "failed getting geometry");
......@@ -439,8 +455,10 @@ void CloseVaapiX11 (vlc_object_t *obj)
if (sys->conn && sys->conn->p_display_x11)
{
sys->conn->lock();
XFlush(sys->conn->p_display_x11);
XSync(sys->conn->p_display_x11, False);
sys->conn->unlock();
}
if (sys->embed)
......@@ -553,12 +571,17 @@ static VASubpictureID SubpictureCreate(vout_display_t *vd, const subpicture_t *s
{
vout_display_sys_t *sys = vd->sys;
sys->conn->lock();
VAStatus status;
VASubpictureID sub_id = VA_INVALID_ID;
status = vaCreateSubpicture(sys->conn->p_display, image->image_id, &sub_id);
if (status != VA_STATUS_SUCCESS)
{
sys->conn->unlock();
return VA_INVALID_ID;
}
bool b_alpha = (flags & VA_SUBPICTURE_GLOBAL_ALPHA);
bool b_chroma = (flags & VA_SUBPICTURE_CHROMA_KEYING);
......@@ -590,6 +613,7 @@ static VASubpictureID SubpictureCreate(vout_display_t *vd, const subpicture_t *s
msg_Err(vd, "failed applying chroma valuesto subpicture");
}
sys->conn->unlock();
return sub_id;
}
......@@ -619,6 +643,8 @@ static int SubpictureLink(vout_display_t *vd, VASurfaceID surface_id,
unsigned int dst_top = video.y + scale_h * region->i_y;
unsigned int dst_bottom = dst_top + scale_h * region->fmt.i_visible_height;
sys->conn->lock();
/* Associate subpicture with surface */
VAStatus status;
status = vaAssociateSubpicture(sys->conn->p_display, vasub_id,
......@@ -629,10 +655,8 @@ static int SubpictureLink(vout_display_t *vd, VASurfaceID surface_id,
((video.width - dst_right) / 2), dst_top,
dst_right - dst_left, dst_bottom - dst_top,
flags);
if (status != VA_STATUS_SUCCESS)
return VLC_EGENERIC;
return VLC_SUCCESS;
sys->conn->unlock();
return (status != VA_STATUS_SUCCESS) ? VLC_EGENERIC : VLC_SUCCESS;
}
static VAStatus SubpictureUnlink( vlc_va_conn_t *p_connection, VASurfaceID surface_id,
......@@ -642,8 +666,10 @@ static VAStatus SubpictureUnlink( vlc_va_conn_t *p_connection, VASurfaceID surfa
if( (surface_id != VA_INVALID_SURFACE) &&
(sub_id != VA_INVALID_ID) )
{
p_connection->lock();
status = vaDeassociateSubpicture( p_connection->p_display, sub_id,
&surface_id, 1 );
p_connection->unlock();
}
return status;
}
......@@ -684,10 +710,12 @@ static void CopyPalette(vout_display_t *vd, VAImage *image, video_palette_t *p_p
image->num_palette_entries = entries;
image->entry_bytes = 4; /* RGBA has 4 components */
sys->conn->lock();
VAStatus status = vaSetImagePalette(sys->conn->p_display,
image->image_id, (unsigned char *)palette);
if (status != VA_STATUS_SUCCESS)
msg_Err(vd, "failed setting palette. (%d)", status);
sys->conn->unlock();
}
#endif
......@@ -696,11 +724,16 @@ static int CopyPictureToVAImage(vout_display_t *vd, picture_t *pic,
{
vout_display_sys_t *sys = vd->sys;
sys->conn->lock();
VAStatus status;
status = vaCreateImage(sys->conn->p_display, fmt,
pic->format.i_width, pic->format.i_height, image);
if (status != VA_STATUS_SUCCESS)
{
sys->conn->unlock();
return VLC_EGENERIC;
}
/* Sanity checks */
if ((image->image_id == VA_INVALID_ID) ||
......@@ -775,12 +808,14 @@ static int CopyPictureToVAImage(vout_display_t *vd, picture_t *pic,
goto out_va_free;
}
sys->conn->unlock();
return VLC_SUCCESS;
out_va_free:
vaDestroyImage(sys->conn->p_display, image->image_id);
image->image_id = VA_INVALID_ID;
image->buf = VA_INVALID_ID;
sys->conn->unlock();
return VLC_EGENERIC;
}
......@@ -827,10 +862,12 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
image, sys->sflags);
if (vasub_cache->i_id == VA_INVALID_ID)
{
sys->conn->lock();
vaDestroyImage(sys->conn->p_display, image->image_id);
vasub_cache->i_id = VA_INVALID_ID;
image->image_id = VA_INVALID_ID;
image->buf = VA_INVALID_ID;
sys->conn->unlock();
subpicture_cache_destroy(vasub_cache);
vasub_cache = NULL;
goto cleanup;
......@@ -842,11 +879,13 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
vasub_cache->i_id, sys->sflags);
if (err != VLC_SUCCESS)
{
sys->conn->lock();
vaDestroySubpicture(sys->conn->p_display, vasub_cache->i_id);
vaDestroyImage(sys->conn->p_display, image->image_id);
vasub_cache->i_id = VA_INVALID_ID;
image->image_id = VA_INVALID_ID;
image->buf = VA_INVALID_ID;
sys->conn->unlock();
subpicture_cache_destroy(vasub_cache);
vasub_cache = NULL;
goto cleanup;
......@@ -1126,6 +1165,8 @@ static void DisplayVASurface(vout_display_t *vd, VASurfaceID surface, picture_t
vout_display_place_t place;
vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);
sys->conn->lock();
VAStatus status;
status = vaPutSurface(sys->conn->p_display, surface, sys->embed->handle.xid,
picture->format.i_x_offset, picture->format.i_y_offset,
......@@ -1139,6 +1180,8 @@ static void DisplayVASurface(vout_display_t *vd, VASurfaceID surface, picture_t
if (status != VA_STATUS_SUCCESS)
msg_Err(vd, "failed displaying picture: %d (surface id=%d): %p",
status, surface, picture);
sys->conn->unlock();
}
static void DisplayPicture(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
......
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