求助:Gstreamer1.0+GTK+3.0无法将视频嵌入指定GtkWidget,视频弹出新窗口
Hey there! Let's figure out why your video keeps opening in a new window instead of embedding into your target GtkWidget. I’ve run into similar quirks on older Ubuntu releases, so here’s what to check and fix:
1. You’re Not Properly Binding the Video Sink to Your GtkWidget’s Window Handle
Both GStreamer and LibVLC require explicit binding to your widget’s X11 window ID to embed video. Skip this step, and the library will default to creating a new window. The key detail here: you can only get a valid XID after the widget has been realized (i.e., drawn to the screen).
For GStreamer:
First, use a sink that supports X11 embedding (avoid autovideosink—it might pick a Wayland-compatible sink that doesn’t support embedding):
sink = gst_element_factory_make("xvimagesink", "video-sink"); // Use "ximagesink" if xvimagesink isn’t available on your system
Then bind the sink to your widget’s window ID, either immediately (if the widget is already realized) or via a signal callback:
// Assume your target container widget is GtkWidget *video_container; static void on_widget_realized(GtkWidget *widget, GstElement *sink) { // Grab the X11 window ID of the widget Window xwin = gdk_x11_window_get_xid(gtk_widget_get_window(widget)); // Attach the sink to the widget’s window GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(sink); gst_video_overlay_set_window_handle(overlay, xwin); } // In your main setup: if (gtk_widget_get_realized(video_container)) { // Widget is already ready—set the handle right away on_widget_realized(video_container, sink); } else { // Wait for the widget to be realized before binding g_signal_connect(video_container, "realize", G_CALLBACK(on_widget_realized), sink); }
For LibVLC:
The logic is identical—pass your widget’s XID to the media player once the widget is realized:
// Assume you have a libvlc_media_player_t *player; // And your target widget is GtkWidget *video_container; static void on_vlc_widget_realized(GtkWidget *widget, libvlc_media_player_t *player) { unsigned long xid = gdk_x11_window_get_xid(gtk_widget_get_window(widget)); libvlc_media_player_set_xwindow(player, xid); } // In your setup: if (gtk_widget_get_realized(video_container)) { on_vlc_widget_realized(video_container, player); } else { g_signal_connect(video_container, "realize", G_CALLBACK(on_vlc_widget_realized), player); }
2. Wayland Might Be Blocking Embedding (Ubuntu 17.10 Default)
Ubuntu 17.10 uses GNOME on Wayland by default, and Wayland has poor support for X11 window embedding—this is likely the root cause if both GStreamer and LibVLC behave the same way.
Fix: Switch to an Xorg session when logging in:
- At the Ubuntu login screen, click the gear icon in the bottom-right corner.
- Select Ubuntu on Xorg from the menu, then log in as usual.
3. Double-Check Your GStreamer Pipeline
If you’re using autovideosink, it might be selecting a non-embeddable sink (like waylandsink). Force it to use an X11-compatible sink as shown earlier. Also, ensure your pipeline is fully linked and set to the PLAYING state after binding the window handle.
内容的提问来源于stack exchange,提问作者Станислав Гичак

