[RFC,spice-streaming-agent,3/3] gst-plugin: Use Xlib capture helper

Submitted by Snir Sheriber on Aug. 26, 2019, 8:39 a.m.

Details

Message ID 20190826083948.29309-3-ssheribe@redhat.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Spice

Not browsing as part of any series.

Commit Message

Snir Sheriber Aug. 26, 2019, 8:39 a.m.
---
 src/Makefile.am    |  2 ++
 src/gst-plugin.cpp | 43 +++++++++++++++++++------------------------
 2 files changed, 21 insertions(+), 24 deletions(-)

Patch hide | download patch | download mbox

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));