This commit is contained in:
Oleg Shishlyannikov 2025-12-16 07:29:47 +03:00
parent caa465a3eb
commit ee5faf01e2
2 changed files with 59 additions and 40 deletions

View File

@ -3,6 +3,7 @@
#include <limits.h> #include <limits.h>
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>
#include <linux/uinput.h> #include <linux/uinput.h>
#include <msgpack/object.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -14,6 +15,7 @@
#include <wayland-client-protocol.h> #include <wayland-client-protocol.h>
#include <wayland-util.h> #include <wayland-util.h>
#include <msgpack.h> #include <msgpack.h>
#include <cjson/cJSON.h>
#include "glib-object.h" #include "glib-object.h"
#include "glib.h" #include "glib.h"
@ -52,8 +54,7 @@ static void gst_westonimagesrc_class_init(GstWestonImageSrcClass *klass);
static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc); static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc);
static void gst_westonimagesrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_westonimagesrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gst_westonimagesrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gst_westonimagesrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static GstCaps *gst_westonimagesrc_get_caps(GstBaseSrc *src, GstCaps *filter); static gboolean gst_westonimagesrc_set_caps(GstBaseSrc *src, GstCaps *caps);
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);
@ -104,46 +105,70 @@ static gpointer rcontrol_listener_thread(gpointer data) {
GstWestonImageSrc *westonimagesrc = data; GstWestonImageSrc *westonimagesrc = data;
g_mutex_lock(&westonimagesrc->lock); g_mutex_lock(&westonimagesrc->lock);
westonimagesrc->udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); westonimagesrc->udp_socket_fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (westonimagesrc->udp_socket_fd < 0) { if (westonimagesrc->udp_socket_fd < 0) {
GST_WARNING_OBJECT(westonimagesrc, "socket() UDP socket creation failed"); GST_ERROR_OBJECT(westonimagesrc, "socket() UDP socket creation failed: %s", strerror(errno));
return NULL; return NULL;
} }
struct sockaddr_in addr; /* ВАЖНО: разрешаем dual-stack (IPv4 + IPv6) */
int off = 0;
if (setsockopt(westonimagesrc->udp_socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) < 0) {
GST_WARNING_OBJECT(westonimagesrc, "setsockopt() IPV6_V6ONLY failed: %s", strerror(errno));
}
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; addr.sin6_family = AF_INET6;
addr.sin_port = htons(port); addr.sin6_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY; addr.sin6_addr = in6addr_any; /* :: */
if (bind(westonimagesrc->udp_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (bind(westonimagesrc->udp_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
GST_ERROR_OBJECT(westonimagesrc, "bind() UDP socket binding failed"); GST_ERROR_OBJECT(westonimagesrc, "bind() UDP socket binding failed: %s", strerror(errno));
close(westonimagesrc->udp_socket_fd); close(westonimagesrc->udp_socket_fd);
return NULL; return NULL;
} }
GST_INFO_OBJECT(westonimagesrc, "UDP listener started on port %d\n", port);
g_mutex_unlock(&westonimagesrc->lock); g_mutex_unlock(&westonimagesrc->lock);
GST_INFO_OBJECT(westonimagesrc, "UDP listener started on port %d\n", port);
char msgpack_buf[1024u], msg_buf[1024u];
char addrstr[INET6_ADDRSTRLEN];
int src_port = 0;
char buf[1024u];
msgpack_zone mempool; msgpack_zone mempool;
msgpack_zone_init(&mempool, sizeof(buf)); msgpack_zone_init(&mempool, sizeof(msgpack_buf));
while (TRUE) { while (TRUE) {
struct sockaddr_in src; struct sockaddr_in src;
socklen_t srclen = sizeof(src); socklen_t srclen = sizeof(src);
ssize_t len = recvfrom(westonimagesrc->udp_socket_fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&src, &srclen); ssize_t len = recvfrom(westonimagesrc->udp_socket_fd, msgpack_buf, sizeof(msgpack_buf) - 1, 0, (struct sockaddr *)&src, &srclen);
if (len < 0) { if (len < 0) {
GST_WARNING_OBJECT(westonimagesrc, "recvfrom() failed"); GST_WARNING_OBJECT(westonimagesrc, "recvfrom() failed");
continue; continue;
} }
buf[len] = '\0'; if (src.sin_family == AF_INET6) {
struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&src;
inet_ntop(AF_INET6, &s6->sin6_addr, addrstr, sizeof(addrstr));
src_port = ntohs(s6->sin6_port);
} else if (src.sin_family == AF_INET) {
struct sockaddr_in *s4 = (struct sockaddr_in *)&src;
inet_ntop(AF_INET, &s4->sin_addr, addrstr, sizeof(addrstr));
src_port = ntohs(s4->sin_port);
} else {
strcpy(addrstr, "unknown");
}
msgpack_object deserialized; msgpack_object deserialized;
msgpack_unpack(buf, sizeof(buf), NULL, &mempool, &deserialized); msgpack_unpack(msgpack_buf, sizeof(msgpack_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); msgpack_object_print_buffer(msg_buf, sizeof(msg_buf), deserialized);
GST_INFO_OBJECT(westonimagesrc, "[UDP %s:%d]: %s", addrstr, src_port, msg_buf);
} }
close(westonimagesrc->udp_socket_fd); close(westonimagesrc->udp_socket_fd);
@ -157,8 +182,6 @@ static void rcontrol_init_server(GstWestonImageSrc *westonimagesrc) {
} }
static void rcontrol_init_uinput(GstWestonImageSrc *westonimagesrc) { static void rcontrol_init_uinput(GstWestonImageSrc *westonimagesrc) {
struct uinput_user_dev uud;
g_mutex_lock(&westonimagesrc->lock); g_mutex_lock(&westonimagesrc->lock);
westonimagesrc->uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); westonimagesrc->uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (westonimagesrc->uinput_fd < 0) { if (westonimagesrc->uinput_fd < 0) {
@ -336,8 +359,11 @@ static void gst_westonimagesrc_class_init(GstWestonImageSrcClass *klass) {
gstbasesrc_class->start = GST_DEBUG_FUNCPTR(gst_westonimagesrc_start); gstbasesrc_class->start = GST_DEBUG_FUNCPTR(gst_westonimagesrc_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_stop); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_stop);
gstbasesrc_class->create = GST_DEBUG_FUNCPTR(gst_westonimagesrc_create); gstbasesrc_class->create = GST_DEBUG_FUNCPTR(gst_westonimagesrc_create);
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR(gst_westonimagesrc_set_caps);
gstbasesrc_class->get_caps = NULL; gstbasesrc_class->get_caps = NULL;
gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR(gst_westonimagesrc_negotiate); gstbasesrc_class->negotiate = NULL;
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock); gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock);
gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock_stop); gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock_stop);
@ -357,7 +383,7 @@ static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc) {
westonimagesrc->offset = 0; westonimagesrc->offset = 0;
westonimagesrc->framerate_n = 30; westonimagesrc->framerate_n = 30;
westonimagesrc->framerate_d = 1; westonimagesrc->framerate_d = 1;
g_mutex_init(&westonimagesrc->lock); g_mutex_init(&westonimagesrc->lock);
g_cond_init(&westonimagesrc->cond); g_cond_init(&westonimagesrc->cond);
@ -388,34 +414,25 @@ static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc) {
rcontrol_init(westonimagesrc); rcontrol_init(westonimagesrc);
} }
static GstCaps *gst_westonimagesrc_get_caps(GstBaseSrc *src, GstCaps *filter) { static gboolean gst_westonimagesrc_set_caps(GstBaseSrc *basesrc, GstCaps *caps) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(src);
GstCaps *caps = gst_caps_new_simple("video/x-raw", "format", GST_TYPE_VIDEO_FORMAT, westonimagesrc->format, "width", G_TYPE_INT, westonimagesrc->width, "height", G_TYPE_INT,
westonimagesrc->height, "framerate", GST_TYPE_FRACTION, westonimagesrc->framerate_n, westonimagesrc->framerate_d, NULL);
if (filter) {
GstCaps *tmp = gst_caps_intersect_full(filter, caps, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref(caps);
return tmp;
}
return caps;
}
static gboolean gst_westonimagesrc_negotiate(GstBaseSrc *basesrc) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc); GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
GstCaps *caps;
GstStructure *s; GstStructure *s;
const gchar *fmt;
caps = gst_pad_get_current_caps(GST_BASE_SRC_PAD(basesrc)); GST_INFO_OBJECT(westonimagesrc, "set_caps called: %" GST_PTR_FORMAT, caps);
s = gst_caps_get_structure(caps, 0); s = gst_caps_get_structure(caps, 0);
gst_structure_get_int(s, "width", &westonimagesrc->width); gst_structure_get_int(s, "width", &westonimagesrc->width);
gst_structure_get_int(s, "height", &westonimagesrc->height); gst_structure_get_int(s, "height", &westonimagesrc->height);
gst_structure_get_fraction(s, "framerate", &westonimagesrc->framerate_n, &westonimagesrc->framerate_d); gst_structure_get_fraction(s, "framerate", &westonimagesrc->framerate_n, &westonimagesrc->framerate_d);
gst_caps_unref(caps); fmt = gst_structure_get_string(s, "format");
if (!fmt)
return FALSE;
westonimagesrc->format = gst_video_format_from_string(fmt);
GST_INFO_OBJECT(westonimagesrc, "Caps accepted: %s %dx%d @ %d/%d", fmt, westonimagesrc->width, westonimagesrc->height, westonimagesrc->framerate_n, westonimagesrc->framerate_d);
return TRUE; return TRUE;
} }

View File

@ -369,6 +369,8 @@ if get_option('shell-desktop')
fallback : ['gstreamer', 'gstvideo_dep']) fallback : ['gstreamer', 'gstvideo_dep'])
msgpack_dep = dependency('msgpack-c') msgpack_dep = dependency('msgpack-c')
cjson_dep = dependency('cjson')
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()
@ -391,7 +393,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, msgpack_dep], dependencies : [gst_dep, gstbase_dep, gstvideo_dep, dep_toytoolkit, msgpack_dep, cjson_dep],
install : true, install : true,
install_dir : plugins_install_dir, install_dir : plugins_install_dir,
) )