[Spice-devel] [RFC spice-streaming-agent 3/3] gst-plugin: Use Xlib capture helper
Snir Sheriber
ssheribe at redhat.com
Mon Aug 26 08:39:48 UTC 2019
---
src/Makefile.am | 2 ++
src/gst-plugin.cpp | 43 +++++++++++++++++++------------------------
2 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 31b8af1..1de8f9a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -98,6 +98,8 @@ gst_plugin_la_LIBADD = \
gst_plugin_la_SOURCES = \
gst-plugin.cpp \
+ xlib-capture.cpp \
+ xlib-capture.hpp \
$(NULL)
gst_plugin_la_CPPFLAGS = \
diff --git a/src/gst-plugin.cpp b/src/gst-plugin.cpp
index 70bc6c8..83a54d5 100644
--- a/src/gst-plugin.cpp
+++ b/src/gst-plugin.cpp
@@ -17,6 +17,7 @@
#define XLIB_CAPTURE 1
#if XLIB_CAPTURE
#include <gst/app/gstappsrc.h>
+#include "xlib-capture.hpp"
#endif
#include <spice-streaming-agent/plugin.hpp>
@@ -71,6 +72,7 @@ private:
Display *const dpy;
#if XLIB_CAPTURE
void xlib_capture();
+ XlibCapture *xc;
#endif
GstElementUPtr pipeline, capture, sink;
GstSampleUPtr sample;
@@ -281,6 +283,7 @@ GstreamerFrameCapture::GstreamerFrameCapture(const GstreamerEncoderSettings &set
if (!dpy) {
throw std::runtime_error("Unable to initialize X11");
}
+ xc = new XlibCapture(dpy);
pipeline_init(settings);
}
@@ -296,6 +299,7 @@ GstreamerFrameCapture::~GstreamerFrameCapture()
{
free_sample();
gst_element_set_state(pipeline.get(), GST_STATE_NULL);
+ delete xc;
XCloseDisplay(dpy);
}
@@ -305,27 +309,23 @@ void GstreamerFrameCapture::Reset()
}
#if XLIB_CAPTURE
-void free_ximage(gpointer data)
+void free_ximg(gpointer data)
{
- XImage *image = (XImage*)data;
- image->f.destroy_image(image);
+ delete (XImg *) data;
}
void GstreamerFrameCapture::xlib_capture()
{
- int screen = XDefaultScreen(dpy);
- Window win = RootWindow(dpy, screen);
- XWindowAttributes win_info;
- XGetWindowAttributes(dpy, win, &win_info);
+ XImg *image = xc->capture();
+ if (!image) {
+ throw std::runtime_error("Cannot capture from X");
+ }
/* Some encoders cannot handle odd resolution make sure it's even number of pixels */
- cur_width = win_info.width - win_info.width % 2;
- cur_height = win_info.height - win_info.height % 2;
-
- if (cur_width != last_width || cur_height != last_height) {
- last_width = cur_width;
- last_height = cur_height;
+ if (image->new_resolution()) {
+ last_width = cur_width = image->width(); // TODO: drop?
+ last_height = cur_height = image->height();
is_first = true;
gst_app_src_end_of_stream(GST_APP_SRC(capture.get()));
@@ -333,24 +333,19 @@ void GstreamerFrameCapture::xlib_capture()
gst_element_set_state(pipeline.get(), GST_STATE_PLAYING);
}
- XImage *image = XGetImage(dpy, win, 0, 0,
- cur_width, cur_height, AllPlanes, ZPixmap);
- if (!image) {
- throw std::runtime_error("Cannot capture from X");
- }
+ GstBufferUPtr buf(gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS, image->get_data(),
+ image->data_size(), 0,
+ image->data_size(), image,
+ free_ximg));
- GstBufferUPtr buf(gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS, image->data,
- image->height * image->bytes_per_line, 0,
- image->height * image->bytes_per_line, image,
- free_ximage));
if (!buf) {
throw std::runtime_error("Failed to wrap image in gstreamer buffer");
}
GstCapsUPtr caps(gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, "BGRx",
- "width", G_TYPE_INT, image->width,
- "height", G_TYPE_INT, image->height,
+ "width", G_TYPE_INT, image->width(),
+ "height", G_TYPE_INT, image->height(),
"framerate", GST_TYPE_FRACTION, settings.fps, 1,
nullptr));
--
2.21.0
More information about the Spice-devel
mailing list