Commit fae953b6 authored by Jean-Paul Saman's avatar Jean-Paul Saman

modules/codec/avcodec: Add VAAPI X11 vout

Video output VAAPI-X11 (-V vaapi-x11) depends on --ffmpeg-hw to be enabled.
parent ffe7367b
......@@ -10,9 +10,11 @@ libavcodec_plugin_la_SOURCES = \
chroma.h \
chroma.c \
vaapi.c \
vaapi_x11.c \
dxva2.c \
copy.c \
copy.h \
va.c \
va.h \
$(NULL)
if ENABLE_SOUT
......@@ -54,4 +56,3 @@ EXTRA_LTLIBRARIES += \
# FIXME mux.c \
# FIXME scale.c \
# FIXME $(NULL)
......@@ -141,7 +141,6 @@ vlc_module_begin ()
add_integer( "ffmpeg-threads", 0, THREADS_TEXT, THREADS_LONGTEXT, true );
#endif
#ifdef ENABLE_SOUT
/* encoder submodule */
add_submodule ()
......@@ -219,6 +218,17 @@ vlc_module_begin ()
add_submodule ()
AVIO_MODULE
#endif
#if defined(HAVE_AVCODEC_VAAPI)
/* vaapi_x11 submodule */
add_submodule()
set_description (N_("VAAPI X11 video output"))
set_category (CAT_VIDEO)
set_subcategory (SUBCAT_VIDEO_VOUT)
set_capability ("vout display", 75)
set_callbacks (OpenVaapiX11, CloseVaapiX11)
add_shortcut ("vaapi-x11")
#endif
vlc_module_end ()
/*****************************************************************************
......
......@@ -52,6 +52,12 @@ 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 );
......
......@@ -44,6 +44,12 @@
#endif
#include "avcodec.h"
#ifdef HAVE_AVCODEC_VAAPI
# include <vlc_xlib.h>
# include <libavcodec/vaapi.h>
# include <va/va.h>
# include <va/va_x11.h>
#endif
#include "va.h"
#include "copy.h"
......
/*****************************************************************************
* va.c: Video Acceleration API for avcodec
*****************************************************************************
* Copyright (C) 2011, M2X BV
* $Id$
*
* Authors: Jean-Paul Saman
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_fourcc.h>
#include <assert.h>
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
# include <libavcodec/avcodec.h>
#else
# include <avcodec.h>
#endif
#include "avcodec.h"
#ifdef HAVE_AVCODEC_VAAPI
# include <vlc_xlib.h>
# include <libavcodec/vaapi.h>
# include <va/va.h>
# include <va/va_x11.h>
#endif
#include "va.h"
#ifdef HAVE_AVCODEC_VAAPI
/* Global VAAPI connection state */
static vlc_va_conn_t vlc_va_conn = { 0, 0, 0, 0 };
static vlc_va_conn_t *vlc_va_get_conn( void )
{
return (vlc_va_conn_t *) &vlc_va_conn;
}
int vlc_va_Initialize( vlc_va_conn_t *conn, const char *display_name )
{
static bool b_va_inited = false;
assert(conn == NULL);
/* connect global to caller */
conn = vlc_va_get_conn();
if (b_va_inited)
return VLC_SUCCESS;
/* Create a VA display */
conn->p_display_x11 = XOpenDisplay(display_name);
if( !conn->p_display_x11 )
goto error;
conn->p_display = vaGetDisplay(conn->p_display_x11);
if( !conn->p_display )
goto error;
if( vaInitialize(conn->p_display, &conn->i_version_major, &conn->i_version_minor) )
goto error;
b_va_inited = true;
return VLC_SUCCESS;
error:
return VLC_EGENERIC;
}
#endif
......@@ -61,5 +61,18 @@ static inline void vlc_va_Delete(vlc_va_t *va)
vlc_va_t *vlc_va_NewVaapi(vlc_object_t *obj, int codec_id);
vlc_va_t *vlc_va_NewDxva2(vlc_object_t *log, int codec_id);
#ifdef HAVE_AVCODEC_VAAPI
typedef struct vlc_va_conn_t vlc_va_conn_t;
struct vlc_va_conn_t
{
Display *p_display_x11;
VADisplay p_display;
int i_version_major;
int i_version_minor;
};
int vlc_va_Initialize(vlc_va_conn_t *conn, const char *display_name);
#endif
#endif
......@@ -36,18 +36,17 @@
#endif
#include "avcodec.h"
#ifdef HAVE_AVCODEC_VAAPI
# include <vlc_xlib.h>
# include <libavcodec/vaapi.h>
# include <va/va.h>
# include <va/va_x11.h>
#endif
#include "va.h"
#include "copy.h"
#ifdef HAVE_AVCODEC_VAAPI
#include <vlc_xlib.h>
#include <libavcodec/vaapi.h>
#include <X11/Xlib.h>
#include <va/va_x11.h>
typedef struct
{
VASurfaceID i_id;
......@@ -61,18 +60,13 @@ typedef struct
vlc_va_t va;
/* */
Display *p_display_x11;
VADisplay p_display;
vlc_va_conn_t *conn;
VAConfigID i_config_id;
VAContextID i_context_id;
struct vaapi_context hw_ctx;
/* */
int i_version_major;
int i_version_minor;
/* */
int i_surface_count;
unsigned int i_surface_order;
......@@ -133,29 +127,21 @@ static int Open( vlc_va_vaapi_t *p_va, int i_codec_id )
p_va->image.image_id = VA_INVALID_ID;
/* Create a VA display */
p_va->p_display_x11 = XOpenDisplay(NULL);
if( !p_va->p_display_x11 )
goto error;
p_va->p_display = vaGetDisplay( p_va->p_display_x11 );
if( !p_va->p_display )
goto error;
if( vaInitialize( p_va->p_display, &p_va->i_version_major, &p_va->i_version_minor ) )
if( vlc_va_Initialize( p_va->conn, NULL ) != VLC_SUCCESS )
goto error;
/* Create a VA configuration */
VAConfigAttrib attrib;
memset( &attrib, 0, sizeof(attrib) );
attrib.type = VAConfigAttribRTFormat;
if( vaGetConfigAttributes( p_va->p_display,
if( vaGetConfigAttributes( p_va->conn->p_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( p_va->p_display,
if( vaCreateConfig( p_va->conn->p_display,
i_profile, VAEntrypointVLD, &attrib, 1, &p_va->i_config_id ) )
{
p_va->i_config_id = VA_INVALID_ID;
......@@ -165,7 +151,7 @@ static int Open( vlc_va_vaapi_t *p_va, int i_codec_id )
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->conn->i_version_major, p_va->conn->i_version_minor ) < 0 )
p_va->va.description = NULL;
return VLC_SUCCESS;
......@@ -179,18 +165,18 @@ static void DestroySurfaces( vlc_va_vaapi_t *p_va )
if( p_va->image.image_id != VA_INVALID_ID )
{
CopyCleanCache( &p_va->image_cache );
vaDestroyImage( p_va->p_display, p_va->image.image_id );
vaDestroyImage( p_va->conn->p_display, p_va->image.image_id );
}
if( p_va->i_context_id != VA_INVALID_ID )
vaDestroyContext( p_va->p_display, p_va->i_context_id );
vaDestroyContext( p_va->conn->p_display, p_va->i_context_id );
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 );
vaDestroySurfaces( p_va->conn->p_display, &p_surface->i_id, 1 );
}
free( p_va->p_surface );
......@@ -215,7 +201,7 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
/* Create surfaces */
VASurfaceID pi_surface_id[p_va->i_surface_count];
if( vaCreateSurfaces( p_va->p_display, i_width, i_height, VA_RT_FORMAT_YUV420,
if( vaCreateSurfaces( p_va->conn->p_display, i_width, i_height, VA_RT_FORMAT_YUV420,
p_va->i_surface_count, pi_surface_id ) )
{
for( int i = 0; i < p_va->i_surface_count; i++ )
......@@ -233,7 +219,7 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
}
/* Create a context */
if( vaCreateContext( p_va->p_display, p_va->i_config_id,
if( vaCreateContext( p_va->conn->p_display, p_va->i_config_id,
i_width, i_height, VA_PROGRESSIVE,
pi_surface_id, p_va->i_surface_count, &p_va->i_context_id ) )
{
......@@ -242,12 +228,12 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
}
/* Find and create a supported image chroma */
int i_fmt_count = vaMaxNumImageFormats( p_va->p_display );
int i_fmt_count = vaMaxNumImageFormats( p_va->conn->p_display );
VAImageFormat *p_fmt = calloc( i_fmt_count, sizeof(*p_fmt) );
if( !p_fmt )
goto error;
if( vaQueryImageFormats( p_va->p_display, p_fmt, &i_fmt_count ) )
if( vaQueryImageFormats( p_va->conn->p_display, p_fmt, &i_fmt_count ) )
{
free( p_fmt );
goto error;
......@@ -261,17 +247,17 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
p_fmt[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ||
p_fmt[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) )
{
if( vaCreateImage( p_va->p_display, &p_fmt[i], i_width, i_height, &p_va->image ) )
if( vaCreateImage( p_va->conn->p_display, &p_fmt[i], i_width, i_height, &p_va->image ) )
{
p_va->image.image_id = VA_INVALID_ID;
continue;
}
/* Validate that vaGetImage works with this format */
if( vaGetImage( p_va->p_display, pi_surface_id[0],
if( vaGetImage( p_va->conn->p_display, pi_surface_id[0],
0, 0, i_width, i_height,
p_va->image.image_id) )
{
vaDestroyImage( p_va->p_display, p_va->image.image_id );
vaDestroyImage( p_va->conn->p_display, p_va->image.image_id );
p_va->image.image_id = VA_INVALID_ID;
continue;
}
......@@ -292,7 +278,7 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
*pp_hw_ctx = &p_va->hw_ctx;
memset( &p_va->hw_ctx, 0, sizeof(p_va->hw_ctx) );
p_va->hw_ctx.display = p_va->p_display;
p_va->hw_ctx.display = p_va->conn->p_display;
p_va->hw_ctx.config_id = p_va->i_config_id;
p_va->hw_ctx.context_id = p_va->i_context_id;
......@@ -340,9 +326,9 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
VASurfaceID i_surface_id = (VASurfaceID)(uintptr_t)p_ff->data[3];
#if VA_CHECK_VERSION(0,31,0)
if( vaSyncSurface( p_va->p_display, i_surface_id ) )
if( vaSyncSurface( p_va->conn->p_display, i_surface_id ) )
#else
if( vaSyncSurface( p_va->p_display, p_va->i_context_id, i_surface_id ) )
if( vaSyncSurface( p_va->conn->p_display, p_va->i_context_id, i_surface_id ) )
#endif
return VLC_EGENERIC;
......@@ -350,13 +336,13 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
* my setup.
*/
if( vaGetImage( p_va->p_display, i_surface_id,
if( vaGetImage( p_va->conn->p_display, i_surface_id,
0, 0, p_va->i_surface_width, p_va->i_surface_height,
p_va->image.image_id) )
return VLC_EGENERIC;
void *p_base;
if( vaMapBuffer( p_va->p_display, p_va->image.buf, &p_base ) )
if( vaMapBuffer( p_va->conn->p_display, p_va->image.buf, &p_base ) )
return VLC_EGENERIC;
const uint32_t i_fourcc = p_va->image.format.fourcc;
......@@ -395,7 +381,7 @@ static int Extract( vlc_va_t *p_external, picture_t *p_picture, AVFrame *p_ff )
&p_va->image_cache );
}
if( vaUnmapBuffer( p_va->p_display, p_va->image.buf ) )
if( vaUnmapBuffer( p_va->conn->p_display, p_va->image.buf ) )
return VLC_EGENERIC;
return VLC_SUCCESS;
......@@ -458,11 +444,11 @@ static void Close( vlc_va_vaapi_t *p_va )
DestroySurfaces( p_va );
if( p_va->i_config_id != VA_INVALID_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 );
vaDestroyConfig( p_va->conn->p_display, p_va->i_config_id );
if( p_va->conn->p_display )
vaTerminate( p_va->conn->p_display );
if( p_va->conn->p_display_x11 )
XCloseDisplay( p_va->conn->p_display_x11 );
}
static void Delete( vlc_va_t *p_external )
{
......
This diff is collapsed.
......@@ -51,6 +51,12 @@
#endif
#include "avcodec.h"
#ifdef HAVE_AVCODEC_VAAPI
# include <vlc_xlib.h>
# include <va/va.h>
#endif
#include "va.h"
#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2)
# define HAVE_AVCODEC_VA
......
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