diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2017-11-21 18:02:46 +0000 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2017-11-23 11:39:01 +0000 |
commit | 1deb0dd4f76897e3476189f925d7a3f07288ed76 (patch) | |
tree | 19436406270e62ecffa1d7e2f4d07e469b90bffd | |
parent | 3d2699ec83122e00eef0c523c084aa9952515280 (diff) |
Separate SpiceStream into new files
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/spice-stream.cpp | 162 | ||||
-rw-r--r-- | src/spice-stream.hpp | 57 | ||||
-rw-r--r-- | src/spice-streaming-agent.cpp | 184 |
4 files changed, 223 insertions, 182 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 35efa49..ef508f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,4 +58,6 @@ spice_streaming_agent_SOURCES = \ mjpeg-fallback.cpp \ jpeg.cpp \ jpeg.hpp \ + spice-stream.cpp \ + spice-stream.hpp \ $(NULL) diff --git a/src/spice-stream.cpp b/src/spice-stream.cpp new file mode 100644 index 0000000..3aa951c --- /dev/null +++ b/src/spice-stream.cpp @@ -0,0 +1,162 @@ +/* Utility to manage registration of plugins compiled statically + * + * \copyright + * Copyright 2017 Red Hat Inc. All rights reserved. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <syslog.h> +#include <string.h> +#include <memory> +#include <spice/stream-device.h> +#include <spice/enums.h> + +#include "spice-stream.hpp" + +// FIXME +extern int streaming_requested; + +using namespace SpiceStreamingAgent; + +struct SpiceStreamFormatMessage +{ + StreamDevHeader hdr; + StreamMsgFormat msg; +}; + +struct SpiceStreamDataMessage +{ + StreamDevHeader hdr; + StreamMsgData msg; +}; + +int SpiceStream::read_command() +{ + StreamDevHeader hdr; + uint8_t msg[64]; + int n; + + std::lock_guard<std::mutex> stream_guard(stream_mtx); + n = read(streamfd, &hdr, sizeof(hdr)); + if (n != sizeof(hdr)) { + syslog(LOG_WARNING, + "read command from device FAILED -- read %d expected %lu\n", + n, sizeof(hdr)); + return -1; + } + if (hdr.protocol_version != STREAM_DEVICE_PROTOCOL) { + syslog(LOG_WARNING, "BAD VERSION %d (expected is %d)\n", hdr.protocol_version, + STREAM_DEVICE_PROTOCOL); + return 0; // return -1; -- fail over this ? + } + if (hdr.type != STREAM_TYPE_START_STOP) { + syslog(LOG_WARNING, "UNKNOWN msg of type %d\n", hdr.type); + return 0; // return -1; + } + if (hdr.size >= sizeof(msg)) { + syslog(LOG_WARNING, + "msg size (%d) is too long (longer than %lu)\n", + hdr.size, sizeof(msg)); + return 0; // return -1; + } + n = read(streamfd, &msg, hdr.size); + if (n != hdr.size) { + syslog(LOG_WARNING, + "read command from device FAILED -- read %d expected %d\n", + n, hdr.size); + return -1; + } + streaming_requested = msg[0]; /* num_codecs */ + syslog(LOG_INFO, "GOT START_STOP message -- request to %s streaming\n", + streaming_requested ? "START" : "STOP"); + return 1; +} + +int SpiceStream::send_format(unsigned w, unsigned h, unsigned c) +{ + + SpiceStreamFormatMessage msg; + const size_t msgsize = sizeof(msg); + const size_t hdrsize = sizeof(msg.hdr); + memset(&msg, 0, msgsize); + msg.hdr.protocol_version = STREAM_DEVICE_PROTOCOL; + msg.hdr.type = STREAM_TYPE_FORMAT; + msg.hdr.size = msgsize - hdrsize; /* includes only the body? */ + msg.msg.width = w; + msg.msg.height = h; + msg.msg.codec = c; + syslog(LOG_DEBUG, "writing format\n"); + std::lock_guard<std::mutex> stream_guard(stream_mtx); + if (write_all(&msg, msgsize) != msgsize) { + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int SpiceStream::send_frame(const void *buf, const unsigned size) +{ + SpiceStreamDataMessage msg; + const size_t msgsize = sizeof(msg); + ssize_t n; + + memset(&msg, 0, msgsize); + msg.hdr.protocol_version = STREAM_DEVICE_PROTOCOL; + msg.hdr.type = STREAM_TYPE_DATA; + msg.hdr.size = size; /* includes only the body? */ + std::lock_guard<std::mutex> stream_guard(stream_mtx); + n = write_all(&msg, msgsize); + syslog(LOG_DEBUG, + "wrote %ld bytes of header of data msg with frame of size %u bytes\n", + n, msg.hdr.size); + if (n != msgsize) { + syslog(LOG_WARNING, "write_all header: wrote %ld expected %lu\n", + n, msgsize); + return EXIT_FAILURE; + } + n = write_all(buf, size); + syslog(LOG_DEBUG, "wrote data msg body of size %ld\n", n); + if (n != size) { + syslog(LOG_WARNING, "write_all header: wrote %ld expected %u\n", + n, size); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +void SpiceStream::send_cursor(unsigned width, unsigned height, int hotspot_x, int hotspot_y, + std::function<void(uint32_t *)> fill_cursor) +{ + if (width >= STREAM_MSG_CURSOR_SET_MAX_WIDTH || + height >= STREAM_MSG_CURSOR_SET_MAX_HEIGHT) + return; + + size_t cursor_size = + sizeof(StreamDevHeader) + sizeof(StreamMsgCursorSet) + + width * height * sizeof(uint32_t); + std::unique_ptr<uint8_t[]> msg(new uint8_t[cursor_size]); + + StreamDevHeader &dev_hdr(*reinterpret_cast<StreamDevHeader*>(msg.get())); + memset(&dev_hdr, 0, sizeof(dev_hdr)); + dev_hdr.protocol_version = STREAM_DEVICE_PROTOCOL; + dev_hdr.type = STREAM_TYPE_CURSOR_SET; + dev_hdr.size = cursor_size - sizeof(StreamDevHeader); + + StreamMsgCursorSet &cursor_msg(*reinterpret_cast<StreamMsgCursorSet *>(msg.get() + sizeof(StreamDevHeader))); + memset(&cursor_msg, 0, sizeof(cursor_msg)); + + cursor_msg.type = SPICE_CURSOR_TYPE_ALPHA; + cursor_msg.width = width; + cursor_msg.height = height; + cursor_msg.hot_spot_x = hotspot_x; + cursor_msg.hot_spot_y = hotspot_y; + + uint32_t *pixels = reinterpret_cast<uint32_t *>(cursor_msg.data); + fill_cursor(pixels); + + std::lock_guard<std::mutex> stream_guard(stream_mtx); + write_all(msg.get(), cursor_size); +} + diff --git a/src/spice-stream.hpp b/src/spice-stream.hpp new file mode 100644 index 0000000..5ef8cb5 --- /dev/null +++ b/src/spice-stream.hpp @@ -0,0 +1,57 @@ +/* Class to manage the streaming system device + * + * \copyright + * Copyright 2017 Red Hat Inc. All rights reserved. + */ +#ifndef SPICE_STREAMING_AGENT_SPICE_STREAM_HPP +#define SPICE_STREAMING_AGENT_SPICE_STREAM_HPP + +#include <unistd.h> +#include <fcntl.h> +#include <mutex> +#include <functional> + +#include "file-util.h" + +namespace SpiceStreamingAgent { + +class SpiceStream +{ +public: + SpiceStream(const char *name): streamfd(open(name, O_RDWR)) + { + if (streamfd < 0) + throw std::runtime_error("failed to open streaming device"); + } + ~SpiceStream() + { + close(streamfd); + } + +public: + /*! + * Return file descriptor to poll from + */ + int eventFd() const { return streamfd; } + int read_command(); + int send_format(unsigned w, unsigned h, unsigned c); + int send_frame(const void *buf, const unsigned size); + void send_cursor(unsigned width, unsigned height, int hotspot_x, int hotspot_y, + std::function<void(uint32_t *)> fill_cursor); + +private: + size_t write_all(const void *buf, const size_t len) { + return ::write_all(streamfd, buf, len); + } + + SpiceStream(const SpiceStream &) = delete; + SpiceStream &operator=(const SpiceStream &) = delete; + +private: + std::mutex stream_mtx; + int streamfd; +}; + +} + +#endif diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp index 7e2ec54..d18e8be 100644 --- a/src/spice-streaming-agent.cpp +++ b/src/spice-streaming-agent.cpp @@ -19,78 +19,25 @@ #include <exception> #include <stdexcept> #include <memory> -#include <mutex> #include <thread> #include <vector> -#include <functional> #include <X11/Xlib.h> #include <X11/extensions/Xfixes.h> -#include <spice/stream-device.h> -#include <spice/enums.h> - #include <spice-streaming-agent/frame-capture.hpp> #include <spice-streaming-agent/plugin.hpp> #include "hexdump.h" #include "file-util.h" #include "concrete-agent.hpp" +#include "spice-stream.hpp" using namespace std; using namespace SpiceStreamingAgent; static ConcreteAgent agent; -struct SpiceStreamFormatMessage -{ - StreamDevHeader hdr; - StreamMsgFormat msg; -}; - -struct SpiceStreamDataMessage -{ - StreamDevHeader hdr; - StreamMsgData msg; -}; - -class SpiceStream -{ -public: - SpiceStream(const char *name): streamfd(open(name, O_RDWR)) - { - if (streamfd < 0) - throw std::runtime_error("failed to open streaming device"); - } - ~SpiceStream() - { - close(streamfd); - } - -public: - /*! - * Return file descriptor to poll from - */ - int eventFd() const { return streamfd; } - int read_command(); - int send_format(unsigned w, unsigned h, unsigned c); - int send_frame(const void *buf, const unsigned size); - void send_cursor(unsigned width, unsigned height, int hotspot_x, int hotspot_y, - std::function<void(uint32_t *)> fill_cursor); - -private: - size_t write_all(const void *buf, const size_t len) { - return ::write_all(streamfd, buf, len); - } - - SpiceStream(const SpiceStream &) = delete; - SpiceStream &operator=(const SpiceStream &) = delete; - -private: - std::mutex stream_mtx; - int streamfd; -}; - -static int streaming_requested; +int streaming_requested; static bool quit; static bool stdin_ok; static int log_binary = 0; @@ -141,48 +88,6 @@ static int read_command_from_stdin(void) return 1; } -int SpiceStream::read_command() -{ - StreamDevHeader hdr; - uint8_t msg[64]; - int n; - - std::lock_guard<std::mutex> stream_guard(stream_mtx); - n = read(streamfd, &hdr, sizeof(hdr)); - if (n != sizeof(hdr)) { - syslog(LOG_WARNING, - "read command from device FAILED -- read %d expected %lu\n", - n, sizeof(hdr)); - return -1; - } - if (hdr.protocol_version != STREAM_DEVICE_PROTOCOL) { - syslog(LOG_WARNING, "BAD VERSION %d (expected is %d)\n", hdr.protocol_version, - STREAM_DEVICE_PROTOCOL); - return 0; // return -1; -- fail over this ? - } - if (hdr.type != STREAM_TYPE_START_STOP) { - syslog(LOG_WARNING, "UNKNOWN msg of type %d\n", hdr.type); - return 0; // return -1; - } - if (hdr.size >= sizeof(msg)) { - syslog(LOG_WARNING, - "msg size (%d) is too long (longer than %lu)\n", - hdr.size, sizeof(msg)); - return 0; // return -1; - } - n = read(streamfd, &msg, hdr.size); - if (n != hdr.size) { - syslog(LOG_WARNING, - "read command from device FAILED -- read %d expected %d\n", - n, hdr.size); - return -1; - } - streaming_requested = msg[0]; /* num_codecs */ - syslog(LOG_INFO, "GOT START_STOP message -- request to %s streaming\n", - streaming_requested ? "START" : "STOP"); - return 1; -} - static int read_command(SpiceStream &stream, bool blocking) { int fd, n=1; @@ -205,57 +110,6 @@ static int read_command(SpiceStream &stream, bool blocking) return n; } -int SpiceStream::send_format(unsigned w, unsigned h, unsigned c) -{ - - SpiceStreamFormatMessage msg; - const size_t msgsize = sizeof(msg); - const size_t hdrsize = sizeof(msg.hdr); - memset(&msg, 0, msgsize); - msg.hdr.protocol_version = STREAM_DEVICE_PROTOCOL; - msg.hdr.type = STREAM_TYPE_FORMAT; - msg.hdr.size = msgsize - hdrsize; /* includes only the body? */ - msg.msg.width = w; - msg.msg.height = h; - msg.msg.codec = c; - syslog(LOG_DEBUG, "writing format\n"); - std::lock_guard<std::mutex> stream_guard(stream_mtx); - if (write_all(&msg, msgsize) != msgsize) { - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - -int SpiceStream::send_frame(const void *buf, const unsigned size) -{ - SpiceStreamDataMessage msg; - const size_t msgsize = sizeof(msg); - ssize_t n; - - memset(&msg, 0, msgsize); - msg.hdr.protocol_version = STREAM_DEVICE_PROTOCOL; - msg.hdr.type = STREAM_TYPE_DATA; - msg.hdr.size = size; /* includes only the body? */ - std::lock_guard<std::mutex> stream_guard(stream_mtx); - n = write_all(&msg, msgsize); - syslog(LOG_DEBUG, - "wrote %ld bytes of header of data msg with frame of size %u bytes\n", - n, msg.hdr.size); - if (n != msgsize) { - syslog(LOG_WARNING, "write_all header: wrote %ld expected %lu\n", - n, msgsize); - return EXIT_FAILURE; - } - n = write_all(buf, size); - syslog(LOG_DEBUG, "wrote data msg body of size %ld\n", n); - if (n != size) { - syslog(LOG_WARNING, "write_all header: wrote %ld expected %u\n", - n, size); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - /* returns current time in micro-seconds */ static uint64_t get_time(void) { @@ -302,40 +156,6 @@ static void usage(const char *progname) exit(1); } -void SpiceStream::send_cursor(unsigned width, unsigned height, int hotspot_x, int hotspot_y, - std::function<void(uint32_t *)> fill_cursor) -{ - if (width >= STREAM_MSG_CURSOR_SET_MAX_WIDTH || - height >= STREAM_MSG_CURSOR_SET_MAX_HEIGHT) - return; - - size_t cursor_size = - sizeof(StreamDevHeader) + sizeof(StreamMsgCursorSet) + - width * height * sizeof(uint32_t); - std::unique_ptr<uint8_t[]> msg(new uint8_t[cursor_size]); - - StreamDevHeader &dev_hdr(*reinterpret_cast<StreamDevHeader*>(msg.get())); - memset(&dev_hdr, 0, sizeof(dev_hdr)); - dev_hdr.protocol_version = STREAM_DEVICE_PROTOCOL; - dev_hdr.type = STREAM_TYPE_CURSOR_SET; - dev_hdr.size = cursor_size - sizeof(StreamDevHeader); - - StreamMsgCursorSet &cursor_msg(*reinterpret_cast<StreamMsgCursorSet *>(msg.get() + sizeof(StreamDevHeader))); - memset(&cursor_msg, 0, sizeof(cursor_msg)); - - cursor_msg.type = SPICE_CURSOR_TYPE_ALPHA; - cursor_msg.width = width; - cursor_msg.height = height; - cursor_msg.hot_spot_x = hotspot_x; - cursor_msg.hot_spot_y = hotspot_y; - - uint32_t *pixels = reinterpret_cast<uint32_t *>(cursor_msg.data); - fill_cursor(pixels); - - std::lock_guard<std::mutex> stream_guard(stream_mtx); - write_all(msg.get(), cursor_size); -} - static void cursor_changes(Display *display, int event_base, SpiceStream *stream) { unsigned long last_serial = 0; |