diff options
author | Seungha Yang <seungha@centricular.com> | 2021-06-03 19:15:22 +0900 |
---|---|---|
committer | Seungha Yang <seungha@centricular.com> | 2021-07-30 02:01:13 +0900 |
commit | f886766a6bdd8abd4145ab8016e3190748b9fcc2 (patch) | |
tree | d2b818cb28132d2ea133ba6b2b95a2eab4a7fece | |
parent | 32170aa6c2c46aed1a5795f62c6e458d448f65bb (diff) | |
download | gstreamer-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.c | 149 |
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); |