基于GTK的窗口

时间:2018-04-02 12:28:04

标签: linux gstreamer x11 gtk3 xlib

我创建了一个简单的gstreamer + gtk应用程序来播放视频文件。 “filesrc”,“decodebin”,“autovideosink”,“autoaudiosink”gstreamer元素用于此。

主窗口使用gtk_window_new(GTK_WINDOW_TOPLEVEL)创建,绘图区域使用gtk_drawing_area_new()创建。绘图窗口嵌入在主窗口中。

要在gtk绘图窗口上渲染,使用gstreamer api gst_video_overlay_set_window_handle()将其句柄作为叠加层传递给gstreamer视频插件 通过这样做,视频不会被渲染,只播放音频。

如果我将XCreateWindow()句柄传递给gstreamer视频插件作为叠加层,那么一切正常,而不是GTK窗口。但我必须创建基于GTK的播放器。

现在,当我开始调试问题时,我发现了以下细节。

  1. “autovideosink”插件在mainloop线程内的XNextEvent上被阻止(幸运的是我有源代码并使用日志验证)
  2. 然后使用xtrace实用程序发现大多数X请求失败(见下文),而在XCreateWindow的情况下,所有此类请求都获得成功响应。
  3.   

    002:<:000f:52:Request(1):CreateWindow depth = 0x18 window = 0x01600001 parent = 0x01400007 x = 0 y = 0 width = 640 height = 368 border-width = 0 class = InputOutput(0x0001) visual = 0x00000021 value-list = {background-pixel = 0x00000000 border-pixel = 0x00000000 backing-store = NotUseful(0x00)override-redirect = false(0x00)colormap = CopyFromParent(0x00000000)}

         

    002:<:0010:24:Request(16):InternAtom only-if-exists = true(0x01)name ='_ NET_WM_STATE'

         

    002:>:000f:错误8 =匹配:major = 1,minor = 0,bad = 20971527

         

    002:<:001d:8:Request(3):GetWindowAttributes window = 0x01600001

         

    002:<:001e:8:Request(14):GetGeometry drawable = 0x01600001

         

    002:>:001d:错误3 =窗口:major = 3,minor = 0,bad = 23068673

         

    002:>:001e:错误9 = Drawable:major = 14,minor = 0,bad = 23068673

    我不知道为什么这些请求因GTK窗口而失败。而在我的旧系统(ubuntu 14.04)中,我可以很好地运行同一个播放器。目前的系统是ubuntu 16.04

    任何与X Server相关的配置设置都是这样做的吗? 请建议一些解决方案或任何想法如何进一步调试以捕捉真正的原因。

1 个答案:

答案 0 :(得分:0)

原型:

XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valuemask, attributes)
提到的autovideosink实际上是imxeglvivsink。 imxeglvivsink使用gtk-window作为父窗口创建子窗口(检查XCreateWindow api的第二个参数)。

现在GDK默认用于父Windodw(GTK)的Visual与X默认Visual不同,这就是X CreateWindow请求失败的原因。

我用2个解决方案解决了这个问题。

解决方案1: 在imxeglvivsink中,在创建子窗口时,我使用了' CopyFromParent'标志为' visual' XCreateWindow api的参数。通过这样做,Visual for Parent和Child匹配,X请求CreateWindow成功。

我不喜欢这个解决方案,因为我必须用我的新库替换原始的imxeglvivsink库。

解决方案2: 我的最终目标仍然是一样的。我必须为父窗口和子窗口保持相同的视觉效果。在此解决方案中,我将Visual of Parent窗口(GTK)更改为X Default Visual。我在应用程序级别进行了此更改,并且我没有依赖imxeglvivsink。更改GDK视觉的代码片段如下:

static int change_visual(GtkWidget *widget)
{
  int nitems_return;
  Display *x_display = XOpenDisplay(NULL);
  Visual *x_visual = XDefaultVisual(x_display, DefaultScreen(x_display));

  GdkScreen *gdk_screen = gdk_screen_get_default();
  GList *gdk_visual_list = gdk_screen_list_visuals(gdk_screen);
  GList *l;
  for (l = gdk_visual_list; l != NULL; l = l->next)
  {
    Visual *temp = gdk_x11_visual_get_xvisual((GdkVisual *)l->data);
    if(temp->visualid == x_visual->visualid) break;
  }
  //l is pointing the visual which is similar to system x visual. Lets change it.
  gtk_widget_set_visual (widget, (GdkVisual *)l->data);
  return 0;
}

我知道如果visualid在for循环中不匹配,我就不会小心。对我来说,我总是发现GDK视觉效果与X Default Visual相同。