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.
No related merge requests found
......@@ -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