使用GtkVideo在GTK4窗口播放视频遇空白屏问题求助
GTK4 GtkVideo播放视频空白问题解决方法及替代方案
问题排查与修复步骤
1. 检查依赖组件
GtkVideo依赖GStreamer提供媒体解码能力,缺失对应插件会导致视频无法加载:
- Debian/Ubuntu系统执行:
sudo apt install gstreamer1.0-gtk4 gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-libav - Fedora/RHEL系统执行:
sudo dnf install gtk4-gstreamer gstreamer1-plugins-good gstreamer1-plugins-bad-free gstreamer1-libav
2. 修正原代码问题
原代码存在几处关键问题:
gtk_media_stream_play调用时机过早,媒体资源尚未加载完成- 存在不必要的
return 0(activate为void类型函数) - 未释放
g_file_new_for_path创建的GFile对象(内存泄漏)
修正后的代码:
#include <gtk/gtk.h> static void activate(GtkApplication *app, gpointer user_data) { GtkWidget *window; GtkWidget *video; GFile *file; // 创建主应用窗口 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); // 创建GtkVideo并启用自动播放 video = gtk_video_new(); gtk_video_set_autoplay(GTK_VIDEO(video), TRUE); // 加载视频文件并释放资源 file = g_file_new_for_path("my_video.mp4"); gtk_video_set_file(GTK_VIDEO(video), file); g_object_unref(file); // 将视频部件添加到窗口 gtk_window_set_child(GTK_WINDOW(window), video); // 显示窗口 gtk_widget_show(window); } int main(int argc, char *argv[]) { GtkApplication *app; int status; app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }
3. 编译与运行
使用pkg-config链接必要库进行编译:
gcc -o gtk4-video-player gtk4-video-player.c $(pkg-config --cflags --libs gtk4 gstreamer-1.0 gstreamer-video-1.0)
确保my_video.mp4位于程序运行的当前目录,或替换为绝对路径后执行程序。
替代方案:直接使用GStreamer GTK4 Sink
如果GtkVideo仍无法正常工作,可以直接基于GStreamer构建播放管道,示例代码如下:
#include <gtk/gtk.h> #include <gst/gst.h> #include <gst/video/videooverlay.h> static GstElement *pipeline; static void activate(GtkApplication *app, gpointer user_data) { GtkWidget *window; GtkWidget *video_widget; GstElement *source, *decodebin, *videoconvert, *sink; // 创建主窗口 window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window), "GStreamer GTK4 Player"); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); // 初始化GStreamer管道元素 pipeline = gst_pipeline_new("video-pipeline"); source = gst_element_factory_make("filesrc", "file-source"); decodebin = gst_element_factory_make("decodebin3", "decoder"); videoconvert = gst_element_factory_make("videoconvert", "converter"); sink = gst_element_factory_make("gtk4sink", "video-sink"); if (!pipeline || !source || !decodebin || !videoconvert || !sink) { g_printerr("Failed to create GStreamer elements\n"); return; } // 设置视频文件路径 g_object_set(source, "location", "my_video.mp4", NULL); // 获取GTK播放部件并添加到窗口 g_object_get(sink, "widget", &video_widget, NULL); gtk_window_set_child(GTK_WINDOW(window), video_widget); // 将元素添加到管道 gst_bin_add_many(GST_BIN(pipeline), source, decodebin, videoconvert, sink, NULL); // 链接源元素与解码器 if (!gst_element_link(source, decodebin)) { g_printerr("Failed to link source and decodebin\n"); gst_object_unref(pipeline); return; } // 处理解码器的pad-added信号,动态链接到转换元素 g_signal_connect(decodebin, "pad-added", G_CALLBACK( (void (*)(GstElement*, GstPad*, gpointer)) ([](GstElement *decodebin, GstPad *pad, gpointer data) { GstElement *videoconvert = data; GstPad *sink_pad = gst_element_get_static_pad(videoconvert, "sink"); if (gst_pad_is_compatible(pad, sink_pad)) { gst_pad_link(pad, sink_pad); } gst_object_unref(sink_pad); }), videoconvert); // 链接转换元素与输出sink if (!gst_element_link(videoconvert, sink)) { g_printerr("Failed to link videoconvert and sink\n"); gst_object_unref(pipeline); return; } // 启动播放管道 gst_element_set_state(pipeline, GST_STATE_PLAYING); // 显示窗口 gtk_widget_show(window); // 窗口关闭时停止管道并释放资源 g_signal_connect(window, "destroy", G_CALLBACK( (void (*)(GtkWidget*, gpointer)) ([](GtkWidget *window, gpointer data) { GstElement *pipeline = data; gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); }), pipeline); } int main(int argc, char *argv[]) { GtkApplication *app; int status; // 初始化GStreamer gst_init(&argc, &argv); app = gtk_application_new("org.gtk.gstreamer-example", G_APPLICATION_FLAGS_NONE); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); return status; }
编译命令:
gcc -o gstreamer-gtk4-player gstreamer-gtk4-player.c $(pkg-config --cflags --libs gtk4 gstreamer-1.0 gstreamer-video-1.0)
内容的提问来源于stack exchange,提问作者teena meheren
相关产品推荐
相关产品推荐

