#c #gstreamer #x11 #xorg #v4l2
Вопрос:
Я пытаюсь показать результат следующего конвейера
$ gst-launch-1.0 v4l2src device="/dev/video0" ! videoconvert ! xvimagesink
в пользовательское окно x11, которое предназначено для наложения поверх всех экранов:
Как уже упоминалось здесь, я могу установить идентификатор окна для GstVideoOverlay
объекта, но так как я не смог найти прямой интерфейс к нему, я синхронизировал функцию с шиной сообщений конвейера, чтобы делать это каждый раз.
код:
[...]
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, amp;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);
[...]
}
Но это не работает. Иногда он даже не запускает веб-камеру, хотя, если я выхожу из сообщений в функциях, кажется, что телефонная линия запускается просто отлично.
Я все еще не думаю, что это правильный путь, но я не могу понять, что я делаю неправильно.
Предоставлен краткий код для удобства чтения. Когда я запустил код создания окна и часть запуска конвейера как отдельные сценарии, они работают, проблема в том, чтобы назначить это окно для приемника. дайте мне знать, если вы хотите, чтобы я добавил полный сценарий.
Я совершенно новичок в X11 и gstreamer. На самом деле, это мой первый раз, когда я строю что-то такое сложное с помощью C. Так что любая помощь будет признательна. Спасибо
Ответ №1:
Использовал бесконечный цикл while вместо g_main_loop_run
, и это сработало. Этот цикл также можно было бы заменить, XEventsQueued
но я просто закончил тем, что сделал это внутри бесконечного цикла while.