vulkan/sink: implement GstNavigation support
authorMatthew Waters <matthew@centricular.com>
Mon, 17 Feb 2020 04:08:47 +0000 (15:08 +1100)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 3 Mar 2020 05:00:50 +0000 (05:00 +0000)
ext/vulkan/vksink.c
ext/vulkan/vksink.h

index b7d2c27..9177b98 100644 (file)
@@ -67,6 +67,14 @@ static GstFlowReturn gst_vulkan_sink_show_frame (GstVideoSink * bsink,
 static void gst_vulkan_sink_video_overlay_init (GstVideoOverlayInterface *
     iface);
 
+static void gst_vulkan_sink_navigation_interface_init (GstNavigationInterface *
+    iface);
+static void gst_vulkan_sink_key_event_cb (GstVulkanWindow * window,
+    char *event_name, char *key_string, GstVulkanSink * vk_sink);
+static void gst_vulkan_sink_mouse_event_cb (GstVulkanWindow * window,
+    char *event_name, int button, double posx, double posy,
+    GstVulkanSink * vk_sink);
+
 
 static GstStaticPadTemplate gst_vulkan_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
@@ -97,7 +105,9 @@ G_DEFINE_TYPE_WITH_CODE (GstVulkanSink, gst_vulkan_sink,
     GST_TYPE_VIDEO_SINK, GST_DEBUG_CATEGORY_INIT (gst_debug_vulkan_sink,
         "vulkansink", 0, "Vulkan Video Sink");
     G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
-        gst_vulkan_sink_video_overlay_init));
+        gst_vulkan_sink_video_overlay_init);
+    G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
+        gst_vulkan_sink_navigation_interface_init));
 
 static void
 gst_vulkan_sink_class_init (GstVulkanSinkClass * klass)
@@ -337,6 +347,14 @@ gst_vulkan_sink_change_state (GstElement * element, GstStateChange transition)
           return GST_STATE_CHANGE_FAILURE;
         }
       }
+
+      vk_sink->key_sig_id =
+          g_signal_connect (vk_sink->window, "key-event",
+          G_CALLBACK (gst_vulkan_sink_key_event_cb), vk_sink);
+      vk_sink->mouse_sig_id =
+          g_signal_connect (vk_sink->window, "mouse-event",
+          G_CALLBACK (gst_vulkan_sink_mouse_event_cb), vk_sink);
+
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
@@ -357,6 +375,14 @@ gst_vulkan_sink_change_state (GstElement * element, GstStateChange transition)
       vk_sink->swapper = NULL;
       if (vk_sink->window) {
         gst_vulkan_window_close (vk_sink->window);
+
+        if (vk_sink->key_sig_id)
+          g_signal_handler_disconnect (vk_sink->window, vk_sink->key_sig_id);
+        vk_sink->key_sig_id = 0;
+        if (vk_sink->mouse_sig_id)
+          g_signal_handler_disconnect (vk_sink->window, vk_sink->mouse_sig_id);
+        vk_sink->mouse_sig_id = 0;
+
         gst_object_unref (vk_sink->window);
       }
       vk_sink->window = NULL;
@@ -569,3 +595,103 @@ gst_vulkan_sink_video_overlay_init (GstVideoOverlayInterface * iface)
 {
   iface->set_window_handle = gst_vulkan_sink_set_window_handle;
 }
+
+static void
+_display_size_to_stream_size (GstVulkanSink * vk_sink,
+    GstVideoRectangle * display_rect, gdouble x, gdouble y, gdouble * stream_x,
+    gdouble * stream_y)
+{
+  gdouble stream_width, stream_height;
+
+  stream_width = (gdouble) GST_VIDEO_INFO_WIDTH (&vk_sink->v_info);
+  stream_height = (gdouble) GST_VIDEO_INFO_HEIGHT (&vk_sink->v_info);
+
+  /* from display coordinates to stream coordinates */
+  if (display_rect->w > 0)
+    *stream_x = (x - display_rect->x) / display_rect->w * stream_width;
+  else
+    *stream_x = 0.;
+
+  /* clip to stream size */
+  *stream_x = CLAMP (*stream_x, 0., stream_width);
+
+  /* same for y-axis */
+  if (display_rect->h > 0)
+    *stream_y = (y - display_rect->y) / display_rect->h * stream_height;
+  else
+    *stream_y = 0.;
+
+  *stream_y = CLAMP (*stream_y, 0., stream_height);
+
+  GST_TRACE_OBJECT (vk_sink, "transform %fx%f into %fx%f", x, y, *stream_x,
+      *stream_y);
+}
+
+static void
+gst_vulkan_sink_navigation_send_event (GstNavigation * navigation,
+    GstStructure * structure)
+{
+  GstVulkanSink *vk_sink = GST_VULKAN_SINK (navigation);
+  GstVideoRectangle display_rect;
+  GstEvent *event = NULL;
+  gdouble x, y;
+
+  if (!vk_sink->swapper || !vk_sink->swapper->window) {
+    gst_structure_free (structure);
+    return;
+  }
+
+  gst_vulkan_swapper_get_surface_rectangles (vk_sink->swapper, NULL, NULL,
+      &display_rect);
+
+  /* Converting pointer coordinates to the non scaled geometry */
+  if (display_rect.w != 0 && display_rect.h != 0
+      && gst_structure_get_double (structure, "pointer_x", &x)
+      && gst_structure_get_double (structure, "pointer_y", &y)) {
+    gdouble stream_x, stream_y;
+
+    _display_size_to_stream_size (vk_sink, &display_rect, x, y, &stream_x,
+        &stream_y);
+
+    gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
+        stream_x, "pointer_y", G_TYPE_DOUBLE, stream_y, NULL);
+  }
+
+  event = gst_event_new_navigation (structure);
+  if (event) {
+    gboolean handled;
+
+    gst_event_ref (event);
+    handled = gst_pad_push_event (GST_VIDEO_SINK_PAD (vk_sink), event);
+
+    if (!handled)
+      gst_element_post_message ((GstElement *) vk_sink,
+          gst_navigation_message_new_event ((GstObject *) vk_sink, event));
+
+    gst_event_unref (event);
+  }
+}
+
+static void
+gst_vulkan_sink_navigation_interface_init (GstNavigationInterface * iface)
+{
+  iface->send_event = gst_vulkan_sink_navigation_send_event;
+}
+
+static void
+gst_vulkan_sink_key_event_cb (GstVulkanWindow * window, char *event_name, char
+    *key_string, GstVulkanSink * vk_sink)
+{
+  GST_DEBUG_OBJECT (vk_sink, "event %s key %s pressed", event_name, key_string);
+  gst_navigation_send_key_event (GST_NAVIGATION (vk_sink),
+      event_name, key_string);
+}
+
+static void
+gst_vulkan_sink_mouse_event_cb (GstVulkanWindow * window, char *event_name,
+    int button, double posx, double posy, GstVulkanSink * vk_sink)
+{
+  GST_DEBUG_OBJECT (vk_sink, "event %s at %g, %g", event_name, posx, posy);
+  gst_navigation_send_mouse_event (GST_NAVIGATION (vk_sink),
+      event_name, button, posx, posy);
+}
index 73cd857..40ec8da 100644 (file)
@@ -59,6 +59,9 @@ struct _GstVulkanSink
 
   /* the currently set window handle */
   guintptr set_window_handle;
+
+  gulong key_sig_id;
+  gulong mouse_sig_id;
 };
 
 struct _GstVulkanSinkClass