From ee5faf01e24b4c503db2c18a48cbfad45a9c207f Mon Sep 17 00:00:00 2001 From: Oleg Shishlyannikov Date: Tue, 16 Dec 2025 07:29:47 +0300 Subject: [PATCH] add json --- clients/gstwestonimagesrc.c | 95 ++++++++++++++++++++++--------------- clients/meson.build | 4 +- 2 files changed, 59 insertions(+), 40 deletions(-) diff --git a/clients/gstwestonimagesrc.c b/clients/gstwestonimagesrc.c index 5d12588..9a0d9ab 100644 --- a/clients/gstwestonimagesrc.c +++ b/clients/gstwestonimagesrc.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #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); @@ -357,7 +383,7 @@ static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc) { westonimagesrc->offset = 0; westonimagesrc->framerate_n = 30; westonimagesrc->framerate_d = 1; - + g_mutex_init(&westonimagesrc->lock); g_cond_init(&westonimagesrc->cond); @@ -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; } diff --git a/clients/meson.build b/clients/meson.build index 8cd1125..21b6631 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -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, )