in development
This commit is contained in:
parent
88a35b2316
commit
caa465a3eb
|
|
@ -1,20 +1,25 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
|
#include <msgpack.h>
|
||||||
|
|
||||||
#include "glib-object.h"
|
#include "glib-object.h"
|
||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "gst/gstbuffer.h"
|
#include "gst/gstbuffer.h"
|
||||||
#include "gst/gstinfo.h"
|
#include "gst/gstinfo.h"
|
||||||
|
#include "gst/gstobject.h"
|
||||||
#include "gst/gstparamspecs.h"
|
#include "gst/gstparamspecs.h"
|
||||||
#include "gst/gstvalue.h"
|
#include "gst/gstvalue.h"
|
||||||
#include "gst/video/video-format.h"
|
#include "gst/video/video-format.h"
|
||||||
|
|
@ -36,10 +41,7 @@ enum {
|
||||||
N_PROPERTIES,
|
N_PROPERTIES,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *properties[N_PROPERTIES] = {
|
// Gstreamer related
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean gst_westonimagesrc_start(GstBaseSrc *basesrc);
|
static gboolean gst_westonimagesrc_start(GstBaseSrc *basesrc);
|
||||||
static gboolean gst_westonimagesrc_stop(GstBaseSrc *basesrc);
|
static gboolean gst_westonimagesrc_stop(GstBaseSrc *basesrc);
|
||||||
static GstFlowReturn gst_westonimagesrc_create(GstBaseSrc *basesrc, guint64 offset, guint size, GstBuffer **buf);
|
static GstFlowReturn gst_westonimagesrc_create(GstBaseSrc *basesrc, guint64 offset, guint size, GstBuffer **buf);
|
||||||
|
|
@ -55,6 +57,7 @@ static gboolean gst_westonimagesrc_negotiate(GstBaseSrc *basesrc);
|
||||||
|
|
||||||
G_DEFINE_TYPE(GstWestonImageSrc, gst_westonimagesrc, GST_TYPE_BASE_SRC);
|
G_DEFINE_TYPE(GstWestonImageSrc, gst_westonimagesrc, GST_TYPE_BASE_SRC);
|
||||||
|
|
||||||
|
// Weston related
|
||||||
static void weston_display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, int width, int height, int refresh);
|
static void weston_display_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, int width, int height, int refresh);
|
||||||
static void weston_display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, int physical_width, int physical_height, int subpixel, const char *make,
|
static void weston_display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, int physical_width, int physical_height, int subpixel, const char *make,
|
||||||
const char *model, int transform);
|
const char *model, int transform);
|
||||||
|
|
@ -65,12 +68,159 @@ static void weston_handle_global_remove(void *data, struct wl_registry *registry
|
||||||
static void weston_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { /* XXX: unimplemented */ }
|
static void weston_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { /* XXX: unimplemented */ }
|
||||||
static struct wl_buffer *weston_screenshot_create_shm_buffer(int width, int height, void **data_out, struct wl_shm *shm);
|
static struct wl_buffer *weston_screenshot_create_shm_buffer(int width, int height, void **data_out, struct wl_shm *shm);
|
||||||
static int weston_screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list);
|
static int weston_screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list);
|
||||||
static void weston_capture_frame();
|
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {weston_display_handle_geometry, weston_display_handle_mode};
|
static const struct wl_output_listener output_listener = {weston_display_handle_geometry, weston_display_handle_mode};
|
||||||
static const struct weston_screenshooter_listener screenshooter_listener = {weston_screenshot_done};
|
static const struct weston_screenshooter_listener screenshooter_listener = {weston_screenshot_done};
|
||||||
static const struct wl_registry_listener registry_listener = {weston_handle_global, weston_handle_global_remove};
|
static const struct wl_registry_listener registry_listener = {weston_handle_global, weston_handle_global_remove};
|
||||||
|
|
||||||
|
// Remote control
|
||||||
|
static void rcontrol_init(GstWestonImageSrc *westonimagesrc);
|
||||||
|
static void rcontrol_init_uinput(GstWestonImageSrc *westonimagesrc);
|
||||||
|
static void rcontrol_init_server(GstWestonImageSrc *westonimagesrc);
|
||||||
|
static gpointer rcontrol_listener_thread(gpointer data);
|
||||||
|
static void rcontrol_destroy(GstWestonImageSrc *westonimagesrc);
|
||||||
|
static void rcontrol_emit(GstWestonImageSrc *westonimagesrc, int fd, int type, int code, int value);
|
||||||
|
|
||||||
|
static void rcontrol_emit(GstWestonImageSrc *westonimagesrc, int fd, int type, int code, int value) {
|
||||||
|
struct input_event ev;
|
||||||
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
gettimeofday(&ev.time, NULL);
|
||||||
|
ev.type = type;
|
||||||
|
ev.code = code;
|
||||||
|
ev.value = value;
|
||||||
|
|
||||||
|
if (write(fd, &ev, sizeof(ev)) < 0) {
|
||||||
|
GST_WARNING_OBJECT(westonimagesrc, "write() input_event %i:%i:%i:%i failed", fd, type, code, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcontrol_init(GstWestonImageSrc *westonimagesrc) {
|
||||||
|
rcontrol_init_uinput(westonimagesrc);
|
||||||
|
rcontrol_init_server(westonimagesrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer rcontrol_listener_thread(gpointer data) {
|
||||||
|
const uint16_t port = 7755u;
|
||||||
|
GstWestonImageSrc *westonimagesrc = data;
|
||||||
|
g_mutex_lock(&westonimagesrc->lock);
|
||||||
|
|
||||||
|
westonimagesrc->udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (westonimagesrc->udp_socket_fd < 0) {
|
||||||
|
GST_WARNING_OBJECT(westonimagesrc, "socket() UDP socket creation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
if (bind(westonimagesrc->udp_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
GST_ERROR_OBJECT(westonimagesrc, "bind() UDP socket binding failed");
|
||||||
|
close(westonimagesrc->udp_socket_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_INFO_OBJECT(westonimagesrc, "UDP listener started on port %d\n", port);
|
||||||
|
g_mutex_unlock(&westonimagesrc->lock);
|
||||||
|
|
||||||
|
char buf[1024u];
|
||||||
|
msgpack_zone mempool;
|
||||||
|
msgpack_zone_init(&mempool, sizeof(buf));
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
struct sockaddr_in src;
|
||||||
|
socklen_t srclen = sizeof(src);
|
||||||
|
ssize_t len = recvfrom(westonimagesrc->udp_socket_fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&src, &srclen);
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
GST_WARNING_OBJECT(westonimagesrc, "recvfrom() failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
msgpack_object deserialized;
|
||||||
|
msgpack_unpack(buf, sizeof(buf), NULL, &mempool, &deserialized);
|
||||||
|
GST_INFO_OBJECT(westonimagesrc, "[UDP %s:%d]: %s\r\n", inet_ntoa(src.sin_addr), ntohs(src.sin_port), deserialized.via.str.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(westonimagesrc->udp_socket_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcontrol_init_server(GstWestonImageSrc *westonimagesrc) {
|
||||||
|
g_mutex_lock(&westonimagesrc->lock);
|
||||||
|
westonimagesrc->listener_thread = g_thread_new("UDP listener thread", rcontrol_listener_thread, westonimagesrc);
|
||||||
|
g_mutex_unlock(&westonimagesrc->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcontrol_init_uinput(GstWestonImageSrc *westonimagesrc) {
|
||||||
|
struct uinput_user_dev uud;
|
||||||
|
|
||||||
|
g_mutex_lock(&westonimagesrc->lock);
|
||||||
|
westonimagesrc->uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
||||||
|
if (westonimagesrc->uinput_fd < 0) {
|
||||||
|
GST_ERROR_OBJECT(westonimagesrc, "open() /dev/uinput failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init keyboard
|
||||||
|
{
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_EVBIT, EV_KEY);
|
||||||
|
|
||||||
|
for (int key = KEY_ESC; key <= KEY_MICMUTE; key++) {
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_KEYBIT, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init mouse
|
||||||
|
{
|
||||||
|
// Mouse events
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_EVBIT, EV_REL);
|
||||||
|
|
||||||
|
// Mouse buttons
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_KEYBIT, BTN_LEFT);
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_KEYBIT, BTN_RIGHT);
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_KEYBIT, BTN_MIDDLE);
|
||||||
|
|
||||||
|
// Mouse rels
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_RELBIT, REL_X);
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_RELBIT, REL_Y);
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_RELBIT, REL_WHEEL);
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_RELBIT, REL_HWHEEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init device
|
||||||
|
struct uinput_setup usetup;
|
||||||
|
memset(&usetup, 0, sizeof(usetup));
|
||||||
|
|
||||||
|
snprintf(usetup.name, UINPUT_MAX_NAME_SIZE, "Virtual Keyboard + Mouse");
|
||||||
|
usetup.id.bustype = BUS_USB;
|
||||||
|
usetup.id.vendor = 0x7777;
|
||||||
|
usetup.id.product = 0x8888;
|
||||||
|
usetup.id.version = 1;
|
||||||
|
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_SET_EVBIT, EV_SYN);
|
||||||
|
if (ioctl(westonimagesrc->uinput_fd, UI_DEV_SETUP, &usetup) < 0) {
|
||||||
|
GST_ERROR_OBJECT(westonimagesrc, "ioctl() UI_DEV_SETUP failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(westonimagesrc->uinput_fd, UI_DEV_CREATE) < 0) {
|
||||||
|
GST_ERROR_OBJECT(westonimagesrc, "ioctl() UI_DEV_CREATE failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock(&westonimagesrc->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rcontrol_destroy(GstWestonImageSrc *westonimagesrc) {
|
||||||
|
ioctl(westonimagesrc->uinput_fd, UI_DEV_DESTROY);
|
||||||
|
close(westonimagesrc->uinput_fd);
|
||||||
|
}
|
||||||
|
|
||||||
static int weston_screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list) {
|
static int weston_screenshot_set_buffer_size(struct buffer_size *buff_size, struct wl_list *output_list) {
|
||||||
struct screenshooter_output *output;
|
struct screenshooter_output *output;
|
||||||
buff_size->min_x = buff_size->min_y = INT_MAX;
|
buff_size->min_x = buff_size->min_y = INT_MAX;
|
||||||
|
|
@ -234,6 +384,8 @@ static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc) {
|
||||||
GST_INFO_OBJECT(westonimagesrc, "Creating shared mem buffer ...");
|
GST_INFO_OBJECT(westonimagesrc, "Creating shared mem buffer ...");
|
||||||
output->buffer = weston_screenshot_create_shm_buffer(output->width, output->height, &output->data, sh_data.shm);
|
output->buffer = weston_screenshot_create_shm_buffer(output->width, output->height, &output->data, sh_data.shm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcontrol_init(westonimagesrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *gst_westonimagesrc_get_caps(GstBaseSrc *src, GstCaps *filter) {
|
static GstCaps *gst_westonimagesrc_get_caps(GstBaseSrc *src, GstCaps *filter) {
|
||||||
|
|
@ -318,16 +470,6 @@ static gboolean gst_westonimagesrc_stop(GstBaseSrc *basesrc) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void weston_capture_frame() {
|
|
||||||
wl_list_for_each(output, &sh_data.output_list, link) {
|
|
||||||
weston_screenshooter_shoot(sh_data.screenshooter, output->output, output->buffer);
|
|
||||||
sh_data.buffer_copy_done = 0;
|
|
||||||
|
|
||||||
while (!sh_data.buffer_copy_done)
|
|
||||||
wl_display_roundtrip(display);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn gst_westonimagesrc_create(GstBaseSrc *basesrc, guint64 offset, guint size, GstBuffer **buf) {
|
static GstFlowReturn gst_westonimagesrc_create(GstBaseSrc *basesrc, guint64 offset, guint size, GstBuffer **buf) {
|
||||||
GstWestonImageSrc *src = GST_WESTONIMAGESRC(basesrc);
|
GstWestonImageSrc *src = GST_WESTONIMAGESRC(basesrc);
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "glib.h"
|
||||||
#include "weston-screenshooter-client-protocol.h"
|
#include "weston-screenshooter-client-protocol.h"
|
||||||
#include "shared/os-compatibility.h"
|
#include "shared/os-compatibility.h"
|
||||||
#include "shared/xalloc.h"
|
#include "shared/xalloc.h"
|
||||||
|
|
@ -61,6 +62,10 @@ struct _GstWestonImageSrc {
|
||||||
guint64 frame_number;
|
guint64 frame_number;
|
||||||
gboolean do_timestamp;
|
gboolean do_timestamp;
|
||||||
|
|
||||||
|
// Remote control
|
||||||
|
gint uinput_fd, udp_socket_fd;
|
||||||
|
GThread *listener_thread;
|
||||||
|
|
||||||
// Stat
|
// Stat
|
||||||
GstClockTime last_timestamp;
|
GstClockTime last_timestamp;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,7 @@ if get_option('shell-desktop')
|
||||||
gstvideo_dep = dependency('gstreamer-video-1.0', version : '>=1.18',
|
gstvideo_dep = dependency('gstreamer-video-1.0', version : '>=1.18',
|
||||||
fallback : ['gstreamer', 'gstvideo_dep'])
|
fallback : ['gstreamer', 'gstvideo_dep'])
|
||||||
|
|
||||||
|
msgpack_dep = dependency('msgpack-c')
|
||||||
gst_westonimagesrc_plugin_c_args = ['-DHAVE_CONFIG_H']
|
gst_westonimagesrc_plugin_c_args = ['-DHAVE_CONFIG_H']
|
||||||
|
|
||||||
gst_westonimagesrc_cdata = configuration_data()
|
gst_westonimagesrc_cdata = configuration_data()
|
||||||
|
|
@ -390,7 +391,7 @@ if get_option('shell-desktop')
|
||||||
weston_screenshooter_protocol_c,
|
weston_screenshooter_protocol_c,
|
||||||
include_directories: common_inc,
|
include_directories: common_inc,
|
||||||
c_args: gst_westonimagesrc_plugin_c_args,
|
c_args: gst_westonimagesrc_plugin_c_args,
|
||||||
dependencies : [gst_dep, gstbase_dep, gstvideo_dep, dep_toytoolkit],
|
dependencies : [gst_dep, gstbase_dep, gstvideo_dep, dep_toytoolkit, msgpack_dep],
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : plugins_install_dir,
|
install_dir : plugins_install_dir,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue