[vlc-commits] vaapi: reduce reference count overhead and fix data race
Rémi Denis-Courmont
git at videolan.org
Fri Apr 24 22:47:03 CEST 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Fri Apr 24 22:04:46 2015 +0300| [fb755df87bd64dd99155152b68acf8f47e94fcff] | committer: Rémi Denis-Courmont
vaapi: reduce reference count overhead and fix data race
(The reference count was updated without the mutex.)
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=fb755df87bd64dd99155152b68acf8f47e94fcff
---
modules/codec/avcodec/vaapi.c | 75 ++++++++++++++++++++---------------------
1 file changed, 37 insertions(+), 38 deletions(-)
diff --git a/modules/codec/avcodec/vaapi.c b/modules/codec/avcodec/vaapi.c
index 3087fe2..06e63df 100644
--- a/modules/codec/avcodec/vaapi.c
+++ b/modules/codec/avcodec/vaapi.c
@@ -58,8 +58,7 @@
typedef struct
{
VASurfaceID i_id;
- int i_refcount;
- vlc_mutex_t *p_lock;
+ vlc_va_sys_t *sys;
} vlc_va_surface_t;
struct vlc_va_sys_t
@@ -79,7 +78,6 @@ struct vlc_va_sys_t
/* */
vlc_mutex_t lock;
- int i_surface_count;
int i_surface_width;
int i_surface_height;
vlc_fourcc_t i_surface_chroma;
@@ -90,6 +88,9 @@ struct vlc_va_sys_t
copy_cache_t image_cache;
bool b_supports_derive;
+
+ uint8_t count;
+ uint32_t available;
};
static void DestroySurfaces( vlc_va_sys_t *sys )
@@ -107,7 +108,7 @@ static void DestroySurfaces( vlc_va_sys_t *sys )
if( sys->i_context_id != VA_INVALID_ID )
vaDestroyContext( sys->p_display, sys->i_context_id );
- for( int i = 0; i < sys->i_surface_count && sys->p_surface; i++ )
+ for( unsigned i = 0; i < sys->count && sys->p_surface; i++ )
{
vlc_va_surface_t *p_surface = &sys->p_surface[i];
@@ -131,35 +132,36 @@ static int CreateSurfaces( vlc_va_sys_t *sys, void **pp_hw_ctx, vlc_fourcc_t *pi
assert( i_width > 0 && i_height > 0 );
/* */
- sys->p_surface = calloc( sys->i_surface_count, sizeof(*sys->p_surface) );
+ 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->i_context_id = VA_INVALID_ID;
/* Create surfaces */
- VASurfaceID pi_surface_id[sys->i_surface_count];
+ VASurfaceID pi_surface_id[sys->count];
if( vaCreateSurfaces( sys->p_display, VA_RT_FORMAT_YUV420, i_width, i_height,
- pi_surface_id, sys->i_surface_count, NULL, 0 ) )
+ pi_surface_id, sys->count, NULL, 0 ) )
{
- for( int i = 0; i < sys->i_surface_count; i++ )
+ for( unsigned i = 0; i < sys->count; i++ )
sys->p_surface[i].i_id = VA_INVALID_SURFACE;
goto error;
}
- for( int i = 0; i < sys->i_surface_count; i++ )
+ 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->i_refcount = 0;
- p_surface->p_lock = &sys->lock;
+ p_surface->sys = sys;
}
/* Create a context */
if( vaCreateContext( sys->p_display, sys->i_config_id,
i_width, i_height, VA_PROGRESSIVE,
- pi_surface_id, sys->i_surface_count, &sys->i_context_id ) )
+ pi_surface_id, sys->count, &sys->i_context_id ) )
{
sys->i_context_id = VA_INVALID_ID;
goto error;
@@ -349,24 +351,21 @@ static int Extract( vlc_va_t *va, picture_t *p_picture, uint8_t *data )
static int Get( vlc_va_t *va, picture_t *pic, uint8_t **data )
{
vlc_va_sys_t *sys = va->sys;
- int i;
+ unsigned i = sys->count;
vlc_mutex_lock( &sys->lock );
- for( i = 0; i < sys->i_surface_count; i++ )
+ if (sys->available)
{
- vlc_va_surface_t *p_surface = &sys->p_surface[i];
-
- if( !p_surface->i_refcount )
- break;
+ i = ctz(sys->available);
+ sys->available &= ~(1 << i);
}
vlc_mutex_unlock( &sys->lock );
- if( i == sys->i_surface_count )
+ if( i >= sys->count )
return VLC_ENOMEM;
vlc_va_surface_t *p_surface = &sys->p_surface[i];
- p_surface->i_refcount = 1;
pic->context = p_surface;
*data = (void *)(uintptr_t)p_surface->i_id;
return VLC_SUCCESS;
@@ -376,10 +375,13 @@ static void Release( void *opaque, uint8_t *data )
{
picture_t *pic = opaque;
vlc_va_surface_t *p_surface = pic->context;
+ vlc_va_sys_t *sys = p_surface->sys;
+ unsigned i = p_surface - sys->p_surface;
- vlc_mutex_lock( p_surface->p_lock );
- p_surface->i_refcount--;
- vlc_mutex_unlock( p_surface->p_lock );
+ vlc_mutex_lock( &sys->lock );
+ assert(((sys->available >> i) & 1) == 0);
+ sys->available |= 1 << i;
+ vlc_mutex_unlock( &sys->lock );
pic->context = NULL;
picture_Release(pic);
@@ -445,14 +447,10 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
}
#endif
- vlc_va_sys_t *sys = calloc( 1, sizeof(*sys) );
- if ( unlikely(sys == NULL) )
- return VLC_ENOMEM;
-
VAProfile i_profile, *p_profiles_list;
bool b_supported_profile = false;
int i_profiles_nb = 0;
- int i_surface_count;
+ unsigned count = 3;
/* */
switch( ctx->codec_id )
@@ -460,33 +458,38 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
case AV_CODEC_ID_MPEG1VIDEO:
case AV_CODEC_ID_MPEG2VIDEO:
i_profile = VAProfileMPEG2Main;
- i_surface_count = 2 + 2;
+ count = 4;
break;
case AV_CODEC_ID_MPEG4:
i_profile = VAProfileMPEG4AdvancedSimple;
- i_surface_count = 2+1;
break;
case AV_CODEC_ID_WMV3:
i_profile = VAProfileVC1Main;
- i_surface_count = 2+1;
break;
case AV_CODEC_ID_VC1:
i_profile = VAProfileVC1Advanced;
- i_surface_count = 2+1;
break;
case AV_CODEC_ID_H264:
i_profile = VAProfileH264High;
- i_surface_count = 16 + ctx->thread_count + 2;
+ count = 18;
break;;
default:
- free( sys );
return VLC_EGENERIC;
}
+ count += ctx->thread_count;
+
+ vlc_va_sys_t *sys = calloc( 1, sizeof(*sys) );
+ if ( unlikely(sys == NULL) )
+ return VLC_ENOMEM;
/* */
sys->i_config_id = VA_INVALID_ID;
sys->i_context_id = VA_INVALID_ID;
sys->image.image_id = VA_INVALID_ID;
+ sys->b_supports_derive = false;
+ sys->count = count;
+ sys->available = 0;
+ assert(count < sizeof (sys->available) * CHAR_BIT);
/* Create a VA display */
#ifdef VLC_VA_BACKEND_XLIB
@@ -566,10 +569,6 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
goto error;
}
- sys->i_surface_count = i_surface_count;
-
- sys->b_supports_derive = false;
-
vlc_mutex_init(&sys->lock);
va->sys = sys;
More information about the vlc-commits
mailing list