Initial opengl support with va-api only.

This commit is contained in:
Johns 2013-04-16 16:44:42 +02:00
parent c0286b3ab4
commit 8f99f80d44
5 changed files with 344 additions and 290 deletions

View File

@ -1,6 +1,7 @@
User johns
Date:
Initial opengl support with va-api only.
Fix "broken driver" message if empty ring buffer.
Enable seamless audio track change.
Fix bug #1302: Unsupported pixel format crash.

View File

@ -19,6 +19,8 @@ OSS ?= 1
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
# support VA-API video output modue
VAAPI ?= $(shell pkg-config --exists libva && echo 1)
# support glx output
#OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
# screensaver disable/enable
SCREENSAVER ?= 1
# use ffmpeg libswresample
@ -34,6 +36,7 @@ CONFIG += -DUSE_PIP # PIP support
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser
#CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
#CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
#CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill
ifeq ($(ALSA),1)
CONFIG += -DUSE_ALSA
@ -52,6 +55,15 @@ ifeq ($(VAAPI),1)
CONFIG += -DUSE_VAAPI
_CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
LIBS += $(shell pkg-config --libs libva-x11 libva)
ifeq ($(OPENGL),1)
_CFLAGS += $(shell pkg-config --cflags libva-glx)
LIBS += $(shell pkg-config --libs libva-glx)
endif
endif
ifeq ($(OPENGL),1)
CONFIG += -DUSE_GLX
_CFLAGS += $(shell pkg-config --cflags gl glu)
LIBS += $(shell pkg-config --libs gl glu)
endif
ifeq ($(SCREENSAVER),1)
CONFIG += -DUSE_SCREENSAVER

2
Todo
View File

@ -1,6 +1,6 @@
@file Todo @brief A software HD output device for VDR
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
Contributor(s):

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR \n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2013-03-09 19:20+0100\n"
"POT-Creation-Date: 2013-04-16 15:10+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -895,6 +895,9 @@ msgstr ""
msgid "unsupported"
msgstr ""
msgid "video/glx: glx error\n"
msgstr ""
#, c-format
msgid "video/vaapi: unsupported pixel format %d\n"
msgstr ""
@ -1355,6 +1358,10 @@ msgstr ""
msgid "video: Can't connect to X11 server on '%s'\n"
msgstr ""
#, c-format
msgid "video: Can't initialize X11 thread support on '%s'\n"
msgstr ""
msgid "video: Can't convert XLIB display to XCB connection\n"
msgstr ""

610
video.c
View File

@ -43,7 +43,7 @@
#define USE_AUTOCROP ///< compile auto-crop support
#define USE_GRAB ///< experimental grab code
#define noUSE_GLX ///< outdated GLX code
#define noUSE_DOUBLEBUFFER ///< use GLX double buffers
#define USE_DOUBLEBUFFER ///< use GLX double buffers
//#define USE_VAAPI ///< enable vaapi support
//#define USE_VDPAU ///< enable vdpau support
#define noUSE_BITMAP ///< use vdpau bitmap surface
@ -137,7 +137,7 @@ typedef enum
#include <va/va_glx.h>
#endif
#ifndef VA_SURFACE_ATTRIB_SETTABLE
/// make source compatible with old libva
/// make source compatible with stable libva
#define vaCreateSurfaces(d, f, w, h, s, ns, a, na) \
vaCreateSurfaces(d, w, h, f, ns, s)
#endif
@ -622,10 +622,15 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width,
#ifdef USE_GLX
static int GlxEnabled = 1; ///< use GLX
static int GlxVSyncEnabled = 0; ///< enable/disable v-sync
static int GlxEnabled; ///< use GLX
static int GlxVSyncEnabled; ///< enable/disable v-sync
static GLXContext GlxSharedContext; ///< shared gl context
static GLXContext GlxContext; ///< our gl context
#ifdef USE_VIDEO_THREAD
static GLXContext GlxThreadContext; ///< our gl context for the thread
#endif
static XVisualInfo *GlxVisualInfo; ///< our gl visual
static GLuint OsdGlTextures[2]; ///< gl texture for OSD
@ -681,26 +686,22 @@ static int GlxIsExtensionSupported(const char *ext)
return 0;
}
#if 0
///
/// Setup GLX decoder
///
/// @param decoder VA-API decoder
/// @param width input video textures width
/// @param height input video textures height
/// @param[OUT] textures created and prepared textures
///
void GlxSetupDecoder(VaapiDecoder * decoder)
static void GlxSetupDecoder(int width, int height, GLuint * textures)
{
int width;
int height;
int i;
width = decoder->InputWidth;
height = decoder->InputHeight;
glEnable(GL_TEXTURE_2D); // create 2d texture
glGenTextures(2, decoder->GlTexture);
glGenTextures(2, textures);
GlxCheck();
for (i = 0; i < 2; ++i) {
glBindTexture(GL_TEXTURE_2D, decoder->GlTexture[i]);
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -714,12 +715,15 @@ void GlxSetupDecoder(VaapiDecoder * decoder)
GlxCheck();
}
#endif
///
/// Render texture.
///
/// @param texture 2d texture
/// @param x window x
/// @param y window y
/// @param width window width
/// @param height window height
///
static inline void GlxRenderTexture(GLuint texture, int x, int y, int width,
int height)
@ -737,16 +741,6 @@ static inline void GlxRenderTexture(GLuint texture, int x, int y, int width,
glVertex2i(x, y);
glTexCoord2f(1.0f, 0.0f);
glVertex2i(x + width, y);
#if 0
glTexCoord2f(0.0f, 0.0f);
glVertex2i(x, y);
glTexCoord2f(0.0f, 1.0f);
glVertex2i(x, y + height);
glTexCoord2f(1.0f, 1.0f);
glVertex2i(x + width, y + height);
glTexCoord2f(1.0f, 0.0f);
glVertex2i(x + width, y);
#endif
}
glEnd();
@ -755,15 +749,20 @@ static inline void GlxRenderTexture(GLuint texture, int x, int y, int width,
}
///
/// Upload texture.
/// Upload OSD texture.
///
static void GlxUploadTexture(int x, int y, int width, int height,
/// @param x x coordinate texture
/// @param y y coordinate texture
/// @param width argb image width
/// @param height argb image height
/// @param argb argb image
///
static void GlxUploadOsdTexture(int x, int y, int width, int height,
const uint8_t * argb)
{
// FIXME: use other / faster uploads
// ARB_pixelbuffer_object GL_PIXEL_UNPACK_BUFFER glBindBufferARB()
// glMapBuffer() glUnmapBuffer()
// glTexSubImage2D
glEnable(GL_TEXTURE_2D); // upload 2d texture
@ -776,59 +775,164 @@ static void GlxUploadTexture(int x, int y, int width, int height,
}
///
/// Render to glx texture.
/// GLX initialize OSD.
///
static void GlxRender(int osd_width, int osd_height)
/// @param width osd width
/// @param height osd height
///
static void GlxOsdInit(int width, int height)
{
static uint8_t *image;
static uint8_t cycle;
int x;
int y;
int i;
if (!OsdGlTextures[0] || !OsdGlTextures[1]) {
#ifdef DEBUG
if (!GlxEnabled) {
Debug(3, "video/glx: %s called without glx enabled\n", __FUNCTION__);
return;
}
// render each frame kills performance
#endif
// osd 1920 * 1080 * 4 (RGBA) * 50 (HZ) = 396 Mb/s
Debug(3, "video/glx: osd init context %p <-> %p\n", glXGetCurrentContext(),
GlxContext);
// too big for alloca
if (!image) {
image = malloc(4 * osd_width * osd_height);
memset(image, 0x00, 4 * osd_width * osd_height);
}
for (y = 0; y < osd_height; ++y) {
for (x = 0; x < osd_width; ++x) {
((uint32_t *) image)[x + y * osd_width] =
0x00FFFFFF | (cycle++) << 24;
}
}
cycle++;
// FIXME: convert is for GLX texture unneeded
// convert internal osd to image
//GfxConvert(image, 0, 4 * osd_width);
//
// create a RGBA texture.
//
glEnable(GL_TEXTURE_2D); // create 2d texture(s)
GlxUploadTexture(0, 0, osd_width, osd_height, image);
glGenTextures(2, OsdGlTextures);
for (i = 0; i < 2; ++i) {
glBindTexture(GL_TEXTURE_2D, OsdGlTextures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA,
GL_UNSIGNED_BYTE, NULL);
}
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
///
/// GLX cleanup osd.
///
static void GlxOsdExit(void)
{
if (OsdGlTextures[0]) {
glDeleteTextures(2, OsdGlTextures);
OsdGlTextures[0] = 0;
OsdGlTextures[1] = 0;
}
}
///
/// Upload ARGB image to texture.
///
/// @param x x coordinate of image in osd texture
/// @param y y coordinate of image in osd texture
/// @param width width of image
/// @param height height of image
/// @param argb argb image
///
/// @note looked by caller
///
static void GlxOsdDrawARGB(int x, int y, int width, int height,
const uint8_t * argb)
{
#ifdef DEBUG
uint32_t start;
uint32_t end;
#endif
#ifdef DEBUG
if (!GlxEnabled) {
Debug(3, "video/glx: %s called without glx enabled\n", __FUNCTION__);
return;
}
start = GetMsTicks();
Debug(3, "video/glx: osd context %p <-> %p\n", glXGetCurrentContext(),
GlxContext);
#endif
// set glx context
if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxContext)) {
Error(_("video/glx: can't make glx context current\n"));
return;
}
GlxUploadOsdTexture(x, y, width, height, argb);
glXMakeCurrent(XlibDisplay, None, NULL);
#ifdef DEBUG
end = GetMsTicks();
Debug(3, "video/glx: osd upload %dx%d%+d%+d %dms %d\n", width, height, x,
y, end - start, width * height * 4);
#endif
}
///
/// Clear OSD texture.
///
/// @note looked by caller
///
static void GlxOsdClear(void)
{
void *texbuf;
#ifdef DEBUG
if (!GlxEnabled) {
Debug(3, "video/glx: %s called without glx enabled\n", __FUNCTION__);
return;
}
Debug(3, "video/glx: osd context %p <-> %p\n", glXGetCurrentContext(),
GlxContext);
#endif
// FIXME: any opengl function to clear an area?
// FIXME: if not; use zero buffer
// FIXME: if not; use dirty area
texbuf = calloc(OsdWidth * OsdHeight, 4);
// set glx context
if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxContext)) {
Error(_("video/glx: can't make glx context current\n"));
return;
}
GlxUploadOsdTexture(0, 0, OsdWidth, OsdHeight, texbuf);
glXMakeCurrent(XlibDisplay, None, NULL);
free(texbuf);
}
///
/// Setup GLX window.
///
static void GlxSetupWindow(xcb_window_t window, int width, int height)
/// @param window xcb window id
/// @param width window width
/// @param height window height
/// @param context GLX context
///
static void GlxSetupWindow(xcb_window_t window, int width, int height,
GLXContext context)
{
#ifdef DEBUG
uint32_t start;
uint32_t end;
int i;
unsigned count;
#endif
Debug(3, "video/glx: %s\n %x %dx%d", __FUNCTION__, window, width, height);
Debug(3, "video/glx: %s %x %dx%d context:%p", __FUNCTION__, window, width,
height, context);
// set glx context
if (!glXMakeCurrent(XlibDisplay, window, GlxContext)) {
Fatal(_("video/glx: can't make glx context current\n"));
// FIXME: disable glx
if (!glXMakeCurrent(XlibDisplay, window, context)) {
Error(_("video/glx: can't make glx context current\n"));
GlxEnabled = 0;
return;
}
@ -996,7 +1100,8 @@ static void GlxInit(void)
if (!context) {
Error(_("video/glx: can't create glx context\n"));
GlxEnabled = 0;
// FIXME: destroy GlxSharedContext
glXDestroyContext(XlibDisplay, GlxSharedContext);
GlxSharedContext = 0;
return;
}
GlxContext = context;
@ -1093,12 +1198,10 @@ static void GlxExit(void)
if (GlxContext) {
glXDestroyContext(XlibDisplay, GlxContext);
}
#if 0
if (GlxThreadContext) {
glXDestroyContext(XlibDisplay, GlxThreadContext);
}
// FIXME: must free GlxVisualInfo
#endif
}
#endif
@ -1394,8 +1497,8 @@ struct _vaapi_decoder_
AutoCropCtx AutoCrop[1]; ///< auto-crop variables
#endif
#ifdef USE_GLX
GLuint GlTexture[2]; ///< gl texture for VA-API
void *GlxSurface[2]; ///< VA-API/GLX surface
GLuint GlTextures[2]; ///< gl texture for VA-API
void *GlxSurfaces[2]; ///< VA-API/GLX surface
#endif
VASurfaceID BlackSurface; ///< empty black surface
@ -1852,8 +1955,8 @@ static VaapiDecoder *VaapiNewHwDecoder(VideoStream * stream)
decoder->VaapiContext->context_id = VA_INVALID_ID;
#ifdef USE_GLX
decoder->GlxSurface[0] = VA_INVALID_ID;
decoder->GlxSurface[1] = VA_INVALID_ID;
decoder->GlxSurfaces[0] = NULL;
decoder->GlxSurfaces[1] = NULL;
if (GlxEnabled) {
// FIXME: create GLX context here
}
@ -2009,20 +2112,22 @@ static void VaapiDelHwDecoder(VaapiDecoder * decoder)
}
}
#ifdef USE_GLX
if (decoder->GlxSurface[0] != VA_INVALID_ID) {
if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurface[0])
if (decoder->GlxSurfaces[0]) {
if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurfaces[0])
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't destroy glx surface!\n"));
}
decoder->GlxSurfaces[0] = NULL;
}
if (decoder->GlxSurface[1] != VA_INVALID_ID) {
if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurface[1])
if (decoder->GlxSurfaces[1]) {
if (vaDestroySurfaceGLX(VaDisplay, decoder->GlxSurfaces[1])
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't destroy glx surface!\n"));
}
decoder->GlxSurfaces[0] = NULL;
}
if (decoder->GlTexture[0]) {
glDeleteTextures(2, decoder->GlTexture);
if (decoder->GlTextures[0]) {
glDeleteTextures(2, decoder->GlTextures);
}
#endif
@ -2244,6 +2349,33 @@ static int VaapiInit(const char *display_name)
return 1;
}
#ifdef USE_GLX
///
/// VA-API GLX setup.
///
/// @param display_name x11/xcb display name
///
/// @returns true if VA-API could be initialized, false otherwise.
///
static int VaapiGlxInit(const char *display_name)
{
GlxEnabled = 1;
GlxInit();
if (GlxEnabled) {
GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight,
GlxContext);
}
if (!GlxEnabled) {
Error(_("video/glx: glx error\n"));
}
return VaapiInit(display_name);
}
#endif
///
/// VA-API cleanup
///
@ -2251,7 +2383,7 @@ static void VaapiExit(void)
{
int i;
// FIXME: more VA-API cleanups...
// FIXME: more VA-API cleanups...
for (i = 0; i < VaapiDecoderN; ++i) {
if (VaapiDecoders[i]) {
@ -2405,16 +2537,18 @@ static void VaapiSetup(VaapiDecoder * decoder,
if (GlxEnabled) {
// FIXME: destroy old context
GlxSetupDecoder(decoder);
GlxSetupDecoder(decoder->InputWidth, decoder->InputHeight,
decoder->GlTextures);
// FIXME: try two textures
if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
decoder->GlTexture[0], &decoder->GlxSurface[0])
decoder->GlTextures[0], &decoder->GlxSurfaces[0])
!= VA_STATUS_SUCCESS) {
Fatal(_("video/glx: can't create glx surfaces\n"));
// FIXME: no fatal here
}
/*
if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
decoder->GlTexture[1], &decoder->GlxSurface[1])
decoder->GlTextures[1], &decoder->GlxSurfaces[1])
!= VA_STATUS_SUCCESS) {
Fatal(_("video/glx: can't create glx surfaces\n"));
}
@ -2827,44 +2961,6 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
#ifdef USE_GLX
///
/// Render texture.
///
/// @param texture 2d texture
///
static inline void VideoRenderTexture(GLuint texture, int x, int y, int width,
int height)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // no color
glBegin(GL_QUADS); {
glTexCoord2f(1.0f, 1.0f);
glVertex2i(x + width, y + height);
glTexCoord2f(0.0f, 1.0f);
glVertex2i(x, y + height);
glTexCoord2f(0.0f, 0.0f);
glVertex2i(x, y);
glTexCoord2f(1.0f, 0.0f);
glVertex2i(x + width, y);
#if 0
glTexCoord2f(0.0f, 0.0f);
glVertex2i(x, y);
glTexCoord2f(0.0f, 1.0f);
glVertex2i(x, y + height);
glTexCoord2f(1.0f, 1.0f);
glVertex2i(x + width, y + height);
glTexCoord2f(1.0f, 0.0f);
glVertex2i(x + width, y);
#endif
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
///
/// Draw surface of the VA-API decoder with glx.
///
@ -2878,12 +2974,14 @@ static void VaapiPutSurfaceGLX(VaapiDecoder * decoder, VASurfaceID surface,
int interlaced, int top_field_first, int field)
{
unsigned type;
uint32_t start;
uint32_t copy;
uint32_t end;
//uint32_t start;
//uint32_t copy;
//uint32_t end;
// deinterlace
if (interlaced
&& VideoDeinterlace[decoder->Resolution] < VideoDeinterlaceSoftBob
&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
if (top_field_first) {
if (field) {
@ -2901,18 +2999,20 @@ static void VaapiPutSurfaceGLX(VaapiDecoder * decoder, VASurfaceID surface,
} else {
type = VA_FRAME_PICTURE;
}
start = GetMsTicks();
if (vaCopySurfaceGLX(decoder->VaDisplay, decoder->GlxSurface[0], surface,
//start = GetMsTicks();
if (vaCopySurfaceGLX(decoder->VaDisplay, decoder->GlxSurfaces[0], surface,
type | decoder->SurfaceFlagsTable[decoder->Resolution]) !=
VA_STATUS_SUCCESS) {
Error(_("video/glx: vaCopySurfaceGLX failed\n"));
return;
}
copy = GetMsTicks();
//copy = GetMsTicks();
// hardware surfaces are always busy
VideoRenderTexture(decoder->GlTexture[0], decoder->OutputX,
// FIXME: CropX, ...
GlxRenderTexture(decoder->GlTextures[0], decoder->OutputX,
decoder->OutputY, decoder->OutputWidth, decoder->OutputHeight);
end = GetMsTicks();
//end = GetMsTicks();
//Debug(3, "video/vaapi/glx: %d copy %d render\n", copy - start, end - copy);
}
@ -4577,8 +4677,16 @@ static void VaapiDisplayFrame(void)
put2 = GetMsTicks();
#endif
} else {
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, decoder->SurfaceField);
#ifdef USE_GLX
if (GlxEnabled) {
VaapiPutSurfaceGLX(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, decoder->SurfaceField);
} else
#endif
{
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, decoder->SurfaceField);
}
#ifdef DEBUG
put1 = GetMsTicks();
put2 = put1;
@ -4611,6 +4719,22 @@ static void VaapiDisplayFrame(void)
decoder->FrameTime = nowtime;
}
#ifdef USE_GLX
//
// add OSD
//
if (OsdShown) {
GlxRenderTexture(OsdGlTextures[OsdIndex], 0, 0, VideoWindowWidth,
VideoWindowHeight);
// FIXME: toggle osd
}
//glFinish();
glXSwapBuffers(XlibDisplay, VideoWindow);
GlxCheck();
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
#endif
}
///
@ -5230,6 +5354,44 @@ static const VideoModule VaapiModule = {
.Exit = VaapiExit,
};
#ifdef USE_GLX
///
/// VA-API module.
///
static const VideoModule VaapiGlxModule = {
.Name = "va-api-glx",
.Enabled = 1,
.NewHwDecoder =
(VideoHwDecoder * (*const)(VideoStream *)) VaapiNewHwDecoder,
.DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelHwDecoder,
.GetSurface = (unsigned (*const) (VideoHwDecoder *,
const AVCodecContext *))VaapiGetSurface,
.ReleaseSurface =
(void (*const) (VideoHwDecoder *, unsigned))VaapiReleaseSurface,
.get_format = (enum PixelFormat(*const) (VideoHwDecoder *,
AVCodecContext *, const enum PixelFormat *))Vaapi_get_format,
.RenderFrame = (void (*const) (VideoHwDecoder *,
const AVCodecContext *, const AVFrame *))VaapiSyncRenderFrame,
.SetClock = (void (*const) (VideoHwDecoder *, int64_t))VaapiSetClock,
.GetClock = (int64_t(*const) (const VideoHwDecoder *))VaapiGetClock,
.SetTrickSpeed =
(void (*const) (const VideoHwDecoder *, int))VaapiSetTrickSpeed,
.GrabOutput = NULL,
.SetBackground = VaapiSetBackground,
.SetVideoMode = VaapiSetVideoMode,
.ResetAutoCrop = VaapiResetAutoCrop,
.DisplayHandlerThread = VaapiDisplayHandlerThread,
.OsdClear = GlxOsdClear,
.OsdDrawARGB = GlxOsdDrawARGB,
.OsdInit = GlxOsdInit,
.OsdExit = GlxOsdExit,
.Init = VaapiGlxInit,
.Exit = VaapiExit,
};
#endif
#endif
//----------------------------------------------------------------------------
@ -5276,8 +5438,8 @@ typedef struct _vdpau_decoder_
AutoCropCtx AutoCrop[1]; ///< auto-crop variables
#endif
#ifdef noyetUSE_GLX
GLuint GlTexture[2]; ///< gl texture for VDPAU
void *GlxSurface[2]; ///< VDPAU/GLX surface
GLuint GlTextures[2]; ///< gl texture for VDPAU
void *GlxSurfaces[2]; ///< VDPAU/GLX surface
#endif
VdpDecoderProfile Profile; ///< vdp decoder profile
@ -9029,26 +9191,9 @@ static const VideoModule NoopModule = {
void VideoOsdClear(void)
{
VideoThreadLock();
#ifdef USE_GLX
if (GlxEnabled) {
void *texbuf;
texbuf = calloc(OsdWidth * OsdHeight, 4);
glEnable(GL_TEXTURE_2D); // 2d texture
glBindTexture(GL_TEXTURE_2D, OsdGlTextures[OsdIndex]);
// upload no image data, clears texture (on some drivers only)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, OsdWidth, OsdHeight, 0,
GL_BGRA, GL_UNSIGNED_BYTE, texbuf);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
GlxCheck();
free(texbuf);
}
#endif
VideoUsedModule->OsdClear();
OsdDirtyX = OsdWidth;
OsdDirtyX = OsdWidth; // reset dirty area
OsdDirtyY = OsdHeight;
OsdDirtyWidth = 0;
OsdDirtyHeight = 0;
@ -9092,14 +9237,6 @@ void VideoOsdDrawARGB(int x, int y, int width, int height,
Debug(4, "video: osd dirty %dx%d%+d%+d -> %dx%d%+d%+d\n", width, height, x,
y, OsdDirtyWidth, OsdDirtyHeight, OsdDirtyX, OsdDirtyY);
#ifdef USE_GLX
if (GlxEnabled) {
Debug(3, "video: %p <-> %p\n", glXGetCurrentContext(), GlxContext);
GlxUploadTexture(x, y, height, width, argb);
VideoThreadUnlock();
return;
}
#endif
VideoUsedModule->OsdDrawARGB(x, y, width, height, argb);
OsdShown = 1;
@ -9163,38 +9300,6 @@ void VideoOsdInit(void)
OsdHeight = VideoWindowHeight;
}
#ifdef USE_GLX
// FIXME: make an extra function for this
if (GlxEnabled) {
int i;
Debug(3, "video/glx: %p <-> %p\n", glXGetCurrentContext(), GlxContext);
//
// create a RGBA texture.
//
glEnable(GL_TEXTURE_2D); // create 2d texture(s)
glGenTextures(2, OsdGlTextures);
for (i = 0; i < 2; ++i) {
glBindTexture(GL_TEXTURE_2D, OsdGlTextures[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, OsdWidth, OsdHeight, 0,
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
}
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
return;
}
#endif
VideoThreadLock();
VideoUsedModule->OsdInit(OsdWidth, OsdHeight);
VideoThreadUnlock();
@ -9213,84 +9318,6 @@ void VideoOsdExit(void)
OsdDirtyHeight = 0;
}
#if 0
//----------------------------------------------------------------------------
// Overlay
//----------------------------------------------------------------------------
///
/// Render osd surface.
///
void VideoRenderOverlay(void)
{
#ifdef USE_GLX
if (GlxEnabled) {
GlxRender(OsdWidth, OsdHeight);
} else
#endif
{
}
}
///
/// Display overlay surface.
///
void VideoDisplayOverlay(void)
{
#ifdef USE_GLX
if (GlxEnabled) {
int osd_x1;
int osd_y1;
osd_x1 = 0;
osd_y1 = 0;
#ifdef noDEBUG
osd_x1 = 100;
osd_y1 = 100;
#endif
GlxRenderTexture(OsdGlTextures[OsdIndex], osd_x1, osd_y1,
VideoWindowWidth, VideoWindowHeight);
return;
}
#endif
#ifdef USE_VAAPI
{
void *image_buffer;
static int counter;
// upload needs long time
if (counter == 5) {
//return;
}
// osd image available?
if (VaOsdImage.image_id == VA_INVALID_ID) {
return;
}
// FIXME: this version hangups
//return;
// map osd surface/image into memory.
if (vaMapBuffer(VaDisplay, VaOsdImage.buf,
&image_buffer) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't map osd image buffer\n"));
return;
}
// 100% transparent
memset(image_buffer, 0x80 | counter++, VaOsdImage.data_size);
// convert internal osd to VA-API image
//GfxConvert(image_buffer, VaOsdImage.offsets[0], VaOsdImage.pitches[0]);
if (vaUnmapBuffer(VaDisplay, VaOsdImage.buf) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't unmap osd image buffer\n"));
}
}
#endif
}
#endif
//----------------------------------------------------------------------------
// Events
//----------------------------------------------------------------------------
@ -9438,10 +9465,6 @@ void VideoPollEvent(void)
#ifdef USE_VIDEO_THREAD
#ifdef USE_GLX
static GLXContext GlxThreadContext; ///< our gl context for the thread
#endif
///
/// Lock video thread.
///
@ -9475,20 +9498,21 @@ static void *VideoDisplayHandlerThread(void *dummy)
#ifdef USE_GLX
if (GlxEnabled) {
Debug(3, "video: %p <-> %p\n", glXGetCurrentContext(),
GlxThreadContext);
Debug(3, "video/glx: thread context %p <-> %p\n",
glXGetCurrentContext(), GlxThreadContext);
Debug(3, "video/glx: context %p <-> %p\n", glXGetCurrentContext(),
GlxContext);
GlxThreadContext =
glXCreateContext(XlibDisplay, GlxVisualInfo, GlxContext, GL_TRUE);
glXCreateContext(XlibDisplay, GlxVisualInfo, GlxSharedContext,
GL_TRUE);
if (!GlxThreadContext) {
Error(_("video/glx: can't create glx context\n"));
return NULL;
}
// set glx context
if (!glXMakeCurrent(XlibDisplay, VideoWindow, GlxThreadContext)) {
GlxCheck();
Error(_("video/glx: can't make glx context current\n"));
return NULL;
}
GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight,
GlxThreadContext);
}
#endif
@ -9511,6 +9535,9 @@ static void *VideoDisplayHandlerThread(void *dummy)
///
static void VideoThreadInit(void)
{
#ifdef USE_GLX
glXMakeCurrent(XlibDisplay, None, NULL);
#endif
pthread_mutex_init(&VideoMutex, NULL);
pthread_mutex_init(&VideoLockMutex, NULL);
pthread_cond_init(&VideoWakeupCond, NULL);
@ -9568,7 +9595,7 @@ void VideoDisplayWakeup(void)
//----------------------------------------------------------------------------
///
/// Table of all audio modules.
/// Table of all video modules.
///
static const VideoModule *VideoModules[] = {
#ifdef USE_VDPAU
@ -9576,6 +9603,9 @@ static const VideoModule *VideoModules[] = {
#endif
#ifdef USE_VAAPI
&VaapiModule,
#endif
#ifdef USE_GLX
&VaapiGlxModule, // FIXME: if working, prefer this
#endif
&NoopModule
};
@ -9712,6 +9742,8 @@ void VideoRenderFrame(VideoHwDecoder * hw_decoder,
///
/// Get VA-API ffmpeg context
///
/// FIXME: new ffmpeg supports vdpau hw context
///
/// @param hw_decoder video hardware decoder (must be VA-API)
///
struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder * hw_decoder)
@ -9720,6 +9752,11 @@ struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder * hw_decoder)
if (VideoUsedModule == &VaapiModule) {
return hw_decoder->Vaapi.VaapiContext;
}
#ifdef USE_GLX
if (VideoUsedModule == &VaapiGlxModule) {
return hw_decoder->Vaapi.VaapiContext;
}
#endif
#endif
(void)hw_decoder;
Error(_("video/vaapi: get vaapi context, without vaapi enabled\n"));
@ -10864,7 +10901,12 @@ void VideoInit(const char *display_name)
// FIXME: we need to retry connection
return;
}
//XInitThreads();
#ifdef USE_GLX_doesn_t_help_still_crash
if (!XInitThreads()) {
Error(_("video: Can't initialize X11 thread support on '%s'\n"),
display_name);
}
#endif
// Register error handler
XSetIOErrorHandler(VideoIOErrorHandler);
@ -10912,13 +10954,15 @@ void VideoInit(const char *display_name)
// prepare opengl
//
#ifdef USE_GLX
if (GlxEnabled) {
// FIXME: module selected below
if (0) {
GlxInit();
// FIXME: use root window?
VideoCreateWindow(screen->root, GlxVisualInfo->visualid,
GlxVisualInfo->depth);
GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight);
GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight,
GlxContext);
} else
#endif
@ -11177,16 +11221,6 @@ int main(int argc, char *const argv[])
start_tick = GetMsTicks();
n = 0;
for (;;) {
#if 0
VideoRenderOverlay();
VideoDisplayOverlay();
glXSwapBuffers(XlibDisplay, VideoWindow);
GlxCheck();
glClear(GL_COLOR_BUFFER_BIT);
XSync(XlibDisplay, False);
XFlush(XlibDisplay);
#endif
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
VaapiDisplayFrame();