mirror of
https://github.com/wang-bin/QtAV.git
synced 2026-10-29 11:36:51 +08:00
vaapi: va-x11 + glx tfp
sometimes ui blocks, why?
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#include "SurfaceInteropVAAPI.h"
|
||||
#include "utils/OpenGLHelper.h"
|
||||
#include <GL/glx.h>
|
||||
#include <va/va_x11.h>
|
||||
|
||||
namespace QtAV {
|
||||
namespace vaapi {
|
||||
@@ -23,6 +25,8 @@ void* SurfaceInteropVAAPI::map(SurfaceType type, const VideoFormat &fmt, void *h
|
||||
{
|
||||
if (!fmt.isRGB())
|
||||
return 0;
|
||||
QMutexLocker lock(&mutex);
|
||||
|
||||
if (!handle)
|
||||
handle = createHandle(type, fmt, plane);
|
||||
if (type == GLTextureSurface) {
|
||||
@@ -37,7 +41,7 @@ void* SurfaceInteropVAAPI::map(SurfaceType type, const VideoFormat &fmt, void *h
|
||||
glx->set(m_surface);
|
||||
if (!glx->copy())
|
||||
return 0;
|
||||
glx->sync();
|
||||
VAWARN(vaSyncSurface(m_surface->display(), m_surface->get()));
|
||||
return handle;
|
||||
} else
|
||||
if (type == HostMemorySurface) {
|
||||
@@ -78,6 +82,143 @@ void* SurfaceInteropVAAPI::createHandle(SurfaceType type, const VideoFormat &fmt
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef QT_OPENGL_ES_2
|
||||
VAAPI_X_GLX_Interop::glXReleaseTexImage_t VAAPI_X_GLX_Interop::glXReleaseTexImage = 0;
|
||||
VAAPI_X_GLX_Interop::glXBindTexImage_t VAAPI_X_GLX_Interop::glXBindTexImage = 0;
|
||||
|
||||
VAAPI_X_GLX_Interop::VAAPI_X_GLX_Interop()
|
||||
: xdisplay(0)
|
||||
, fbc(0)
|
||||
, pixmap(0)
|
||||
, glxpixmap(0)
|
||||
, width(0)
|
||||
, height(0)
|
||||
{}
|
||||
|
||||
VAAPI_X_GLX_Interop::~VAAPI_X_GLX_Interop()
|
||||
{
|
||||
if (glxpixmap) {
|
||||
glXReleaseTexImage(xdisplay, glxpixmap, GLX_FRONT_EXT);
|
||||
XSync((::Display*)xdisplay, False);
|
||||
glXDestroyPixmap((::Display*)xdisplay, glxpixmap);
|
||||
}
|
||||
glxpixmap = 0;
|
||||
|
||||
if (pixmap)
|
||||
XFreePixmap((::Display*)xdisplay, pixmap);
|
||||
pixmap = 0;
|
||||
}
|
||||
|
||||
bool VAAPI_X_GLX_Interop::ensureGLX()
|
||||
{
|
||||
if (fbc)
|
||||
return true;
|
||||
xdisplay = (Display*)glXGetCurrentDisplay();
|
||||
if (!xdisplay)
|
||||
return false;
|
||||
int xscr = DefaultScreen(xdisplay);
|
||||
const char *glxext = glXQueryExtensionsString((::Display*)xdisplay, xscr);
|
||||
if (!glxext || !strstr(glxext, "GLX_EXT_texture_from_pixmap"))
|
||||
return false;
|
||||
glXBindTexImage = (glXBindTexImage_t)glXGetProcAddressARB((const GLubyte*)"glXBindTexImageEXT");
|
||||
if (!glXBindTexImage) {
|
||||
qWarning("glXBindTexImage not found");
|
||||
return false;
|
||||
}
|
||||
glXReleaseTexImage = (glXReleaseTexImage_t)glXGetProcAddressARB((const GLubyte*)"glXReleaseTexImageEXT");
|
||||
if (!glXReleaseTexImage) {
|
||||
qWarning("glXReleaseTexImage not found");
|
||||
return false;
|
||||
}
|
||||
int attribs[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT, //xbmc
|
||||
GLX_X_RENDERABLE, True, //xbmc
|
||||
GLX_BIND_TO_TEXTURE_RGBA_EXT, True,
|
||||
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
||||
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
|
||||
GLX_Y_INVERTED_EXT, True,
|
||||
GLX_DOUBLEBUFFER, False,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
None
|
||||
};
|
||||
|
||||
int fbcount;
|
||||
GLXFBConfig *fbcs = glXChooseFBConfig((::Display*)xdisplay, xscr, attribs, &fbcount);
|
||||
if (!fbcount) {
|
||||
qWarning("No texture-from-pixmap support");
|
||||
return false;
|
||||
}
|
||||
if (fbcount)
|
||||
fbc = fbcs[0];
|
||||
XFree(fbcs);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VAAPI_X_GLX_Interop::ensurePixmaps(int w, int h)
|
||||
{
|
||||
if (pixmap && width == w && height == h)
|
||||
return true;
|
||||
if (!ensureGLX()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pixmap = XCreatePixmap((::Display*)xdisplay, RootWindow((::Display*)xdisplay, DefaultScreen((::Display*)xdisplay)), w, h, 24);
|
||||
if (!pixmap) {
|
||||
qWarning("VAAPI_X_GLX_Interop could not create pixmap");
|
||||
return false;
|
||||
}
|
||||
|
||||
int attribs[] = {
|
||||
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
|
||||
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
|
||||
GLX_MIPMAP_TEXTURE_EXT, False,
|
||||
None,
|
||||
};
|
||||
glxpixmap = glXCreatePixmap((::Display*)xdisplay, fbc, pixmap, attribs);
|
||||
return true;
|
||||
}
|
||||
|
||||
void* VAAPI_X_GLX_Interop::map(SurfaceType type, const VideoFormat &fmt, void *handle, int plane)
|
||||
{
|
||||
Q_UNUSED(plane);
|
||||
if (!handle)
|
||||
return 0;
|
||||
QMutexLocker lock(&mutex);
|
||||
if (!m_surface)
|
||||
return 0;
|
||||
if (type != GLTextureSurface)
|
||||
return 0;
|
||||
if (!fmt.isRGB()) {
|
||||
return 0;
|
||||
}
|
||||
if (!ensurePixmaps(m_surface->width(), m_surface->height()))
|
||||
return 0;
|
||||
|
||||
VA_ENSURE_TRUE(vaPutSurface(m_surface->display(), m_surface->get(), pixmap
|
||||
, 0, 0, m_surface->width(), m_surface->height()
|
||||
, 0, 0, m_surface->width(), m_surface->height()
|
||||
, NULL, 0, VA_FRAME_PICTURE | VA_SRC_BT709)
|
||||
, NULL);
|
||||
XSync((::Display*)xdisplay, False);
|
||||
VAWARN(vaSyncSurface(m_surface->display(), m_surface->get()));
|
||||
DYGL(glBindTexture(GL_TEXTURE_2D, *((GLuint*)handle)));
|
||||
glXBindTexImage(xdisplay, glxpixmap, GLX_FRONT_EXT, NULL);
|
||||
DYGL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void VAAPI_X_GLX_Interop::unmap(void *handle)
|
||||
{
|
||||
DYGL(glBindTexture(GL_TEXTURE_2D, *((GLuint*)handle)));
|
||||
glXReleaseTexImage(xdisplay, glxpixmap, GLX_FRONT_EXT);
|
||||
DYGL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
}
|
||||
|
||||
#endif //QT_OPENGL_ES_2
|
||||
} //namespace QtAV
|
||||
} //namespace vaapi
|
||||
|
||||
|
||||
@@ -3,28 +3,82 @@
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include "vaapi_helper.h"
|
||||
#include <QtCore/QMutex>
|
||||
#include "QtAV/SurfaceInterop.h"
|
||||
#include "vaapi_helper.h"
|
||||
|
||||
|
||||
#if defined(QT_OPENGL_ES_2)
|
||||
#include <EGL/egl.h>
|
||||
#else
|
||||
#include <GL/glx.h>
|
||||
#endif //defined(QT_OPENGL_ES_2)
|
||||
#ifdef Bool
|
||||
#undef Bool
|
||||
#endif //Bool
|
||||
#ifdef CursorShape
|
||||
#undef CursorShape //used in qvariant and x11
|
||||
#endif //CursorShape
|
||||
#ifdef Status
|
||||
#undef Status // qtextstream
|
||||
#endif //Status
|
||||
namespace QtAV {
|
||||
namespace vaapi {
|
||||
|
||||
// TODO: move create glx surface to decoder, interop only map/unmap, 1 interop per frame
|
||||
// load/resolve symbols only once in decoder and pass a VAAPI_XXX ptr
|
||||
// or use pool
|
||||
class SurfaceInteropVAAPI : public VideoSurfaceInterop, public VAAPI_GLX
|
||||
{
|
||||
public:
|
||||
SurfaceInteropVAAPI();
|
||||
void setSurface(const surface_ptr& surface) { m_surface = surface; }
|
||||
|
||||
void setSurface(const surface_ptr& surface) {
|
||||
QMutexLocker lock(&mutex);
|
||||
m_surface = surface;
|
||||
}
|
||||
// return glx surface
|
||||
surface_glx_ptr createGLXSurface(void* handle);
|
||||
virtual void* map(SurfaceType type, const VideoFormat& fmt, void* handle, int plane);
|
||||
virtual void unmap(void *handle);
|
||||
virtual void* createHandle(SurfaceType type, const VideoFormat& fmt, int plane = 0);
|
||||
private:
|
||||
surface_ptr m_surface;
|
||||
QMap<GLuint*,surface_glx_ptr> glx_surfaces, tmp_surfaces;
|
||||
surface_ptr m_surface;
|
||||
QMutex mutex;
|
||||
};
|
||||
typedef QSharedPointer<SurfaceInteropVAAPI> SurfaceInteropVAAPIPtr;
|
||||
|
||||
#ifndef QT_OPENGL_ES_2
|
||||
class VAAPI_X_GLX_Interop Q_DECL_FINAL: public VideoSurfaceInterop, public VAAPI_X11
|
||||
{
|
||||
public:
|
||||
VAAPI_X_GLX_Interop();
|
||||
~VAAPI_X_GLX_Interop();
|
||||
void setSurface(const surface_ptr& surface) {
|
||||
QMutexLocker lock(&mutex);
|
||||
m_surface = surface;
|
||||
}
|
||||
void* map(SurfaceType type, const VideoFormat& fmt, void* handle, int plane) Q_DECL_OVERRIDE;
|
||||
void unmap(void *handle) Q_DECL_OVERRIDE;
|
||||
private:
|
||||
bool ensureGLX();
|
||||
bool ensurePixmaps(int w, int h);
|
||||
Display *xdisplay;
|
||||
GLXFBConfig fbc;
|
||||
Pixmap pixmap;
|
||||
GLXPixmap glxpixmap;
|
||||
int width, height;
|
||||
surface_ptr m_surface;
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
typedef void (*glXBindTexImage_t)(Display *dpy, GLXDrawable draw, int buffer, int *a);
|
||||
typedef void (*glXReleaseTexImage_t)(Display *dpy, GLXDrawable draw, int buffer);
|
||||
static glXBindTexImage_t glXBindTexImage;
|
||||
static glXReleaseTexImage_t glXReleaseTexImage;
|
||||
};
|
||||
#endif //QT_OPENGL_ES_2
|
||||
} //namespace QtAV
|
||||
} //namespace vaapi
|
||||
//Q_DECLARE_METATYPE(QtAV::vaapi::SurfaceInteropVAAPIPtr)
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
#elif defined(QT_OPENGL_LIB)
|
||||
#include <qgl.h>
|
||||
#else
|
||||
#if !defined(QT_OPENGL_ES_2)
|
||||
#include <GL/gl.h>
|
||||
#endif //!defined(QT_OPENGL_ES_2)
|
||||
#endif
|
||||
#include "utils/SharedPtr.h"
|
||||
|
||||
@@ -117,16 +119,33 @@ private:
|
||||
};
|
||||
class VAAPI_X11 : public dll_helper {
|
||||
public:
|
||||
typedef unsigned long Drawable;
|
||||
typedef VADisplay vaGetDisplay_t(Display *);
|
||||
typedef VAStatus vaPutSurface_t(VADisplay, VASurfaceID, Drawable,
|
||||
short, short, unsigned short, unsigned short,
|
||||
short, short, unsigned short, unsigned short,
|
||||
VARectangle *, unsigned int, unsigned int);
|
||||
VAAPI_X11(): dll_helper("va-x11",1) {
|
||||
fp_vaGetDisplay = (vaGetDisplay_t*)resolve("vaGetDisplay");
|
||||
fp_vaPutSurface = (vaPutSurface_t*)resolve("vaPutSurface");
|
||||
}
|
||||
VADisplay vaGetDisplay(Display *dpy) {
|
||||
assert(fp_vaGetDisplay);
|
||||
return fp_vaGetDisplay(dpy);
|
||||
}
|
||||
VAStatus vaPutSurface (VADisplay dpy, VASurfaceID surface, Drawable draw, /* X Drawable */
|
||||
short srcx, short srcy, unsigned short srcw, unsigned short srch,
|
||||
short destx, short desty, unsigned short destw, unsigned short desth,
|
||||
VARectangle *cliprects, /* client supplied destination clip list */
|
||||
unsigned int number_cliprects, /* number of clip rects in the clip list */
|
||||
unsigned int flags /* PutSurface flags */
|
||||
) {
|
||||
assert(fp_vaPutSurface);
|
||||
return fp_vaPutSurface(dpy, surface, draw, srcx, srcy, srcw, srch, destx, desty, destw, desth, cliprects, number_cliprects, flags);
|
||||
}
|
||||
private:
|
||||
vaGetDisplay_t* fp_vaGetDisplay;
|
||||
vaPutSurface_t* fp_vaPutSurface;
|
||||
};
|
||||
class VAAPI_GLX : public dll_helper {
|
||||
public:
|
||||
@@ -244,9 +263,6 @@ public:
|
||||
VA_ENSURE_TRUE(vaCopySurfaceGLX(display(), m_glx, m_surface->get(), VA_FRAME_PICTURE | VA_SRC_BT709), false);
|
||||
return true;
|
||||
}
|
||||
void sync() {
|
||||
VAWARN(vaSyncSurface(display(), m_surface->get()));
|
||||
}
|
||||
VADisplay display() const { return m_surface->display();}
|
||||
surface_t* surface() { return m_surface.get();}
|
||||
void* glxSurface() { return m_glx;}
|
||||
|
||||
Reference in New Issue
Block a user