Я разрабатываю приложение C ++ для встроенного Linux, и мне нужно отобразить видео с камеры в нем. Я использовал gstreamer для создания окна и запуска захвата видео (потому что он имеет аппаратную поддержку на Tegra) с помощью команды:
system("gst-launch -e v4l2src device=\"/dev/video0\" \
! \"video/x-raw-yuv,width=320,height=240\" \
! videoflip method=counterclockwise \
! nvvidconv \
! nvxvimagesink &")
Основное приложение на устройстве работает в полноэкранном режиме, поэтому мне нужно расположить это окно в определенном месте на экране, чтобы у пользователя было ощущение, что все это работает в одном и том же «окне». Мне удалось сделать это с:
XMoveWindow(display, win_video, x, y); // x, y from top left point in landscape mode!
Проблема, с которой я сталкиваюсь, заключается в том, что gst-launch сначала отображается с координатами 0, 0 (поскольку он запускается из командной строки), а затем «привязывается» к правильному месту (программно) в приложении. Я делаю это, запустив XQueryTree для поиска по всем отображаемым окнам, поиска с помощью gst-launch и перемещения его. Это занимает некоторое время и выглядит не очень хорошо, поэтому я ищу лучшие решения.
Я пытался использовать видеобокс в конвейере gst-launch для позиционирования видео на экране, но проблема в том, что он рисует черную границу от 0, 0 до окна видео (border-alpha = 0 должна решить эту проблему, но это не так — я думаю, что проблема где-то в nvvidconv или nvxvimagesink, но у меня нет возможности узнать):
gst-launch -e v4l2src device="/dev/video0" ! "video/x-raw-yuv,width=320,height=240" ! videobox border-alpha=0 top=-50 left=-50 ! nvvidconv ! nvxvimagesink
Второе решение состояло в том, что я установил главное окно своего приложения как всегда сверху, и после того, как я нашел видеоокно, переместил его в положение, затем вернул основное приложение в нормальное положение и переместил окно видео сверху.
Я попробовал два метода, которые я нашел здесь, чтобы установить всегда на вершине, но оба не работали.
Первый:
Status x11_window_set_on_top (Display* display, Window xid)
{
XEvent event;
event.xclient.type = ClientMessage;
event.xclient.serial = 0;
event.xclient.send_event = True;
event.xclient.display = display;
event.xclient.window = xid;
event.xclient.message_type = XInternAtom (display, "_NET_WM_STATE", False);
event.xclient.format = 32;
event.xclient.data.l[0] = _NET_WM_STATE_ADD;
event.xclient.data.l[1] = XInternAtom (display, "_NET_WM_STATE_ABOVE", False);
event.xclient.data.l[2] = 0; //unused.
event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = 0;
return XSendEvent (display,
DefaultRootWindow(display),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&event);
}
Во-вторых:
void Keep_Window_Always_Top(Display *dpy, Window w)
{
Atom stateAbove;
if (w) {
stateAbove = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False);
XChangeProperty(dpy, w, XInternAtom(dpy, "_NET_WM_STATE", False), XA_ATOM, 32, PropModeReplace, (unsigned char *) &stateAbove, 1);
}
}
Я не знаю, почему это не работает так, как должно.
Вопрос в том, как расположить окно из консольной команды или программно перехватить окно, прежде чем оно отобразится, и установить для него правильные координаты, или каким-то образом заставить мое приложение всегда находиться сверху, чтобы я мог избавиться от эффекта привязки?
Любые другие предложения приветствуются.
Задача ещё не решена.