GTK4中如何无内存泄漏地顺序渲染视频组件?
解决GTK4循环视频轮播的内存泄漏问题
你的核心问题是切换视频时,旧的媒体流资源没有被彻底释放——虽然你对新流做了g_object_unref,但旧的GtkMediaStream实例还被GStreamer内部资源引用,无法被自动回收,导致内存持续上涨。
修复方案
在切换新视频前,必须主动停止旧媒体流的播放,并强制释放其关联的所有资源,具体步骤:
- 获取当前GtkVideo正在使用的媒体流
- 停止流的播放
- 强制销毁流的内部资源(避免GStreamer侧残留引用)
- 释放流的引用
修改后的完整代码
#include <gtk/gtk.h> #include <string> static gboolean switch_video(gpointer user_data) { static bool toggle = false; GtkVideo *video = GTK_VIDEO(user_data); // 处理旧媒体流:停止+销毁+释放 GtkMediaStream *old_stream = gtk_video_get_media_stream(video); if (old_stream != NULL) { gtk_media_stream_stop(old_stream); // 强制销毁内部资源,确保GStreamer pipeline被清理 g_object_run_dispose(G_OBJECT(old_stream)); g_object_unref(old_stream); } // 创建并设置新媒体流 std::string path = toggle ? "files/video1.mp4" : "files/video2.mp4"; GtkMediaStream *new_media_file = GTK_MEDIA_STREAM(gtk_media_file_new_for_filename(path.c_str())); gtk_video_set_media_stream(video, new_media_file); gtk_media_stream_play(new_media_file); // 这里unref是对的,因为GtkVideo会持有新流的引用 g_object_unref(new_media_file); toggle = !toggle; return TRUE; } static void activate(GtkApplication *app, gpointer user_data) { GtkWidget *window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window), "GTK4 Video Player"); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); GtkWidget *video = gtk_video_new(); gtk_window_set_child(GTK_WINDOW(window), video); gtk_widget_show(window); g_timeout_add_seconds(5, switch_video, video); } int main(int argc, char *argv[]) { GtkApplication *app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }
关键说明
g_object_run_dispose:这个函数会强制销毁对象的所有内部子对象(比如GStreamer的pipeline、解码器等),避免这些资源因为隐式引用无法被GC回收,这是解决内存泄漏的核心步骤。- 必须先调用
gtk_media_stream_stop:如果流还在播放状态,直接销毁会导致资源无法正常释放,所以要先停止播放。
内容的提问来源于stack exchange,提问作者Éloïk Rousseau
相关产品推荐
相关产品推荐

