Example #1
0
/**
 * gst_vaapi_surface_query_status:
 * @surface: a #GstVaapiSurface
 * @pstatus: return location for the #GstVaapiSurfaceStatus
 *
 * Finds out any pending operations on the @surface. The
 * #GstVaapiSurfaceStatus flags are returned into @pstatus.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_query_status(
    GstVaapiSurface       *surface,
    GstVaapiSurfaceStatus *pstatus
)
{
    VASurfaceStatus surface_status;
    VAStatus status;

    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);

    GST_VAAPI_OBJECT_LOCK_DISPLAY(surface);
    status = vaQuerySurfaceStatus(
        GST_VAAPI_OBJECT_VADISPLAY(surface),
        GST_VAAPI_OBJECT_ID(surface),
        &surface_status
    );
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(surface);
    if (!vaapi_check_status(status, "vaQuerySurfaceStatus()"))
        return FALSE;

    if (pstatus)
        *pstatus = to_GstVaapiSurfaceStatus(surface_status);
    return TRUE;
}
Example #2
0
/**
 * gst_vaapi_surface_deassociate_subpicture:
 * @surface: a #GstVaapiSurface
 * @subpicture: a #GstVaapiSubpicture
 *
 * Deassociates @subpicture from @surface. Other associations are kept.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_deassociate_subpicture(
    GstVaapiSurface         *surface,
    GstVaapiSubpicture      *subpicture
)
{
    gboolean success;

    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
    g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);

    if (!surface->priv->subpictures)
        return TRUE;

    /* First, check subpicture was really associated with this surface */
    if (!g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
        GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT " was not bound to "
                  "surface %" GST_VAAPI_ID_FORMAT,
                  GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(subpicture)),
                  GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(surface)));
        return TRUE;
    }

    success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
    g_object_unref(subpicture);
    return success;
}
Example #3
0
/**
 * gst_vaapi_surface_get_parent_context:
 * @surface: a #GstVaapiSurface
 *
 * Retrieves the parent #GstVaapiContext, or %NULL if there is
 * none. The surface shall still own a reference to the context.
 * i.e. the caller shall not unreference the returned context object.
 *
 * Return value: the parent context, if any.
 */
GstVaapiContext *
gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface)
{
    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);

    return surface->priv->parent_context;
}
Example #4
0
/**
 * 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
 * g_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;

    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 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;

    return gst_vaapi_image_new_with_image(display, &va_image);
}
Example #5
0
/**
 * gst_vaapi_surface_get_height:
 * @surface: a #GstVaapiSurface
 *
 * Returns the @surface height.
 *
 * Return value: the surface height, in pixels.
 */
guint
gst_vaapi_surface_get_height(GstVaapiSurface *surface)
{
    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);

    return surface->priv->height;
}
Example #6
0
/**
 * gst_vaapi_surface_get_chroma_type:
 * @surface: a #GstVaapiSurface
 *
 * Returns the #GstVaapiChromaType the @surface was created with.
 *
 * Return value: the #GstVaapiChromaType
 */
GstVaapiChromaType
gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface)
{
    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);

    return surface->priv->chroma_type;
}
Example #7
0
/**
 * gst_vaapi_surface_get_id:
 * @surface: a #GstVaapiSurface
 *
 * Returns the underlying VASurfaceID of the @surface.
 *
 * Return value: the underlying VA surface id
 */
GstVaapiID
gst_vaapi_surface_get_id(GstVaapiSurface *surface)
{
    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), VA_INVALID_SURFACE);

    return GST_VAAPI_OBJECT_ID(surface);
}
Example #8
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;
}
/**
 * gst_vaapi_surface_proxy_new:
 * @context: a #GstVaapiContext
 * @surface: a #GstVaapiSurface
 *
 * Creates a new #GstVaapiSurfaceProxy with the specified context and
 * surface.
 *
 * Return value: the newly allocated #GstVaapiSurfaceProxy object
 */
GstVaapiSurfaceProxy *
gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface)
{
    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);

    return g_object_new(GST_VAAPI_TYPE_SURFACE_PROXY,
                        "context",  context,
                        "surface",  surface,
                        NULL);
}
Example #10
0
/**
 * gst_vaapi_surface_get_size:
 * @surface: a #GstVaapiSurface
 * @pwidth: return location for the width, or %NULL
 * @pheight: return location for the height, or %NULL
 *
 * Retrieves the dimensions of a #GstVaapiSurface.
 */
void
gst_vaapi_surface_get_size(
    GstVaapiSurface *surface,
    guint           *pwidth,
    guint           *pheight
)
{
    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));

    if (pwidth)
        *pwidth = gst_vaapi_surface_get_width(surface);

    if (pheight)
        *pheight = gst_vaapi_surface_get_height(surface);
}
Example #11
0
/**
 * gst_vaapi_surface_set_parent_context:
 * @surface: a #GstVaapiSurface
 * @context: a #GstVaapiContext
 *
 * Sets new parent context, or clears any parent context if @context
 * is %NULL. This function owns an extra reference to the context,
 * which will be released when the surface is destroyed.
 */
void
gst_vaapi_surface_set_parent_context(
    GstVaapiSurface *surface,
    GstVaapiContext *context
)
{
    GstVaapiSurfacePrivate *priv;

    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));

    priv = surface->priv;

    g_clear_object(&priv->parent_context);

    if (context)
        priv->parent_context = g_object_ref(context);
}
/**
 * gst_vaapi_surface_proxy_set_surface:
 * @proxy: a #GstVaapiSurfaceProxy
 * @surface: the new #GstVaapiSurface to be stored in @proxy
 *
 * Stores a new @surface into the @proxy. The proxy releases the
 * previous reference, if any, and then holds a reference to the new
 * @surface.
 */
void
gst_vaapi_surface_proxy_set_surface(
    GstVaapiSurfaceProxy *proxy,
    GstVaapiSurface      *surface
)
{
    g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
    g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));

    if (proxy->priv->surface) {
        g_object_unref(proxy->priv->surface);
        proxy->priv->surface = NULL;
    }

    if (surface)
        proxy->priv->surface = g_object_ref(surface);
}
Example #13
0
/**
 * gst_vaapi_surface_associate_subpicture:
 * @surface: a #GstVaapiSurface
 * @subpicture: a #GstVaapiSubpicture
 * @src_rect: the sub-rectangle of the source subpicture
 *   image to extract and process. If %NULL, the entire image will be used.
 * @dst_rect: the sub-rectangle of the destination
 *   surface into which the image is rendered. If %NULL, the entire
 *   surface will be used.
 *
 * Associates the @subpicture with the @surface. The @src_rect
 * coordinates and size are relative to the source image bound to
 * @subpicture. The @dst_rect coordinates and size are relative to the
 * target @surface. Note that the @surface holds an additional
 * reference to the @subpicture.
 *
 * Return value: %TRUE on success
 */
gboolean
gst_vaapi_surface_associate_subpicture(
    GstVaapiSurface         *surface,
    GstVaapiSubpicture      *subpicture,
    const GstVaapiRectangle *src_rect,
    const GstVaapiRectangle *dst_rect
)
{
    gboolean success;

    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
    g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);

    if (!surface->priv->subpictures) {
        surface->priv->subpictures = g_ptr_array_new();
        if (!surface->priv->subpictures)
            return FALSE;
    }

    if (g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
        success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
        g_object_unref(subpicture);
        if (!success)
            return FALSE;
    }

    success = _gst_vaapi_surface_associate_subpicture(
        surface,
        subpicture,
        src_rect,
        dst_rect
    );
    if (!success)
        return FALSE;

    g_ptr_array_add(surface->priv->subpictures, g_object_ref(subpicture));
    return TRUE;
}
Example #14
0
/**
 * 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(GST_VAAPI_IS_SURFACE(surface), 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;
}
Example #15
0
/**
 * 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(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 = 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;
}