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 <linux/input-event-codes.h>
#include <linux/uinput.h>
#include <msgpack/object.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -14,6 +15,7 @@
#include <wayland-client-protocol.h>
#include <wayland-util.h>
#include <msgpack.h>
#include <cjson/cJSON.h>
#include "glib-object.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_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 GstCaps *gst_westonimagesrc_get_caps(GstBaseSrc *src, GstCaps *filter);
static gboolean gst_westonimagesrc_negotiate(GstBaseSrc *basesrc);
static gboolean gst_westonimagesrc_set_caps(GstBaseSrc *src, GstCaps *caps);
G_DEFINE_TYPE(GstWestonImageSrc, gst_westonimagesrc, GST_TYPE_BASE_SRC);
@ -104,46 +105,70 @@ static gpointer rcontrol_listener_thread(gpointer data) {
GstWestonImageSrc *westonimagesrc = data;
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) {
GST_WARNING_OBJECT(westonimagesrc, "socket() UDP socket creation failed");
GST_ERROR_OBJECT(westonimagesrc, "socket() UDP socket creation failed: %s", strerror(errno));
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));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(port);
addr.sin6_addr = in6addr_any; /* :: */
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);
return NULL;
}
GST_INFO_OBJECT(westonimagesrc, "UDP listener started on port %d\n", port);
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_init(&mempool, sizeof(buf));
msgpack_zone_init(&mempool, sizeof(msgpack_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);
ssize_t len = recvfrom(westonimagesrc->udp_socket_fd, msgpack_buf, sizeof(msgpack_buf) - 1, 0, (struct sockaddr *)&src, &srclen);
if (len < 0) {
GST_WARNING_OBJECT(westonimagesrc, "recvfrom() failed");
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_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);
msgpack_unpack(msgpack_buf, sizeof(msgpack_buf), NULL, &mempool, &deserialized);
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);
@ -157,8 +182,6 @@ static void rcontrol_init_server(GstWestonImageSrc *westonimagesrc) {
}
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) {
@ -336,8 +359,11 @@ static void gst_westonimagesrc_class_init(GstWestonImageSrcClass *klass) {
gstbasesrc_class->start = GST_DEBUG_FUNCPTR(gst_westonimagesrc_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_stop);
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->negotiate = GST_DEBUG_FUNCPTR(gst_westonimagesrc_negotiate);
gstbasesrc_class->negotiate = NULL;
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock);
gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock_stop);
@ -388,34 +414,25 @@ static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc) {
rcontrol_init(westonimagesrc);
}
static GstCaps *gst_westonimagesrc_get_caps(GstBaseSrc *src, GstCaps *filter) {
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) {
static gboolean gst_westonimagesrc_set_caps(GstBaseSrc *basesrc, GstCaps *caps) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
GstCaps *caps;
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);
gst_structure_get_int(s, "width", &westonimagesrc->width);
gst_structure_get_int(s, "height", &westonimagesrc->height);
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;
}

View File

@ -369,6 +369,8 @@ if get_option('shell-desktop')
fallback : ['gstreamer', 'gstvideo_dep'])
msgpack_dep = dependency('msgpack-c')
cjson_dep = dependency('cjson')
gst_westonimagesrc_plugin_c_args = ['-DHAVE_CONFIG_H']
gst_westonimagesrc_cdata = configuration_data()
@ -391,7 +393,7 @@ if get_option('shell-desktop')
weston_screenshooter_protocol_c,
include_directories: common_inc,
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_dir : plugins_install_dir,
)