无法为 xvimagesink 更改 window
Unable to change window for xvimagesink
我正在尝试显示以下管道的输出
$ gst-launch-1.0 v4l2src device="/dev/video0" ! videoconvert ! xvimagesink
到自定义 x11 window 中,意在充当所有屏幕顶部的叠加层:
如前所述 here 我可以为 GstVideoOverlay
对象设置一个 window Id,但是由于找不到它的直接接口,我将一个函数同步到消息总线每次都执行此操作的管道。
代码:
[...]
Display* d;
Window overlay;
// Func to sync call sink setting to this window on some specific bus message
static GstBusSyncReply change_window_handle (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
return GST_BUS_PASS;
XMapRaised (d, overlay);
XSync (d, FALSE);
// Setting the X11 window to be used for xvimagesink
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), overlay);
gst_message_unref (message);
return GST_BUS_DROP;
}
int main(int argc, char **argv) {
d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
XSetWindowAttributes attrs;
XVisualInfo vinfo;
[...]
overlay = XCreateWindow(
d, root,
x, y,
window_width, window_height, 0,
vinfo.depth, InputOutput,
vinfo.visual,
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
);
XMapWindow(d, overlay);
/* Creating pipeline*/
[...]
gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL);
/*Adding sync handler*/
GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) change_window_handle, pipeline, notify);
if (!gst_element_link_many (source, filter, sink, NULL)) {
g_warning ("Failed to link elements!");
}
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
[...]
}
但这不起作用。它有时甚至不启动网络摄像头,即使我在函数中注销消息,似乎管道启动得很好。
我仍然不认为这是正确的方法,但我无法弄清楚我做错了什么。
Provided brief code for readability. When I ran the window creation code and the pipeline running part as separate scripts, they work, the problem is to assign that window for the sink. let me know if you want me to add the complete script.
我对 X11 和 gstreamer 完全陌生。事实上,这是我第一次使用 C 构建如此复杂的东西。因此,我们将不胜感激。谢谢
使用无限 while 循环而不是 g_main_loop_run
,并且成功了。这个循环也可以用 XEventsQueued
代替,但我只是在无限 while 循环中这样做。
我正在尝试显示以下管道的输出
$ gst-launch-1.0 v4l2src device="/dev/video0" ! videoconvert ! xvimagesink
到自定义 x11 window 中,意在充当所有屏幕顶部的叠加层:
如前所述 here 我可以为 GstVideoOverlay
对象设置一个 window Id,但是由于找不到它的直接接口,我将一个函数同步到消息总线每次都执行此操作的管道。
代码:
[...]
Display* d;
Window overlay;
// Func to sync call sink setting to this window on some specific bus message
static GstBusSyncReply change_window_handle (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
return GST_BUS_PASS;
XMapRaised (d, overlay);
XSync (d, FALSE);
// Setting the X11 window to be used for xvimagesink
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), overlay);
gst_message_unref (message);
return GST_BUS_DROP;
}
int main(int argc, char **argv) {
d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
XSetWindowAttributes attrs;
XVisualInfo vinfo;
[...]
overlay = XCreateWindow(
d, root,
x, y,
window_width, window_height, 0,
vinfo.depth, InputOutput,
vinfo.visual,
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
);
XMapWindow(d, overlay);
/* Creating pipeline*/
[...]
gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL);
/*Adding sync handler*/
GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) change_window_handle, pipeline, notify);
if (!gst_element_link_many (source, filter, sink, NULL)) {
g_warning ("Failed to link elements!");
}
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
[...]
}
但这不起作用。它有时甚至不启动网络摄像头,即使我在函数中注销消息,似乎管道启动得很好。 我仍然不认为这是正确的方法,但我无法弄清楚我做错了什么。
Provided brief code for readability. When I ran the window creation code and the pipeline running part as separate scripts, they work, the problem is to assign that window for the sink. let me know if you want me to add the complete script.
我对 X11 和 gstreamer 完全陌生。事实上,这是我第一次使用 C 构建如此复杂的东西。因此,我们将不胜感激。谢谢
使用无限 while 循环而不是 g_main_loop_run
,并且成功了。这个循环也可以用 XEventsQueued
代替,但我只是在无限 while 循环中这样做。