/*****************************************************************************
- * vaapi.h: VAAPI helpers for the ffmpeg decoder
+ * va.h: Video Acceleration API for avcodec
*****************************************************************************
* Copyright (C) 2009 Laurent Aimar
* $Id$
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
-#ifndef _VLC_VAAPI_H
-#define _VLC_VAAPI_H 1
+#ifndef _VLC_VA_H
+#define _VLC_VA_H 1
typedef struct vlc_va_t vlc_va_t;
+struct vlc_va_t {
+ char *description;
-vlc_va_t *VaNew( int i_codec_id );
-void VaDelete( vlc_va_t *p_va );
+ int (*setup)(vlc_va_t *, void **hw, vlc_fourcc_t *output,
+ 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,
- 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 );
+vlc_va_t *vlc_va_NewVaapi(int codec_id);
#endif
+
#endif
#include "avcodec.h"
-#include "vaapi.h"
+#include "va.h"
#ifdef HAVE_AVCODEC_VAAPI
} vlc_va_surface_t;
-struct vlc_va_t
+typedef struct
{
+ vlc_va_t va;
+
/* */
Display *p_display_x11;
VADisplay p_display;
VAImage image;
-};
-
-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_vaapi_t;
-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;
}
-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;
int 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;
error:
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 )
- VaDestroySurfaces( p_va );
+ if( p_va->image.image_id )
+ vaDestroyImage( p_va->p_display, p_va->image.image_id );
- if( p_va->i_config_id )
- vaDestroyConfig( p_va->p_display, p_va->i_config_id );
- if( p_va->p_display )
- vaTerminate( p_va->p_display );
- if( p_va->p_display_x11 )
- XCloseDisplay( p_va->p_display_x11 );
-}
+ if( p_va->i_context_id )
+ vaDestroyContext( p_va->p_display, p_va->i_context_id );
-static int VaCreateSurfaces( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
- int i_width, int i_height )
+ 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->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 );
return VLC_SUCCESS;
error:
- VaDestroySurfaces( p_va );
+ DestroySurfaces( p_va );
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 )
- vaDestroyImage( p_va->p_display, p_va->image.image_id );
+ vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
- if( p_va->i_context_id )
- vaDestroyContext( p_va->p_display, p_va->i_context_id );
+ if( p_va->i_surface_width == i_width &&
+ 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++ )
- {
- vlc_va_surface_t *p_surface = &p_va->p_surface[i];
+ *pp_hw_ctx = NULL;
+ *pi_chroma = 0;
+ if( p_va->i_surface_width || p_va->i_surface_height )
+ DestroySurfaces( p_va );
- if( p_surface->i_id != VA_INVALID_SURFACE )
- vaDestroySurfaces( p_va->p_display, &p_surface->i_id, 1 );
- }
- free( p_va->p_surface );
+ if( i_width > 0 && i_height > 0 )
+ return CreateSurfaces( p_va, pp_hw_ctx, pi_chroma, i_width, i_height );
- /* */
- 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;
+ return VLC_EGENERIC;
}
-
-int VaExtract( vlc_va_t *p_va, picture_t *p_picture, AVFrame *p_ff )
+static int Extract( vlc_va_t *p_external, 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];
#if VA_CHECK_VERSION(0,31,0)
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;
}
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];
for( int i = 0; i < p_va->i_surface_count; i++ )
}
}
-#else
-
-vlc_va_t *VaNew( int i_codec_id )
-{
- VLC_UNUSED(i_codec_id);
- return NULL;
-}
-void VaDelete( vlc_va_t *p_va )
+static void Close( vlc_va_vaapi_t *p_va )
{
- VLC_UNUSED(p_va);
- assert( 0 );
-}
+ if( p_va->i_surface_width || p_va->i_surface_height )
+ DestroySurfaces( p_va );
-void VaVersion( vlc_va_t *p_va, char *psz_version, size_t i_version )
-{
- VLC_UNUSED(p_va); VLC_UNUSED(psz_version); VLC_UNUSED(i_version);
- assert(0);
+ if( p_va->i_config_id )
+ vaDestroyConfig( p_va->p_display, p_va->i_config_id );
+ if( p_va->p_display )
+ vaTerminate( p_va->p_display );
+ if( p_va->p_display_x11 )
+ XCloseDisplay( p_va->p_display_x11 );
}
-
-int VaSetup( vlc_va_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
- int i_width, int i_height )
+static void Delete( vlc_va_t *p_external )
{
- VLC_UNUSED(p_va); VLC_UNUSED(pp_hw_ctx); VLC_UNUSED(pi_chroma);
- VLC_UNUSED(i_width); VLC_UNUSED(i_height);
- assert(0);
- return -1;
+ vlc_va_vaapi_t *p_va = vlc_va_vaapi_Get(p_external);
+ Close( p_va );
+ free( p_va->va.description );
+ 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);
- assert(0);
- return -1;
-}
+ vlc_va_vaapi_t *p_va = calloc( 1, sizeof(*p_va) );
+ if( !p_va )
+ return NULL;
-int VaGrabSurface( vlc_va_t *p_va, AVFrame *p_ff )
-{
- VLC_UNUSED(p_va); VLC_UNUSED(p_ff);
- assert(0);
- return -1;
-}
+ if( Open( p_va, i_codec_id ) )
+ {
+ free( p_va );
+ return NULL;
+ }
-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);
- assert(0);
+ VLC_UNUSED( i_codec_id );
+ return NULL;
}
-
#endif
#endif
#include "avcodec.h"
-#include "vaapi.h"
+#include "va.h"
/*****************************************************************************
* decoder_sys_t : decoder descriptor
if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );
if( p_sys->p_va )
- VaDelete( p_sys->p_va );
+ vlc_va_Delete( p_sys->p_va );
}
/*****************************************************************************
p_sys->b_delayed_open = false;
- if( p_sys->p_va )
- {
- 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 );
- }
+ if( p_sys->p_va && p_sys->p_va->description )
+ msg_Info( p_dec, "Using %s for hardware decoding.", p_sys->p_va->description );
return VLC_SUCCESS;
}
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 )
{
{
#ifdef HAVE_AVCODEC_VAAPI
/* hwaccel_context is not present in old fffmpeg version */
- if( VaSetup( p_sys->p_va,
- &p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
- p_sys->p_context->width, p_sys->p_context->height ) )
+ 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->width, p_sys->p_context->height ) )
{
msg_Err( p_dec, "VaSetup failed" );
return -1;
/* FIXME what is that, should give good value */
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" );
return -1;
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++ )
if( p_sys->p_va )
{
- VaDelete( p_sys->p_va );
+ vlc_va_Delete( p_sys->p_va );
p_sys->p_va = NULL;
}
if( pi_fmt[i] == PIX_FMT_VAAPI_VLD )
{
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 )
{
/* FIXME this will disabled direct rendering