【2018.03.12更新】GStreamer在GTK窗口实现指定功能黑屏求助
解决GTK+窗口中GStreamer RTP H264流黑屏问题
我之前也碰到过一模一样的问题——用gst-launch能正常接收RTP H264流,但转成GTK+代码后窗口就黑屏,控制台还没输出线索。结合你的情况,我整理了几个关键的解决步骤,应该能帮到你:
核心问题:视频输出没有绑定到GTK窗口
你的gst-launch命令里用了autovideosink,这个元件会自动创建独立的系统窗口来渲染视频,所以你自己的GTK窗口自然是空的。要让视频显示在GTK窗口里,必须把GStreamer的视频输出元件和GTK控件绑定起来。
1. 替换视频输出元件,绑定到GTK控件
把autovideosink换成GStreamer提供的GTK专用输出元件gtksink(GStreamer 1.14及以上版本支持),然后把它的内置widget添加到你的GTK窗口中。这里给你一个调整后的代码片段:
#include <gtk/gtk.h> #include <gst/gst.h> #include <gst/video/videooverlay.h> static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) { GtkWidget *window = GTK_WIDGET(data); switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error(msg, &err, &debug); g_printerr("管线错误: %s\n", err->message); g_error_free(err); g_free(debug); gtk_widget_destroy(window); break; } case GST_MESSAGE_EOS: g_print("视频流结束\n"); gtk_widget_destroy(window); break; default: break; } return TRUE; } int main(int argc, char *argv[]) { gtk_init(&argc, &argv); gst_init(&argc, &argv); // 创建GTK主窗口 GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); // 创建GStreamer管线及元件 GstElement *pipeline = gst_pipeline_new("rtp-h264-player"); GstElement *udpsrc = gst_element_factory_make("udpsrc", "udp-source"); GstElement *capsfilter = gst_element_factory_make("capsfilter", "rtp-caps"); GstElement *rtph264depay = gst_element_factory_make("rtph264depay", "h264-depay"); GstElement *h264parse = gst_element_factory_make("h264parse", "h264-parse"); GstElement *decoder = gst_element_factory_make("omxh264dec", "h264-decoder"); GstElement *gtksink = gst_element_factory_make("gtksink", "gtk-video-sink"); // 检查元件是否创建成功 if (!pipeline || !udpsrc || !capsfilter || !rtph264depay || !h264parse || !decoder || !gtksink) { g_printerr("Failed to create one or more GStreamer elements!\n"); return -1; } // 设置UDPSRC端口 g_object_set(G_OBJECT(udpsrc), "port", 6000, NULL); // 设置RTP Caps(比你原来的更精确,避免匹配问题) GstCaps *caps = gst_caps_from_string( "application/x-rtp, " "media=(string)video, " "clock-rate=(int)90000, " "encoding-name=(string)H264, " "payload=(int)96" ); g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL); gst_caps_unref(caps); // 获取GTKSink的Widget并添加到窗口 GtkWidget *sink_widget; g_object_get(G_OBJECT(gtksink), "widget", &sink_widget, NULL); gtk_container_add(GTK_CONTAINER(window), sink_widget); // 链接所有元件 if (!gst_element_link_many(udpsrc, capsfilter, rtph264depay, h264parse, decoder, gtksink, NULL)) { g_printerr("Failed to link GStreamer elements!\n"); return -1; } // 监听总线消息,捕获错误和状态 GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); gst_bus_add_watch(bus, bus_call, window); gst_object_unref(bus); // 启动管线和GTK主循环 gst_element_set_state(pipeline, GST_STATE_PLAYING); gtk_widget_show_all(window); gtk_main(); // 清理资源 gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); return 0; }
2. 确保安装了GStreamer GTK插件
如果编译时提示找不到gtksink,说明你缺少对应的插件包。以Ubuntu为例,执行以下命令安装:
sudo apt install gstreamer1.0-gtk3
3. 用总线监听排查隐藏错误
你提到控制台输出缺失,这是因为没有监听GStreamer的消息总线。上面的代码里已经加入了bus_call函数,它会把管线的错误、EOS等信息打印出来,帮你定位问题(比如元件链接失败、解码器不兼容等)。
4. 尝试替换硬件解码器
如果用omxh264dec还是黑屏,可以换成软件解码器avdec_h264试试:
GstElement *decoder = gst_element_factory_make("avdec_h264", "h264-decoder");
有时候硬件解码器的输出格式和GTK sink不兼容,软件解码能绕过这个问题。
最后验证
调整完代码后,先确认你的视频源仍在往6000端口发送RTP H264流(用原来的gst-launch命令再跑一次),然后编译运行你的GTK代码,应该就能看到视频正常显示在窗口里了。
内容的提问来源于stack exchange,提问作者Njål Arne Gjermundshaug
相关产品推荐
相关产品推荐

