6

我正在嵌入式 Linux 上开发一个 C++ 应用程序,我需要在其中显示来自摄像头的视频。我使用 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 管道中使用 videobox 将视频定位在屏幕上,但问题是它从 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);
    }
}

我不知道为什么这不能正常工作。

问题是如何从控制台命令定位窗口,或者在窗口显示之前以编程方式截取窗口并设置正确的坐标,或者以某种方式让我的应用程序始终位于顶部,这样我就可以摆脱捕捉效果?

欢迎任何其他建议。

4

0 回答 0