[vlc-commits] avcodec: vaapi: use vlc_vaapi helpers
Thomas Guillem
git at videolan.org
Fri Jun 16 16:48:37 CEST 2017
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Jun 15 17:56:25 2017 +0200| [f9b5400d73afdf84214221449d532997064b7e62] | committer: Thomas Guillem
avcodec: vaapi: use vlc_vaapi helpers
This module will now always output opaque VLC_CODEC_VAAPI_420 pictures.
For cpu rendering, we now use the vaapi chroma filter.
Remove the Extract implementation.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f9b5400d73afdf84214221449d532997064b7e62
---
modules/codec/Makefile.am | 11 +-
modules/codec/avcodec/va.c | 2 +-
modules/codec/avcodec/vaapi.c | 375 +++++++++---------------------------------
3 files changed, 84 insertions(+), 304 deletions(-)
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index 14fc7f00b1..8c4e86f8a9 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -375,19 +375,18 @@ endif
### avcodec hardware acceleration ###
libvaapi_drm_plugin_la_SOURCES = \
- video_chroma/copy.c video_chroma/copy.h \
- codec/avcodec/vaapi.c
+ codec/avcodec/vaapi.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
libvaapi_drm_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_DRM
libvaapi_drm_plugin_la_CFLAGS = $(AM_CFLAGS) \
$(LIBVA_DRM_CFLAGS) $(AVCODEC_CFLAGS)
-libvaapi_drm_plugin_la_LIBADD = $(LIBVA_DRM_LIBS)
+libvaapi_drm_plugin_la_LIBADD = $(LIBVA_DRM_LIBS) libvlc_vaapi_instance.la
libvaapi_x11_plugin_la_SOURCES = \
- video_chroma/copy.c video_chroma/copy.h \
- codec/avcodec/vaapi.c
+ codec/avcodec/vaapi.c hw/vaapi/vlc_vaapi.c hw/vaapi/vlc_vaapi.h
libvaapi_x11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_VA_BACKEND_XLIB
libvaapi_x11_plugin_la_CFLAGS = $(AM_CFLAGS) \
$(LIBVA_X11_CFLAGS) $(X_CFLAGS) $(AVCODEC_CFLAGS)
-libvaapi_x11_plugin_la_LIBADD = $(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11
+libvaapi_x11_plugin_la_LIBADD = $(LIBVA_X11_LIBS) $(X_LIBS) $(X_PRE_LIBS) \
+ -lX11 libvlc_vaapi_instance.la
if HAVE_AVCODEC_VAAPI
if HAVE_VAAPI_DRM
codec_LTLIBRARIES += libvaapi_drm_plugin.la
diff --git a/modules/codec/avcodec/va.c b/modules/codec/avcodec/va.c
index de10736013..1298f24e1e 100644
--- a/modules/codec/avcodec/va.c
+++ b/modules/codec/avcodec/va.c
@@ -38,7 +38,7 @@ vlc_fourcc_t vlc_va_GetChroma(enum PixelFormat hwfmt, enum PixelFormat swfmt)
switch (hwfmt)
{
case AV_PIX_FMT_VAAPI_VLD:
- return VLC_CODEC_YV12;
+ return VLC_CODEC_VAAPI_420;
case AV_PIX_FMT_DXVA2_VLD:
switch (swfmt)
diff --git a/modules/codec/avcodec/vaapi.c b/modules/codec/avcodec/vaapi.c
index c04821e100..2f0d045a05 100644
--- a/modules/codec/avcodec/vaapi.c
+++ b/modules/codec/avcodec/vaapi.c
@@ -1,6 +1,7 @@
/*****************************************************************************
* vaapi.c: VAAPI helpers for the libavcodec decoder
*****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
* Copyright (C) 2009-2010 Laurent Aimar
* Copyright (C) 2012-2014 RĂ©mi Denis-Courmont
*
@@ -31,6 +32,7 @@
#include <vlc_plugin.h>
#include <vlc_fourcc.h>
#include <vlc_picture.h>
+#include <vlc_picture_pool.h>
#ifdef VLC_VA_BACKEND_XLIB
# include <vlc_xlib.h>
@@ -48,35 +50,19 @@
#include "avcodec.h"
#include "va.h"
-#include "../../video_chroma/copy.h"
-
-#ifndef VA_SURFACE_ATTRIB_SETTABLE
-#define vaCreateSurfaces(d, f, w, h, s, ns, a, na) \
- vaCreateSurfaces(d, w, h, f, ns, s)
-#endif
+#include "../../hw/vaapi/vlc_vaapi.h"
struct vlc_va_sys_t
{
#ifdef VLC_VA_BACKEND_XLIB
- Display *p_display_x11;
+ Display *p_display_x11;
#endif
#ifdef VLC_VA_BACKEND_DRM
- int drm_fd;
+ int drm_fd;
#endif
struct vaapi_context hw_ctx;
- /* */
- vlc_mutex_t lock;
- int width;
- int height;
- VAImageFormat format;
-
- copy_cache_t image_cache;
-
- bool do_derive;
- uint8_t count;
- uint32_t available;
- VASurfaceID surfaces[32];
+ picture_pool_t *pool;
};
static int GetVaProfile(AVCodecContext *ctx, VAProfile *va_profile,
@@ -138,256 +124,91 @@ static int GetVaProfile(AVCodecContext *ctx, VAProfile *va_profile,
return VLC_SUCCESS;
}
-static int Extract( vlc_va_t *va, picture_t *p_picture, uint8_t *data )
+static int Extract(vlc_va_t *va, picture_t *pic, uint8_t *data)
{
- vlc_va_sys_t *sys = va->sys;
- VASurfaceID surface = (VASurfaceID)(uintptr_t)data;
- VAImage image;
- int ret = VLC_EGENERIC;
-
-#if VA_CHECK_VERSION(0,31,0)
- if (vaSyncSurface(sys->hw_ctx.display, surface))
-#else
- if (vaSyncSurface(sys->hw_ctx.display, sys->hw_ctx.context_id, surface))
-#endif
- return VLC_EGENERIC;
-
- if (!sys->do_derive || vaDeriveImage(sys->hw_ctx.display, surface, &image))
- { /* Fallback if image derivation is not supported */
- if (vaCreateImage(sys->hw_ctx.display, &sys->format, sys->width,
- sys->height, &image))
- return VLC_EGENERIC;
- if (vaGetImage(sys->hw_ctx.display, surface, 0, 0, sys->width,
- sys->height, image.image_id))
- goto error;
- }
-
- void *p_base;
- if (vaMapBuffer(sys->hw_ctx.display, image.buf, &p_base))
- goto error;
-
- const unsigned i_fourcc = sys->format.fourcc;
- if( i_fourcc == VA_FOURCC_YV12 ||
- i_fourcc == VA_FOURCC_IYUV )
- {
- bool b_swap_uv = i_fourcc == VA_FOURCC_IYUV;
- uint8_t *pp_plane[3];
- size_t pi_pitch[3];
-
- for( int i = 0; i < 3; i++ )
- {
- const int i_src_plane = (b_swap_uv && i != 0) ? (3 - i) : i;
- pp_plane[i] = (uint8_t*)p_base + image.offsets[i_src_plane];
- pi_pitch[i] = image.pitches[i_src_plane];
- }
- CopyFromYv12ToYv12( p_picture, pp_plane, pi_pitch,
- sys->height, &sys->image_cache );
- }
- else
- {
- assert( i_fourcc == VA_FOURCC_NV12 );
- uint8_t *pp_plane[2];
- size_t pi_pitch[2];
-
- for( int i = 0; i < 2; i++ )
- {
- pp_plane[i] = (uint8_t*)p_base + image.offsets[i];
- pi_pitch[i] = image.pitches[i];
- }
- CopyFromNv12ToYv12( p_picture, pp_plane, pi_pitch,
- sys->height, &sys->image_cache );
- }
-
- vaUnmapBuffer(sys->hw_ctx.display, image.buf);
- ret = VLC_SUCCESS;
-error:
- vaDestroyImage(sys->hw_ctx.display, image.image_id);
- return ret;
+ (void) va; (void) pic; (void) data;
+ return VLC_SUCCESS;
}
-static int Get( vlc_va_t *va, picture_t *pic, uint8_t **data )
+static int Get(vlc_va_t *va, picture_t *pic, uint8_t **data)
{
vlc_va_sys_t *sys = va->sys;
- unsigned i = sys->count;
-
- vlc_mutex_lock( &sys->lock );
- if (sys->available)
- {
- i = ctz(sys->available);
- sys->available &= ~(1 << i);
- }
- vlc_mutex_unlock( &sys->lock );
- if( i >= sys->count )
- return VLC_ENOMEM;
+ picture_t *vapic = picture_pool_Wait(sys->pool);
+ if (vapic == NULL)
+ return VLC_EGENERIC;
+ vlc_vaapi_PicAttachContext(vapic);
- VASurfaceID *surface = &sys->surfaces[i];
+ pic->context = vapic->context->copy(vapic->context);
+ picture_Release(vapic);
+ if (pic->context == NULL)
+ return VLC_EGENERIC;
- pic->context = surface;
- *data = (void *)(uintptr_t)*surface;
+ *data = (void *)(uintptr_t)vlc_vaapi_PicGetSurface(pic);
return VLC_SUCCESS;
}
-static void Release( void *opaque, uint8_t *data )
-{
- (void) data;
- picture_t *pic = opaque;
- VASurfaceID *surface = pic->context;
- vlc_va_sys_t *sys = (void *)((((uintptr_t)surface)
- - offsetof(vlc_va_sys_t, surfaces)) & ~(sizeof (sys->surfaces) - 1));
- unsigned i = surface - sys->surfaces;
-
- 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);
-}
-
-static void Delete( vlc_va_t *va, AVCodecContext *avctx )
+static void Delete(vlc_va_t *va, AVCodecContext *avctx)
{
vlc_va_sys_t *sys = va->sys;
+ vlc_object_t *o = VLC_OBJECT(va);
(void) avctx;
-
- vlc_mutex_destroy(&sys->lock);
- CopyCleanCache(&sys->image_cache);
-
- vaDestroyContext(sys->hw_ctx.display, sys->hw_ctx.context_id);
- vaDestroySurfaces(sys->hw_ctx.display, sys->surfaces, sys->count);
- vaDestroyConfig(sys->hw_ctx.display, sys->hw_ctx.config_id);
- vaTerminate(sys->hw_ctx.display);
+ picture_pool_Release(sys->pool);
+ vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id);
+ vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
+ vlc_vaapi_ReleaseInstance(sys->hw_ctx.display);
#ifdef VLC_VA_BACKEND_XLIB
- XCloseDisplay( sys->p_display_x11 );
+ XCloseDisplay(sys->p_display_x11);
#endif
#ifdef VLC_VA_BACKEND_DRM
- vlc_close( sys->drm_fd );
+ vlc_close(sys->drm_fd);
#endif
- free( sys );
-}
-
-/** Finds a supported image chroma */
-static int FindFormat(vlc_va_sys_t *sys)
-{
- int count = vaMaxNumImageFormats(sys->hw_ctx.display);
-
- VAImageFormat *fmts = malloc(count * sizeof (*fmts));
- if (unlikely(fmts == NULL))
- return VLC_ENOMEM;
-
- if (vaQueryImageFormats(sys->hw_ctx.display, fmts, &count))
- {
- free(fmts);
- return VLC_EGENERIC;
- }
-
- sys->format.fourcc = 0;
-
- for (int i = 0; i < count; i++)
- {
- unsigned fourcc = fmts[i].fourcc;
-
- if (fourcc != VA_FOURCC_YV12 && fourcc != VA_FOURCC_IYUV
- && fourcc != VA_FOURCC_NV12)
- continue;
-
- VAImage image;
-
- if (vaCreateImage(sys->hw_ctx.display, &fmts[i], sys->width,
- sys->height, &image))
- continue;
-
- /* Validate that vaGetImage works with this format */
- int val = vaGetImage(sys->hw_ctx.display, sys->surfaces[0], 0, 0,
- sys->width, sys->height, image.image_id);
-
- vaDestroyImage(sys->hw_ctx.display, image.image_id);
-
- if (val != VA_STATUS_SUCCESS)
- continue;
-
- /* Mark NV12 as supported, but favor other formats first */
- sys->format = fmts[i];
- if (fourcc != VA_FOURCC_NV12)
- break;
- }
-
- free(fmts);
-
- if (sys->format.fourcc == 0)
- return VLC_EGENERIC; /* None of the formats work */
-
- VAImage image;
-
- /* Use vaDerive() iif it supports the best selected format */
- sys->do_derive = false;
-
- if (vaDeriveImage(sys->hw_ctx.display, sys->surfaces[0],
- &image) == VA_STATUS_SUCCESS)
- {
- if (image.format.fourcc == sys->format.fourcc)
- {
- sys->do_derive = true;
- sys->format = image.format;
- }
- vaDestroyImage(sys->hw_ctx.display, image.image_id);
- }
-
- return VLC_SUCCESS;
+ free(sys);
}
-static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
- const es_format_t *fmt, picture_sys_t *p_sys )
+static int Create(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
+ const es_format_t *fmt, picture_sys_t *p_sys)
{
- if( pix_fmt != AV_PIX_FMT_VAAPI_VLD )
+ if (pix_fmt != AV_PIX_FMT_VAAPI_VLD)
return VLC_EGENERIC;
(void) fmt;
(void) p_sys;
+ vlc_object_t *o = VLC_OBJECT(va);
+
#ifdef VLC_VA_BACKEND_XLIB
- if( !vlc_xlib_init( VLC_OBJECT(va) ) )
+ if (!vlc_xlib_init(o))
{
- msg_Warn( va, "Ignoring VA-X11 API" );
+ msg_Warn(va, "Ignoring VA-X11 API");
return VLC_EGENERIC;
}
#endif
- VAProfile i_profile, *p_profiles_list;
- bool b_supported_profile = false;
- int i_profiles_nb = 0;
+ VAProfile i_profile;
unsigned count;
if (GetVaProfile(ctx, &i_profile, &count) != VLC_SUCCESS)
return VLC_EGENERIC;
vlc_va_sys_t *sys;
- void *mem;
- assert(popcount(sizeof (sys->surfaces)) == 1);
- if (unlikely(posix_memalign(&mem, sizeof (sys->surfaces), sizeof (*sys))))
+ sys = malloc(sizeof(vlc_va_sys_t));
+ if (!sys)
return VLC_ENOMEM;
-
- sys = mem;
memset(sys, 0, sizeof (*sys));
/* */
sys->hw_ctx.display = NULL;
sys->hw_ctx.config_id = VA_INVALID_ID;
sys->hw_ctx.context_id = VA_INVALID_ID;
- sys->width = ctx->coded_width;
- sys->height = ctx->coded_height;
- sys->count = count;
- sys->available = (1 << sys->count) - 1;
- assert(count < sizeof (sys->available) * CHAR_BIT);
- assert(count * sizeof (sys->surfaces[0]) <= sizeof (sys->surfaces));
+ sys->pool = NULL;
/* Create a VA display */
#ifdef VLC_VA_BACKEND_XLIB
sys->p_display_x11 = XOpenDisplay(NULL);
- if( !sys->p_display_x11 )
+ if (!sys->p_display_x11)
{
- msg_Err( va, "Could not connect to X server" );
+ msg_Err(va, "Could not connect to X server");
goto error;
}
@@ -399,7 +220,8 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
"/dev/dri/card0"
};
- for (int i = 0; ARRAY_SIZE(drm_device_paths); i++) {
+ for (int i = 0; ARRAY_SIZE(drm_device_paths); i++)
+ {
sys->drm_fd = vlc_open(drm_device_paths[i], O_RDWR);
if (sys->drm_fd < 0)
continue;
@@ -414,117 +236,76 @@ static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
#endif
if (sys->hw_ctx.display == NULL)
{
- msg_Err( va, "Could not get a VAAPI device" );
+ msg_Err(va, "Could not get a VAAPI device");
goto error;
}
- int major, minor;
- if (vaInitialize(sys->hw_ctx.display, &major, &minor))
+ if (vlc_vaapi_Initialize(o, sys->hw_ctx.display))
{
- msg_Err( va, "Failed to initialize the VAAPI device" );
+ sys->hw_ctx.display = NULL;
goto error;
}
- /* Check if the selected profile is supported */
- i_profiles_nb = vaMaxNumProfiles(sys->hw_ctx.display);
- p_profiles_list = calloc( i_profiles_nb, sizeof( VAProfile ) );
- if( !p_profiles_list )
- goto error;
-
- if (vaQueryConfigProfiles(sys->hw_ctx.display, p_profiles_list,
- &i_profiles_nb) == VA_STATUS_SUCCESS)
+ if (vlc_vaapi_SetInstance(sys->hw_ctx.display))
{
- for( int i = 0; i < i_profiles_nb; i++ )
- {
- if ( p_profiles_list[i] == i_profile )
- {
- b_supported_profile = true;
- break;
- }
- }
- }
- free( p_profiles_list );
- if ( !b_supported_profile )
- {
- msg_Dbg( va, "Codec and profile not supported by the hardware" );
+ msg_Err(va, "VAAPI instance already in use");
goto error;
}
- /* Create a VA configuration */
- VAConfigAttrib attrib;
- memset( &attrib, 0, sizeof(attrib) );
- attrib.type = VAConfigAttribRTFormat;
- if (vaGetConfigAttributes(sys->hw_ctx.display, i_profile, VAEntrypointVLD,
- &attrib, 1))
- goto error;
-
- /* Not sure what to do if not, I don't have a way to test */
- if( (attrib.value & VA_RT_FORMAT_YUV420) == 0 )
- goto error;
- if (vaCreateConfig(sys->hw_ctx.display, i_profile, VAEntrypointVLD,
- &attrib, 1, &sys->hw_ctx.config_id))
- {
- sys->hw_ctx.config_id = VA_INVALID_ID;
- goto error;
- }
+ sys->hw_ctx.config_id =
+ vlc_vaapi_CreateConfigChecked(o, sys->hw_ctx.display, i_profile,
+ VAEntrypointVLD, 0);
/* 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;
- }
-
- /* Create a context */
- if (vaCreateContext(sys->hw_ctx.display, sys->hw_ctx.config_id,
- ctx->coded_width, ctx->coded_height, VA_PROGRESSIVE,
- sys->surfaces, sys->count, &sys->hw_ctx.context_id))
- {
- sys->hw_ctx.context_id = VA_INVALID_ID;
- vaDestroySurfaces(sys->hw_ctx.display, sys->surfaces, sys->count);
- goto error;
- }
+ video_format_t vfmt = {
+ .i_chroma = VLC_CODEC_VAAPI_420,
+ .i_width = ctx->coded_width,
+ .i_height = ctx->coded_height,
+ .i_visible_width = ctx->coded_width,
+ .i_visible_height = ctx->coded_height
+ };
+ VASurfaceID *surfaces;
+ sys->pool = vlc_vaapi_PoolNew(o, sys->hw_ctx.display, count,
+ &surfaces, &vfmt, VA_RT_FORMAT_YUV420, 0);
- if (FindFormat(sys))
+ if (!sys->pool)
goto error;
- if (unlikely(CopyInitCache(&sys->image_cache, ctx->coded_width)))
+ /* Create a context */
+ sys->hw_ctx.context_id =
+ vlc_vaapi_CreateContext(o, sys->hw_ctx.display, sys->hw_ctx.config_id,
+ ctx->coded_width, ctx->coded_height,
+ VA_PROGRESSIVE, surfaces, count);
+ if (sys->hw_ctx.context_id == VA_INVALID_ID)
goto error;
- vlc_mutex_init(&sys->lock);
-
- msg_Dbg(va, "using %s image format 0x%08x",
- sys->do_derive ? "derive" : "get", sys->format.fourcc);
-
ctx->hwaccel_context = &sys->hw_ctx;
va->sys = sys;
va->description = vaQueryVendorString(sys->hw_ctx.display);
va->get = Get;
- va->release = Release;
+ va->release = NULL;
va->extract = Extract;
return VLC_SUCCESS;
error:
if (sys->hw_ctx.context_id != VA_INVALID_ID)
- {
- vaDestroyContext(sys->hw_ctx.display, sys->hw_ctx.context_id);
- vaDestroySurfaces(sys->hw_ctx.display, sys->surfaces, sys->count);
- }
+ vlc_vaapi_DestroyContext(o, sys->hw_ctx.display, sys->hw_ctx.context_id);
+ if (sys->pool != NULL)
+ picture_pool_Release(sys->pool);
if (sys->hw_ctx.config_id != VA_INVALID_ID)
- vaDestroyConfig(sys->hw_ctx.display, sys->hw_ctx.config_id);
+ vlc_vaapi_DestroyConfig(o, sys->hw_ctx.display, sys->hw_ctx.config_id);
if (sys->hw_ctx.display != NULL)
- vaTerminate(sys->hw_ctx.display);
+ vlc_vaapi_ReleaseInstance(sys->hw_ctx.display);
#ifdef VLC_VA_BACKEND_XLIB
- if( sys->p_display_x11 != NULL )
- XCloseDisplay( sys->p_display_x11 );
+ if( sys->p_display_x11 != NULL)
+ XCloseDisplay(sys->p_display_x11);
#endif
#ifdef VLC_VA_BACKEND_DRM
if( sys->drm_fd != -1 )
- vlc_close( sys->drm_fd );
+ vlc_close(sys->drm_fd);
#endif
- free( sys );
+ free(sys);
return VLC_EGENERIC;
}
More information about the vlc-commits
mailing list