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
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <sys/ipc.h>
|
||||
@ -16,7 +15,7 @@ class X11Grabber
|
||||
{
|
||||
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();
|
||||
|
||||
@ -28,7 +27,8 @@ public:
|
||||
|
||||
private:
|
||||
ImageResampler _imageResampler;
|
||||
|
||||
|
||||
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
||||
int _cropLeft;
|
||||
int _cropRight;
|
||||
int _cropTop;
|
||||
@ -41,6 +41,13 @@ private:
|
||||
Display* _x11Display;
|
||||
Window _window;
|
||||
XWindowAttributes _windowAttr;
|
||||
|
||||
Pixmap _pixmap;
|
||||
XRenderPictFormat* _srcFormat;
|
||||
XRenderPictFormat* _dstFormat;
|
||||
XRenderPictureAttributes _pictAttr;
|
||||
Picture _srcPicture;
|
||||
Picture _dstPicture;
|
||||
|
||||
unsigned _screenWidth;
|
||||
unsigned _screenHeight;
|
||||
|
@ -2,19 +2,22 @@
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
// X11 includes
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
// X11Grabber includes
|
||||
#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(),
|
||||
_useXGetImage(useXGetImage),
|
||||
_cropLeft(cropLeft),
|
||||
_cropRight(cropRight),
|
||||
_cropTop(cropTop),
|
||||
_cropBottom(cropBottom),
|
||||
_x11Display(nullptr),
|
||||
_pixmap(None),
|
||||
_srcFormat(nullptr),
|
||||
_dstFormat(nullptr),
|
||||
_srcPicture(None),
|
||||
_dstPicture(None),
|
||||
_screenWidth(0),
|
||||
_screenHeight(0),
|
||||
_croppedWidth(0),
|
||||
@ -23,7 +26,9 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom,
|
||||
{
|
||||
_imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation);
|
||||
_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()
|
||||
@ -38,23 +43,45 @@ X11Grabber::~X11Grabber()
|
||||
void X11Grabber::freeResources()
|
||||
{
|
||||
// Cleanup allocated resources of the X11 grab
|
||||
XShmDetach(_x11Display, &_shminfo);
|
||||
XDestroyImage(_xImage);
|
||||
shmdt(_shminfo.shmaddr);
|
||||
shmctl(_shminfo.shmid, IPC_RMID, 0);
|
||||
if(_XShmAvailable && !_useXGetImage) {
|
||||
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()
|
||||
{
|
||||
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
|
||||
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
|
||||
_croppedWidth, _croppedHeight);
|
||||
if(_XShmAvailable && !_useXGetImage) {
|
||||
_xImage = XShmCreateImage(_x11Display, _windowAttr.visual,
|
||||
_windowAttr.depth, ZPixmap, NULL, &_shminfo,
|
||||
_croppedWidth, _croppedHeight);
|
||||
|
||||
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
||||
_xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
||||
_shminfo.shmaddr = _xImage->data;
|
||||
_shminfo.readOnly = False;
|
||||
|
||||
_shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777);
|
||||
_shminfo.shmaddr = _xImage->data = (char*)shmat(_shminfo.shmid,0,0);
|
||||
_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()
|
||||
@ -72,14 +99,48 @@ bool X11Grabber::Setup()
|
||||
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
std::cerr << "X11GRABBER ERROR: Grab failed" << std::endl;
|
||||
@ -125,6 +186,14 @@ int X11Grabber::updateScreenDimensions()
|
||||
_croppedHeight = _screenHeight - _cropTop - _cropBottom;
|
||||
else
|
||||
_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();
|
||||
|
||||
|
@ -52,6 +52,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||
protoserver
|
||||
x11-grabber
|
||||
${X11_LIBRARIES}
|
||||
${X11_Xrender_LIB}
|
||||
pthread
|
||||
)
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Hyperion-X11 includes
|
||||
#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),
|
||||
_grabber(cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
|
||||
_grabber(useXGetImage, cropLeft, cropRight, cropTop, cropBottom, horizontalPixelDecimation, verticalPixelDecimation)
|
||||
{
|
||||
_timer.setSingleShot(false);
|
||||
_timer.setInterval(grabInterval);
|
||||
|
@ -9,7 +9,7 @@ class X11Wrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
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();
|
||||
|
||||
|
@ -36,6 +36,7 @@ int main(int argc, char ** argv)
|
||||
ParameterSet & parameters = optionParser.getParameters();
|
||||
|
||||
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 & 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)");
|
||||
@ -75,8 +76,10 @@ int main(int argc, char ** argv)
|
||||
|
||||
// Create the X11 grabbing stuff
|
||||
int grabInterval = 1000 / argFps.getValue();
|
||||
bool useXGetImage = argXGetImage.isSet();
|
||||
X11Wrapper x11Wrapper(
|
||||
grabInterval,
|
||||
useXGetImage,
|
||||
argCropLeft.getValue(),
|
||||
argCropRight.getValue(),
|
||||
argCropTop.getValue(),
|
||||
|
Loading…
Reference in New Issue
Block a user