mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +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;
|
||||
guint width;
|
||||
guint height;
|
||||
guint create_image : 1;
|
||||
guint is_constructed : 1;
|
||||
guint is_linear : 1;
|
||||
};
|
||||
|
@ -51,6 +52,7 @@ enum {
|
|||
PROP_0,
|
||||
|
||||
PROP_DISPLAY,
|
||||
PROP_IMAGE,
|
||||
PROP_IMAGE_ID,
|
||||
PROP_FORMAT,
|
||||
PROP_WIDTH,
|
||||
|
@ -69,6 +71,75 @@ _gst_vaapi_image_map(GstVaapiImage *image);
|
|||
static gboolean
|
||||
_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
|
||||
gst_vaapi_image_destroy(GstVaapiImage *image)
|
||||
{
|
||||
|
@ -103,6 +174,10 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
|
|||
const VAImageFormat *va_format;
|
||||
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))
|
||||
return FALSE;
|
||||
|
||||
|
@ -127,40 +202,6 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
|
|||
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
|
||||
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);
|
||||
priv->is_linear = _gst_vaapi_image_is_linear(image);
|
||||
priv->is_linear = vaapi_image_is_linear(&priv->image);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -229,6 +270,12 @@ gst_vaapi_image_set_property(
|
|||
case PROP_DISPLAY:
|
||||
priv->display = g_object_ref(g_value_get_object(value));
|
||||
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:
|
||||
priv->format = g_value_get_uint(value);
|
||||
break;
|
||||
|
@ -258,6 +305,9 @@ gst_vaapi_image_get_property(
|
|||
case PROP_DISPLAY:
|
||||
g_value_set_pointer(value, gst_vaapi_image_get_display(image));
|
||||
break;
|
||||
case PROP_IMAGE:
|
||||
g_value_set_boxed(value, &image->priv->image);
|
||||
break;
|
||||
case PROP_IMAGE_ID:
|
||||
g_value_set_uint(value, gst_vaapi_image_get_id(image));
|
||||
break;
|
||||
|
@ -310,6 +360,15 @@ gst_vaapi_image_class_init(GstVaapiImageClass *klass)
|
|||
GST_VAAPI_TYPE_DISPLAY,
|
||||
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
|
||||
(object_class,
|
||||
PROP_IMAGE_ID,
|
||||
|
@ -359,6 +418,7 @@ gst_vaapi_image_init(GstVaapiImage *image)
|
|||
priv->height = 0;
|
||||
priv->internal_format = 0;
|
||||
priv->format = 0;
|
||||
priv->create_image = TRUE;
|
||||
priv->is_constructed = FALSE;
|
||||
priv->is_linear = FALSE;
|
||||
|
||||
|
@ -406,6 +466,37 @@ gst_vaapi_image_new(
|
|||
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
|
||||
gst_vaapi_image_get_id(GstVaapiImage *image)
|
||||
{
|
||||
|
@ -427,6 +518,61 @@ gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
|
|||
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 *
|
||||
gst_vaapi_image_get_display(GstVaapiImage *image)
|
||||
{
|
||||
|
|
|
@ -82,6 +82,9 @@ gst_vaapi_image_new(
|
|||
guint height
|
||||
);
|
||||
|
||||
GstVaapiImage *
|
||||
gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image);
|
||||
|
||||
VAImageID
|
||||
gst_vaapi_image_get_id(GstVaapiImage *image);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "config.h"
|
||||
#include "gstvaapiutils.h"
|
||||
#include "gstvaapisurface.h"
|
||||
#include "gstvaapiimage.h"
|
||||
#include <va/va_backend.h>
|
||||
|
||||
#define DEBUG 1
|
||||
|
@ -342,6 +343,32 @@ gst_vaapi_surface_get_size(
|
|||
*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
|
||||
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
|
||||
{
|
||||
|
|
|
@ -107,6 +107,9 @@ gst_vaapi_surface_get_size(
|
|||
guint *pheight
|
||||
);
|
||||
|
||||
GstVaapiImage *
|
||||
gst_vaapi_surface_derive_image(GstVaapiSurface *surface);
|
||||
|
||||
gboolean
|
||||
gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image);
|
||||
|
||||
|
|
Loading…
Reference in a new issue