mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
XRender support for X11 Grabber (#649)
* Update X11Grabber.h * Update X11Grabber.cpp * Update CMakeLists.txt * Update hyperion-x11.cpp * Update X11Wrapper.cpp * Update X11Wrapper.h Former-commit-id: d2f7cb0e22248a0c2963bf53728f2e0d7bb9dee1
This commit is contained in:
parent
84a9125542
commit
409ef383f3
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
// X11 includes
|
// X11 includes
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <X11/extensions/XShm.h>
|
#include <X11/extensions/XShm.h>
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
@ -16,7 +15,7 @@ class X11Grabber
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
||||||
|
|
||||||
virtual ~X11Grabber();
|
virtual ~X11Grabber();
|
||||||
|
|
||||||
@ -29,6 +28,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
ImageResampler _imageResampler;
|
ImageResampler _imageResampler;
|
||||||
|
|
||||||
|
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
||||||
int _cropLeft;
|
int _cropLeft;
|
||||||
int _cropRight;
|
int _cropRight;
|
||||||
int _cropTop;
|
int _cropTop;
|
||||||
@ -42,6 +42,13 @@ private:
|
|||||||
Window _window;
|
Window _window;
|
||||||
XWindowAttributes _windowAttr;
|
XWindowAttributes _windowAttr;
|
||||||
|
|
||||||
|
Pixmap _pixmap;
|
||||||
|
XRenderPictFormat* _srcFormat;
|
||||||
|
XRenderPictFormat* _dstFormat;
|
||||||
|
XRenderPictureAttributes _pictAttr;
|
||||||
|
Picture _srcPicture;
|
||||||
|
Picture _dstPicture;
|
||||||
|
|
||||||
unsigned _screenWidth;
|
unsigned _screenWidth;
|
||||||
unsigned _screenHeight;
|
unsigned _screenHeight;
|
||||||
unsigned _croppedWidth;
|
unsigned _croppedWidth;
|
||||||
|
@ -2,19 +2,22 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// X11 includes
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
|
|
||||||
// X11Grabber includes
|
// X11Grabber includes
|
||||||
#include <grabber/X11Grabber.h>
|
#include <grabber/X11Grabber.h>
|
||||||
|
|
||||||
X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
|
X11Grabber::X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
|
||||||
_imageResampler(),
|
_imageResampler(),
|
||||||
|
_useXGetImage(useXGetImage),
|
||||||
_cropLeft(cropLeft),
|
_cropLeft(cropLeft),
|
||||||
_cropRight(cropRight),
|
_cropRight(cropRight),
|
||||||
_cropTop(cropTop),
|
_cropTop(cropTop),
|
||||||
_cropBottom(cropBottom),
|
_cropBottom(cropBottom),
|
||||||
_x11Display(nullptr),
|
_x11Display(nullptr),
|
||||||
|
_pixmap(None),
|
||||||
|
_srcFormat(nullptr),
|
||||||
|
_dstFormat(nullptr),
|
||||||
|
_srcPicture(None),
|
||||||
|
_dstPicture(None),
|
||||||
_screenWidth(0),
|
_screenWidth(0),
|
||||||
_screenHeight(0),
|
_screenHeight(0),
|
||||||
_croppedWidth(0),
|
_croppedWidth(0),
|
||||||
@ -23,7 +26,9 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom,
|
|||||||
{
|
{
|
||||||
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
|
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
|
||||||
_imageResampler.setVerticalPixelDecimation(verticalPixelDecimation);
|
_imageResampler.setVerticalPixelDecimation(verticalPixelDecimation);
|
||||||
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage
|
_imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage or XGetImage
|
||||||
|
memset(&_pictAttr, 0, sizeof(_pictAttr));
|
||||||
|
_pictAttr.repeat = RepeatNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
X11Grabber::~X11Grabber()
|
X11Grabber::~X11Grabber()
|
||||||
@ -38,23 +43,45 @@ X11Grabber::~X11Grabber()
|
|||||||
void X11Grabber::freeResources()
|
void X11Grabber::freeResources()
|
||||||
{
|
{
|
||||||
// Cleanup allocated resources of the X11 grab
|
// Cleanup allocated resources of the X11 grab
|
||||||
XShmDetach(_x11Display, &_shminfo);
|
|
||||||
XDestroyImage(_xImage);
|
XDestroyImage(_xImage);
|
||||||
shmdt(_shminfo.shmaddr);
|
if(_XShmAvailable && !_useXGetImage) {
|
||||||
shmctl(_shminfo.shmid, IPC_RMID, 0);
|
XShmDetach(_x11Display, &_shminfo);
|
||||||
|
shmdt(_shminfo.shmaddr);
|
||||||
|
shmctl(_shminfo.shmid, IPC_RMID, 0);
|
||||||
|
}
|
||||||
|
if (_XRenderAvailable && !_useXGetImage) {
|
||||||
|
XRenderFreePicture(_x11Display, _srcPicture);
|
||||||
|
XRenderFreePicture(_x11Display, _dstPicture);
|
||||||
|
XFreePixmap(_x11Display, _pixmap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11Grabber::setupResources()
|
void X11Grabber::setupResources()
|
||||||
{
|
{
|
||||||
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
|
if(_XShmAvailable && !_useXGetImage) {
|
||||||
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
|
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
|
||||||
_croppedWidth, _croppedHeight);
|
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
|
||||||
|
_croppedWidth, _croppedHeight);
|
||||||
|
|
||||||
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
||||||
_shminfo.shmaddr = _xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
_xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
||||||
_shminfo.readOnly = False;
|
_shminfo.shmaddr = _xImage->data;
|
||||||
|
_shminfo.readOnly = False;
|
||||||
|
|
||||||
XShmAttach(_x11Display, &_shminfo);
|
XShmAttach(_x11Display, &_shminfo);
|
||||||
|
}
|
||||||
|
if (_XRenderAvailable && !_useXGetImage) {
|
||||||
|
if(_XShmPixmapAvailable) {
|
||||||
|
_pixmap = XShmCreatePixmap(_x11Display, _window, _xImage->data, &_shminfo, _croppedWidth, _croppedHeight, _windowAttr.depth);
|
||||||
|
} else {
|
||||||
|
_pixmap = XCreatePixmap(_x11Display, _window, _croppedWidth, _croppedHeight, _windowAttr.depth);
|
||||||
|
}
|
||||||
|
_srcFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual);
|
||||||
|
_dstFormat = XRenderFindVisualFormat(_x11Display, _windowAttr.visual);
|
||||||
|
_srcPicture = XRenderCreatePicture(_x11Display, _window, _srcFormat, CPRepeat, &_pictAttr);
|
||||||
|
_dstPicture = XRenderCreatePicture(_x11Display, _pixmap, _dstFormat, CPRepeat, &_pictAttr);
|
||||||
|
XRenderSetPictureFilter(_x11Display, _srcPicture, "bilinear", NULL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X11Grabber::Setup()
|
bool X11Grabber::Setup()
|
||||||
@ -72,14 +99,48 @@ bool X11Grabber::Setup()
|
|||||||
|
|
||||||
_window = DefaultRootWindow(_x11Display);
|
_window = DefaultRootWindow(_x11Display);
|
||||||
|
|
||||||
|
int dummy, pixmaps_supported;
|
||||||
|
|
||||||
|
_XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy);
|
||||||
|
_XShmAvailable = XShmQueryExtension(_x11Display);
|
||||||
|
XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported);
|
||||||
|
_XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image<ColorRgb> & X11Grabber::grab()
|
Image<ColorRgb> & X11Grabber::grab()
|
||||||
{
|
{
|
||||||
updateScreenDimensions();
|
if (_XRenderAvailable && !_useXGetImage) {
|
||||||
|
XRenderComposite( _x11Display, // *dpy,
|
||||||
|
PictOpSrc, // op,
|
||||||
|
_srcPicture, // src
|
||||||
|
None, // mask
|
||||||
|
_dstPicture, // dst
|
||||||
|
_cropLeft, // src_x
|
||||||
|
_cropTop, // src_y
|
||||||
|
0, // mask_x
|
||||||
|
0, // mask_y
|
||||||
|
0, // dst_x
|
||||||
|
0, // dst_y
|
||||||
|
_croppedWidth, // width
|
||||||
|
_croppedHeight); // height
|
||||||
|
|
||||||
|
XSync(_x11Display, False);
|
||||||
|
|
||||||
|
if (_XShmAvailable) {
|
||||||
|
XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes);
|
||||||
|
} else {
|
||||||
|
_xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_XShmAvailable && !_useXGetImage) {
|
||||||
|
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes);
|
||||||
|
} else {
|
||||||
|
_xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF);
|
|
||||||
if (_xImage == nullptr)
|
if (_xImage == nullptr)
|
||||||
{
|
{
|
||||||
std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl;
|
std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl;
|
||||||
@ -126,6 +187,14 @@ int X11Grabber::updateScreenDimensions()
|
|||||||
else
|
else
|
||||||
_croppedHeight = _screenHeight;
|
_croppedHeight = _screenHeight;
|
||||||
|
|
||||||
|
std::cout << "X11GRABBER INFO: Using ";
|
||||||
|
|
||||||
|
if (_XRenderAvailable && !_useXGetImage) {
|
||||||
|
std::cout << "XRender for grabbing" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "XGetImage for grabbing" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
setupResources();
|
setupResources();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -52,6 +52,7 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
protoserver
|
protoserver
|
||||||
x11-grabber
|
x11-grabber
|
||||||
${X11_LIBRARIES}
|
${X11_LIBRARIES}
|
||||||
|
${X11_Xrender_LIB}
|
||||||
pthread
|
pthread
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
// Hyperion-X11 includes
|
// Hyperion-X11 includes
|
||||||
#include "X11Wrapper.h"
|
#include "X11Wrapper.h"
|
||||||
|
|
||||||
X11Wrapper::X11Wrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
|
X11Wrapper::X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation) :
|
||||||
_timer(this),
|
_timer(this),
|
||||||
_grabber(cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
|
_grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
|
||||||
{
|
{
|
||||||
_timer.setSingleShot(false);
|
_timer.setSingleShot(false);
|
||||||
_timer.setInterval(grabInterval);
|
_timer.setInterval(grabInterval);
|
||||||
|
@ -9,7 +9,7 @@ class X11Wrapper : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
X11Wrapper(int grabInterval, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
X11Wrapper(int grabInterval, bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
||||||
|
|
||||||
const Image<ColorRgb> & getScreenshot();
|
const Image<ColorRgb> & getScreenshot();
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ int main(int argc, char ** argv)
|
|||||||
ParameterSet & parameters = optionParser.getParameters();
|
ParameterSet & parameters = optionParser.getParameters();
|
||||||
|
|
||||||
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default: 10]");
|
IntParameter & argFps = parameters.add<IntParameter> ('f', "framerate", "Capture frame rate [default: 10]");
|
||||||
|
SwitchParameter<> & argXGetImage = parameters.add<SwitchParameter<>> ('x', "xgetimage", "Use XGetImage instead of XRender");
|
||||||
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
|
IntParameter & argCropWidth = parameters.add<IntParameter> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: 0]");
|
||||||
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
|
IntParameter & argCropHeight = parameters.add<IntParameter> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: 0]");
|
||||||
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
IntParameter & argCropLeft = parameters.add<IntParameter> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
|
||||||
@ -75,8 +76,10 @@ int main(int argc, char ** argv)
|
|||||||
|
|
||||||
// Create the X11 grabbing stuff
|
// Create the X11 grabbing stuff
|
||||||
int grabInterval = 1000 / argFps.getValue();
|
int grabInterval = 1000 / argFps.getValue();
|
||||||
|
bool useXGetImage = argXGetImage.isSet();
|
||||||
X11Wrapper x11Wrapper(
|
X11Wrapper x11Wrapper(
|
||||||
grabInterval,
|
grabInterval,
|
||||||
|
useXGetImage,
|
||||||
argCropLeft.getValue(),
|
argCropLeft.getValue(),
|
||||||
argCropRight.getValue(),
|
argCropRight.getValue(),
|
||||||
argCropTop.getValue(),
|
argCropTop.getValue(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user