cgstreamerx11xorgv4l2

Unable to change window for xvimagesink


I am trying to show the output of the following pipeline

$ gst-launch-1.0 v4l2src device="/dev/video0" ! videoconvert ! xvimagesink

into a custom x11 window that is meant to act as an overlay on top of all screens: overlay window

As mentioned here I can set a window Id to the GstVideoOverlay object but since I couldn't find a direct interface to it I synced a function to the message bus of the pipeline to do it everytime.

code:

[...]
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, &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);

  [...]
}

But this does not work. It sometimes even does not start the webcam, even though if I log out the messages in the functions, it seems like the pipline is starting just fine. I still don't think it is the right way, but I can't figure out what I am doing wrong.

Provided brief code for readability. When I ran the window creation code and the pipeline running part as separate scripts, they work, the problem is to assign that window for the sink. let me know if you want me to add the complete script.

I am completely new to X11 and gstreamer. In fact, this is my first time building something this complex with C. So any help is appreciated. Thanks


Solution

  • Used an infinite while loop instead of g_main_loop_run and it worked. This loop could also be replaced with XEventsQueued but I just ended up doing that inside the infinite while loop.