mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 04:56:24 +00:00
Add gst_vaapi_surface_derive_image() API.
This commit is contained in:
parent
b9bf5678f9
commit
ea2c6c502c
4 changed files with 214 additions and 35 deletions
|
@ -43,6 +43,7 @@ struct _GstVaapiImagePrivate {
|
||||||
GstVaapiImageFormat format;
|
GstVaapiImageFormat format;
|
||||||
guint width;
|
guint width;
|
||||||
guint height;
|
guint height;
|
||||||
|
guint create_image : 1;
|
||||||
guint is_constructed : 1;
|
guint is_constructed : 1;
|
||||||
guint is_linear : 1;
|
guint is_linear : 1;
|
||||||
};
|
};
|
||||||
|
@ -51,6 +52,7 @@ enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
PROP_DISPLAY,
|
PROP_DISPLAY,
|
||||||
|
PROP_IMAGE,
|
||||||
PROP_IMAGE_ID,
|
PROP_IMAGE_ID,
|
||||||
PROP_FORMAT,
|
PROP_FORMAT,
|
||||||
PROP_WIDTH,
|
PROP_WIDTH,
|
||||||
|
@ -69,6 +71,75 @@ _gst_vaapi_image_map(GstVaapiImage *image);
|
||||||
static gboolean
|
static gboolean
|
||||||
_gst_vaapi_image_unmap(GstVaapiImage *image);
|
_gst_vaapi_image_unmap(GstVaapiImage *image);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VAImage wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VAAPI_TYPE_IMAGE vaapi_image_get_type()
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
vaapi_image_copy(gpointer va_image)
|
||||||
|
{
|
||||||
|
return g_slice_dup(VAImage, va_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vaapi_image_free(gpointer va_image)
|
||||||
|
{
|
||||||
|
if (G_LIKELY(va_image))
|
||||||
|
g_slice_free(VAImage, va_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GType
|
||||||
|
vaapi_image_get_type(void)
|
||||||
|
{
|
||||||
|
static GType type = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY(type == 0))
|
||||||
|
type = g_boxed_type_register_static(
|
||||||
|
"VAImage",
|
||||||
|
vaapi_image_copy,
|
||||||
|
vaapi_image_free
|
||||||
|
);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
vaapi_image_is_linear(const VAImage *va_image)
|
||||||
|
{
|
||||||
|
guint i, width, height, width2, height2, data_size;
|
||||||
|
|
||||||
|
for (i = 1; i < va_image->num_planes; i++)
|
||||||
|
if (va_image->offsets[i] < va_image->offsets[i - 1])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
width = va_image->width;
|
||||||
|
height = va_image->height;
|
||||||
|
width2 = (width + 1) / 2;
|
||||||
|
height2 = (height + 1) / 2;
|
||||||
|
|
||||||
|
switch (va_image->format.fourcc) {
|
||||||
|
case VA_FOURCC('N','V','1','2'):
|
||||||
|
case VA_FOURCC('Y','V','1','2'):
|
||||||
|
case VA_FOURCC('I','4','2','0'):
|
||||||
|
data_size = width * height + 2 * width2 * height2;
|
||||||
|
break;
|
||||||
|
case VA_FOURCC('A','R','G','B'):
|
||||||
|
case VA_FOURCC('R','G','B','A'):
|
||||||
|
case VA_FOURCC('A','B','G','R'):
|
||||||
|
case VA_FOURCC('B','G','R','A'):
|
||||||
|
data_size = 4 * width * height;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_error("FIXME: incomplete formats");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return va_image->data_size == data_size;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_vaapi_image_destroy(GstVaapiImage *image)
|
gst_vaapi_image_destroy(GstVaapiImage *image)
|
||||||
{
|
{
|
||||||
|
@ -103,6 +174,10 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
|
||||||
const VAImageFormat *va_format;
|
const VAImageFormat *va_format;
|
||||||
VAStatus status;
|
VAStatus status;
|
||||||
|
|
||||||
|
if (!priv->create_image)
|
||||||
|
return (priv->image.image_id != VA_INVALID_ID &&
|
||||||
|
priv->image.buf != VA_INVALID_ID);
|
||||||
|
|
||||||
if (!gst_vaapi_display_has_image_format(priv->display, format))
|
if (!gst_vaapi_display_has_image_format(priv->display, format))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -127,40 +202,6 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_gst_vaapi_image_is_linear(GstVaapiImage *image)
|
|
||||||
{
|
|
||||||
GstVaapiImagePrivate * const priv = image->priv;
|
|
||||||
guint i, width, height, width2, height2, data_size;
|
|
||||||
|
|
||||||
for (i = 1; i < priv->image.num_planes; i++)
|
|
||||||
if (priv->image.offsets[i] < priv->image.offsets[i - 1])
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
width = priv->width;
|
|
||||||
height = priv->height;
|
|
||||||
width2 = (width + 1) / 2;
|
|
||||||
height2 = (height + 1) / 2;
|
|
||||||
|
|
||||||
switch (priv->internal_format) {
|
|
||||||
case GST_VAAPI_IMAGE_NV12:
|
|
||||||
case GST_VAAPI_IMAGE_YV12:
|
|
||||||
case GST_VAAPI_IMAGE_I420:
|
|
||||||
data_size = width * height + 2 * width2 * height2;
|
|
||||||
break;
|
|
||||||
case GST_VAAPI_IMAGE_ARGB:
|
|
||||||
case GST_VAAPI_IMAGE_RGBA:
|
|
||||||
case GST_VAAPI_IMAGE_ABGR:
|
|
||||||
case GST_VAAPI_IMAGE_BGRA:
|
|
||||||
data_size = 4 * width * height;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_error("FIXME: incomplete formats");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return priv->image.data_size == data_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vaapi_image_create(GstVaapiImage *image)
|
gst_vaapi_image_create(GstVaapiImage *image)
|
||||||
{
|
{
|
||||||
|
@ -202,7 +243,7 @@ gst_vaapi_image_create(GstVaapiImage *image)
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG("image 0x%08x", priv->image.image_id);
|
GST_DEBUG("image 0x%08x", priv->image.image_id);
|
||||||
priv->is_linear = _gst_vaapi_image_is_linear(image);
|
priv->is_linear = vaapi_image_is_linear(&priv->image);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +270,12 @@ gst_vaapi_image_set_property(
|
||||||
case PROP_DISPLAY:
|
case PROP_DISPLAY:
|
||||||
priv->display = g_object_ref(g_value_get_object(value));
|
priv->display = g_object_ref(g_value_get_object(value));
|
||||||
break;
|
break;
|
||||||
|
case PROP_IMAGE: {
|
||||||
|
const VAImage * const va_image = g_value_get_boxed(value);
|
||||||
|
if (va_image)
|
||||||
|
_gst_vaapi_image_set_image(image, va_image);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PROP_FORMAT:
|
case PROP_FORMAT:
|
||||||
priv->format = g_value_get_uint(value);
|
priv->format = g_value_get_uint(value);
|
||||||
break;
|
break;
|
||||||
|
@ -258,6 +305,9 @@ gst_vaapi_image_get_property(
|
||||||
case PROP_DISPLAY:
|
case PROP_DISPLAY:
|
||||||
g_value_set_pointer(value, gst_vaapi_image_get_display(image));
|
g_value_set_pointer(value, gst_vaapi_image_get_display(image));
|
||||||
break;
|
break;
|
||||||
|
case PROP_IMAGE:
|
||||||
|
g_value_set_boxed(value, &image->priv->image);
|
||||||
|
break;
|
||||||
case PROP_IMAGE_ID:
|
case PROP_IMAGE_ID:
|
||||||
g_value_set_uint(value, gst_vaapi_image_get_id(image));
|
g_value_set_uint(value, gst_vaapi_image_get_id(image));
|
||||||
break;
|
break;
|
||||||
|
@ -310,6 +360,15 @@ gst_vaapi_image_class_init(GstVaapiImageClass *klass)
|
||||||
GST_VAAPI_TYPE_DISPLAY,
|
GST_VAAPI_TYPE_DISPLAY,
|
||||||
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
|
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class,
|
||||||
|
PROP_IMAGE,
|
||||||
|
g_param_spec_boxed("image",
|
||||||
|
"Image",
|
||||||
|
"The VA image",
|
||||||
|
VAAPI_TYPE_IMAGE,
|
||||||
|
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
|
||||||
g_object_class_install_property
|
g_object_class_install_property
|
||||||
(object_class,
|
(object_class,
|
||||||
PROP_IMAGE_ID,
|
PROP_IMAGE_ID,
|
||||||
|
@ -359,6 +418,7 @@ gst_vaapi_image_init(GstVaapiImage *image)
|
||||||
priv->height = 0;
|
priv->height = 0;
|
||||||
priv->internal_format = 0;
|
priv->internal_format = 0;
|
||||||
priv->format = 0;
|
priv->format = 0;
|
||||||
|
priv->create_image = TRUE;
|
||||||
priv->is_constructed = FALSE;
|
priv->is_constructed = FALSE;
|
||||||
priv->is_linear = FALSE;
|
priv->is_linear = FALSE;
|
||||||
|
|
||||||
|
@ -406,6 +466,37 @@ gst_vaapi_image_new(
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstVaapiImage *
|
||||||
|
gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
|
||||||
|
{
|
||||||
|
GstVaapiImage *image;
|
||||||
|
|
||||||
|
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
|
||||||
|
g_return_val_if_fail(va_image, NULL);
|
||||||
|
g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL);
|
||||||
|
g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL);
|
||||||
|
|
||||||
|
GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u",
|
||||||
|
va_image->image_id,
|
||||||
|
GST_FOURCC_ARGS(va_image->format.fourcc),
|
||||||
|
va_image->width, va_image->height);
|
||||||
|
|
||||||
|
image = g_object_new(
|
||||||
|
GST_VAAPI_TYPE_IMAGE,
|
||||||
|
"display", display,
|
||||||
|
"image", va_image,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (!image)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!image->priv->is_constructed) {
|
||||||
|
g_object_unref(image);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
VAImageID
|
VAImageID
|
||||||
gst_vaapi_image_get_id(GstVaapiImage *image)
|
gst_vaapi_image_get_id(GstVaapiImage *image)
|
||||||
{
|
{
|
||||||
|
@ -427,6 +518,61 @@ gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
|
||||||
|
{
|
||||||
|
GstVaapiImagePrivate * const priv = image->priv;
|
||||||
|
GstVaapiImageFormat format;
|
||||||
|
VAImage alt_va_image;
|
||||||
|
const VAImageFormat *alt_va_format;
|
||||||
|
|
||||||
|
if (!va_image)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
format = gst_vaapi_image_format(&va_image->format);
|
||||||
|
if (!format)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
priv->create_image = FALSE;
|
||||||
|
priv->internal_image = *va_image;
|
||||||
|
priv->internal_format = format;
|
||||||
|
priv->is_linear = vaapi_image_is_linear(va_image);
|
||||||
|
priv->image = *va_image;
|
||||||
|
priv->format = format;
|
||||||
|
priv->width = va_image->width;
|
||||||
|
priv->height = va_image->height;
|
||||||
|
|
||||||
|
/* Try to linearize image */
|
||||||
|
if (!priv->is_linear) {
|
||||||
|
switch (format) {
|
||||||
|
case GST_VAAPI_IMAGE_I420:
|
||||||
|
format = GST_VAAPI_IMAGE_YV12;
|
||||||
|
break;
|
||||||
|
case GST_VAAPI_IMAGE_YV12:
|
||||||
|
format = GST_VAAPI_IMAGE_I420;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
format = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (format &&
|
||||||
|
(alt_va_format = gst_vaapi_image_format_get_va_format(format))) {
|
||||||
|
alt_va_image = *va_image;
|
||||||
|
alt_va_image.format = *alt_va_format;
|
||||||
|
SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]);
|
||||||
|
SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
|
||||||
|
if (vaapi_image_is_linear(&alt_va_image)) {
|
||||||
|
priv->image = alt_va_image;
|
||||||
|
priv->format = format;
|
||||||
|
priv->is_linear = TRUE;
|
||||||
|
GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
|
||||||
|
GST_FOURCC_ARGS(format));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
GstVaapiDisplay *
|
GstVaapiDisplay *
|
||||||
gst_vaapi_image_get_display(GstVaapiImage *image)
|
gst_vaapi_image_get_display(GstVaapiImage *image)
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,6 +82,9 @@ gst_vaapi_image_new(
|
||||||
guint height
|
guint height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
GstVaapiImage *
|
||||||
|
gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image);
|
||||||
|
|
||||||
VAImageID
|
VAImageID
|
||||||
gst_vaapi_image_get_id(GstVaapiImage *image);
|
gst_vaapi_image_get_id(GstVaapiImage *image);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gstvaapiutils.h"
|
#include "gstvaapiutils.h"
|
||||||
#include "gstvaapisurface.h"
|
#include "gstvaapisurface.h"
|
||||||
|
#include "gstvaapiimage.h"
|
||||||
#include <va/va_backend.h>
|
#include <va/va_backend.h>
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
@ -342,6 +343,32 @@ gst_vaapi_surface_get_size(
|
||||||
*pheight = gst_vaapi_surface_get_height(surface);
|
*pheight = gst_vaapi_surface_get_height(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstVaapiImage *
|
||||||
|
gst_vaapi_surface_derive_image(GstVaapiSurface *surface)
|
||||||
|
{
|
||||||
|
VAImage va_image;
|
||||||
|
VAStatus status;
|
||||||
|
|
||||||
|
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
|
||||||
|
|
||||||
|
va_image.image_id = VA_INVALID_ID;
|
||||||
|
va_image.buf = VA_INVALID_ID;
|
||||||
|
|
||||||
|
GST_VAAPI_DISPLAY_LOCK(surface->priv->display);
|
||||||
|
status = vaDeriveImage(
|
||||||
|
GST_VAAPI_DISPLAY_VADISPLAY(surface->priv->display),
|
||||||
|
surface->priv->surface_id,
|
||||||
|
&va_image
|
||||||
|
);
|
||||||
|
GST_VAAPI_DISPLAY_UNLOCK(surface->priv->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(surface->priv->display, &va_image);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
|
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,6 +107,9 @@ gst_vaapi_surface_get_size(
|
||||||
guint *pheight
|
guint *pheight
|
||||||
);
|
);
|
||||||
|
|
||||||
|
GstVaapiImage *
|
||||||
|
gst_vaapi_surface_derive_image(GstVaapiSurface *surface);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image);
|
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue