Hello
Despite my best efforts, I cannot see this issue (if it is indeed an issue!) mentioned anywhere online. I'll go into as much detail as I can, though I hope it's unnecessary in that it'll just turn out to be silly user error.
---
I maintain a GTK-based application, written in C++. More recently we are testing the waters for a Python version; the issue appears in both. I have confirmed this behaviour on both a CM4 and a full Pi 5 with the most recent release of Pi OS (Nov 2024). I have not tested on non-Pi devices, nor on non-Pi-OS OSes. The images are completely stock apart from the libraries needed to compile Gtkmm et al., and the gstreamer Gtk and GL plugins. Oh, and for completeness' sake, tmux.
One of the newer features of the application is to be able to show a video only some of the time. In other words: it must be created, played, and then destroyed. As the application is intended to run indefinitely, this means during its lifetime the above cycle could (or rather will) be repeated an arbitrary number of times.
I have implemented the above fairly trivially using a Gtk::MediaStream + Gtk::Picture as I do not care about the playback controls provided with Gtk::Video; the issue happens in both setups, though and the example code below uses Gtk::Video for simplicity.
The issue appears to be that when the above Widgets are destroyed, the underlying resources are not. In the example below, I create the video and then delete it repeatedly. If you observe /proc/xxxx/fd during this time, you will see the directory gradually filling with descriptors that are not cleared. If you run ps -L -p xxxx, you will see gstreamer threads repeatedly being created but then never finishing. If you observe top you will see subprocesses remaining open and memory remaining filled. I have had a look in the GTK debugger, and although it's a bit awkward to find, I think I can see that the ref count of some GObjects relating to the video never go to zero (but I may be misinterpreting this).
If allowed to continue long enough, the entire system will just give up (understandable really).
I have tried re-encoding the video, though this is not really my area of knowledge so have not explored this much. I have also tried to use gstreamer directly, but that had its own issues (I think unreleated to the one this post is about), but ideally I'd want to use Gtk stock widgets wherever possible.
I have attached Python and C++ examples. For both, please provide the filepath to a video as the first argument.
I use (replace VideoTest with Python for the python version, assuming you only have one python application running)
I would be greatful for any insight anyone can provide, even if it's just me being an idiot and not understanding how all of this works.
Thanks!
PythonC++CMake
Despite my best efforts, I cannot see this issue (if it is indeed an issue!) mentioned anywhere online. I'll go into as much detail as I can, though I hope it's unnecessary in that it'll just turn out to be silly user error.
---
I maintain a GTK-based application, written in C++. More recently we are testing the waters for a Python version; the issue appears in both. I have confirmed this behaviour on both a CM4 and a full Pi 5 with the most recent release of Pi OS (Nov 2024). I have not tested on non-Pi devices, nor on non-Pi-OS OSes. The images are completely stock apart from the libraries needed to compile Gtkmm et al., and the gstreamer Gtk and GL plugins. Oh, and for completeness' sake, tmux.
One of the newer features of the application is to be able to show a video only some of the time. In other words: it must be created, played, and then destroyed. As the application is intended to run indefinitely, this means during its lifetime the above cycle could (or rather will) be repeated an arbitrary number of times.
I have implemented the above fairly trivially using a Gtk::MediaStream + Gtk::Picture as I do not care about the playback controls provided with Gtk::Video; the issue happens in both setups, though and the example code below uses Gtk::Video for simplicity.
The issue appears to be that when the above Widgets are destroyed, the underlying resources are not. In the example below, I create the video and then delete it repeatedly. If you observe /proc/xxxx/fd during this time, you will see the directory gradually filling with descriptors that are not cleared. If you run ps -L -p xxxx, you will see gstreamer threads repeatedly being created but then never finishing. If you observe top you will see subprocesses remaining open and memory remaining filled. I have had a look in the GTK debugger, and although it's a bit awkward to find, I think I can see that the ref count of some GObjects relating to the video never go to zero (but I may be misinterpreting this).
If allowed to continue long enough, the entire system will just give up (understandable really).
I have tried re-encoding the video, though this is not really my area of knowledge so have not explored this much. I have also tried to use gstreamer directly, but that had its own issues (I think unreleated to the one this post is about), but ideally I'd want to use Gtk stock widgets wherever possible.
I have attached Python and C++ examples. For both, please provide the filepath to a video as the first argument.
I use (replace VideoTest with Python for the python version, assuming you only have one python application running)
to quantify the threads associated with the applications, andps -L -p $(pgrep VideoTest) | wc -l
to quantify the fds.ls /proc/$(pgrep VideoTest)/fd | wc -l
I would be greatful for any insight anyone can provide, even if it's just me being an idiot and not understanding how all of this works.
Thanks!
Python
Code:
from sys import argvimport gigi.require_version("GLib", "2.0")from gi.repository import GLibgi.require_version("Gtk", "4.0")from gi.repository import Gtkdef on_activate(app): win = Gtk.ApplicationWindow(application=app) win.set_default_size(800, 600); win.present() start(win)def start(win): label = Gtk.Label() label.set_text("Let's see how this goes...") win.set_child(label) GLib.timeout_add(2000, create, win) return Falsedef create(win):[b][/b] vid = Gtk.Video() vid.set_filename(argv[1]) vid.set_autoplay(True) win.set_child(vid) GLib.timeout_add(2000, stop, (win, vid)) return Falsedef stop(user_data): win, vid = user_data vid.set_autoplay(False) vid.set_filename(None) GLib.timeout_add(2000, start, win) return Falseif len(argv) != 2: print("Provide 1 argument: the video file path."); exit(1)app = Gtk.Application(application_id='org.video.PythonExample')app.connect('activate', on_activate)app.run(None)Code:
#include <glibmm/main.h>#include <gtkmm/application.h>#include <gtkmm/label.h>#include <gtkmm/video.h>#include <gtkmm/window.h>const char * s_video_path;class Window : public Gtk::Window{ Gtk::Video * m_video; bool start(void) { auto label = Gtk::make_managed<Gtk::Label>("Let's see how this goes..."); set_child(*label); Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Window::create), 2); return false; } bool create(void) { m_video = Gtk::make_managed<Gtk::Video>(s_video_path); m_video->set_autoplay(true); set_child(*m_video); Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Window::stop), 5); return false; } bool stop(void) { m_video->set_autoplay(false); m_video->set_file(nullptr); Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Window::start), 2); return false; } public: Window() { start(); }};int main(int argc, char **argv){ if (argc != 2) { printf("Provide 1 argument: the video file path.\n"); return 1; } s_video_path = argv[1]; Glib::RefPtr<Gtk::Application> app = Gtk::Application::create("com.video.CppExample"); return app->make_window_and_run<Window>(1, argv);}Code:
cmake_minimum_required(VERSION 3.5)project(VideoTest VERSION 1.0)add_compile_options(-Wall -Wextra -pedantic -Werror -std=c++2b)find_package(PkgConfig)pkg_check_modules(GTKMM gtkmm-4.0)include_directories (${GTKMM_INCLUDE_DIRS})link_directories(${GTKMM_LIBRARY_DIRS})add_executable(VideoTest cpp_version.cc)target_link_libraries (VideoTest LINK_PUBLIC ${GTKMM_LIBRARIES})Statistics: Posted by alex-gc — Thu Apr 24, 2025 3:12 pm