Commit 50eebc56 authored by Jean-Paul Saman's avatar Jean-Paul Saman

VAAPI-XCB: Adding GLX based video output.

Reuse as much code as possible from vaapi-xcb implementation. Most of
the routines can be shared and are placed inside common.{c,h}. The
video output has been moved to modules/video_output/vaapi/, but is
still build from modules/codec/avcodec/Modules.am. This is because
the video output shares the same libva connection as the decoder.
Since this is mandatory for some GPU implementations such as AMD Fusion.
parent a941d753
......@@ -3061,6 +3061,7 @@ AC_ARG_ENABLE(glx,
])
have_xcb="no"
have_glx="no"
AS_IF([test "${enable_xcb}" != "no"], [
dnl libxcb
PKG_CHECK_MODULES(XCB, [xcb >= 1.6])
......@@ -3093,7 +3094,7 @@ AS_IF([test "${enable_xcb}" != "no"], [
AC_MSG_WARN([${XCB_KEYSYMS_PKG_ERRORS}. Hotkeys will not work.])
])
dnl avcodec (vaapi-x11)
dnl avcodec (vaapi-xcb)
AS_IF([test "${enable_libva}" != "no"], [
AS_IF([test "${have_avcodec}" != "no"], [
PKG_CHECK_MODULES(XLIB_XCB, [x11-xcb])
......@@ -3108,10 +3109,24 @@ AS_IF([test "${enable_xcb}" != "no"], [
AS_IF([test "${have_gl}" != "yes"], [
AC_MSG_ERROR([${GL_PKG_ERRORS}. Pass --disable-glx if you do not need OpenGL X11 support.])
])
have_glx="yes"
dnl avcodec (vaapi-glx)
AS_IF([test "${enable_libva}" != "no"], [
AS_IF([test "${have_avcodec}" != "no"], [
PKG_CHECK_MODULES(LIBVA, [libva libva-x11 libva-glx], [
VLC_ADD_CFLAGS([avcodec], [${GL_CFLAGS} ${GL_CFLAGS}])
VLC_ADD_LIBS([avcodec], [${GL_LIBS} ${GL_LIBS} -lva-glx])
AC_DEFINE(HAVE_GLX, 1, [Define if avcodec has to be built with GL support.])
], [
AC_MSG_WARN([libva XCB and GLX present, but not libva-glx.])
])
])
])
VLC_ADD_PLUGIN([xcb_glx])
])
])
AM_CONDITIONAL([HAVE_XCB], [test "${have_xcb}" = "yes"])
AM_CONDITIONAL([HAVE_GLX], [test "${have_glx}" = "yes"])
dnl
dnl SDL module
......
......@@ -19,13 +19,24 @@ libavcodec_plugin_la_SOURCES = \
if HAVE_XCB
libavcodec_plugin_la_SOURCES += \
vasub.h \
vasub.c \
vaapi_x11.c \
../../video_output/vaapi/spu.h \
../../video_output/vaapi/spu.c \
../../video_output/vaapi/common.h \
../../video_output/vaapi/common.c \
../../video_output/vaapi/xcb.h \
../../video_output/vaapi/xcb.c \
../../video_output/xcb/events.c \
../../video_output/xcb/xcb_events_vlc.h \
$(NULL)
endif
if HAVE_GLX
libavcodec_plugin_la_SOURCES += \
../../video_output/vaapi/glx.h \
../../video_output/vaapi/glx.c \
../../video_output/opengl.h \
../../video_output/opengl.c
$(NULL)
endif
if ENABLE_SOUT
libavcodec_plugin_la_SOURCES += \
......
......@@ -81,6 +81,13 @@ static const char *const enc_hq_list_text[] = {
# include "../../access/avio.h"
#endif
#if defined(HAVE_AVCODEC_VAAPI) && defined(HAVE_XCB)
# include "../../video_output/vaapi/xcb.h"
# ifdef HAVE_GLX
# include "../../video_output/vaapi/glx.h"
# endif
#endif
/*****************************************************************************
* Module descriptor
*****************************************************************************/
......@@ -216,17 +223,33 @@ vlc_module_begin ()
#endif
#if defined(HAVE_AVCODEC_VAAPI) && defined(HAVE_XCB)
/* vaapi_x11 submodule */
/* vaapi_xcb submodule */
add_submodule()
set_description (N_("VAAPI X11 video output (XCB)"))
set_category (CAT_VIDEO)
set_subcategory (SUBCAT_VIDEO_VOUT)
set_capability ("vout display", 275)
set_callbacks (OpenVaapiX11, CloseVaapiX11)
set_callbacks (OpenVaapiXCB, CloseVaapiXCB)
add_shortcut ("vaapi-x11", "vaapi-xcb", "xid")
add_bool( VOUT_CFG_PREFIX "recycle", false,
VOUT_RECYCLE_TEXT, VOUT_RECYCLE_LONGTEXT, true )
/* vaapi_glx submodule */
# ifdef HAVE_GLX
add_submodule()
set_description (N_("VAAPI GLX video output (XCB)"))
set_category (CAT_VIDEO)
set_subcategory (SUBCAT_VIDEO_VOUT)
set_capability ("vout display", 250)
set_callbacks (OpenVaapiGLX, CloseVaapiGLX)
add_shortcut ("vaapi-glx", "xid")
add_bool( VOUT_CFG_PREFIX "recycle", false,
VOUT_RECYCLE_TEXT, VOUT_RECYCLE_LONGTEXT, true )
# endif
#endif
vlc_module_end ()
......
......@@ -61,12 +61,6 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
AVCodec *p_codec, int i_codec_id, const char *psz_namecodec );
void EndVideoDec( decoder_t *p_dec );
/* VAAPI X11 Video Output */
#ifdef HAVE_AVCODEC_VAAPI
int OpenVaapiX11 (vlc_object_t *);
void CloseVaapiX11 (vlc_object_t *);
#endif
/* Audio Decoder */
int InitAudioDec( decoder_t *p_dec, AVCodecContext *p_context,
AVCodec *p_codec, int i_codec_id, const char *psz_namecodec );
......
......@@ -42,6 +42,9 @@
# include <libavcodec/vaapi.h>
# include <va/va.h>
# include <va/va_x11.h>
# if HAVE_GLX
# include <va/va_glx.h>
# endif
#endif
#include "va.h"
#include "vaapi.h"
......@@ -468,11 +471,17 @@ vlc_va_conn_t *vlc_va_Initialize( const char *display )
goto error;
/* Create a VA display */
/* FIXME: allow for runtime choice of OpenGL or not */
#warning "fix the non-openGL case"
#if HAVE_GLX
conn->p_display = vaGetDisplayGLX(conn->x11);
#else
conn->p_display = vaGetDisplay(conn->x11);
#endif
if( !conn->p_display )
goto error;
if( vaInitialize( conn->p_display, &conn->i_version_major, &conn->i_version_minor ) )
if( vaInitialize(conn->p_display, &conn->i_version_major, &conn->i_version_minor) )
goto error;
conn->i_ref_count++;
......
/*****************************************************************************
* Copyright © 2011 - 2013, M2X BV
* Author: Jean-Paul Saman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout_display.h>
#include <vlc_vout_window.h>
#include <vlc_picture_pool.h>
#include <vlc_arrays.h>
#include <xcb/xcb.h>
#include <X11/Xlib-xcb.h>
#include <vlc_xlib.h>
#include <X11/Xutil.h>
#include "../../video_output/xcb/xcb_events_vlc.h"
#if defined(HAVE_AVCODEC_VAAPI) && defined(HAVE_XCB)
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
# include <libavcodec/avcodec.h>
#else
# include <avcodec.h>
#endif
#include "../../codec/avcodec/avcodec.h"
#include <libavcodec/vaapi.h>
#include <va/va.h>
#include <va/va_x11.h>
#include "../../codec/avcodec/va.h"
#include "../../codec/avcodec/vaapi.h"
#include "common.h"
#include "spu.h"
vout_window_t *MakeWindow(vout_display_t *vd)
{
vout_window_cfg_t wnd_cfg;
memset (&wnd_cfg, 0, sizeof (wnd_cfg));
wnd_cfg.type = VOUT_WINDOW_TYPE_XID;
wnd_cfg.x = var_InheritInteger(vd, "video-x");
wnd_cfg.y = var_InheritInteger(vd, "video-y");
wnd_cfg.width = vd->cfg->display.width;
wnd_cfg.height = vd->cfg->display.height;
vout_window_t *wnd = vout_display_NewWindow(vd, &wnd_cfg);
if (wnd == NULL)
msg_Err(vd, "parent window not available");
return wnd;
}
const xcb_screen_t *FindWindow(vout_display_t *vd,
vout_window_t *embed, xcb_connection_t *conn,
unsigned *restrict pnum, uint8_t *restrict pdepth,
uint16_t *restrict pwidth, uint16_t *restrict pheight)
{
xcb_get_geometry_reply_t *geo =
xcb_get_geometry_reply(conn,
xcb_get_geometry(conn, embed->handle.xid), NULL);
if (geo == NULL)
{
msg_Err (vd, "parent window not valid");
return NULL;
}
xcb_window_t root = geo->root;
*pdepth = geo->depth;
*pwidth = geo->width;
*pheight = geo->height;
free (geo);
/* Find the selected screen */
const xcb_setup_t *setup = xcb_get_setup(conn);
const xcb_screen_t *screen = NULL;
unsigned num = 0;
for (xcb_screen_iterator_t i = xcb_setup_roots_iterator(setup);
i.rem > 0;
xcb_screen_next (&i))
{
if (i.data->root == root)
{
screen = i.data;
break;
}
num++;
}
if (screen == NULL)
{
msg_Err(vd, "parent window screen not found");
return NULL;
}
msg_Dbg(vd, "using screen 0x%"PRIx32 " (number: %u)", root, num);
*pnum = num;
return screen;
}
int CreateWindow(vout_display_t *vd,
vout_window_t *embed, xcb_connection_t *conn,
uint_fast8_t depth, xcb_visualid_t vid,
uint_fast16_t width, uint_fast16_t height,
xcb_window_t *restrict window)
{
const uint32_t mask = XCB_CW_EVENT_MASK;
const uint32_t values[] = {
/* XCB_CW_EVENT_MASK */
XCB_EVENT_MASK_VISIBILITY_CHANGE,
};
xcb_void_cookie_t cc, cm;
cc = xcb_create_window_checked(conn, depth, *window,
embed->handle.xid, 0, 0,
width, height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
vid, mask, values);
cm = xcb_map_window_checked(conn, *window);
if (CheckError(vd, conn, "cannot create XCB window", cc) ||
CheckError(vd, conn, "cannot map XCB window", cm))
return VLC_EGENERIC;
msg_Dbg (vd, "using VAAPI XCB window %08"PRIx32, *window);
xcb_flush(conn);
return VLC_SUCCESS;
}
/**
* PictureLock and PictureUnlock will be called by picture_pool_*
* when the picture is held and released. Both are called only
* once. PictureLock when the picture is retrieved from the pool
* and PictureUnlock when the picture is returned to the pool.
*/
static int PictureLock(picture_t *picture)
{
vlc_va_surface_t *surface = picture->p_sys;
if (surface == NULL)
abort();
vlc_va_SurfaceHold(surface);
return VLC_SUCCESS;
}
static void PictureUnlock(picture_t *picture)
{
assert(picture->p_sys);
vlc_va_surface_t *surface = picture->p_sys;
if (surface == NULL)
abort();
vlc_va_SurfaceRelease(surface);
}
/* PictureRelease is called when the picture pool is destroyed. */
static void PictureRelease(picture_t *picture)
{
if (picture->i_refcount > 0)
picture->i_refcount--;
picture->p_sys = NULL;
}
/**
* Create a pool of direct buffers to use.
*/
picture_pool_t *vout_vaapi_GetPool(vout_display_t *vd, vlc_va_conn_t *va, unsigned requested)
{
picture_pool_t *pool = NULL;
assert(va);
assert(vd);
assert(requested > 0);
/* Create surfaces */
va->lock();
unsigned int alloc_count = __MAX(vlc_va_conn_SurfacesCount(va), requested);
va->unlock();
picture_t **pic_array = (picture_t **) calloc(alloc_count, sizeof(picture_t *));
if (!pic_array)
return NULL;
unsigned int count;
for (count = 0; count < alloc_count; count++)
{
picture_t *pic = (picture_t*) picture_NewFromFormat(&vd->fmt);
if (!pic)
break;
assert(pic->p_sys == NULL);
pic->format.i_chroma = VLC_CODEC_VAAPI_SURFACE;
pic_array[count] = pic;
pic_array[count]->b_progressive = true;
pic_array[count]->pf_release = PictureRelease;
}
assert( count > 0 );
if (count == 0)
goto error;
unsigned int i_surface_count = __MIN(count, alloc_count);
assert(i_surface_count == count);
msg_Info(vd, "Requested %d/%d surfaces for picture pool.",
i_surface_count, vlc_va_conn_SurfacesCount(va));
/* Create surfaces */
va->lock();
if (!vlc_va_conn_CreateSurface(va,
vd->fmt.i_visible_width,
vd->fmt.i_visible_height,
VA_RT_FORMAT_YUV420, i_surface_count))
{
/* FAIL */
va->unlock();
goto error;
}
for (unsigned int i = 0; i < i_surface_count; i++)
{
vlc_va_surface_t *surface = vlc_va_conn_GetSurface(va);
if( surface )
pic_array[i]->p_sys = (picture_sys_t *)surface;
}
va->unlock();
/* Register pool with video output core */
picture_pool_configuration_t cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.picture_count = count;
cfg.picture = pic_array;
cfg.lock = PictureLock;
cfg.unlock = PictureUnlock;
pool = picture_pool_NewExtended(&cfg);
if (!pool)
goto error;
free(pic_array);
return pool;
error:
/* Cleanup on error */
va->lock();
for (unsigned int i = 0; i < count; i++)
{
picture_t *pic = pic_array[i];
if (!pic)
continue;
if (pic->p_sys)
{
vlc_va_surface_t *surface = (vlc_va_surface_t *) pic->p_sys;
vlc_va_conn_ReleaseSurface(va, surface);
}
picture_Release(pic);
}
free(pic_array);
va->unlock();
return NULL;
}
#endif /* HAVE_AVCODEC_VAAPI */
/*****************************************************************************
* Copyright © 2011 - 2013, M2X BV
* Author: Jean-Paul Saman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef VLC_VAAPI_COMMON_H
#define VLC_VAAPI_COMMON_H 1
vout_window_t *MakeWindow(vout_display_t *vd);
const xcb_screen_t *FindWindow(vout_display_t *vd,
vout_window_t *embed, xcb_connection_t *conn,
unsigned *restrict pnum, uint8_t *restrict pdepth,
uint16_t *restrict pwidth, uint16_t *restrict pheight);
int CreateWindow(vout_display_t *vd,
vout_window_t *embed, xcb_connection_t *conn,
uint_fast8_t depth, xcb_visualid_t vid,
uint_fast16_t width, uint_fast16_t height,
xcb_window_t *restrict window);
picture_pool_t *vout_vaapi_GetPool(vout_display_t *, vlc_va_conn_t *, unsigned);
#endif
This diff is collapsed.
/*****************************************************************************
* Copyright © 2013, M2X BV
* Author: Jean-Paul Saman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef VLC_VAAPI_GLX_H
#define VLC_VAAPI_GLX_H 1
int OpenVaapiGLX(vlc_object_t *);
void CloseVaapiGLX(vlc_object_t *);
#endif
......@@ -17,12 +17,21 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef VLC_VAAPI_VASUB_H
#define VLC_VAAPI_VASUB_H 1
#ifndef VLC_VAAPI_SPU_H
#define VLC_VAAPI_SPU_H 1
#ifdef HAVE_AVCODEC_VAAPI
/* Available subtitle formats */
static const vlc_fourcc_t va_subpicture_chromas[] = {
VLC_CODEC_RGBA,
0
};
/* NOTE: call all functions with sys->cache_lock held */
/* Check if subtitle format is supported by VA API */
int VASubtitleFourCC(vlc_va_conn_t *vaconn, const unsigned int vafourcc, VAImageFormat *sub_fmt, int *flags);
int VASubtitleFourCC(vlc_va_conn_t *va, const unsigned int vafourcc, VAImageFormat *sub_fmt, int *flags);
/* */
typedef struct vasubpicture_cache_t vasubpicture_cache_t;
......@@ -31,8 +40,11 @@ typedef struct subpicture_cache_t subpicture_cache_t;
/* Get Cache id */
unsigned int cache_GetCacheID(const subpicture_cache_t *cache);
/* Empty the array of cached subpictures */
void cache_SubpictureEmpty(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *restrict cache);
/* Create new VASubpicture */
vasubpicture_cache_t *cache_SubpictureCreate(vlc_object_t *obj, vlc_va_conn_t *vaconn, VAImageFormat *sub_fmt,
vasubpicture_cache_t *cache_SubpictureCreate(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *sub_fmt,
const subpicture_t *subpicture, const subpicture_region_t *region, const int flags);
/* Destory VASubpicture and cached subpicture */
void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *conn, subpicture_cache_t *cache, const bool b_force);
......@@ -40,20 +52,20 @@ void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *conn, subpicture_
/* Hold reference to subpicture cache object */
void cache_SubpictureHold(vlc_object_t *obj, vlc_array_t *cache_array, const int cache_id);
/* Release reference to subpicture cache object */
void cache_SubpictureRelease(vlc_object_t *obj, vlc_va_conn_t *vaconn, vlc_array_t *cache_array, const int cache_id);
void cache_SubpictureRelease(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, const int cache_id);
/* Link VASubpicture to VASurface */
int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *vaconn, vlc_array_t *cache_array,
int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
const picture_t *picture, const int flags);
/* Unlink VASubpicture from VASurface */
int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *vaconn, vlc_array_t *cache_array,
int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
const picture_t *picture);
/* Render VLC subpictures as VASubpictures and put them into a subpicture cache */
subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *vaconn, VAImageFormat *fmt,
subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt,
picture_t *picture, subpicture_t *subpicture, int flags);
/* Check if cached subpicture can be reused for the next Subpicture Render cycle */
int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *vaconn, vlc_array_t *cache_array,
int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
const unsigned int cache_id, picture_t *picture, subpicture_t *subpicture);
#endif
......
/*****************************************************************************
* Copyright © 2011 - 2013, M2X BV
* Author: Jean-Paul Saman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef VLC_VAAPI_XCB_H
#define VLC_VAAPI_XCB_H 1
int OpenVaapiXCB(vlc_object_t *);
void CloseVaapiXCB(vlc_object_t *);
#endif
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