From e3da18121f836a3ef361a8f1847f6ae30d536770 Mon Sep 17 00:00:00 2001 From: Michael Gruner Date: Thu, 1 Oct 2020 19:48:15 -0600 Subject: [PATCH] Enable a GMainLoop when capturing using GStreamer A running GMainLoop processes many events on the GLib/GStreamer world. While some things may work without it, many others wont. Examples of these are signals, timers and many other source events. The problem becomes more concerning by the fact that some GStreamer elements rely on signals to work. This commit allows the user to specify an OpenCV option to start a main loop, if needed. Since the loop blocks, this is done in a separate thread. --- modules/videoio/src/cap_gstreamer.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/modules/videoio/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp index 4d9330daf8..67c119cd36 100644 --- a/modules/videoio/src/cap_gstreamer.cpp +++ b/modules/videoio/src/cap_gstreamer.cpp @@ -54,6 +54,7 @@ #include #include +#include #include #include @@ -107,6 +108,7 @@ template<> inline void GSafePtr_release(GstBuffer** pPtr) { if (pPtr) template<> inline void GSafePtr_release(GstSample** pPtr) { if (pPtr) { gst_sample_unref(*pPtr); *pPtr = NULL; } } template<> inline void GSafePtr_release(GstBus** pPtr) { if (pPtr) { gst_object_unref(G_OBJECT(*pPtr)); *pPtr = NULL; } } template<> inline void GSafePtr_release(GstMessage** pPtr) { if (pPtr) { gst_message_unref(*pPtr); *pPtr = NULL; } } +template<> inline void GSafePtr_release(GMainLoop** pPtr) { if (pPtr) { g_main_loop_unref(*pPtr); *pPtr = NULL; } } template<> inline void GSafePtr_release(GstEncodingVideoProfile** pPtr) { if (pPtr) { gst_encoding_profile_unref(*pPtr); *pPtr = NULL; } } template<> inline void GSafePtr_release(GstEncodingContainerProfile** pPtr) { if (pPtr) { gst_object_unref(G_OBJECT(*pPtr)); *pPtr = NULL; } } @@ -194,10 +196,15 @@ public: private: bool isFailed; bool call_deinit; + bool start_loop; + GSafePtr loop; + std::thread thread; + gst_initializer() : isFailed(false) { call_deinit = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_GSTREAMER_CALL_DEINIT", false); + start_loop = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_GSTREAMER_START_MAINLOOP", false); GSafePtr err; gst_init_check(NULL, NULL, err.getRef()); @@ -215,6 +222,14 @@ private: isFailed = true; return; } + + if (start_loop) + { + loop.attach(g_main_loop_new (NULL, FALSE)); + thread = std::thread([this](){ + g_main_loop_run (loop); + }); + } } ~gst_initializer() { @@ -223,6 +238,12 @@ private: // Debug leaks: GST_LEAKS_TRACER_STACK_TRACE=1 GST_DEBUG="GST_TRACER:7" GST_TRACERS="leaks" gst_deinit(); } + + if (start_loop) + { + g_main_loop_quit(loop); + thread.join(); + } } };