static gboolean
gst_vaapi_window_wayland_create (GstVaapiWindow * window,
                                 guint * width, guint * height)
{
    GstVaapiWindowWaylandPrivate *const priv =
        GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
    GstVaapiDisplayWaylandPrivate *const priv_display =
        GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (GST_VAAPI_OBJECT_DISPLAY (window));

    GST_DEBUG ("create window, size %ux%u", *width, *height);

    g_return_val_if_fail (priv_display->compositor != NULL, FALSE);
    g_return_val_if_fail (priv_display->shell != NULL, FALSE);

    GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
    priv->event_queue = wl_display_create_queue (priv_display->wl_display);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
    if (!priv->event_queue)
        return FALSE;

    GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
    priv->surface = wl_compositor_create_surface (priv_display->compositor);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
    if (!priv->surface)
        return FALSE;
    wl_proxy_set_queue ((struct wl_proxy *) priv->surface, priv->event_queue);

    GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
    priv->shell_surface =
        wl_shell_get_shell_surface (priv_display->shell, priv->surface);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
    if (!priv->shell_surface)
        return FALSE;
    wl_proxy_set_queue ((struct wl_proxy *) priv->shell_surface,
                        priv->event_queue);

    wl_shell_surface_add_listener (priv->shell_surface,
                                   &shell_surface_listener, priv);
    wl_shell_surface_set_toplevel (priv->shell_surface);

    priv->poll = gst_poll_new (TRUE);
    gst_poll_fd_init (&priv->pollfd);

    if (priv->fullscreen_on_show)
        gst_vaapi_window_wayland_set_fullscreen (window, TRUE);

    priv->surface_format = GST_VIDEO_FORMAT_ENCODED;
    priv->use_vpp = GST_VAAPI_DISPLAY_HAS_VPP (GST_VAAPI_OBJECT_DISPLAY (window));
    priv->is_shown = TRUE;

    return TRUE;
}
/**
 * gst_vaapi_subpicture_set_global_alpha:
 * @subpicture: a #GstVaapiSubpicture
 * @global_alpha: value for global-alpha (range: 0.0 to 1.0, inclusive)
 *
 * Sets the global_alpha value of @subpicture. This function calls
 * vaSetSubpictureGlobalAlpha() if the format of @subpicture, i.e.
 * the current VA driver supports it.
 *
 * Return value: %TRUE if global_alpha could be set, %FALSE otherwise
 */
gboolean
gst_vaapi_subpicture_set_global_alpha (GstVaapiSubpicture * subpicture,
    gfloat global_alpha)
{
  GstVaapiDisplay *display;
  VAStatus status;

  g_return_val_if_fail (subpicture != NULL, FALSE);

  if (!(subpicture->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA))
    return FALSE;

  if (subpicture->global_alpha == global_alpha)
    return TRUE;

  display = GST_VAAPI_OBJECT_DISPLAY (subpicture);

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaSetSubpictureGlobalAlpha (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (subpicture), global_alpha);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaSetSubpictureGlobalAlpha()"))
    return FALSE;

  subpicture->global_alpha = global_alpha;
  return TRUE;
}
/**
 * gst_vaapi_subpicture_new:
 * @image: a #GstVaapiImage
 * @flags: #GstVaapiSubpictureFlags, or zero
 *
 * Creates a new #GstVaapiSubpicture with @image as source pixels. The
 * newly created object holds a reference on @image.
 *
 * Return value: the newly allocated #GstVaapiSubpicture object
 */
     GstVaapiSubpicture *gst_vaapi_subpicture_new (GstVaapiImage * image,
    guint flags)
{
  GstVaapiSubpicture *subpicture;
  GstVaapiDisplay *display;
  GstVideoFormat format;
  guint va_flags;

  g_return_val_if_fail (image != NULL, NULL);

  GST_DEBUG ("create from image %" GST_VAAPI_ID_FORMAT,
      GST_VAAPI_ID_ARGS (GST_VAAPI_OBJECT_ID (image)));

  display = GST_VAAPI_OBJECT_DISPLAY (image);
  format = GST_VAAPI_IMAGE_FORMAT (image);
  if (!gst_vaapi_display_has_subpicture_format (display, format, &va_flags))
    return NULL;
  if (flags & ~va_flags)
    return NULL;

  subpicture = gst_vaapi_object_new (gst_vaapi_subpicture_class (), display);
  if (!subpicture)
    return NULL;

  subpicture->global_alpha = 1.0f;
  if (!gst_vaapi_subpicture_set_image (subpicture, image))
    goto error;
  return subpicture;

error:
  gst_vaapi_object_unref (subpicture);
  return NULL;
}
/**
 * gst_vaapi_pixmap_get_display:
 * @pixmap: a #GstVaapiPixmap
 *
 * Returns the #GstVaapiDisplay this @pixmap is bound to.
 *
 * Return value: the parent #GstVaapiDisplay object
 */
GstVaapiDisplay *
gst_vaapi_pixmap_get_display (GstVaapiPixmap * pixmap)
{
    g_return_val_if_fail (pixmap != NULL, NULL);

    return GST_VAAPI_OBJECT_DISPLAY (pixmap);
}
Example #5
0
gboolean
_gst_vaapi_image_unmap(GstVaapiImage *image)
{
    GstVaapiDisplay *display;
    VAStatus status;

    if (!_gst_vaapi_image_is_mapped(image))
        return FALSE;

    display = GST_VAAPI_OBJECT_DISPLAY(image);
    if (!display)
        return FALSE;

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaUnmapBuffer(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        image->priv->image.buf
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (!vaapi_check_status(status, "vaUnmapBuffer()"))
        return FALSE;

    image->priv->image_data = NULL;
    return TRUE;
}
Example #6
0
static gboolean
_gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
{
    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
    GstVaapiImagePrivate * const priv = image->priv;
    const VAImageFormat *va_format;
    VAStatus status;

    if (!gst_vaapi_display_has_image_format(display, format))
        return FALSE;

    va_format = gst_vaapi_image_format_get_va_format(format);
    if (!va_format)
        return FALSE;

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaCreateImage(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        (VAImageFormat *)va_format,
        priv->width,
        priv->height,
        &priv->internal_image
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (status != VA_STATUS_SUCCESS ||
        priv->internal_image.format.fourcc != va_format->fourcc)
        return FALSE;

    priv->internal_format = format;
    return TRUE;
}
static void
gst_vaapi_subpicture_destroy (GstVaapiSubpicture * subpicture)
{
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (subpicture);
  VASubpictureID subpicture_id;
  VAStatus status;

  subpicture_id = GST_VAAPI_OBJECT_ID (subpicture);
  GST_DEBUG ("subpicture %" GST_VAAPI_ID_FORMAT,
      GST_VAAPI_ID_ARGS (subpicture_id));

  if (subpicture_id != VA_INVALID_ID) {
    if (display) {
      GST_VAAPI_DISPLAY_LOCK (display);
      status = vaDestroySubpicture (GST_VAAPI_DISPLAY_VADISPLAY (display),
          subpicture_id);
      GST_VAAPI_DISPLAY_UNLOCK (display);
      if (!vaapi_check_status (status, "vaDestroySubpicture()"))
        g_warning ("failed to destroy subpicture %" GST_VAAPI_ID_FORMAT,
            GST_VAAPI_ID_ARGS (subpicture_id));
    }
    GST_VAAPI_OBJECT_ID (subpicture) = VA_INVALID_ID;
  }
  gst_vaapi_object_replace (&subpicture->image, NULL);
}
Example #8
0
/**
 * gst_vaapi_object_get_display:
 * @object: a #GstVaapiObject
 *
 * Returns the #GstVaapiDisplay this @object is bound to.
 *
 * Return value: the parent #GstVaapiDisplay object
 */
GstVaapiDisplay *
gst_vaapi_object_get_display (GstVaapiObject * object)
{
  g_return_val_if_fail (object != NULL, NULL);

  return GST_VAAPI_OBJECT_DISPLAY (object);
}
/*
 * gst_vaapi_coded_buffer_new:
 * @context: the parent #GstVaapiContext object
 * @buf_size: the buffer size in bytes
 *
 * Creates a new VA coded buffer bound to the supplied @context.
 *
 * Return value: the newly allocated #GstVaapiCodedBuffer object, or
 *   %NULL if an error occurred
 */
GstVaapiCodedBuffer *
gst_vaapi_coded_buffer_new (GstVaapiContext * context, guint buf_size)
{
  GstVaapiCodedBuffer *buf;
  GstVaapiDisplay *display;

  g_return_val_if_fail (context != NULL, NULL);
  g_return_val_if_fail (buf_size > 0, NULL);

  display = GST_VAAPI_OBJECT_DISPLAY (context);
  g_return_val_if_fail (display != NULL, NULL);

  buf = gst_vaapi_object_new (gst_vaapi_coded_buffer_class (), display);
  if (!buf)
    return NULL;

  if (!coded_buffer_create (buf, buf_size, context))
    goto error;
  return buf;

  /* ERRORS */
error:
  {
    gst_vaapi_object_unref (buf);
    return NULL;
  }
}
/**
 * gst_vaapi_surface_derive_image:
 * @surface: a #GstVaapiSurface
 *
 * Derives a #GstVaapiImage from the @surface. This image buffer can
 * then be mapped/unmapped for direct CPU access. This operation is
 * only possible if the underlying implementation supports direct
 * rendering capabilities and internal surface formats that can be
 * represented with a #GstVaapiImage.
 *
 * When the operation is not possible, the function returns %NULL and
 * the user should then fallback to using gst_vaapi_surface_get_image()
 * or gst_vaapi_surface_put_image() to accomplish the same task in an
 * indirect manner (additional copy).
 *
 * An image created with gst_vaapi_surface_derive_image() should be
 * unreferenced when it's no longer needed. The image and image buffer
 * data structures will be destroyed. However, the surface contents
 * will remain unchanged until destroyed through the last call to
 * gst_vaapi_object_unref().
 *
 * Return value: the newly allocated #GstVaapiImage object, or %NULL
 *   on failure
 */
GstVaapiImage *
gst_vaapi_surface_derive_image (GstVaapiSurface * surface)
{
  GstVaapiDisplay *display;
  VAImage va_image;
  VAStatus status;
  GstVaapiImage *image;

  g_return_val_if_fail (surface != NULL, NULL);

  display = GST_VAAPI_OBJECT_DISPLAY (surface);
  va_image.image_id = VA_INVALID_ID;
  va_image.buf = VA_INVALID_ID;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaDeriveImage (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (surface), &va_image);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaDeriveImage()"))
    return NULL;
  if (va_image.image_id == VA_INVALID_ID || va_image.buf == VA_INVALID_ID)
    return NULL;

  image = gst_vaapi_image_new_with_image (display, &va_image);
  if (!image)
    vaDestroyImage (GST_VAAPI_DISPLAY_VADISPLAY (display), va_image.image_id);
  return image;
}
/**
 * gst_vaapi_surface_put_image:
 * @surface: a #GstVaapiSurface
 * @image: a #GstVaapiImage
 *
 * Copies data from a #GstVaapiImage into a @surface. The @image must
 * have a format supported by the @surface.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_put_image (GstVaapiSurface * surface, GstVaapiImage * image)
{
  GstVaapiDisplay *display;
  VAImageID image_id;
  VAStatus status;
  guint width, height;

  g_return_val_if_fail (surface != NULL, FALSE);
  g_return_val_if_fail (image != NULL, FALSE);

  display = GST_VAAPI_OBJECT_DISPLAY (surface);
  if (!display)
    return FALSE;

  width = GST_VAAPI_IMAGE_WIDTH (image);
  height = GST_VAAPI_IMAGE_HEIGHT (image);
  if (width != surface->width || height != surface->height)
    return FALSE;

  image_id = GST_VAAPI_OBJECT_ID (image);
  if (image_id == VA_INVALID_ID)
    return FALSE;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaPutImage (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (surface), image_id, 0, 0, width, height,
      0, 0, width, height);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaPutImage()"))
    return FALSE;

  return TRUE;
}
static void
gst_vaapi_surface_destroy (GstVaapiSurface * surface)
{
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface);
  VASurfaceID surface_id;
  VAStatus status;

  surface_id = GST_VAAPI_OBJECT_ID (surface);
  GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id));

  gst_vaapi_surface_destroy_subpictures (surface);
  gst_vaapi_surface_set_parent_context (surface, NULL);

  if (surface_id != VA_INVALID_SURFACE) {
    GST_VAAPI_DISPLAY_LOCK (display);
    status = vaDestroySurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display),
        &surface_id, 1);
    GST_VAAPI_DISPLAY_UNLOCK (display);
    if (!vaapi_check_status (status, "vaDestroySurfaces()"))
      g_warning ("failed to destroy surface %" GST_VAAPI_ID_FORMAT,
          GST_VAAPI_ID_ARGS (surface_id));
    GST_VAAPI_OBJECT_ID (surface) = VA_INVALID_SURFACE;
  }
  gst_vaapi_buffer_proxy_replace (&surface->extbuf_proxy, NULL);
}
gboolean
_gst_vaapi_surface_deassociate_subpicture (GstVaapiSurface * surface,
    GstVaapiSubpicture * subpicture)
{
  GstVaapiDisplay *display;
  VASurfaceID surface_id;
  VAStatus status;

  display = GST_VAAPI_OBJECT_DISPLAY (surface);
  if (!display)
    return FALSE;

  surface_id = GST_VAAPI_OBJECT_ID (surface);
  if (surface_id == VA_INVALID_SURFACE)
    return FALSE;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaDeassociateSubpicture (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (subpicture), &surface_id, 1);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaDeassociateSubpicture()"))
    return FALSE;

  return TRUE;
}
static gboolean
gst_vaapi_surface_create (GstVaapiSurface * surface,
    GstVaapiChromaType chroma_type, guint width, guint height)
{
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface);
  VASurfaceID surface_id;
  VAStatus status;
  guint va_chroma_format;

  va_chroma_format = from_GstVaapiChromaType (chroma_type);
  if (!va_chroma_format)
    goto error_unsupported_chroma_type;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaCreateSurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display),
      width, height, va_chroma_format, 1, &surface_id);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaCreateSurfaces()"))
    return FALSE;

  surface->format = GST_VIDEO_FORMAT_UNKNOWN;
  surface->chroma_type = chroma_type;
  surface->width = width;
  surface->height = height;

  GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id));
  GST_VAAPI_OBJECT_ID (surface) = surface_id;
  return TRUE;

  /* ERRORS */
error_unsupported_chroma_type:
  GST_ERROR ("unsupported chroma-type %u", chroma_type);
  return FALSE;
}
static gboolean
gst_vaapi_window_egl_create (GstVaapiWindowEGL * window,
    guint * width, guint * height)
{
  GstVaapiDisplayEGL *const display =
      GST_VAAPI_DISPLAY_EGL (GST_VAAPI_OBJECT_DISPLAY (window));
  const GstVaapiDisplayClass *const native_dpy_class =
      GST_VAAPI_DISPLAY_GET_CLASS (display->display);
  CreateObjectsArgs args;

  g_return_val_if_fail (native_dpy_class != NULL, FALSE);

  window->window =
      native_dpy_class->create_window (GST_VAAPI_DISPLAY (display->display),
      GST_VAAPI_ID_INVALID, *width, *height);
  if (!window->window)
    return FALSE;

  gst_vaapi_window_get_size (window->window, width, height);

  args.window = window;
  args.width = *width;
  args.height = *height;
  args.egl_context = GST_VAAPI_DISPLAY_EGL_CONTEXT (display);
  return egl_context_run (args.egl_context,
      (EglContextRunFunc) do_create_objects, &args) && args.success;
}
Example #16
0
gboolean
_gst_vaapi_surface_associate_subpicture(
    GstVaapiSurface         *surface,
    GstVaapiSubpicture      *subpicture,
    const GstVaapiRectangle *src_rect,
    const GstVaapiRectangle *dst_rect
)
{
    GstVaapiDisplay *display;
    GstVaapiRectangle src_rect_default, dst_rect_default;
    GstVaapiImage *image;
    VASurfaceID surface_id;
    VAStatus status;

    display = GST_VAAPI_OBJECT_DISPLAY(surface);
    if (!display)
        return FALSE;

    surface_id = GST_VAAPI_OBJECT_ID(surface);
    if (surface_id == VA_INVALID_SURFACE)
        return FALSE;

    if (!src_rect) {
        image = gst_vaapi_subpicture_get_image(subpicture);
        if (!image)
            return FALSE;
        src_rect                = &src_rect_default;
        src_rect_default.x      = 0;
        src_rect_default.y      = 0;
        gst_vaapi_image_get_size(
            image,
            &src_rect_default.width,
            &src_rect_default.height
        );
    }

    if (!dst_rect) {
        dst_rect                = &dst_rect_default;
        dst_rect_default.x      = 0;
        dst_rect_default.y      = 0;
        dst_rect_default.width  = surface->priv->width;
        dst_rect_default.height = surface->priv->height;
    }

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaAssociateSubpicture(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        GST_VAAPI_OBJECT_ID(subpicture),
        &surface_id, 1,
        src_rect->x, src_rect->y, src_rect->width, src_rect->height,
        dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height,
        0
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (!vaapi_check_status(status, "vaAssociateSubpicture()"))
        return FALSE;

    return TRUE;
}
Example #17
0
/**
 * gst_vaapi_surface_set_subpictures_from_composition:
 * @surface: a #GstVaapiSurface
 * @compostion: a #GstVideoOverlayCompositon
 * @propagate_context: a flag specifying whether to apply composition
 *     to the parent context, if any
 *
 * Helper to update the subpictures from #GstVideoOverlayCompositon. Sending
 * a NULL composition will clear all the current subpictures. Note that this
 * method will clear existing subpictures.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_set_subpictures_from_composition(
    GstVaapiSurface            *surface,
    GstVideoOverlayComposition *composition,
    gboolean                    propagate_context
)
{
    GstVaapiDisplay *display;
    guint n, nb_rectangles;

    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);

    if (propagate_context) {
        GstVaapiContext * const context = surface->priv->parent_context;
        if (context)
            return gst_vaapi_context_apply_composition(context, composition);
    }

    display = GST_VAAPI_OBJECT_DISPLAY(surface);
    if (!display)
        return FALSE;

    /* Clear current subpictures */
    gst_vaapi_surface_destroy_subpictures(surface);

    if (!composition)
        return TRUE;

    nb_rectangles = gst_video_overlay_composition_n_rectangles (composition);

    /* Overlay all the rectangles cantained in the overlay composition */
    for (n = 0; n < nb_rectangles; ++n) {
        GstVideoOverlayRectangle *rect;
        GstVaapiRectangle sub_rect;
        GstVaapiSubpicture *subpicture;

        rect = gst_video_overlay_composition_get_rectangle (composition, n);
        subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle (display,
                rect);

        gst_video_overlay_rectangle_get_render_rectangle (rect,
                (gint *)&sub_rect.x, (gint *)&sub_rect.y,
                &sub_rect.width, &sub_rect.height);

        if (!gst_vaapi_surface_associate_subpicture (surface, subpicture,
                    NULL, &sub_rect)) {
            GST_WARNING ("could not render overlay rectangle %p", rect);
            g_object_unref (subpicture);
            return FALSE;
        }
        g_object_unref (subpicture);
    }
    return TRUE;
}
static gboolean
gst_vaapi_texture_upload (GstVideoGLTextureUploadMeta * meta,
    guint texture_id[4])
{
  GstVaapiVideoMeta *const vmeta =
      gst_buffer_get_vaapi_video_meta (meta->buffer);
  GstVaapiVideoMetaTexture *const meta_texture = meta->user_data;
  GstVaapiSurfaceProxy *const proxy =
      gst_vaapi_video_meta_get_surface_proxy (vmeta);
  GstVaapiSurface *const surface = gst_vaapi_surface_proxy_get_surface (proxy);
  GstVaapiDisplay *const dpy = GST_VAAPI_OBJECT_DISPLAY (surface);

  if (!gst_vaapi_display_has_opengl (dpy))
    return FALSE;

  if (!meta_texture->texture ||
      /* Check whether VA display changed */
      GST_VAAPI_OBJECT_DISPLAY (meta_texture->texture) != dpy ||
      /* Check whether texture id changed */
      gst_vaapi_texture_get_id (meta_texture->texture) != texture_id[0]) {
    /* FIXME: should we assume target? */
    GstVaapiTexture *const texture =
        gst_vaapi_texture_new_wrapped (dpy, texture_id[0],
        GL_TEXTURE_2D, meta_texture->gl_format, meta_texture->width,
        meta_texture->height);
    gst_vaapi_texture_replace (&meta_texture->texture, texture);
    if (!texture)
      return FALSE;
    gst_vaapi_texture_unref (texture);
  }

  gst_vaapi_texture_set_orientation_flags (meta_texture->texture,
      get_texture_orientation_flags (meta->texture_orientation));

  return gst_vaapi_texture_put_surface (meta_texture->texture, surface,
      gst_vaapi_surface_proxy_get_crop_rect (proxy),
      gst_vaapi_video_meta_get_render_flags (vmeta));
}
static gboolean
ensure_texture (GstVaapiWindowEGL * window, guint width, guint height)
{
  GstVaapiTexture *texture;

  if (window->texture &&
      GST_VAAPI_TEXTURE_WIDTH (window->texture) == width &&
      GST_VAAPI_TEXTURE_HEIGHT (window->texture) == height)
    return TRUE;

  texture = gst_vaapi_texture_egl_new (GST_VAAPI_OBJECT_DISPLAY (window),
      GL_TEXTURE_2D, GL_RGBA, width, height);
  gst_vaapi_texture_replace (&window->texture, texture);
  gst_vaapi_texture_replace (&texture, NULL);
  return window->texture != NULL;
}
static void
coded_buffer_destroy (GstVaapiCodedBuffer * buf)
{
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (buf);
  VABufferID buf_id;

  buf_id = GST_VAAPI_OBJECT_ID (buf);
  GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id));

  if (buf_id != VA_INVALID_ID) {
    GST_VAAPI_DISPLAY_LOCK (display);
    vaapi_destroy_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display), &buf_id);
    GST_VAAPI_DISPLAY_UNLOCK (display);
    GST_VAAPI_OBJECT_ID (buf) = VA_INVALID_ID;
  }
}
static void
do_destroy_objects (GstVaapiWindowEGL * window)
{
  EglContext *const egl_context =
      GST_VAAPI_DISPLAY_EGL_CONTEXT (GST_VAAPI_OBJECT_DISPLAY (window));
  EglContextState old_cs;

  if (!window->egl_window)
    return;

  GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
  if (egl_context_set_current (egl_context, TRUE, &old_cs)) {
    do_destroy_objects_unlocked (window);
    egl_context_set_current (egl_context, FALSE, &old_cs);
  }
  GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
}
static gboolean
coded_buffer_create (GstVaapiCodedBuffer * buf, guint buf_size,
    GstVaapiContext * context)
{
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (buf);
  VABufferID buf_id;
  gboolean success;

  GST_VAAPI_DISPLAY_LOCK (display);
  success = vaapi_create_buffer (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (context), VAEncCodedBufferType, buf_size, NULL,
      &buf_id, NULL);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!success)
    return FALSE;

  GST_DEBUG ("coded buffer %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (buf_id));
  GST_VAAPI_OBJECT_ID (buf) = buf_id;
  return TRUE;
}
Example #23
0
gboolean
_gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
{
    GstVaapiImagePrivate * const priv = image->priv;
    GstVaapiDisplay *display;
    void *image_data;
    VAStatus status;
    guint i;

    if (_gst_vaapi_image_is_mapped(image))
        return TRUE;

    display = GST_VAAPI_OBJECT_DISPLAY(image);
    if (!display)
        return FALSE;

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaMapBuffer(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        image->priv->image.buf,
        &image_data
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (!vaapi_check_status(status, "vaMapBuffer()"))
        return FALSE;

    image->priv->image_data = image_data;

    if (raw_image) {
        const VAImage * const va_image = &priv->image;
        raw_image->format     = priv->format;
        raw_image->width      = va_image->width;
        raw_image->height     = va_image->height;
        raw_image->num_planes = va_image->num_planes;
        for (i = 0; i < raw_image->num_planes; i++) {
            raw_image->pixels[i] = (guchar *)image_data + va_image->offsets[i];
            raw_image->stride[i] = va_image->pitches[i];
        }
    }
    return TRUE;
}
static gboolean
gst_vaapi_subpicture_create (GstVaapiSubpicture * subpicture,
    GstVaapiImage * image)
{
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (subpicture);
  VASubpictureID subpicture_id;
  VAStatus status;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaCreateSubpicture (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (image), &subpicture_id);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaCreateSubpicture()"))
    return FALSE;

  GST_DEBUG ("subpicture %" GST_VAAPI_ID_FORMAT,
      GST_VAAPI_ID_ARGS (subpicture_id));
  GST_VAAPI_OBJECT_ID (subpicture) = subpicture_id;
  subpicture->image = gst_vaapi_object_ref (image);
  return TRUE;
}
/**
 * gst_vaapi_surface_sync:
 * @surface: a #GstVaapiSurface
 *
 * Blocks until all pending operations on the @surface have been
 * completed.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_sync (GstVaapiSurface * surface)
{
  GstVaapiDisplay *display;
  VAStatus status;

  g_return_val_if_fail (surface != NULL, FALSE);

  display = GST_VAAPI_OBJECT_DISPLAY (surface);
  if (!display)
    return FALSE;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaSyncSurface (GST_VAAPI_DISPLAY_VADISPLAY (display),
      GST_VAAPI_OBJECT_ID (surface));
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaSyncSurface()"))
    return FALSE;

  return TRUE;
}
static gboolean
gst_vaapi_window_wayland_resize (GstVaapiWindow * window,
                                 guint width, guint height)
{
    GstVaapiWindowWaylandPrivate *const priv =
        GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
    GstVaapiDisplayWaylandPrivate *const priv_display =
        GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (GST_VAAPI_OBJECT_DISPLAY (window));

    GST_DEBUG ("resize window, new size %ux%u", width, height);

    gst_vaapi_video_pool_replace (&priv->surface_pool, NULL);
    if (priv->opaque_region)
        wl_region_destroy (priv->opaque_region);
    GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
    priv->opaque_region = wl_compositor_create_region (priv_display->compositor);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
    wl_region_add (priv->opaque_region, 0, 0, width, height);

    return TRUE;
}
Example #27
0
static gboolean
gst_vaapi_surface_create(GstVaapiSurface *surface)
{
    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
    GstVaapiSurfacePrivate * const priv = surface->priv;
    VASurfaceID surface_id;
    VAStatus status;
    guint format;

    switch (priv->chroma_type) {
    case GST_VAAPI_CHROMA_TYPE_YUV420:
        format = VA_RT_FORMAT_YUV420;
        break;
    case GST_VAAPI_CHROMA_TYPE_YUV422:
        format = VA_RT_FORMAT_YUV422;
        break;
    case GST_VAAPI_CHROMA_TYPE_YUV444:
        format = VA_RT_FORMAT_YUV444;
        break;
    default:
        GST_DEBUG("unsupported chroma-type %u\n", priv->chroma_type);
        return FALSE;
    }

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaCreateSurfaces(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        priv->width,
        priv->height,
        format,
        1, &surface_id
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (!vaapi_check_status(status, "vaCreateSurfaces()"))
        return FALSE;

    GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
    GST_VAAPI_OBJECT_ID(surface) = surface_id;
    return TRUE;
}
Example #28
0
static void
gst_vaapi_image_destroy(GstVaapiImage *image)
{
    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
    VAImageID image_id;
    VAStatus status;

    _gst_vaapi_image_unmap(image);

    image_id = GST_VAAPI_OBJECT_ID(image);
    GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));

    if (image_id != VA_INVALID_ID) {
        GST_VAAPI_DISPLAY_LOCK(display);
        status = vaDestroyImage(GST_VAAPI_DISPLAY_VADISPLAY(display), image_id);
        GST_VAAPI_DISPLAY_UNLOCK(display);
        if (!vaapi_check_status(status, "vaDestroyImage()"))
            g_warning("failed to destroy image %" GST_VAAPI_ID_FORMAT,
                      GST_VAAPI_ID_ARGS(image_id));
        GST_VAAPI_OBJECT_ID(image) = VA_INVALID_ID;
    }
}
Example #29
0
/**
 * gst_vaapi_surface_get_image
 * @surface: a #GstVaapiSurface
 * @image: a #GstVaapiImage
 *
 * Retrieves surface data into a #GstVaapiImage. The @image must have
 * a format supported by the @surface.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
{
    GstVaapiDisplay *display;
    VAImageID image_id;
    VAStatus status;
    guint width, height;

    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
    g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);

    display = GST_VAAPI_OBJECT_DISPLAY(surface);
    if (!display)
        return FALSE;

    gst_vaapi_image_get_size(image, &width, &height);
    if (width != surface->priv->width || height != surface->priv->height)
        return FALSE;

    image_id = GST_VAAPI_OBJECT_ID(image);
    if (image_id == VA_INVALID_ID)
        return FALSE;

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaGetImage(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        GST_VAAPI_OBJECT_ID(surface),
        0, 0, width, height,
        image_id
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (!vaapi_check_status(status, "vaGetImage()"))
        return FALSE;

    return TRUE;
}
static gboolean
gst_vaapi_surface_create_from_buffer_proxy (GstVaapiSurface * surface,
    GstVaapiBufferProxy * proxy, const GstVideoInfo * vip)
{
#if VA_CHECK_VERSION (0,36,0)
  GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (surface);
  GstVideoFormat format;
  VASurfaceID surface_id;
  VAStatus status;
  guint chroma_type, va_chroma_format;
  const VAImageFormat *va_format;
  VASurfaceAttrib attribs[2], *attrib;
  VASurfaceAttribExternalBuffers extbuf;
  unsigned long extbuf_handle;
  guint i, width, height;

  format = GST_VIDEO_INFO_FORMAT (vip);
  width = GST_VIDEO_INFO_WIDTH (vip);
  height = GST_VIDEO_INFO_HEIGHT (vip);

  gst_vaapi_buffer_proxy_replace (&surface->extbuf_proxy, proxy);

  va_format = gst_vaapi_video_format_to_va_format (format);
  if (!va_format)
    goto error_unsupported_format;

  chroma_type = gst_vaapi_video_format_get_chroma_type (format);
  if (!chroma_type)
    goto error_unsupported_format;

  va_chroma_format = from_GstVaapiChromaType (chroma_type);
  if (!va_chroma_format)
    goto error_unsupported_format;

  extbuf_handle = GST_VAAPI_BUFFER_PROXY_HANDLE (proxy);
  extbuf.pixel_format = va_format->fourcc;
  extbuf.width = width;
  extbuf.height = height;
  extbuf.data_size = GST_VAAPI_BUFFER_PROXY_SIZE (proxy);
  extbuf.num_planes = GST_VIDEO_INFO_N_PLANES (vip);
  for (i = 0; i < extbuf.num_planes; i++) {
    extbuf.pitches[i] = GST_VIDEO_INFO_PLANE_STRIDE (vip, i);
    extbuf.offsets[i] = GST_VIDEO_INFO_PLANE_OFFSET (vip, i);
  }
  extbuf.buffers = &extbuf_handle;
  extbuf.num_buffers = 1;
  extbuf.flags = 0;
  extbuf.private_data = NULL;

  attrib = attribs;
  attrib->type = VASurfaceAttribExternalBufferDescriptor;
  attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
  attrib->value.type = VAGenericValueTypePointer;
  attrib->value.value.p = &extbuf;
  attrib++;
  attrib->type = VASurfaceAttribMemoryType;
  attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
  attrib->value.type = VAGenericValueTypeInteger;
  attrib->value.value.i =
      from_GstVaapiBufferMemoryType (GST_VAAPI_BUFFER_PROXY_TYPE (proxy));
  attrib++;

  GST_VAAPI_DISPLAY_LOCK (display);
  status = vaCreateSurfaces (GST_VAAPI_DISPLAY_VADISPLAY (display),
      va_chroma_format, width, height, &surface_id, 1, attribs,
      attrib - attribs);
  GST_VAAPI_DISPLAY_UNLOCK (display);
  if (!vaapi_check_status (status, "vaCreateSurfaces()"))
    return FALSE;

  surface->format = format;
  surface->chroma_type = chroma_type;
  surface->width = width;
  surface->height = height;

  GST_DEBUG ("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id));
  GST_VAAPI_OBJECT_ID (surface) = surface_id;
  return TRUE;

  /* ERRORS */
error_unsupported_format:
  GST_ERROR ("unsupported format %s",
      gst_vaapi_video_format_to_string (format));
  return FALSE;
#else
  return FALSE;
#endif
}