Commit 4b01d3cc authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

vaapi: advance and simplify surface allocation

parent a8fe33db
...@@ -55,12 +55,6 @@ ...@@ -55,12 +55,6 @@
vaCreateSurfaces(d, w, h, f, ns, s) vaCreateSurfaces(d, w, h, f, ns, s)
#endif #endif
typedef struct
{
VASurfaceID i_id;
vlc_va_sys_t *sys;
} vlc_va_surface_t;
struct vlc_va_sys_t struct vlc_va_sys_t
{ {
#ifdef VLC_VA_BACKEND_XLIB #ifdef VLC_VA_BACKEND_XLIB
...@@ -77,8 +71,6 @@ struct vlc_va_sys_t ...@@ -77,8 +71,6 @@ struct vlc_va_sys_t
int i_surface_height; int i_surface_height;
vlc_fourcc_t i_surface_chroma; vlc_fourcc_t i_surface_chroma;
vlc_va_surface_t *p_surface;
VAImage image; VAImage image;
copy_cache_t image_cache; copy_cache_t image_cache;
...@@ -86,6 +78,7 @@ struct vlc_va_sys_t ...@@ -86,6 +78,7 @@ struct vlc_va_sys_t
uint8_t count; uint8_t count;
uint32_t available; uint32_t available;
VASurfaceID surfaces[32];
}; };
static void DestroySurfaces( vlc_va_sys_t *sys ) static void DestroySurfaces( vlc_va_sys_t *sys )
...@@ -103,19 +96,9 @@ static void DestroySurfaces( vlc_va_sys_t *sys ) ...@@ -103,19 +96,9 @@ static void DestroySurfaces( vlc_va_sys_t *sys )
if (sys->hw_ctx.context_id != VA_INVALID_ID) if (sys->hw_ctx.context_id != VA_INVALID_ID)
vaDestroyContext(sys->hw_ctx.display, sys->hw_ctx.context_id); vaDestroyContext(sys->hw_ctx.display, sys->hw_ctx.context_id);
for( unsigned i = 0; i < sys->count && sys->p_surface; i++ )
{
vlc_va_surface_t *p_surface = &sys->p_surface[i];
if( p_surface->i_id != VA_INVALID_SURFACE )
vaDestroySurfaces(sys->hw_ctx.display, &p_surface->i_id, 1);
}
free( sys->p_surface );
/* */ /* */
sys->image.image_id = VA_INVALID_ID; sys->image.image_id = VA_INVALID_ID;
sys->hw_ctx.context_id = VA_INVALID_ID; sys->hw_ctx.context_id = VA_INVALID_ID;
sys->p_surface = NULL;
sys->i_surface_width = 0; sys->i_surface_width = 0;
sys->i_surface_height = 0; sys->i_surface_height = 0;
vlc_mutex_destroy(&sys->lock); vlc_mutex_destroy(&sys->lock);
...@@ -127,36 +110,13 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi ...@@ -127,36 +110,13 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi
assert( i_width > 0 && i_height > 0 ); assert( i_width > 0 && i_height > 0 );
/* */ /* */
sys->p_surface = calloc( sys->count, sizeof(*sys->p_surface) );
if( !sys->p_surface )
return VLC_EGENERIC;
sys->image.image_id = VA_INVALID_ID; sys->image.image_id = VA_INVALID_ID;
sys->hw_ctx.context_id = VA_INVALID_ID; sys->hw_ctx.context_id = VA_INVALID_ID;
/* Create surfaces */
VASurfaceID pi_surface_id[sys->count];
if (vaCreateSurfaces(sys->hw_ctx.display, VA_RT_FORMAT_YUV420, i_width,
i_height, pi_surface_id, sys->count, NULL, 0 ) )
{
for( unsigned i = 0; i < sys->count; i++ )
sys->p_surface[i].i_id = VA_INVALID_SURFACE;
goto error;
}
sys->available = (1 << sys->count) - 1;
for( unsigned i = 0; i < sys->count; i++ )
{
vlc_va_surface_t *p_surface = &sys->p_surface[i];
p_surface->i_id = pi_surface_id[i];
p_surface->sys = sys;
}
/* Create a context */ /* Create a context */
if (vaCreateContext(sys->hw_ctx.display, sys->hw_ctx.config_id, if (vaCreateContext(sys->hw_ctx.display, sys->hw_ctx.config_id,
i_width, i_height, VA_PROGRESSIVE, i_width, i_height, VA_PROGRESSIVE,
pi_surface_id, sys->count, &sys->hw_ctx.context_id)) sys->surfaces, sys->count, &sys->hw_ctx.context_id))
{ {
sys->hw_ctx.context_id = VA_INVALID_ID; sys->hw_ctx.context_id = VA_INVALID_ID;
goto error; goto error;
...@@ -176,7 +136,7 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi ...@@ -176,7 +136,7 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi
VAImage test_image; VAImage test_image;
vlc_fourcc_t deriveImageFormat = 0; vlc_fourcc_t deriveImageFormat = 0;
if (vaDeriveImage(sys->hw_ctx.display, pi_surface_id[0], &test_image) == VA_STATUS_SUCCESS) if (vaDeriveImage(sys->hw_ctx.display, sys->surfaces[0], &test_image) == VA_STATUS_SUCCESS)
{ {
sys->b_supports_derive = true; sys->b_supports_derive = true;
deriveImageFormat = test_image.format.fourcc; deriveImageFormat = test_image.format.fourcc;
...@@ -197,7 +157,7 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi ...@@ -197,7 +157,7 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi
continue; continue;
} }
/* Validate that vaGetImage works with this format */ /* Validate that vaGetImage works with this format */
if (vaGetImage(sys->hw_ctx.display, pi_surface_id[0], if (vaGetImage(sys->hw_ctx.display, sys->surfaces[0],
0, 0, i_width, i_height, sys->image.image_id)) 0, 0, i_width, i_height, sys->image.image_id))
{ {
vaDestroyImage(sys->hw_ctx.display, sys->image.image_id); vaDestroyImage(sys->hw_ctx.display, sys->image.image_id);
...@@ -354,19 +314,20 @@ static int Get( vlc_va_t *va, picture_t *pic, uint8_t **data ) ...@@ -354,19 +314,20 @@ static int Get( vlc_va_t *va, picture_t *pic, uint8_t **data )
if( i >= sys->count ) if( i >= sys->count )
return VLC_ENOMEM; return VLC_ENOMEM;
vlc_va_surface_t *p_surface = &sys->p_surface[i]; VASurfaceID *surface = &sys->surfaces[i];
pic->context = p_surface; pic->context = surface;
*data = (void *)(uintptr_t)p_surface->i_id; *data = (void *)(uintptr_t)*surface;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static void Release( void *opaque, uint8_t *data ) static void Release( void *opaque, uint8_t *data )
{ {
picture_t *pic = opaque; picture_t *pic = opaque;
vlc_va_surface_t *p_surface = pic->context; VASurfaceID *surface = pic->context;
vlc_va_sys_t *sys = p_surface->sys; vlc_va_sys_t *sys = (void *)((((uintptr_t)surface)
unsigned i = p_surface - sys->p_surface; - offsetof(vlc_va_sys_t, surfaces)) & ~(sizeof (sys->surfaces) - 1));
unsigned i = surface - sys->surfaces;
vlc_mutex_lock( &sys->lock ); vlc_mutex_lock( &sys->lock );
assert(((sys->available >> i) & 1) == 0); assert(((sys->available >> i) & 1) == 0);
...@@ -407,9 +368,8 @@ static void Delete( vlc_va_t *va, AVCodecContext *avctx ) ...@@ -407,9 +368,8 @@ static void Delete( vlc_va_t *va, AVCodecContext *avctx )
vlc_va_sys_t *sys = va->sys; vlc_va_sys_t *sys = va->sys;
(void) avctx; (void) avctx;
if( sys->i_surface_width || sys->i_surface_height )
DestroySurfaces( sys );
vaDestroySurfaces(sys->hw_ctx.display, sys->surfaces, sys->count);
vaDestroyConfig(sys->hw_ctx.display, sys->hw_ctx.config_id); vaDestroyConfig(sys->hw_ctx.display, sys->hw_ctx.config_id);
vaTerminate(sys->hw_ctx.display); vaTerminate(sys->hw_ctx.display);
#ifdef VLC_VA_BACKEND_XLIB #ifdef VLC_VA_BACKEND_XLIB
...@@ -467,10 +427,16 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, ...@@ -467,10 +427,16 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
} }
count += ctx->thread_count; count += ctx->thread_count;
vlc_va_sys_t *sys = calloc( 1, sizeof(*sys) ); vlc_va_sys_t *sys;
if ( unlikely(sys == NULL) ) void *mem;
assert(popcount(sizeof (sys->surfaces)) == 1);
if (unlikely(posix_memalign(&mem, sizeof (sys->surfaces), sizeof (*sys))))
return VLC_ENOMEM; return VLC_ENOMEM;
sys = mem;
memset(sys, 0, sizeof (*sys));
/* */ /* */
sys->hw_ctx.display = NULL; sys->hw_ctx.display = NULL;
sys->hw_ctx.config_id = VA_INVALID_ID; sys->hw_ctx.config_id = VA_INVALID_ID;
...@@ -478,8 +444,9 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, ...@@ -478,8 +444,9 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
sys->image.image_id = VA_INVALID_ID; sys->image.image_id = VA_INVALID_ID;
sys->b_supports_derive = false; sys->b_supports_derive = false;
sys->count = count; sys->count = count;
sys->available = 0; sys->available = (1 << sys->count) - 1;
assert(count < sizeof (sys->available) * CHAR_BIT); assert(count < sizeof (sys->available) * CHAR_BIT);
assert(count * sizeof (sys->surfaces[0]) <= sizeof (sys->surfaces));
/* Create a VA display */ /* Create a VA display */
#ifdef VLC_VA_BACKEND_XLIB #ifdef VLC_VA_BACKEND_XLIB
...@@ -558,6 +525,15 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, ...@@ -558,6 +525,15 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
goto error; goto error;
} }
/* Create surfaces */
assert(ctx->coded_width > 0 && ctx->coded_height > 0);
if (vaCreateSurfaces(sys->hw_ctx.display, VA_RT_FORMAT_YUV420,
ctx->coded_width, ctx->coded_height,
sys->surfaces, sys->count, NULL, 0))
{
goto error;
}
vlc_mutex_init(&sys->lock); vlc_mutex_init(&sys->lock);
va->sys = sys; va->sys = sys;
...@@ -569,6 +545,8 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, ...@@ -569,6 +545,8 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
if (sys->hw_ctx.config_id != VA_INVALID_ID)
vaDestroyConfig(sys->hw_ctx.display, sys->hw_ctx.config_id);
if (sys->hw_ctx.display != NULL) if (sys->hw_ctx.display != NULL)
vaTerminate(sys->hw_ctx.display); vaTerminate(sys->hw_ctx.display);
#ifdef VLC_VA_BACKEND_XLIB #ifdef VLC_VA_BACKEND_XLIB
......
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