summaryrefslogtreecommitdiff
path: root/gst/vaapi/gstvaapisink.c
diff options
context:
space:
mode:
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>2014-09-16 14:25:40 +0300
committerSreerenj Balachandran <sreerenj.balachandran@intel.com>2014-09-16 14:25:40 +0300
commit33212d96346e25726da59a533ed5f0af89cfd568 (patch)
tree4bf8ce13a2e4d528d76dd2140739c4a1f7ea2991 /gst/vaapi/gstvaapisink.c
parent406aa37373e2b9917714eccd2834a45d18b61fd1 (diff)
downloadgst-vaapi-33212d96346e25726da59a533ed5f0af89cfd568.tar.gz
vaapisink: implement the GstNavigation interface
This is useful for things like DVD menus, where key/mouse events would need to be forwarded from the upstream sink element. https://bugzilla.gnome.org/show_bug.cgi?id=711479
Diffstat (limited to 'gst/vaapi/gstvaapisink.c')
-rw-r--r--gst/vaapi/gstvaapisink.c139
1 files changed, 136 insertions, 3 deletions
diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c
index 2462737f..824c5e51 100644
--- a/gst/vaapi/gstvaapisink.c
+++ b/gst/vaapi/gstvaapisink.c
@@ -41,6 +41,7 @@
#if GST_CHECK_VERSION(1,0,0)
# include <gst/video/videooverlay.h>
# include <gst/video/colorbalance.h>
+# include <gst/video/navigation.h>
#else
# include <gst/interfaces/xoverlay.h>
# include <gst/interfaces/colorbalance.h>
@@ -107,6 +108,9 @@ gst_vaapisink_video_overlay_iface_init (GstVideoOverlayInterface * iface);
static void
gst_vaapisink_color_balance_iface_init (GstColorBalanceInterface * iface);
+static void
+gst_vaapisink_navigation_iface_init (GstNavigationInterface *iface);
+
G_DEFINE_TYPE_WITH_CODE (GstVaapiSink,
gst_vaapisink,
GST_TYPE_VIDEO_SINK,
@@ -114,7 +118,9 @@ G_DEFINE_TYPE_WITH_CODE (GstVaapiSink,
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
gst_vaapisink_video_overlay_iface_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
- gst_vaapisink_color_balance_iface_init));
+ gst_vaapisink_color_balance_iface_init);
+ G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
+ gst_vaapisink_navigation_iface_init));
enum
{
@@ -321,6 +327,8 @@ gst_vaapisink_x11_handle_events (GstVaapiSink * sink)
{
GstVaapiDisplay *const display = GST_VAAPI_PLUGIN_BASE_DISPLAY (sink);
gboolean has_events, do_expose = FALSE;
+ guint pointer_x = 0, pointer_y = 0;
+ gboolean pointer_moved = FALSE;
XEvent e;
if (sink->window) {
@@ -329,6 +337,72 @@ gst_vaapisink_x11_handle_events (GstVaapiSink * sink)
Window x11_win =
gst_vaapi_window_x11_get_xid (GST_VAAPI_WINDOW_X11 (sink->window));
+ /* Track MousePointer interaction */
+ for (;;) {
+ gst_vaapi_display_lock (display);
+ has_events = XCheckWindowEvent (x11_dpy, x11_win,
+ PointerMotionMask, &e);
+ gst_vaapi_display_unlock (display);
+ if (!has_events)
+ break;
+
+ switch (e.type) {
+ case MotionNotify:
+ pointer_x = e.xmotion.x;
+ pointer_y = e.xmotion.y;
+ pointer_moved = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (pointer_moved) {
+ gst_vaapi_display_lock (display);
+ gst_navigation_send_mouse_event (GST_NAVIGATION (sink),
+ "mouse-move", 0, e.xbutton.x, e.xbutton.y);
+ gst_vaapi_display_unlock (display);
+ }
+
+ /* Track KeyPress, KeyRelease, ButtonPress, ButtonRelease */
+ for (;;) {
+ KeySym keysym;
+ const char *key_str = NULL;
+ gst_vaapi_display_lock (display);
+ has_events = XCheckWindowEvent (x11_dpy, x11_win,
+ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask
+ , &e);
+ gst_vaapi_display_unlock (display);
+ if (!has_events)
+ break;
+
+ switch (e.type) {
+ case ButtonPress:
+ gst_navigation_send_mouse_event (GST_NAVIGATION (sink),
+ "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
+ break;
+ case ButtonRelease:
+ gst_navigation_send_mouse_event (GST_NAVIGATION (sink),
+ "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
+ break;
+ case KeyPress:
+ case KeyRelease:
+ gst_vaapi_display_lock (display);
+ keysym = XkbKeycodeToKeysym (x11_dpy, x11_win,
+ e.xkey.keycode, 0, 0);
+ if (keysym != NoSymbol) {
+ key_str = XKeysymToString (keysym);
+ } else {
+ key_str = "unknown";
+ }
+ gst_vaapi_display_unlock (display);
+ gst_navigation_send_key_event (GST_NAVIGATION (sink),
+ e.type == KeyPress ? "key-press" : "key-release", key_str);
+ break;
+ default:
+ break;
+ }
+ }
+
/* Handle Expose + ConfigureNotify */
/* Need to lock whole loop or we corrupt the XEvent queue: */
for (;;) {
@@ -353,7 +427,6 @@ gst_vaapisink_x11_handle_events (GstVaapiSink * sink)
}
if (do_expose)
gst_vaapisink_video_overlay_expose (GST_VIDEO_OVERLAY (sink));
- /* FIXME: handle mouse and key events */
}
return TRUE;
}
@@ -363,11 +436,19 @@ gst_vaapisink_x11_pre_start_event_thread (GstVaapiSink * sink)
{
GstVaapiDisplayX11 *const display =
GST_VAAPI_DISPLAY_X11 (GST_VAAPI_PLUGIN_BASE_DISPLAY (sink));
+ static const int x11_event_mask =
+ (KeyPressMask |
+ KeyReleaseMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ PointerMotionMask |
+ ExposureMask |
+ StructureNotifyMask);
if (sink->window) {
XSelectInput (gst_vaapi_display_x11_get_display (display),
gst_vaapi_window_x11_get_xid (GST_VAAPI_WINDOW_X11 (sink->window)),
- StructureNotifyMask | ExposureMask);
+ x11_event_mask);
}
return TRUE;
}
@@ -744,6 +825,58 @@ gst_vaapisink_color_balance_iface_init (GstColorBalanceInterface * iface)
}
/* ------------------------------------------------------------------------ */
+/* --- GstNavigation interface --- */
+/* ------------------------------------------------------------------------ */
+
+static void
+gst_vaapisink_navigation_send_event (GstNavigation * navigation,
+ GstStructure * structure)
+{
+ GstVaapiSink *const sink = GST_VAAPISINK (navigation);
+ GstVaapiDisplay *const display = GST_VAAPI_PLUGIN_BASE_DISPLAY (sink);
+ GstPad *peer;
+
+ if ((peer = gst_pad_get_peer (GST_VAAPI_PLUGIN_BASE_SINK_PAD (sink)))) {
+ GstEvent *event;
+ GstVaapiRectangle *disp_rect = &sink->display_rect;
+ gdouble x, y, xscale = 1.0, yscale = 1.0;
+
+ event = gst_event_new_navigation (structure);
+
+ if (!sink->window)
+ return;
+
+ /* We calculate scaling using the original video frames geometry to include
+ pixel aspect ratio scaling. */
+ xscale = (gdouble) sink->video_width / disp_rect->width;
+ yscale = (gdouble) sink->video_height / disp_rect->height;
+
+ /* Converting pointer coordinates to the non scaled geometry */
+ if (gst_structure_get_double (structure, "pointer_x", &x)) {
+ x = MIN (x, disp_rect->x + disp_rect->width);
+ x = MAX (x - disp_rect->x, 0);
+ gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
+ (gdouble) x * xscale, NULL);
+ }
+ if (gst_structure_get_double (structure, "pointer_y", &y)) {
+ y = MIN (y, disp_rect->y + disp_rect->height);
+ y = MAX (y - disp_rect->y, 0);
+ gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
+ (gdouble) y * yscale, NULL);
+ }
+
+ gst_pad_send_event (peer, event);
+ gst_object_unref (peer);
+ }
+}
+
+static void
+gst_vaapisink_navigation_iface_init (GstNavigationInterface * iface)
+{
+ iface->send_event = gst_vaapisink_navigation_send_event;
+}
+
+/* ------------------------------------------------------------------------ */
/* --- Common implementation --- */
/* ------------------------------------------------------------------------ */