Не удается изменить окно для xvimagesink

#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.