Commit 6f121876 authored by Laurent Aimar's avatar Laurent Aimar

Modified our vaapi wrapper in avcodec to be more generic.

parent 4668d065
/***************************************************************************** /*****************************************************************************
* vaapi.h: VAAPI helpers for the ffmpeg decoder * va.h: Video Acceleration API for avcodec
***************************************************************************** *****************************************************************************
* Copyright (C) 2009 Laurent Aimar * Copyright (C) 2009 Laurent Aimar
* $Id$ * $Id$
...@@ -21,23 +21,44 @@ ...@@ -21,23 +21,44 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/ *****************************************************************************/
#ifndef _VLC_VAAPI_H #ifndef _VLC_VA_H
#define _VLC_VAAPI_H 1 #define _VLC_VA_H 1
typedef struct vlc_va_t vlc_va_t; typedef struct vlc_va_t vlc_va_t;
struct vlc_va_t {
char *description;
vlc_va_t *VaNew( int i_codec_id ); int (*setup)(vlc_va_t *, void **hw, vlc_fourcc_t *output,
void VaDelete( vlc_va_t *p_va ); int width, int height);
int (*get)(vlc_va_t *, AVFrame *frame);
void (*release)(vlc_va_t *, AVFrame *frame);
int (*extract)(vlc_va_t *, picture_t *dst, AVFrame *src);
void (*close)(vlc_va_t *);
};
void VaVersion( vlc_va_t *p_va, char *psz_version, size_t i_version ); static inline int vlc_va_Setup(vlc_va_t *va, void **hw, vlc_fourcc_t *output,
int width, int height)
{
return va->setup(va, hw, output, width, height);
}
static inline int vlc_va_Get(vlc_va_t *va, AVFrame *frame)
{
return va->get(va, frame);
}
static inline void vlc_va_Release(vlc_va_t *va, AVFrame *frame)
{
va->release(va, frame);
}
static inline int vlc_va_Extract(vlc_va_t *va, picture_t *dst, AVFrame *src)
{
return va->extract(va, dst, src);
}
static inline void vlc_va_Delete(vlc_va_t *va)
{
va->close(va);
}
int VaSetup( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma, vlc_va_t *vlc_va_NewVaapi(int codec_id);
int i_width, int i_height );
int VaExtract( vlc_va_t *p_va, picture_t *p_picture, AVFrame *p_ff );
int VaGrabSurface( vlc_va_t *p_va, AVFrame *p_ff );
void VaUngrabSurface( vlc_va_t *p_va, AVFrame *p_ff );
#endif #endif
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#endif #endif
#include "avcodec.h" #include "avcodec.h"
#include "vaapi.h" #include "va.h"
#ifdef HAVE_AVCODEC_VAAPI #ifdef HAVE_AVCODEC_VAAPI
...@@ -57,8 +57,10 @@ typedef struct ...@@ -57,8 +57,10 @@ typedef struct
} vlc_va_surface_t; } vlc_va_surface_t;
struct vlc_va_t typedef struct
{ {
vlc_va_t va;
/* */ /* */
Display *p_display_x11; Display *p_display_x11;
VADisplay p_display; VADisplay p_display;
...@@ -83,56 +85,15 @@ struct vlc_va_t ...@@ -83,56 +85,15 @@ struct vlc_va_t
VAImage image; VAImage image;
}; } vlc_va_vaapi_t;
static int VaOpen( vlc_va_t *p_va, int i_codec_id );
static void VaClose( vlc_va_t *p_va );
static int VaCreateSurfaces( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
int i_width, int i_height );
static void VaDestroySurfaces( vlc_va_t *p_va );
vlc_va_t *VaNew( int i_codec_id ) static vlc_va_vaapi_t *vlc_va_vaapi_Get( void *p_va )
{ {
vlc_va_t *p_va = calloc( 1, sizeof(*p_va) );
if( !p_va )
return NULL;
if( VaOpen( p_va, i_codec_id ) )
{
free( p_va );
return NULL;
}
return p_va; return p_va;
} }
void VaDelete( vlc_va_t *p_va )
{
VaClose( p_va );
free( p_va );
}
int VaSetup( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
int i_width, int i_height )
{
if( p_va->i_surface_width == i_width &&
p_va->i_surface_height == i_height )
return VLC_SUCCESS;
*pp_hw_ctx = NULL;
*pi_chroma = 0;
if( p_va->i_surface_width || p_va->i_surface_height )
VaDestroySurfaces( p_va );
if( i_width > 0 && i_height > 0 )
return VaCreateSurfaces( p_va, pp_hw_ctx, pi_chroma, i_width, i_height );
return VLC_EGENERIC;
}
void VaVersion( vlc_va_t *p_va, char *psz_version, size_t i_version )
{
snprintf( psz_version, i_version, "%d.%d", p_va->i_version_major, p_va->i_version_minor );
}
static int VaOpen( vlc_va_t *p_va, int i_codec_id ) /* */
static int Open( vlc_va_vaapi_t *p_va, int i_codec_id )
{ {
VAProfile i_profile; VAProfile i_profile;
int i_surface_count; int i_surface_count;
...@@ -200,26 +161,42 @@ static int VaOpen( vlc_va_t *p_va, int i_codec_id ) ...@@ -200,26 +161,42 @@ static int VaOpen( vlc_va_t *p_va, int i_codec_id )
p_va->i_surface_count = i_surface_count; p_va->i_surface_count = i_surface_count;
if( asprintf( &p_va->va.description, "VA API version %d.%d",
p_va->i_version_major, p_va->i_version_minor ) < 0 )
p_va->va.description = NULL;
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
static void VaClose( vlc_va_t *p_va )
static void DestroySurfaces( vlc_va_vaapi_t *p_va )
{ {
if( p_va->i_surface_width || p_va->i_surface_height ) if( p_va->image.image_id )
VaDestroySurfaces( p_va ); vaDestroyImage( p_va->p_display, p_va->image.image_id );
if( p_va->i_config_id ) if( p_va->i_context_id )
vaDestroyConfig( p_va->p_display, p_va->i_config_id ); vaDestroyContext( p_va->p_display, p_va->i_context_id );
if( p_va->p_display )
vaTerminate( p_va->p_display );
if( p_va->p_display_x11 )
XCloseDisplay( p_va->p_display_x11 );
}
static int VaCreateSurfaces( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma, for( int i = 0; i < p_va->i_surface_count && p_va->p_surface; i++ )
int i_width, int i_height ) {
vlc_va_surface_t *p_surface = &p_va->p_surface[i];
if( p_surface->i_id != VA_INVALID_SURFACE )
vaDestroySurfaces( p_va->p_display, &p_surface->i_id, 1 );
}
free( p_va->p_surface );
/* */
p_va->image.image_id = 0;
p_va->i_context_id = 0;
p_va->p_surface = NULL;
p_va->i_surface_width = 0;
p_va->i_surface_height = 0;
}
static int CreateSurfaces( 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 ); assert( i_width > 0 && i_height > 0 );
...@@ -312,36 +289,33 @@ static int VaCreateSurfaces( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_ ...@@ -312,36 +289,33 @@ static int VaCreateSurfaces( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
VaDestroySurfaces( p_va ); DestroySurfaces( p_va );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
static void VaDestroySurfaces( vlc_va_t *p_va )
static int Setup( vlc_va_t *p_external, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
int i_width, int i_height )
{ {
if( p_va->image.image_id ) vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
vaDestroyImage( p_va->p_display, p_va->image.image_id );
if( p_va->i_context_id ) if( p_va->i_surface_width == i_width &&
vaDestroyContext( p_va->p_display, p_va->i_context_id ); p_va->i_surface_height == i_height )
return VLC_SUCCESS;
for( int i = 0; i < p_va->i_surface_count && p_va->p_surface; i++ ) *pp_hw_ctx = NULL;
{ *pi_chroma = 0;
vlc_va_surface_t *p_surface = &p_va->p_surface[i]; if( p_va->i_surface_width || p_va->i_surface_height )
DestroySurfaces( p_va );
if( p_surface->i_id != VA_INVALID_SURFACE ) if( i_width > 0 && i_height > 0 )
vaDestroySurfaces( p_va->p_display, &p_surface->i_id, 1 ); return CreateSurfaces( p_va, pp_hw_ctx, pi_chroma, i_width, i_height );
}
free( p_va->p_surface );
/* */ return VLC_EGENERIC;
p_va->image.image_id = 0;
p_va->i_context_id = 0;
p_va->p_surface = NULL;
p_va->i_surface_width = 0;
p_va->i_surface_height = 0;
} }
static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
int VaExtract( vlc_va_t *p_va, picture_t *p_picture, AVFrame *p_ff )
{ {
vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3]; VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3];
#if VA_CHECK_VERSION(0,31,0) #if VA_CHECK_VERSION(0,31,0)
...@@ -393,8 +367,9 @@ int VaExtract( vlc_va_t *p_va, picture_t *p_picture, AVFrame *p_ff ) ...@@ -393,8 +367,9 @@ int VaExtract( vlc_va_t *p_va, picture_t *p_picture, AVFrame *p_ff )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
int VaGrabSurface( vlc_va_t *p_va, AVFrame *p_ff ) static int Get( vlc_va_t *p_external, AVFrame *p_ff )
{ {
vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
int i_old; int i_old;
int i; int i;
...@@ -429,8 +404,10 @@ int VaGrabSurface( vlc_va_t *p_va, AVFrame *p_ff ) ...@@ -429,8 +404,10 @@ int VaGrabSurface( vlc_va_t *p_va, AVFrame *p_ff )
} }
return VLC_SUCCESS; return VLC_SUCCESS;
} }
void VaUngrabSurface( vlc_va_t *p_va, AVFrame *p_ff ) static void Release( vlc_va_t *p_external, AVFrame *p_ff )
{ {
vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3]; VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3];
for( int i = 0; i < p_va->i_surface_count; i++ ) for( int i = 0; i < p_va->i_surface_count; i++ )
...@@ -442,52 +419,51 @@ void VaUngrabSurface( vlc_va_t *p_va, AVFrame *p_ff ) ...@@ -442,52 +419,51 @@ void VaUngrabSurface( vlc_va_t *p_va, AVFrame *p_ff )
} }
} }
#else static void Close( vlc_va_vaapi_t *p_va )
vlc_va_t *VaNew( int i_codec_id )
{
VLC_UNUSED(i_codec_id);
return NULL;
}
void VaDelete( vlc_va_t *p_va )
{ {
VLC_UNUSED(p_va); if( p_va->i_surface_width || p_va->i_surface_height )
assert( 0 ); DestroySurfaces( p_va );
}
void VaVersion( vlc_va_t *p_va, char *psz_version, size_t i_version ) if( p_va->i_config_id )
{ vaDestroyConfig( p_va->p_display, p_va->i_config_id );
VLC_UNUSED(p_va); VLC_UNUSED(psz_version); VLC_UNUSED(i_version); if( p_va->p_display )
assert(0); vaTerminate( p_va->p_display );
if( p_va->p_display_x11 )
XCloseDisplay( p_va->p_display_x11 );
} }
static void Delete( vlc_va_t *p_external )
int VaSetup( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
int i_width, int i_height )
{ {
VLC_UNUSED(p_va); VLC_UNUSED(pp_hw_ctx); VLC_UNUSED(pi_chroma); vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
VLC_UNUSED(i_width); VLC_UNUSED(i_height); Close( p_va );
assert(0); free( p_va->va.description );
return -1; free( p_va );
} }
int VaExtract( vlc_va_t *p_va, picture_t *p_picture, AVFrame *p_ff ) /* */
vlc_va_t *vlc_va_NewVaapi( int i_codec_id )
{ {
VLC_UNUSED(p_va); VLC_UNUSED(p_picture); VLC_UNUSED(p_ff); vlc_va_vaapi_t *p_va = calloc( 1, sizeof(*p_va) );
assert(0); if( !p_va )
return -1; return NULL;
}
int VaGrabSurface( vlc_va_t *p_va, AVFrame *p_ff ) if( Open( p_va, i_codec_id ) )
{ {
VLC_UNUSED(p_va); VLC_UNUSED(p_ff); free( p_va );
assert(0); return NULL;
return -1; }
}
void VaUngrabSurface( vlc_va_t *p_va, AVFrame *p_ff ) /* */
p_va->va.setup = Setup;
p_va->va.get = Get;
p_va->va.release = Release;
p_va->va.extract = Extract;
p_va->va.close = Delete;
return &p_va->va;
}
#else
vlc_va_t *vlc_va_NewVaapi( int i_codec_id )
{ {
VLC_UNUSED(p_va); VLC_UNUSED(p_ff); VLC_UNUSED( i_codec_id );
assert(0); return NULL;
} }
#endif #endif
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#endif #endif
#include "avcodec.h" #include "avcodec.h"
#include "vaapi.h" #include "va.h"
/***************************************************************************** /*****************************************************************************
* decoder_sys_t : decoder descriptor * decoder_sys_t : decoder descriptor
...@@ -722,7 +722,7 @@ void EndVideoDec( decoder_t *p_dec ) ...@@ -722,7 +722,7 @@ void EndVideoDec( decoder_t *p_dec )
if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic ); if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );
if( p_sys->p_va ) if( p_sys->p_va )
VaDelete( p_sys->p_va ); vlc_va_Delete( p_sys->p_va );
} }
/***************************************************************************** /*****************************************************************************
...@@ -825,13 +825,8 @@ static int ffmpeg_OpenCodec( decoder_t *p_dec ) ...@@ -825,13 +825,8 @@ static int ffmpeg_OpenCodec( decoder_t *p_dec )
p_sys->b_delayed_open = false; p_sys->b_delayed_open = false;
if( p_sys->p_va ) if( p_sys->p_va && p_sys->p_va->description )
{ msg_Info( p_dec, "Using %s for hardware decoding.", p_sys->p_va->description );
char psz_version[128];
VaVersion( p_sys->p_va, psz_version, sizeof(psz_version) );
msg_Info( p_dec, "Using VA API version %s for hardware decoding.", psz_version );
}
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -846,7 +841,7 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec, ...@@ -846,7 +841,7 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec,
if( p_sys->p_va ) if( p_sys->p_va )
{ {
VaExtract( p_sys->p_va, p_pic, p_ff_pic ); vlc_va_Extract( p_sys->p_va, p_pic, p_ff_pic );
} }
else if( TestFfmpegChroma( p_sys->p_context->pix_fmt, -1 ) == VLC_SUCCESS ) else if( TestFfmpegChroma( p_sys->p_context->pix_fmt, -1 ) == VLC_SUCCESS )
{ {
...@@ -904,9 +899,9 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, ...@@ -904,9 +899,9 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
{ {
#ifdef HAVE_AVCODEC_VAAPI #ifdef HAVE_AVCODEC_VAAPI
/* hwaccel_context is not present in old fffmpeg version */ /* hwaccel_context is not present in old fffmpeg version */
if( VaSetup( p_sys->p_va, if( vlc_va_Setup( p_sys->p_va,
&p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma, &p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
p_sys->p_context->width, p_sys->p_context->height ) ) p_sys->p_context->width, p_sys->p_context->height ) )
{ {
msg_Err( p_dec, "VaSetup failed" ); msg_Err( p_dec, "VaSetup failed" );
return -1; return -1;
...@@ -920,7 +915,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, ...@@ -920,7 +915,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
/* FIXME what is that, should give good value */ /* FIXME what is that, should give good value */
p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
if( VaGrabSurface( p_sys->p_va, p_ff_pic ) ) if( vlc_va_Get( p_sys->p_va, p_ff_pic ) )
{ {
msg_Err( p_dec, "VaGrabSurface failed" ); msg_Err( p_dec, "VaGrabSurface failed" );
return -1; return -1;
...@@ -1036,7 +1031,7 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context, ...@@ -1036,7 +1031,7 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
if( p_sys->p_va ) if( p_sys->p_va )
{ {
VaUngrabSurface( p_sys->p_va, p_ff_pic ); vlc_va_Release( p_sys->p_va, p_ff_pic );
/* */ /* */
for( int i = 0; i < 4; i++ ) for( int i = 0; i < 4; i++ )
...@@ -1100,7 +1095,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec, ...@@ -1100,7 +1095,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
if( p_sys->p_va ) if( p_sys->p_va )
{ {
VaDelete( p_sys->p_va ); vlc_va_Delete( p_sys->p_va );
p_sys->p_va = NULL; p_sys->p_va = NULL;
} }
...@@ -1121,7 +1116,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec, ...@@ -1121,7 +1116,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
if( pi_fmt[i] == PIX_FMT_VAAPI_VLD ) if( pi_fmt[i] == PIX_FMT_VAAPI_VLD )
{ {
msg_Dbg( p_dec, "Trying VA API" ); msg_Dbg( p_dec, "Trying VA API" );
p_sys->p_va = VaNew( p_sys->i_codec_id ); p_sys->p_va = vlc_va_NewVaapi( p_sys->i_codec_id );
if( p_sys->p_va ) if( p_sys->p_va )
{ {
/* FIXME this will disabled direct rendering /* FIXME this will disabled direct rendering
......
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