summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeungha Yang <seungha@centricular.com>2021-06-03 19:15:22 +0900
committerSeungha Yang <seungha@centricular.com>2021-07-30 02:01:13 +0900
commitf886766a6bdd8abd4145ab8016e3190748b9fcc2 (patch)
treed2b818cb28132d2ea133ba6b2b95a2eab4a7fece
parent32170aa6c2c46aed1a5795f62c6e458d448f65bb (diff)
downloadgstreamer-plugins-base-f886766a6bdd8abd4145ab8016e3190748b9fcc2.tar.gz
examples: win32-videooverlay: Add test option for threading scenario
Add an option to test the case where window thread and pipeline handling thread are different. Mainly to test the HWND leak fixed by https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2302 Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1188>
-rw-r--r--tests/examples/overlay/win32-videooverlay.c149
1 files changed, 97 insertions, 52 deletions
diff --git a/tests/examples/overlay/win32-videooverlay.c b/tests/examples/overlay/win32-videooverlay.c
index 2c4c45d0d..1a3eb1ec2 100644
--- a/tests/examples/overlay/win32-videooverlay.c
+++ b/tests/examples/overlay/win32-videooverlay.c
@@ -29,11 +29,15 @@
#include <string.h>
static GMainLoop *loop = NULL;
+static GMainLoop *pipeline_loop = NULL;
static gboolean visible = FALSE;
static gboolean test_reuse = FALSE;
static HWND hwnd = NULL;
static gboolean test_fullscreen = FALSE;
static gboolean fullscreen = FALSE;
+static gchar *video_sink = NULL;
+static gboolean run_thread = FALSE;
+
static LONG prev_style = 0;
static RECT prev_rect = { 0, };
@@ -126,9 +130,12 @@ window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_DESTROY:
hwnd = NULL;
- if (loop) {
+ if (loop)
g_main_loop_quit (loop);
- }
+
+ if (pipeline_loop)
+ g_main_loop_quit (pipeline_loop);
+
return 0;
case WM_KEYUP:
if (!test_fullscreen)
@@ -208,21 +215,97 @@ timeout_cb (gpointer user_data)
return G_SOURCE_REMOVE;
}
-gint
-main (gint argc, gchar ** argv)
+static gpointer
+pipeline_runner_func (gpointer user_data)
{
GstElement *pipeline, *src, *sink;
GstStateChangeReturn sret;
+ gint num_repeat = 0;
+ GMainContext *context = NULL;
+ GMainLoop *this_loop;
+
+ if (run_thread) {
+ /* We are in runner thread, create our loop */
+ context = g_main_context_new ();
+ pipeline_loop = g_main_loop_new (context, FALSE);
+
+ g_main_context_push_thread_default (context);
+
+ this_loop = pipeline_loop;
+ } else {
+ this_loop = loop;
+ }
+
+ /* prepare the pipeline */
+ pipeline = gst_pipeline_new ("win32-overlay");
+ src = gst_element_factory_make ("videotestsrc", NULL);
+ sink = gst_element_factory_make (video_sink, NULL);
+
+ if (!sink) {
+ g_printerr ("%s element is not available\n", video_sink);
+ exit (1);
+ }
+
+ gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
+ gst_element_link (src, sink);
+
+ gst_bus_add_watch (GST_ELEMENT_BUS (pipeline), bus_msg, pipeline);
+
+ do {
+ gst_print ("Running loop %d\n", num_repeat++);
+
+ gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink),
+ (guintptr) hwnd);
+
+ sret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ if (sret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Pipeline doesn't want to pause\n");
+ break;
+ } else {
+ /* add timer to repeat and reuse pipeline */
+ if (test_reuse) {
+ GSource *timeout_source = g_timeout_source_new_seconds (3);
+
+ g_source_set_callback (timeout_source,
+ (GSourceFunc) timeout_cb, this_loop, NULL);
+ g_source_attach (timeout_source, NULL);
+ g_source_unref (timeout_source);
+ }
+
+ g_main_loop_run (this_loop);
+ }
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ visible = FALSE;
+ } while (test_reuse);
+
+ gst_bus_remove_watch (GST_ELEMENT_BUS (pipeline));
+ gst_object_unref (pipeline);
+
+ if (run_thread) {
+ g_main_context_pop_thread_default (context);
+ g_main_context_unref (context);
+
+ g_main_loop_quit (loop);
+ g_main_loop_unref (pipeline_loop);
+ }
+
+ return NULL;
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
WNDCLASSEX wc = { 0, };
HINSTANCE hinstance = GetModuleHandle (NULL);
GIOChannel *msg_io_channel;
GOptionContext *option_ctx;
GError *error = NULL;
- gchar *video_sink = NULL;
gchar *title = NULL;
RECT wr = { 0, 0, 320, 240 };
gint exitcode = 0;
gboolean ret;
+ GThread *thread = NULL;
GOptionEntry options[] = {
{"videosink", 0, 0, G_OPTION_ARG_STRING, &video_sink,
"Video sink to use (default is glimagesink)", NULL}
@@ -234,9 +317,11 @@ main (gint argc, gchar ** argv)
"Test full screen (borderless topmost) mode switching via "
"\"SPACE\" key or \"right mouse button\" click", NULL}
,
+ {"run-thread", 0, 0, G_OPTION_ARG_NONE, &run_thread,
+ "Run pipeline from non-window thread", NULL}
+ ,
{NULL}
};
- gint num_repeat = 0;
option_ctx = g_option_context_new ("WIN32 video overlay example");
g_option_context_add_main_entries (option_ctx, options, NULL);
@@ -276,58 +361,18 @@ 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);
- /* prepare the pipeline */
- pipeline = gst_pipeline_new ("win32-overlay");
- src = gst_element_factory_make ("videotestsrc", NULL);
- sink = gst_element_factory_make (video_sink, NULL);
-
- if (!sink) {
- g_printerr ("%s element is not available\n", video_sink);
- exitcode = 1;
-
- goto terminate;
+ if (run_thread) {
+ thread = g_thread_new ("pipeline-thread",
+ (GThreadFunc) pipeline_runner_func, NULL);
+ g_main_loop_run (loop);
+ } else {
+ pipeline_runner_func (NULL);
}
- gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
- gst_element_link (src, sink);
-
- gst_bus_add_watch (GST_ELEMENT_BUS (pipeline), bus_msg, pipeline);
-
- do {
- gst_print ("Running loop %d\n", num_repeat++);
-
- gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink),
- (guintptr) hwnd);
-
- sret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
- if (sret == GST_STATE_CHANGE_FAILURE) {
- g_printerr ("Pipeline doesn't want to pause\n");
- break;
- } else {
- /* add timer to repeat and reuse pipeline */
- if (test_reuse) {
- GSource *timeout_source = g_timeout_source_new_seconds (3);
-
- g_source_set_callback (timeout_source,
- (GSourceFunc) timeout_cb, loop, NULL);
- g_source_attach (timeout_source, NULL);
- g_source_unref (timeout_source);
- }
-
- g_main_loop_run (loop);
- }
- gst_element_set_state (pipeline, GST_STATE_NULL);
-
- visible = FALSE;
- } while (test_reuse);
-
- gst_bus_remove_watch (GST_ELEMENT_BUS (pipeline));
-
terminate:
if (hwnd)
DestroyWindow (hwnd);
- gst_object_unref (pipeline);
g_io_channel_unref (msg_io_channel);
g_main_loop_unref (loop);
g_free (title);