Commit 44eee00d authored by Jean-Paul Saman's avatar Jean-Paul Saman

VAAPI-XCB: rewrite Surface handling.

The surface handling has been rewritten to be more consistent and to
avoid reusing surfaces that are still in use by the display thread. Some
VAAPI wrapper drivers use the DirectSurface mode, meaning that the surface
handed by the application is used directly for displaying. It does not
copy the surface into a display surface. When the driver does this, then
you cannot reuse this surface which is being displayed for rendering the
next picture too
parent d21c629b
This diff is collapsed.
......@@ -28,6 +28,7 @@ typedef struct vlc_va_t vlc_va_t;
struct vlc_va_t {
char *description;
bool direct_rendering;
vlc_object_t *obj;
int (*setup)(vlc_va_t *, void **hw, vlc_fourcc_t *output,
......@@ -37,6 +38,7 @@ struct vlc_va_t {
int (*extract)(vlc_va_t *, picture_t *dst, AVFrame *src);
void (*put)(vlc_va_t *, AVFrame *dst, picture_t *src);
int (*display)(vlc_va_t *, picture_t *dst);
bool (*query)(vlc_va_t *, picture_t *src);
void (*close)(vlc_va_t *);
};
......@@ -61,6 +63,10 @@ static inline void vlc_va_Put(vlc_va_t *va, AVFrame *dst, picture_t *src)
{
va->put(va, dst, src);
}
static inline bool vlc_va_QueryReady(vlc_va_t *va, picture_t *src)
{
return va->query(va, src);
}
static inline int vlc_va_Display(vlc_va_t *va, picture_t *dst)
{
return va->display(va, dst);
......
This diff is collapsed.
......@@ -29,10 +29,13 @@
* context.
*/
typedef struct vlc_va_conn_t vlc_va_conn_t;
typedef struct picture_sys_t vlc_va_surface_t;
struct vlc_va_conn_t
{
Display *x11; /* x11 display connection */
VADisplay p_display;
bool b_direct_rendering; /* VAAPI uses direct rendering */
int i_version_major;
int i_version_minor;
int i_ref_count;
......@@ -41,14 +44,21 @@ struct vlc_va_conn_t
void (*lock)(void);
void (*unlock)(void);
/* NOTE: must be called with lock held */
unsigned int i_surface_count;
VASurfaceID *p_surface_ids;
/* NOTE: must be called with conn->lock held */
struct {
unsigned int count; /* number of surfaces allocated */
unsigned int current; /* current used surface (private use only) */
vlc_va_surface_t *p_surfaces;
} pool; /* vlc_va_surface_t pool */
VAContextID i_context_id;
VASurfaceID *(*create_surfaces)(vlc_va_conn_t *conn, const int width, const int height,
bool (*create_surfaces)(vlc_va_conn_t *conn, const int width, const int height,
const int fourcc, const unsigned num);
void (*destroy_surfaces)(vlc_va_conn_t *conn);
vlc_va_surface_t *(*get_surface)(vlc_va_conn_t *conn);
void (*release_surface)(vlc_va_conn_t *conn, vlc_va_surface_t *surface);
};
/* Initialize shared connection to libva */
......@@ -57,7 +67,7 @@ vlc_va_conn_t *vlc_va_Initialize(const char *display);
/* Deinitialize shared connection to libva */
void vlc_va_Terminate(vlc_va_conn_t *conn);
static inline VASurfaceID *vlc_va_conn_CreateSurface(vlc_va_conn_t *conn,
static inline bool vlc_va_conn_CreateSurface(vlc_va_conn_t *conn,
const int width, const int height, const int fourcc, const int num)
{
return conn->create_surfaces(conn, width, height, fourcc, num);
......@@ -68,34 +78,43 @@ static inline void vlc_va_conn_DestroySurfaces(vlc_va_conn_t *conn)
conn->destroy_surfaces(conn);
}
static inline VASurfaceID *vlc_va_conn_GetSurfaces(vlc_va_conn_t *conn)
static inline vlc_va_surface_t *vlc_va_conn_GetSurface(vlc_va_conn_t *conn)
{
return conn->p_surface_ids;
return conn->get_surface(conn);
}
static inline int vlc_va_conn_SurfacesCount(vlc_va_conn_t *conn)
static inline void vlc_va_conn_ReleaseSurface(vlc_va_conn_t *conn, vlc_va_surface_t *surface)
{
return conn->i_surface_count;
conn->release_surface(conn, surface);
}
/* vlc_va_surface_t */
typedef struct
static inline unsigned int vlc_va_conn_SurfacesCount(vlc_va_conn_t *conn)
{
VASurfaceID i_id;
int i_refcount;
unsigned int i_order;
} vlc_va_surface_t;
return conn->pool.count;
}
/* picture_sys_t */
struct picture_sys_t
{
/* Link surface with picture_sys_t permanently */
VASurfaceID i_id;
int i_refcount;
unsigned int i_cache; /* subpicture cache identifier */
/* subpicture */
unsigned int i_cache;
vlc_mutex_t lock;
};
static inline void vlc_va_SurfaceHold(vlc_va_surface_t *surface)
{
vlc_mutex_lock(&surface->lock);
surface->i_refcount++;
vlc_mutex_unlock(&surface->lock);
}
static inline void vlc_va_SurfaceRelease(vlc_va_surface_t *surface)
{
vlc_mutex_lock(&surface->lock);
surface->i_refcount--;
vlc_mutex_unlock(&surface->lock);
}
#endif
#endif
......@@ -357,7 +357,7 @@ void CloseVaapiX11(vlc_object_t *obj)
if (sys->vaconn)
{
sys->vaconn->lock();
sys->vaconn->destroy_surfaces(sys->vaconn);
vlc_va_conn_DestroySurfaces(sys->vaconn);
sys->vaconn->unlock();
vlc_va_Terminate(sys->vaconn);
}
......@@ -572,6 +572,18 @@ static void DisplayVASurface(vout_display_t *vd, picture_t *picture)
vout_display_place_t place;
vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
/*
#define VA_FILTER_SCALING_DEFAULT 0x00000000
#define VA_FILTER_SCALING_FAST 0x00000100
#define VA_FILTER_SCALING_HQ 0x00000200
#define VA_FILTER_SCALING_NL_ANAMORPHIC 0x00000300
#define VA_FILTER_SCALING_MASK 0x00000f00
*/
unsigned int flags = VA_FILTER_SCALING_DEFAULT;
/* NOTE: vaCreateContext() specifies VA_PROGRESSIVE */
flags |= picture->b_progressive ? VA_FRAME_PICTURE :
(picture->b_top_field_first ? VA_TOP_FIELD : VA_BOTTOM_FIELD);
msg_Dbg( vd, "Displaying surface id: %d / %p", surface->i_id, picture );
VAStatus status;
status = vaPutSurface(sys->vaconn->p_display, surface->i_id, sys->window,
......@@ -579,9 +591,7 @@ static void DisplayVASurface(vout_display_t *vd, picture_t *picture)
vd->source.i_visible_width, vd->source.i_visible_height,
place.x, place.y, place.width, place.height,
NULL, 0, /* clipping */
/* NOTE: vaCreateContext() specifies VA_PROGRESSIVE */
picture->b_progressive ? VA_FRAME_PICTURE :
(picture->b_top_field_first ? VA_TOP_FIELD : VA_BOTTOM_FIELD));
flags);
if (status != VA_STATUS_SUCCESS)
msg_Err(vd, "failed displaying picture: %d (surface id=%d): %p",
status, surface->i_id, picture);
......@@ -648,9 +658,11 @@ out:
*/
static int PictureLock(picture_t *picture)
{
picture_sys_t *surface = picture->p_sys;
if (surface)
surface->i_refcount++;
vlc_va_surface_t *surface = picture->p_sys;
if (surface == NULL)
abort();
vlc_va_SurfaceHold(surface);
return VLC_SUCCESS;
}
......@@ -658,12 +670,11 @@ static void PictureUnlock(picture_t *picture)
{
assert(picture->p_sys);
picture_sys_t *surface = picture->p_sys;
vlc_va_surface_t *surface = picture->p_sys;
if (surface == NULL)
abort();
if (surface->i_refcount > 0)
surface->i_refcount--;
vlc_va_SurfaceRelease(surface);
}
/* PictureRelease is called when the picture pool is destroyed. */
......@@ -672,7 +683,6 @@ static void PictureRelease(picture_t *picture)
if (picture->i_refcount > 0)
picture->i_refcount--;
free(picture->p_sys);
picture->p_sys = NULL;
}
......@@ -689,7 +699,7 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
/* Create surfaces */
sys->vaconn->lock();
unsigned alloc_count = __MAX(sys->vaconn->i_surface_count, requested_count);
unsigned int alloc_count = __MAX(vlc_va_conn_SurfacesCount(sys->vaconn), requested_count);
picture_t **pic_array = (picture_t **) calloc(alloc_count, sizeof(picture_t *));
if (!pic_array)
......@@ -702,21 +712,11 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
if (!pic)
break;
assert(pic->p_sys == NULL);
picture_sys_t *pic_sys = (picture_sys_t *) malloc(sizeof(picture_sys_t));
if (!pic_sys)
{
picture_Release(pic);
break;
}
pic->format.i_chroma = VLC_CODEC_VAAPI_SURFACE;
pic_sys->i_id = VA_INVALID_SURFACE;
pic_sys->i_refcount = 0;
pic_sys->i_cache = 0;
pic->format.i_chroma = VLC_CODEC_VAAPI_SURFACE;
pic_array[count] = pic;
pic_array[count]->b_progressive = true;
pic_array[count]->p_sys = pic_sys;
pic_array[count]->pf_release = PictureRelease;
}
......@@ -725,24 +725,26 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
goto error;
unsigned int i_surface_count = __MIN(count, alloc_count);
/* Create surfaces */
VASurfaceID *pi_surface_id;
pi_surface_id = sys->vaconn->create_surfaces(sys->vaconn,
vd->fmt.i_visible_width, vd->fmt.i_visible_height,
VA_RT_FORMAT_YUV420, i_surface_count);
assert( pi_surface_id );
assert( i_surface_count == count );
if (pi_surface_id == NULL)
msg_Info( vd, "Requested %d/%d surfaces for picture pool.",
i_surface_count, vlc_va_conn_SurfacesCount(sys->vaconn) );
/* Create surfaces */
if( !vlc_va_conn_CreateSurface( sys->vaconn,
vd->fmt.i_visible_width,
vd->fmt.i_visible_height,
VA_RT_FORMAT_YUV420, i_surface_count ) )
{
/* FAIL */
goto error;
}
for (unsigned int i = 0; i < i_surface_count; i++)
{
picture_sys_t *pic_sys = pic_array[i]->p_sys;
assert(pic_sys);
pic_sys->i_id = pi_surface_id[i];
vlc_va_surface_t *surface = vlc_va_conn_GetSurface( sys->vaconn );
if( surface )
pic_array[i]->p_sys = (picture_sys_t *)surface;
}
/* Register pool with video output core */
......@@ -770,8 +772,15 @@ error:
{
picture_t *pic = pic_array[i];
if (pic)
{
if (pic->p_sys)
{
vlc_va_surface_t *surface = (vlc_va_surface_t *) pic->p_sys;
vlc_va_conn_ReleaseSurface(sys->vaconn, surface);
}
picture_Release(pic);
}
}
free(pic_array);
fail:
......
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