From 8593e1517ec22fb98683cb805da0610b959a3b96 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 30 Jul 2021 23:57:20 +0900 Subject: examples: win32-videooverlay: Add support for testing gst_video_overlay_set_render_rectangle Add keyboard handler to test gst_video_overlay_set_render_rectangle() API for Windows video elements Part-of: --- tests/examples/overlay/win32-videooverlay.c | 209 +++++++++++++++++++++++++++- 1 file changed, 208 insertions(+), 1 deletion(-) diff --git a/tests/examples/overlay/win32-videooverlay.c b/tests/examples/overlay/win32-videooverlay.c index ca7f9debb..622256b6f 100644 --- a/tests/examples/overlay/win32-videooverlay.c +++ b/tests/examples/overlay/win32-videooverlay.c @@ -36,11 +36,28 @@ static HWND hwnd = NULL; static gboolean test_fullscreen = FALSE; static gboolean fullscreen = FALSE; static gchar *video_sink = NULL; +static GstElement *sink = NULL; static gboolean run_thread = FALSE; static LONG prev_style = 0; static RECT prev_rect = { 0, }; +static gint x = 0; +static gint y = 0; +static gint width = 320; +static gint height = 240; + +typedef struct +{ + GThread *thread; + HANDLE event_handle; + HANDLE console_handle; + gboolean closing; + GMutex lock; +} Win32KeyHandler; + +static Win32KeyHandler *win32_key_handler = NULL; + #define DEFAULT_VIDEO_SINK "d3d11videosink" static gboolean @@ -218,7 +235,7 @@ timeout_cb (gpointer user_data) static gpointer pipeline_runner_func (gpointer user_data) { - GstElement *pipeline, *src, *sink; + GstElement *pipeline, *src; GstStateChangeReturn sret; gint num_repeat = 0; GMainContext *context = NULL; @@ -246,6 +263,8 @@ pipeline_runner_func (gpointer user_data) exit (1); } + gst_object_ref_sink (sink); + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); gst_element_link (src, sink); @@ -293,6 +312,161 @@ pipeline_runner_func (gpointer user_data) return NULL; } +static void +print_keyboard_help (void) +{ + /* *INDENT-OFF* */ + static struct + { + const gchar *key_desc; + const gchar *key_help; + } key_controls[] = { + { + "\342\206\222", "move overlay to right-hand side"}, { + "\342\206\220", "move overlay to left-hand side"}, { + "\342\206\221", "move overlay to upward"}, { + "\342\206\223", "move overlay to downward"}, { + ">", "increase overlay width"}, { + "<", "decrease overlay width"}, { + "+", "increase overlay height"}, { + "-", "decrease overlay height"}, { + "r", "reset render rectangle"}, { + "e", "expose overlay"}, { + "k", "show keyboard shortcuts"}, + }; + /* *INDENT-ON* */ + + guint i, chars_to_pad, desc_len, max_desc_len = 0; + + gst_print ("\n\n%s\n\n", "Interactive mode - keyboard controls:"); + + for (i = 0; i < G_N_ELEMENTS (key_controls); ++i) { + desc_len = g_utf8_strlen (key_controls[i].key_desc, -1); + max_desc_len = MAX (max_desc_len, desc_len); + } + ++max_desc_len; + + for (i = 0; i < G_N_ELEMENTS (key_controls); ++i) { + chars_to_pad = max_desc_len - g_utf8_strlen (key_controls[i].key_desc, -1); + gst_print ("\t%s", key_controls[i].key_desc); + gst_print ("%-*s: ", chars_to_pad, ""); + gst_print ("%s\n", key_controls[i].key_help); + } + gst_print ("\n"); +} + +static gboolean +win32_kb_source_cb (Win32KeyHandler * handler) +{ + HANDLE h_input = handler->console_handle; + INPUT_RECORD buffer; + DWORD n; + + if (PeekConsoleInput (h_input, &buffer, 1, &n) && n == 1) { + ReadConsoleInput (h_input, &buffer, 1, &n); + + if (buffer.EventType == KEY_EVENT && buffer.Event.KeyEvent.bKeyDown) { + gchar key_val[2] = { 0 }; + + switch (buffer.Event.KeyEvent.wVirtualKeyCode) { + case VK_RIGHT: + gst_println ("Move xpos to %d", x++); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case VK_LEFT: + gst_println ("Move xpos to %d", x--); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case VK_UP: + gst_println ("Move ypos to %d", y--); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case VK_DOWN: + gst_println ("Move ypos to %d", y++); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + default: + key_val[0] = buffer.Event.KeyEvent.uChar.AsciiChar; + switch (key_val[0]) { + case '<': + gst_println ("Decrease width to %d", width--); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case '>': + gst_println ("Increase width to %d", width++); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case '+': + gst_println ("Increase height to %d", height++); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case '-': + gst_println ("Decrease height to %d", height--); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, width, height); + break; + case 'r': + gst_println ("Reset render rectangle by setting -1 width/height"); + gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), + x, y, -1, -1); + break; + case 'e': + gst_println ("Expose overlay"); + gst_video_overlay_expose (GST_VIDEO_OVERLAY (sink)); + break; + case 'k': + print_keyboard_help (); + break; + default: + break; + } + break; + } + } + } + + return G_SOURCE_REMOVE; +} + +static gpointer +win32_kb_thread (gpointer user_data) +{ + Win32KeyHandler *handler = (Win32KeyHandler *) user_data; + HANDLE handles[2]; + + handles[0] = handler->event_handle; + handles[1] = handler->console_handle; + + while (TRUE) { + DWORD ret = WaitForMultipleObjects (2, handles, FALSE, INFINITE); + static guint i = 0; + + if (ret == WAIT_FAILED) { + g_warning ("WaitForMultipleObject Failed"); + return NULL; + } + + g_mutex_lock (&handler->lock); + if (handler->closing) { + g_mutex_unlock (&handler->lock); + + return NULL; + } + g_mutex_unlock (&handler->lock); + + g_idle_add ((GSourceFunc) win32_kb_source_cb, handler); + } + + return NULL; +} + gint main (gint argc, gchar ** argv) { @@ -361,6 +535,25 @@ main (gint argc, gchar ** argv) msg_io_channel = g_io_channel_win32_new_messages (0); g_io_add_watch (msg_io_channel, G_IO_IN, msg_cb, NULL); + { + SECURITY_ATTRIBUTES attrs; + + attrs.nLength = sizeof (SECURITY_ATTRIBUTES); + attrs.lpSecurityDescriptor = NULL; + attrs.bInheritHandle = FALSE; + + win32_key_handler = g_new0 (Win32KeyHandler, 1); + + /* create cancellable event handle */ + win32_key_handler->event_handle = CreateEvent (&attrs, TRUE, FALSE, NULL); + win32_key_handler->console_handle = GetStdHandle (STD_INPUT_HANDLE); + g_mutex_init (&win32_key_handler->lock); + win32_key_handler->thread = + g_thread_new ("key-handler", win32_kb_thread, win32_key_handler); + } + + gst_println ("Press 'k' to see a list of keyboard shortcuts"); + if (run_thread) { thread = g_thread_new ("pipeline-thread", (GThreadFunc) pipeline_runner_func, NULL); @@ -373,6 +566,20 @@ terminate: if (hwnd) DestroyWindow (hwnd); + if (win32_key_handler) { + g_mutex_lock (&win32_key_handler->lock); + win32_key_handler->closing = TRUE; + g_mutex_unlock (&win32_key_handler->lock); + + SetEvent (win32_key_handler->event_handle); + g_thread_join (win32_key_handler->thread); + CloseHandle (win32_key_handler->event_handle); + + g_mutex_clear (&win32_key_handler->lock); + g_free (win32_key_handler); + } + + gst_clear_object (&sink); g_io_channel_unref (msg_io_channel); g_main_loop_unref (loop); g_free (title); -- cgit v1.2.1