You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:22:35