mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-28 03:45:39 +00:00
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>
This commit is contained in:
parent
32170aa6c2
commit
f886766a6b
1 changed files with 97 additions and 52 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue