#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_fourcc.h>
-#include <vlc_xlib.h>
+#ifdef VLC_VA_BACKEND_XLIB
+# include <vlc_xlib.h>
+# include <va/va_x11.h>
+#endif
+#ifdef VLC_VA_BACKEND_DRM
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <vlc_fs.h>
+# include <va/va_drm.h>
+#endif
#include <libavcodec/avcodec.h>
#include <libavcodec/vaapi.h>
-#include <X11/Xlib.h>
-#include <va/va_x11.h>
#include "avcodec.h"
#include "va.h"
static void Delete( vlc_va_t * );
vlc_module_begin ()
- set_description( N_("Video Acceleration (VA) API") )
+#if defined (VLC_VA_BACKEND_XLIB)
+ set_description( N_("VA-API video decoder via X11") )
+#elif defined (VLC_VA_BACKEND_DRM)
+ set_description( N_("VA-API video decoder via DRM") )
+#endif
set_capability( "hw decoder", 0 )
set_category( CAT_INPUT )
set_subcategory( SUBCAT_INPUT_VCODEC )
set_callbacks( Create, Delete )
+ add_shortcut( "vaapi" )
vlc_module_end ()
typedef struct
struct vlc_va_sys_t
{
- Display *p_display_x11;
+#ifdef VLC_VA_BACKEND_XLIB
+ Display *p_display_x11;
+#endif
+#ifdef VLC_VA_BACKEND_DRM
+ int drm_fd;
+#endif
VADisplay p_display;
VAConfigID i_config_id;
i_surface_count = 16 + i_thread_count + 2;
break;;
default:
+ free( sys );
return VLC_EGENERIC;
}
/* */
- va->description = NULL;
sys->i_config_id = VA_INVALID_ID;
sys->i_context_id = VA_INVALID_ID;
sys->image.image_id = VA_INVALID_ID;
/* Create a VA display */
+#ifdef VLC_VA_BACKEND_XLIB
sys->p_display_x11 = XOpenDisplay(NULL);
if( !sys->p_display_x11 )
{
}
sys->p_display = vaGetDisplay( sys->p_display_x11 );
+#endif
+#ifdef VLC_VA_BACKEND_DRM
+ sys->drm_fd = vlc_open("/dev/dri/card0", O_RDWR);
+ if( sys->drm_fd == -1 )
+ {
+ msg_Err( va, "Could not access rendering device: %m" );
+ goto error;
+ }
+
+ sys->p_display = vaGetDisplayDRM( sys->drm_fd );
+#endif
if( !sys->p_display )
{
msg_Err( va, "Could not get a VAAPI device" );
goto error;
}
- if( asprintf( &va->description, "VA API v%d.%d", major, minor ) < 0 )
- va->description = NULL;
-
/* Check if the selected profile is supported */
i_profiles_nb = vaMaxNumProfiles( sys->p_display );
p_profiles_list = calloc( i_profiles_nb, sizeof( VAProfile ) );
vlc_mutex_init(&sys->lock);
va->sys = sys;
+ va->description = vaQueryVendorString( sys->p_display );
return VLC_SUCCESS;
error:
- free( va->description );
if( sys->p_display != NULL )
vaTerminate( sys->p_display );
+#ifdef VLC_VA_BACKEND_XLIB
if( sys->p_display_x11 != NULL )
XCloseDisplay( sys->p_display_x11 );
+#endif
+#ifdef VLC_VA_BACKEND_DRM
+ if( sys->drm_fd != -1 )
+ close( sys->drm_fd );
+#endif
free( sys );
return VLC_EGENERIC;
}
}
VAImage test_image;
+ vlc_fourcc_t deriveImageFormat = 0;
if(vaDeriveImage(sys->p_display, pi_surface_id[0], &test_image) == VA_STATUS_SUCCESS)
{
sys->b_supports_derive = true;
+ deriveImageFormat = test_image.format.fourcc;
vaDestroyImage(sys->p_display, test_image.image_id);
}
vlc_fourcc_t i_chroma = 0;
- VAImageFormat fmt;
+ int nv12support = -1;
for( int i = 0; i < i_fmt_count; i++ )
{
- if( p_fmt[i].fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
- p_fmt[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ||
- p_fmt[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) )
+ if( p_fmt[i].fourcc == VA_FOURCC_YV12 ||
+ p_fmt[i].fourcc == VA_FOURCC_IYUV ||
+ p_fmt[i].fourcc == VA_FOURCC_NV12 )
{
if( vaCreateImage( sys->p_display, &p_fmt[i], i_width, i_height, &sys->image ) )
{
continue;
}
+ if( p_fmt[i].fourcc == VA_FOURCC_NV12 )
+ {
+ /* Mark NV12 as supported, but favor other formats first */
+ nv12support = i;
+ vaDestroyImage( sys->p_display, sys->image.image_id );
+ sys->image.image_id = VA_INVALID_ID;
+ continue;
+ }
i_chroma = VLC_CODEC_YV12;
- fmt = p_fmt[i];
break;
}
}
+
+ if( !i_chroma && nv12support >= 0 )
+ {
+ /* only nv12 is supported, so use that format */
+ if( vaCreateImage( sys->p_display, &p_fmt[nv12support], i_width, i_height, &sys->image ) )
+ {
+ sys->image.image_id = VA_INVALID_ID;
+ }
+ i_chroma = VLC_CODEC_YV12;
+ }
+ else if( sys->b_supports_derive && deriveImageFormat != sys->image.format.fourcc )
+ {
+ /* only use vaDerive if it's giving us a format we handle natively */
+ sys->b_supports_derive = false;
+ }
+
free( p_fmt );
if( !i_chroma )
goto error;
return VLC_EGENERIC;
const uint32_t i_fourcc = sys->image.format.fourcc;
- if( i_fourcc == VA_FOURCC('Y','V','1','2') ||
- i_fourcc == VA_FOURCC('I','4','2','0') )
+ if( i_fourcc == VA_FOURCC_YV12 ||
+ i_fourcc == VA_FOURCC_IYUV )
{
- bool b_swap_uv = i_fourcc == VA_FOURCC('I','4','2','0');
+ bool b_swap_uv = i_fourcc == VA_FOURCC_IYUV;
uint8_t *pp_plane[3];
size_t pi_pitch[3];
}
else
{
- assert( i_fourcc == VA_FOURCC('N','V','1','2') );
+ assert( i_fourcc == VA_FOURCC_NV12 );
uint8_t *pp_plane[2];
size_t pi_pitch[2];
if( sys->i_config_id != VA_INVALID_ID )
vaDestroyConfig( sys->p_display, sys->i_config_id );
vaTerminate( sys->p_display );
+#ifdef VLC_VA_BACKEND_XLIB
XCloseDisplay( sys->p_display_x11 );
+#endif
+#ifdef VLC_VA_BACKEND_DRM
+ close( sys->drm_fd );
+#endif
}
static void Delete( vlc_va_t *va )
{
vlc_va_sys_t *sys = va->sys;
Close( sys );
- free( va->description );
free( sys );
}
static int Create( vlc_va_t *p_va, AVCodecContext *ctx,
const es_format_t *fmt )
{
+#ifdef VLC_VA_BACKEND_XLIB
if( !vlc_xlib_init( VLC_OBJECT(p_va) ) )
{
msg_Warn( p_va, "Ignoring VA API" );
return VLC_EGENERIC;
}
+#endif
(void) fmt;