Commit 7a0dda44 authored by Jean-Paul Saman's avatar Jean-Paul Saman

VAAPI-XCB: XvBA decoding support

Reworked vlc_va_conn_t and vlc_va_t to integrate better.
parent 26cecc2f
......@@ -48,7 +48,7 @@
#ifdef HAVE_AVCODEC_VAAPI
/* Global VAAPI connection state */
static vlc_va_conn_t vlc_va_conn = { 0, 0, 0, 0, NULL, NULL };
static vlc_va_conn_t vlc_va_conn = { 0, 0, 0, 0, NULL, NULL, 0, NULL, NULL, NULL };
static vlc_mutex_t vlc_va_conn_lock = VLC_STATIC_MUTEX;
static void vlc_va_lock(void)
......@@ -61,6 +61,61 @@ static void vlc_va_unlock(void)
vlc_mutex_unlock(&vlc_va_conn_lock);
}
static VASurfaceID *vlc_va_create_surfaces( vlc_va_conn_t *conn,
const int width, const int height, const int fourcc, const int num )
{
assert(conn);
if( (width <= 0) || (height <= 0) || (num <= 0) )
return NULL;
/* FIXME: The size does not necessary match */
if( conn->i_ref_count > 1 )
{
assert( num == conn->i_surface_count );
return conn->p_surface_ids;
}
assert( conn->p_surface_ids == NULL );
assert( conn->i_surface_count == 0 );
VASurfaceID *p_surfaces = (VASurfaceID *)calloc(num, sizeof(VASurfaceID));
if( p_surfaces == NULL )
return NULL;
int i_surface_count = num;
VAStatus status = vaCreateSurfaces( conn->p_display, width, height, fourcc,
num, p_surfaces );
if( status != VA_STATUS_SUCCESS )
{
free( p_surfaces );
return NULL;
}
assert( i_surface_count == num );
conn->p_surface_ids = p_surfaces;
conn->i_surface_count = i_surface_count;
return conn->p_surface_ids;
}
static void vlc_va_destroy_surfaces( vlc_va_conn_t *conn )
{
assert( conn );
assert( conn->i_surface_count > 0 );
assert( conn->p_surface_ids );
if( conn->i_ref_count > 1 )
return;
if( conn->p_surface_ids != NULL )
vaDestroySurfaces( conn->p_display, conn->p_surface_ids,
conn->i_surface_count );
conn->i_surface_count = 0;
conn->p_surface_ids = NULL;
}
/* */
vlc_va_conn_t *vlc_va_get_conn( void )
{
......@@ -84,6 +139,11 @@ vlc_va_conn_t *vlc_va_Initialize( Display *display )
conn->lock = vlc_va_lock;
conn->unlock = vlc_va_unlock;
conn->i_surface_count = 0;
conn->p_surface_ids = NULL;
conn->create_surfaces = vlc_va_create_surfaces;
conn->destroy_surfaces = vlc_va_destroy_surfaces;
/* Create a VA display */
conn->p_display = vaGetDisplay(display);
if( !conn->p_display )
......@@ -109,6 +169,9 @@ void vlc_va_Terminate( vlc_va_conn_t *conn )
if (conn->i_ref_count > 0)
return;
assert(conn->i_surface_count == 0);
assert(conn->p_surface_ids == NULL);
if( conn->p_display )
vaTerminate( conn->p_display );
......
......@@ -24,7 +24,10 @@
#ifndef _VLC_VA_H
#define _VLC_VA_H 1
typedef struct vlc_va_conn_t vlc_va_conn_t;
typedef struct vlc_va_ops_t vlc_va_ops_t;
typedef struct vlc_va_t vlc_va_t;
struct vlc_va_t {
char *description;
vlc_object_t *obj;
......@@ -72,9 +75,4 @@ static inline void vlc_va_Delete(vlc_va_t *va)
vlc_va_t *vlc_va_NewVaapi(vlc_object_t *obj, int codec_id);
vlc_va_t *vlc_va_NewDxva2(vlc_object_t *log, int codec_id);
/* */
typedef struct vlc_va_conn_t vlc_va_conn_t;
vlc_va_conn_t *vlc_va_get_conn( void );
#endif
......@@ -117,7 +117,7 @@ static int Open( vlc_va_vaapi_t *p_va, int i_codec_id )
break;
case CODEC_ID_H264:
i_profile = VAProfileH264High;
i_surface_count = 16+1;
i_surface_count = 30; //16+1;
break;
default:
return VLC_EGENERIC;
......@@ -173,7 +173,63 @@ error:
return VLC_EGENERIC;
}
static void DestroySurfaces( vlc_va_vaapi_t *p_va )
static void DestroySurfaces( vlc_va_conn_t *conn )
{
assert( conn );
assert( conn->i_surface_count > 0 );
assert( conn->p_surface_ids );
if( conn->i_ref_count > 1 )
return;
if( conn->p_surface_ids != NULL )
vaDestroySurfaces( conn->p_display, conn->p_surface_ids,
conn->i_surface_count );
conn->i_surface_count = 0;
conn->p_surface_ids = NULL;
}
static VASurfaceID *CreateSurfaces( vlc_va_conn_t *conn,
const int width, const int height, const int fourcc, const int num )
{
assert(conn);
if( (width <= 0) || (height <= 0) || (num <= 0) )
return NULL;
/* FIXME: The size does not necessary match */
if( conn->i_ref_count > 1 )
{
assert( num == conn->i_surface_count );
return conn->p_surface_ids;
}
assert( conn->p_surface_ids == NULL );
assert( conn->i_surface_count == 0 );
VASurfaceID *p_surfaces = (VASurfaceID *)calloc(num, sizeof(VASurfaceID));
if( p_surfaces == NULL )
return NULL;
int i_surface_count = num;
VAStatus status = vaCreateSurfaces( conn->p_display, width, height, fourcc,
num, p_surfaces );
if( status != VA_STATUS_SUCCESS )
{
free( p_surfaces );
return NULL;
}
assert( i_surface_count == num );
conn->p_surface_ids = p_surfaces;
conn->i_surface_count = i_surface_count;
return conn->p_surface_ids;
}
static void DestroyDecodingContext( vlc_va_vaapi_t *p_va )
{
p_va->conn->lock();
if( p_va->image.image_id != VA_INVALID_ID )
......@@ -185,12 +241,7 @@ static void DestroySurfaces( vlc_va_vaapi_t *p_va )
if( p_va->i_context_id != VA_INVALID_ID )
vaDestroyContext( p_va->conn->p_display, p_va->i_context_id );
for( int i = 0; i < p_va->i_surface_count && p_va->p_surface; i++ )
{
vlc_va_surface_t *p_surface = &p_va->p_surface[i];
if( p_surface->i_id != VA_INVALID_SURFACE )
vaDestroySurfaces( p_va->conn->p_display, &p_surface->i_id, 1 );
}
DestroySurfaces( p_va->conn );
free( p_va->p_surface );
/* */
......@@ -201,7 +252,8 @@ static void DestroySurfaces( vlc_va_vaapi_t *p_va )
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,
static int CreateDecodingContext( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
int i_width, int i_height )
{
assert( i_width > 0 && i_height > 0 );
......@@ -216,9 +268,9 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
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,
p_va->i_surface_count, pi_surface_id ) )
VASurfaceID *pi_surface_id = CreateSurfaces( p_va->conn, i_width, i_height,
VA_RT_FORMAT_YUV420, p_va->i_surface_count );
if( pi_surface_id == NULL )
{
for( int i = 0; i < p_va->i_surface_count; i++ )
p_va->p_surface[i].i_id = VA_INVALID_SURFACE;
......@@ -306,7 +358,7 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
error:
p_va->conn->unlock();
DestroySurfaces( p_va );
DestroyDecodingContext( p_va );
return VLC_EGENERIC;
}
......@@ -326,10 +378,10 @@ static int Setup( vlc_va_t *p_external, void **pp_hw_ctx, vlc_fourcc_t *pi_chrom
*pp_hw_ctx = NULL;
*pi_chroma = 0;
if( p_va->i_surface_width || p_va->i_surface_height )
DestroySurfaces( p_va );
DestroyDecodingContext( p_va );
if( i_width > 0 && i_height > 0 )
return CreateSurfaces( p_va, pp_hw_ctx, pi_chroma, i_width, i_height );
return CreateDecodingContext( p_va, pp_hw_ctx, pi_chroma, i_width, i_height );
return VLC_EGENERIC;
}
......@@ -525,7 +577,7 @@ static void Release( vlc_va_t *p_external, AVFrame *p_ff )
static void Close( vlc_va_vaapi_t *p_va )
{
if( p_va->i_surface_width || p_va->i_surface_height )
DestroySurfaces( p_va );
DestroyDecodingContext( p_va );
if (p_va->conn)
{
......
......@@ -18,20 +18,65 @@
****************************************************************************/
#ifdef HAVE_AVCODEC_VAAPI
/* VA API connection shared structure
* The decoding thread and the display thread
* need to share the connection to libva and
* the created surfaces for use with decoding
* context.
*/
struct vlc_va_conn_t
{
VADisplay p_display;
int i_version_major;
int i_version_minor;
int i_ref_count; /* for internal use only */
int i_ref_count;
/* locking functions */
void (*lock)(void);
void (*unlock)(void);
/* NOTE: must be called with lock held */
int i_surface_count;
VASurfaceID *p_surface_ids;
VASurfaceID *(*create_surfaces)(vlc_va_conn_t *conn, const int width, const int height,
const int fourcc, const int num);
void (*destroy_surfaces)(vlc_va_conn_t *conn);
};
/* Retrieve shared connection struct */
vlc_va_conn_t *vlc_va_get_conn( void );
/* Initialize shared connection to libva */
vlc_va_conn_t *vlc_va_Initialize(Display *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,
const int width, const int height, const int fourcc, const int num)
{
return conn->create_surfaces(conn, width, height, fourcc, num);
}
static inline void vlc_va_conn_DestorySurfaces(vlc_va_conn_t *conn)
{
conn->destroy_surfaces(conn);
}
static inline VASurfaceID *vlc_va_conn_GetSurfaces(vlc_va_conn_t *conn)
{
return conn->p_surface_ids;
}
static inline int vlc_va_conn_SurfacesCount(vlc_va_conn_t *conn)
{
return conn->i_surface_count;
}
/* vlc_va_surface_t */
typedef struct
{
VASurfaceID i_id;
......@@ -39,6 +84,7 @@ typedef struct
unsigned int i_order;
} vlc_va_surface_t;
/* picture_sys_t */
struct picture_sys_t
{
/* */
......
......@@ -492,7 +492,7 @@ int OpenVaapiX11(vlc_object_t *obj)
sys->visible = false;
sys->cursor = CreateBlankCursor(conn, scr);
msg_Dbg(vd, "using VAAPI X11 video output (libva version %d.%d)",
msg_Info(vd, "using VAAPI XCB video output (libva version %d.%d)",
sys->conn->i_version_major, sys->conn->i_version_minor);
/* */
......@@ -583,7 +583,10 @@ void CloseVaapiX11(vlc_object_t *obj)
}
if (sys->conn)
{
sys->conn->destroy_surfaces(sys->conn);
vlc_va_Terminate(sys->conn);
}
if (sys->x11display)
XCloseDisplay(sys->x11display);
......@@ -1426,16 +1429,22 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
}
int i_surface_count = count;
VASurfaceID pi_surface_id[i_surface_count];
if (count == 0)
goto error;
/* Create surfaces */
sys->conn->lock();
if (vaCreateSurfaces(sys->conn->p_display, vd->fmt.i_visible_width,
vd->fmt.i_visible_height, VA_RT_FORMAT_YUV420,
i_surface_count, pi_surface_id))
VASurfaceID *pi_surface_id;
if (sys->conn->i_surface_count < i_surface_count)
{
pi_surface_id = sys->conn->create_surfaces(sys->conn,
vd->fmt.i_visible_width, vd->fmt.i_visible_height,
VA_RT_FORMAT_YUV420, i_surface_count);
}
else pi_surface_id = sys->conn->p_surface_ids;
if (pi_surface_id == NULL)
{
sys->conn->unlock();
goto error;
......
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