[gnome-network-displays/cursor-test: 184/184] "working" cursor stream sending




commit 8d676cf2e02cde65c2cda8fdc1c960ee6912e878
Author: Benjamin Berg <bberg redhat com>
Date:   Thu Dec 20 20:01:47 2018 +0100

    "working" cursor stream sending
    
    This just demonstrates that sending PNGs through UDP to the sink works.

 src/wfd/wfd-client.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/wfd/wfd-media.c  |  12 +++++
 2 files changed, 158 insertions(+), 2 deletions(-)
---
diff --git a/src/wfd/wfd-client.c b/src/wfd/wfd-client.c
index 5ef36c0..f0ef44f 100644
--- a/src/wfd/wfd-client.c
+++ b/src/wfd/wfd-client.c
@@ -34,6 +34,10 @@ struct _WfdClient
   WfdParams         *params;
 
   WfdMediaQuirks     media_quirks;
+
+  GSocket           *cursor_socket;
+  guint              test_id;
+  guint16            cursor_seq;
 };
 
 G_DEFINE_TYPE (WfdClient, wfd_client, GST_TYPE_RTSP_CLIENT)
@@ -70,6 +74,10 @@ wfd_client_finalize (GObject *object)
     g_source_remove (self->keep_alive_source_id);
   self->keep_alive_source_id = 0;
 
+  if (self->test_id)
+    g_source_remove (self->test_id);
+  g_clear_object (&self->cursor_socket);
+
   G_OBJECT_CLASS (wfd_client_parent_class)->finalize (object);
 }
 
@@ -168,8 +176,8 @@ wfd_client_select_codec_and_resolution (WfdClient *self, WfdH264ProfileFlags pro
   self->params->selected_resolution->refresh_rate = 30;
   self->params->selected_resolution->interlaced = FALSE;
 #if 0
-}
-}
+        }
+    }
 #endif
   g_debug ("selected resolution %i, %i @%i", self->params->selected_resolution->width, 
self->params->selected_resolution->height, self->params->selected_resolution->refresh_rate);
 
@@ -188,6 +196,109 @@ wfd_client_select_codec_and_resolution (WfdClient *self, WfdH264ProfileFlags pro
     }
 }
 
+gboolean
+rand_cursor_update (gpointer user_data)
+{
+  WfdClient *self = user_data;
+  gint x, y;
+  g_autoptr(GByteArray) msg = NULL;
+  guint16 seq_be;
+  guint16 msg_size, msg_size_be;
+  gint16 x_be, y_be;
+  guint16 cursor;
+
+  x = g_random_int_range (0, 1000);
+  y = g_random_int_range (0, 1000);
+  cursor = g_random_int_range (1, 10);
+
+  g_print ("doing random cursor update to %i, %i\n", x, y);
+
+  /* No update in this case, but update if cursor is 1-3 (i.e. we have
+   * an image in /tmp/ for it. */
+  if (cursor > 3)
+    cursor = 0;
+
+  msg = g_byte_array_sized_new (200);
+
+  /* Fake an RTP header, bits 0-15, is version and other static things */
+  g_byte_array_append (msg, (guint8*) "\x80\x00", 2);
+  /* 16 - 31, sequence number */
+  seq_be = GUINT16_SWAP_LE_BE (self->cursor_seq);
+  g_byte_array_append (msg, (guint8*) &seq_be, sizeof(seq_be));
+  /* And another 64bit zeros (32bit timestamp and 32bit ssrc identifier) */
+  g_byte_array_append (msg, (guint8*) "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
+
+
+  if (cursor == 0)
+    {
+      /* 0x01 position update, 0x02 shape update, 0x03 shape continuation. */
+      g_byte_array_append (msg, (guint8*) "\x01", 1);
+
+      /* message size is always 0x07 for updates */
+      msg_size = 0x07;
+      msg_size_be = GUINT16_SWAP_LE_BE (msg_size);
+      g_byte_array_append (msg, (guint8*) &msg_size_be, sizeof(msg_size_be));
+
+      x_be = GUINT16_SWAP_LE_BE (x);
+      y_be = GUINT16_SWAP_LE_BE (y);
+      g_byte_array_append (msg, (guint8*) &x_be, sizeof(x_be));
+      g_byte_array_append (msg, (guint8*) &y_be, sizeof(y_be));
+    }
+  else
+    {
+      g_autofree gchar *cursor_file = NULL;
+      g_autofree gchar *cursor_img = NULL;
+      gsize cursor_len = 0;
+      guint32 cursor_len_be;
+      guint16 cursor_img_id_be;
+
+      /* Shape update, assume it fits */
+      g_byte_array_append (msg, (guint8*) "\x02", 1);
+      cursor_file = g_strdup_printf ("/tmp/test-cursor%d.png", cursor);
+      g_file_get_contents (cursor_file, &cursor_img, &cursor_len, NULL);
+      g_assert (cursor_len > 0);
+
+      /* Assume the cursor fits into the packet; if it doesn't then we need
+       * to send multiple packages until it fits. msg_size then is the size
+       * of each package while cursor size is constant. */
+      cursor_len_be = GUINT32_SWAP_LE_BE (cursor_len);
+      msg_size = 18 + cursor_len;
+      msg_size_be = GUINT16_SWAP_LE_BE (msg_size);
+
+      g_byte_array_append (msg, (guint8*) &msg_size_be, sizeof(msg_size_be));
+      g_byte_array_append (msg, (guint8*) &cursor_len_be, sizeof(cursor_len_be));
+
+      cursor_img_id_be = GUINT16_SWAP_LE_BE (cursor);
+      g_byte_array_append (msg, (guint8*) &cursor_img_id_be, sizeof(cursor_img_id_be));
+
+      x_be = GUINT16_SWAP_LE_BE (x);
+      y_be = GUINT16_SWAP_LE_BE (y);
+      g_byte_array_append (msg, (guint8*) &x_be, sizeof(x_be));
+      g_byte_array_append (msg, (guint8*) &y_be, sizeof(y_be));
+
+      /* Image type, 0x01: disabled, 0x02 masked color, 0x03: color */
+      g_byte_array_append (msg, (guint8*) "\x03", 1);
+
+      /* Hotspot */
+      x_be = GUINT16_SWAP_LE_BE (5);
+      y_be = GUINT16_SWAP_LE_BE (5);
+      g_byte_array_append (msg, (guint8*) &x_be, sizeof(x_be));
+      g_byte_array_append (msg, (guint8*) &y_be, sizeof(y_be));
+
+      g_byte_array_append (msg, (guint8*) cursor_img, cursor_len);
+    }
+
+  g_socket_send (self->cursor_socket,
+                 (const gchar*) msg->data,
+                 msg->len,
+                 NULL,
+                 NULL);
+
+  self->cursor_seq += 1;
+
+  return TRUE;
+}
+
 gboolean
 wfd_client_configure_client_media (GstRTSPClient * client,
                                    GstRTSPMedia * media, GstRTSPStream * stream,
@@ -208,6 +319,39 @@ wfd_client_configure_client_media (GstRTSPClient * client,
 
   res = GST_RTSP_CLIENT_CLASS (wfd_client_parent_class)->configure_client_media (client, media, stream, ctx);
 
+  if (self->params->ms_cursor_capability)
+    {
+      GstRTSPConnection *connection;
+      GSocket *socket;
+      g_autoptr(GSocketAddress) sock_addr;
+      GInetAddress *inet_addr;
+      g_autoptr(GSocketAddress) address = NULL;
+
+      self->cursor_socket = g_socket_new (G_SOCKET_FAMILY_IPV6,
+                                          G_SOCKET_TYPE_DATAGRAM,
+                                          G_SOCKET_PROTOCOL_UDP,
+                                          NULL);
+
+      g_socket_set_blocking (self->cursor_socket, FALSE);
+
+      connection = gst_rtsp_client_get_connection (client);
+      socket = gst_rtsp_connection_get_read_socket (connection);
+      sock_addr = g_socket_get_remote_address (socket, NULL);
+      inet_addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (sock_addr));
+
+      gst_rtsp_client_get_connection (client);
+      address = g_inet_socket_address_new (inet_addr, self->params->ms_cursor_port);
+      if (!g_socket_connect (self->cursor_socket, address, NULL, NULL))
+        {
+          g_warning ("Failed to connect to socket");
+
+          g_clear_object (&self->cursor_socket);
+          return res;
+        }
+
+      self->test_id = g_timeout_add (500, rand_cursor_update, self);
+    }
+
   return res;
 }
 
diff --git a/src/wfd/wfd-media.c b/src/wfd/wfd-media.c
index 70a988e..84655b8 100644
--- a/src/wfd/wfd-media.c
+++ b/src/wfd/wfd-media.c
@@ -7,6 +7,8 @@
 struct _WfdMedia
 {
   GstRTSPMedia parent_instance;
+
+  GstPipeline *ms_cursor_pipeline;
 };
 
 G_DEFINE_TYPE (WfdMedia, wfd_media, GST_TYPE_RTSP_MEDIA)
@@ -20,8 +22,12 @@ wfd_media_new (void)
 static void
 wfd_media_finalize (GObject *object)
 {
+  WfdMedia *self = WFD_MEDIA (object);
+
   g_debug ("WfdMedia: Finalize");
 
+  g_clear_object (&self->ms_cursor_pipeline);
+
   G_OBJECT_CLASS (wfd_media_parent_class)->finalize (object);
 }
 
@@ -40,6 +46,12 @@ wfd_media_setup_rtpbin (GstRTSPMedia *media, GstElement *rtpbin)
   return TRUE;
 }
 
+void
+wfd_media_create_cursor_pipeline (WfdMedia *self)
+{
+
+}
+
 static void
 wfd_media_class_init (WfdMediaClass *klass)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]