Exemplo n.º 1
0
static void
gst_vdp_sink_window_update_geometry (VdpSink * vdp_sink, GstVdpWindow * window)
{
  XWindowAttributes attr;

  g_return_if_fail (window != NULL);
  g_return_if_fail (GST_IS_VDP_SINK (vdp_sink));

  /* Update the window geometry */
  g_mutex_lock (vdp_sink->x_lock);

  XGetWindowAttributes (vdp_sink->device->display, window->win, &attr);

  window->width = attr.width;
  window->height = attr.height;

  g_mutex_unlock (vdp_sink->x_lock);
}
Exemplo n.º 2
0
static void
gst_vdp_device_clear (VdpSink * vdp_sink)
{
  g_return_if_fail (GST_IS_VDP_SINK (vdp_sink));

  GST_OBJECT_LOCK (vdp_sink);
  if (vdp_sink->device == NULL) {
    GST_OBJECT_UNLOCK (vdp_sink);
    return;
  }
  GST_OBJECT_UNLOCK (vdp_sink);

  g_mutex_lock (vdp_sink->x_lock);

  g_object_unref (vdp_sink->device);
  vdp_sink->device = NULL;

  g_mutex_unlock (vdp_sink->x_lock);
}
Exemplo n.º 3
0
static gpointer
gst_vdp_sink_event_thread (VdpSink * vdp_sink)
{
  g_return_val_if_fail (GST_IS_VDP_SINK (vdp_sink), NULL);

  GST_OBJECT_LOCK (vdp_sink);
  while (vdp_sink->running) {
    GST_OBJECT_UNLOCK (vdp_sink);

    if (vdp_sink->window) {
      gst_vdp_sink_handle_xevents (vdp_sink);
    }
    g_usleep (100000);

    GST_OBJECT_LOCK (vdp_sink);
  }
  GST_OBJECT_UNLOCK (vdp_sink);

  return NULL;
}
Exemplo n.º 4
0
/* This function destroys a GstVdpWindow */
static void
gst_vdp_sink_window_destroy (VdpSink * vdp_sink, GstVdpWindow * window)
{
  g_return_if_fail (window != NULL);
  g_return_if_fail (GST_IS_VDP_SINK (vdp_sink));

  g_mutex_lock (vdp_sink->x_lock);

  /* If we did not create that window we just free the GC and let it live */
  if (window->internal)
    XDestroyWindow (vdp_sink->device->display, window->win);
  else
    XSelectInput (vdp_sink->device->display, window->win, 0);

  XSync (vdp_sink->device->display, FALSE);

  g_mutex_unlock (vdp_sink->x_lock);

  g_free (window);
}
Exemplo n.º 5
0
static GstFlowReturn
gst_vdp_sink_show_frame (GstBaseSink * bsink, GstBuffer * outbuf)
{
  VdpSink *vdp_sink = GST_VDP_SINK (bsink);
  VdpStatus status;
  GstVdpDevice *device;

  g_return_val_if_fail (GST_IS_VDP_SINK (vdp_sink), FALSE);

  /* We take the flow_lock. If expose is in there we don't want to run
     concurrently from the data flow thread */
  g_mutex_lock (vdp_sink->flow_lock);

  if (G_UNLIKELY (vdp_sink->window == NULL)) {
    g_mutex_unlock (vdp_sink->flow_lock);
    return GST_FLOW_ERROR;
  }

  device = vdp_sink->device;

  if (vdp_sink->cur_image) {
    VdpOutputSurface surface =
        GST_VDP_OUTPUT_BUFFER (vdp_sink->cur_image)->surface;
    VdpPresentationQueueStatus queue_status;
    VdpTime pres_time;

    g_mutex_lock (vdp_sink->x_lock);
    status =
        device->vdp_presentation_queue_query_surface_status (vdp_sink->
        window->queue, surface, &queue_status, &pres_time);
    g_mutex_unlock (vdp_sink->x_lock);

    if (queue_status == VDP_PRESENTATION_QUEUE_STATUS_QUEUED) {
      g_mutex_unlock (vdp_sink->flow_lock);
      return GST_FLOW_OK;
    }
  }

  /* Expose sends a NULL image, we take the latest frame */
  if (!outbuf) {
    if (vdp_sink->cur_image) {
      outbuf = vdp_sink->cur_image;
    } else {
      g_mutex_unlock (vdp_sink->flow_lock);
      return GST_FLOW_OK;
    }
  }

  gst_vdp_sink_window_update_geometry (vdp_sink, vdp_sink->window);

  g_mutex_lock (vdp_sink->x_lock);

  status = device->vdp_presentation_queue_display (vdp_sink->window->queue,
      GST_VDP_OUTPUT_BUFFER (outbuf)->surface, 0, 0, 0);
  if (status != VDP_STATUS_OK) {
    GST_ELEMENT_ERROR (vdp_sink, RESOURCE, READ,
        ("Could not display frame"),
        ("Error returned from vdpau was: %s",
            device->vdp_get_error_string (status)));

    g_mutex_unlock (vdp_sink->x_lock);
    g_mutex_unlock (vdp_sink->flow_lock);
    return GST_FLOW_ERROR;
  }


  if (!vdp_sink->cur_image)
    vdp_sink->cur_image = gst_buffer_ref (outbuf);

  else if (vdp_sink->cur_image != outbuf) {
    gst_buffer_unref (vdp_sink->cur_image);
    vdp_sink->cur_image = gst_buffer_ref (outbuf);
  }

  XSync (vdp_sink->device->display, FALSE);

  g_mutex_unlock (vdp_sink->x_lock);
  g_mutex_unlock (vdp_sink->flow_lock);

  return GST_FLOW_OK;
}
Exemplo n.º 6
0
/* This function handles XEvents that might be in the queue. It generates
   GstEvent that will be sent upstream in the pipeline to handle interactivity
   and navigation.*/
static void
gst_vdp_sink_handle_xevents (VdpSink * vdp_sink)
{
  XEvent e;
  guint pointer_x = 0, pointer_y = 0;
  gboolean pointer_moved = FALSE;
  gboolean exposed = FALSE, configured = FALSE;

  g_return_if_fail (GST_IS_VDP_SINK (vdp_sink));

  /* Then we get all pointer motion events, only the last position is
     interesting. */
  g_mutex_lock (vdp_sink->flow_lock);
  g_mutex_lock (vdp_sink->x_lock);
  while (XCheckWindowEvent (vdp_sink->device->display,
          vdp_sink->window->win, PointerMotionMask, &e)) {
    g_mutex_unlock (vdp_sink->x_lock);
    g_mutex_unlock (vdp_sink->flow_lock);

    switch (e.type) {
      case MotionNotify:
        pointer_x = e.xmotion.x;
        pointer_y = e.xmotion.y;
        pointer_moved = TRUE;
        break;
      default:
        break;
    }
    g_mutex_lock (vdp_sink->flow_lock);
    g_mutex_lock (vdp_sink->x_lock);
  }

  if (pointer_moved) {
    g_mutex_unlock (vdp_sink->x_lock);
    g_mutex_unlock (vdp_sink->flow_lock);

    GST_DEBUG ("vdp_sink pointer moved over window at %d,%d",
        pointer_x, pointer_y);
    gst_navigation_send_mouse_event (GST_NAVIGATION (vdp_sink),
        "mouse-move", 0, pointer_x, pointer_y);

    g_mutex_lock (vdp_sink->flow_lock);
    g_mutex_lock (vdp_sink->x_lock);
  }

  /* We get all remaining events on our window to throw them upstream */
  while (XCheckWindowEvent (vdp_sink->device->display,
          vdp_sink->window->win,
          KeyPressMask | KeyReleaseMask |
          ButtonPressMask | ButtonReleaseMask, &e)) {
    KeySym keysym;

    /* We lock only for the X function call */
    g_mutex_unlock (vdp_sink->x_lock);
    g_mutex_unlock (vdp_sink->flow_lock);

    switch (e.type) {
      case ButtonPress:
        /* Mouse button pressed/released over our window. We send upstream
           events for interactivity/navigation */
        GST_DEBUG ("vdp_sink button %d pressed over window at %d,%d",
            e.xbutton.button, e.xbutton.x, e.xbutton.x);
        gst_navigation_send_mouse_event (GST_NAVIGATION (vdp_sink),
            "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
        break;
      case ButtonRelease:
        GST_DEBUG ("vdp_sink button %d release over window at %d,%d",
            e.xbutton.button, e.xbutton.x, e.xbutton.x);
        gst_navigation_send_mouse_event (GST_NAVIGATION (vdp_sink),
            "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
        break;
      case KeyPress:
      case KeyRelease:
        /* Key pressed/released over our window. We send upstream
           events for interactivity/navigation */
        GST_DEBUG ("vdp_sink key %d pressed over window at %d,%d",
            e.xkey.keycode, e.xkey.x, e.xkey.x);
        g_mutex_lock (vdp_sink->x_lock);
        keysym =
            XKeycodeToKeysym (vdp_sink->device->display, e.xkey.keycode, 0);
        g_mutex_unlock (vdp_sink->x_lock);
        if (keysym != NoSymbol) {
          char *key_str = NULL;

          g_mutex_lock (vdp_sink->x_lock);
          key_str = XKeysymToString (keysym);
          g_mutex_unlock (vdp_sink->x_lock);
          gst_navigation_send_key_event (GST_NAVIGATION (vdp_sink),
              e.type == KeyPress ? "key-press" : "key-release", key_str);

        } else {
          gst_navigation_send_key_event (GST_NAVIGATION (vdp_sink),
              e.type == KeyPress ? "key-press" : "key-release", "unknown");
        }
        break;
      default:
        GST_DEBUG_OBJECT (vdp_sink, "vdp_sink unhandled X event (%d)", e.type);
    }
    g_mutex_lock (vdp_sink->flow_lock);
    g_mutex_lock (vdp_sink->x_lock);
  }

  while (XCheckWindowEvent (vdp_sink->device->display,
          vdp_sink->window->win, ExposureMask | StructureNotifyMask, &e)) {
    switch (e.type) {
      case Expose:
        exposed = TRUE;
        break;
      case ConfigureNotify:
        configured = TRUE;
        break;
      default:
        break;
    }
  }

  if (vdp_sink->handle_expose && (exposed || configured)) {
    g_mutex_unlock (vdp_sink->x_lock);
    g_mutex_unlock (vdp_sink->flow_lock);

    gst_vdp_sink_expose (GST_X_OVERLAY (vdp_sink));

    g_mutex_lock (vdp_sink->flow_lock);
    g_mutex_lock (vdp_sink->x_lock);
  }

  /* Handle Display events */
  while (XPending (vdp_sink->device->display)) {
    XNextEvent (vdp_sink->device->display, &e);

    switch (e.type) {
      case ClientMessage:{
        Atom wm_delete;

        wm_delete = XInternAtom (vdp_sink->device->display,
            "WM_DELETE_WINDOW", False);
        if (wm_delete == (Atom) e.xclient.data.l[0]) {
          /* Handle window deletion by posting an error on the bus */
          GST_ELEMENT_ERROR (vdp_sink, RESOURCE, NOT_FOUND,
              ("Output window was closed"), (NULL));

          g_mutex_unlock (vdp_sink->x_lock);
          gst_vdp_sink_window_destroy (vdp_sink, vdp_sink->window);
          vdp_sink->window = NULL;
          g_mutex_lock (vdp_sink->x_lock);
        }
        break;
      }
      default:
        break;
    }
  }

  g_mutex_unlock (vdp_sink->x_lock);
  g_mutex_unlock (vdp_sink->flow_lock);
}
Exemplo n.º 7
0
/* This function handles a GstVdpWindow creation */
static GstVdpWindow *
gst_vdp_sink_window_new (VdpSink * vdp_sink, gint width, gint height)
{
  GstVdpWindow *window = NULL;
  GstVdpDevice *device = vdp_sink->device;

  Window root;
  gint screen_num;
  gulong black;

  VdpStatus status;
  VdpColor color = { 0, };

  g_return_val_if_fail (GST_IS_VDP_SINK (vdp_sink), NULL);

  window = g_new0 (GstVdpWindow, 1);

  window->width = width;
  window->height = height;
  window->internal = TRUE;

  g_mutex_lock (vdp_sink->x_lock);

  screen_num = DefaultScreen (device->display);
  root = DefaultRootWindow (device->display);
  black = XBlackPixel (device->display, screen_num);

  window->win = XCreateSimpleWindow (vdp_sink->device->display,
      root, 0, 0, window->width, window->height, 0, 0, black);

  /* We have to do that to prevent X from redrawing the background on 
     ConfigureNotify. This takes away flickering of video when resizing. */
  XSetWindowBackgroundPixmap (vdp_sink->device->display, window->win, None);

  /* set application name as a title */
  gst_vdp_sink_window_set_title (vdp_sink, window, NULL);

  if (vdp_sink->handle_events) {
    Atom wm_delete;

    XSelectInput (vdp_sink->device->display, window->win, ExposureMask |
        StructureNotifyMask | PointerMotionMask | KeyPressMask |
        KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);

    /* Tell the window manager we'd like delete client messages instead of
     * being killed */
    wm_delete =
        XInternAtom (vdp_sink->device->display, "WM_DELETE_WINDOW", False);
    (void) XSetWMProtocols (vdp_sink->device->display, window->win, &wm_delete,
        1);
  }

  XMapRaised (vdp_sink->device->display, window->win);

  XSync (vdp_sink->device->display, FALSE);

  g_mutex_unlock (vdp_sink->x_lock);

  gst_vdp_sink_window_decorate (vdp_sink, window);

  status = device->vdp_presentation_queue_target_create_x11 (device->device,
      window->win, &window->target);
  if (status != VDP_STATUS_OK) {
    GST_ELEMENT_ERROR (vdp_sink, RESOURCE, READ,
        ("Could not create presentation target"),
        ("Error returned from vdpau was: %s",
            device->vdp_get_error_string (status)));
  }

  status =
      device->vdp_presentation_queue_create (device->device, window->target,
      &window->queue);
  if (status != VDP_STATUS_OK) {
    GST_ELEMENT_ERROR (vdp_sink, RESOURCE, READ,
        ("Could not create presentation queue"),
        ("Error returned from vdpau was: %s",
            device->vdp_get_error_string (status)));
  }

  status =
      device->vdp_presentation_queue_set_background_color (window->queue,
      &color);
  if (status != VDP_STATUS_OK) {
    GST_ELEMENT_ERROR (vdp_sink, RESOURCE, READ,
        ("Could not set background color"),
        ("Error returned from vdpau was: %s",
            device->vdp_get_error_string (status)));
  }

  gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (vdp_sink), window->win);

  return window;
}
/* This function handles a GstVdpWindow creation */
static GstVdpWindow *
gst_vdp_sink_window_new (VdpSink * vdp_sink, gint width, gint height)
{
  GstVdpDevice *device = vdp_sink->device;
  GstVdpWindow *window = NULL;

  Window root;
  gint screen_num;
  gulong black;

  g_return_val_if_fail (GST_IS_VDP_SINK (vdp_sink), NULL);

  window = g_new0 (GstVdpWindow, 1);

  window->width = width;
  window->height = height;
  window->internal = TRUE;

  g_mutex_lock (vdp_sink->x_lock);

  screen_num = DefaultScreen (device->display);
  root = DefaultRootWindow (device->display);
  black = XBlackPixel (device->display, screen_num);

  window->win = XCreateSimpleWindow (vdp_sink->device->display,
      root, 0, 0, window->width, window->height, 0, 0, black);

  /* We have to do that to prevent X from redrawing the background on 
     ConfigureNotify. This takes away flickering of video when resizing. */
  XSetWindowBackgroundPixmap (vdp_sink->device->display, window->win, None);

  /* set application name as a title */
  gst_vdp_sink_window_set_title (vdp_sink, window, NULL);

  if (vdp_sink->handle_events) {
    Atom wm_delete;

    XSelectInput (vdp_sink->device->display, window->win, ExposureMask |
        StructureNotifyMask | PointerMotionMask | KeyPressMask |
        KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);

    /* Tell the window manager we'd like delete client messages instead of
     * being killed */
    wm_delete =
        XInternAtom (vdp_sink->device->display, "WM_DELETE_WINDOW", False);
    (void) XSetWMProtocols (vdp_sink->device->display, window->win, &wm_delete,
        1);
  }

  XMapRaised (vdp_sink->device->display, window->win);

  XSync (vdp_sink->device->display, FALSE);

  g_mutex_unlock (vdp_sink->x_lock);

  gst_vdp_sink_window_decorate (vdp_sink, window);
  gst_vdp_sink_window_setup_vdpau (vdp_sink, window);

  gst_x_overlay_got_window_handle (GST_X_OVERLAY (vdp_sink),
      (guintptr) window->win);

  return window;
}