libs: use GstVaapiObject for VA objects.

This commit is contained in:
Gwenole Beauchesne 2013-04-30 17:22:15 +02:00
parent 1f15c28a1b
commit 6c46179709
11 changed files with 385 additions and 1182 deletions

View file

@ -29,25 +29,46 @@
#include <assert.h>
#include "gstvaapicompat.h"
#include "gstvaapicontext.h"
#include "gstvaapiobject_priv.h"
#include "gstvaapisurface.h"
#include "gstvaapisurface_priv.h"
#include "gstvaapisurfacepool.h"
#include "gstvaapisurfaceproxy.h"
#include "gstvaapiimage.h"
#include "gstvaapisubpicture.h"
#include "gstvaapiminiobject.h"
#include "gstvaapiutils.h"
#include "gstvaapi_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE(GstVaapiContext, gst_vaapi_context, GST_VAAPI_TYPE_OBJECT)
typedef struct _GstVaapiContextClass GstVaapiContextClass;
#define GST_VAAPI_CONTEXT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContextPrivate))
/**
* GstVaapiContext:
*
* A VA context wrapper.
*/
struct _GstVaapiContext {
/*< private >*/
GstVaapiObject parent_instance;
GstVaapiContextInfo info;
VAConfigID config_id;
GPtrArray *surfaces;
GstVaapiVideoPool *surfaces_pool;
GPtrArray *overlays[2];
guint overlay_id;
};
/**
* GstVaapiContextClass:
*
* A VA context wrapper class.
*/
struct _GstVaapiContextClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
struct _GstVaapiOverlayRectangle {
@ -61,31 +82,6 @@ struct _GstVaapiOverlayRectangle {
guint is_associated : 1;
};
/* XXX: optimize for the effective number of reference frames */
struct _GstVaapiContextPrivate {
VAConfigID config_id;
GPtrArray *surfaces;
GstVaapiVideoPool *surfaces_pool;
GPtrArray *overlays[2];
guint overlay_id;
GstVaapiProfile profile;
GstVaapiEntrypoint entrypoint;
guint width;
guint height;
guint ref_frames;
guint is_constructed : 1;
};
enum {
PROP_0,
PROP_PROFILE,
PROP_ENTRYPOINT,
PROP_WIDTH,
PROP_HEIGHT,
PROP_REF_FRAMES
};
static guint
get_max_ref_frames(GstVaapiProfile profile)
{
@ -188,7 +184,7 @@ overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay)
if (overlay->subpicture) {
overlay_rectangle_deassociate(overlay);
g_object_unref(overlay->subpicture);
gst_vaapi_object_unref(overlay->subpicture);
overlay->subpicture = NULL;
}
}
@ -197,7 +193,7 @@ static gboolean
overlay_rectangle_associate(GstVaapiOverlayRectangle *overlay)
{
GstVaapiSubpicture * const subpicture = overlay->subpicture;
GPtrArray * const surfaces = overlay->context->priv->surfaces;
GPtrArray * const surfaces = overlay->context->surfaces;
guint i, n_associated;
if (overlay->is_associated)
@ -219,7 +215,7 @@ static gboolean
overlay_rectangle_deassociate(GstVaapiOverlayRectangle *overlay)
{
GstVaapiSubpicture * const subpicture = overlay->subpicture;
GPtrArray * const surfaces = overlay->context->priv->surfaces;
GPtrArray * const surfaces = overlay->context->surfaces;
guint i, n_associated;
if (!overlay->is_associated)
@ -388,11 +384,9 @@ overlay_reassociate(GPtrArray *overlays)
static void
gst_vaapi_context_clear_overlay(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
overlay_clear(priv->overlays[0]);
overlay_clear(priv->overlays[1]);
priv->overlay_id = 0;
overlay_clear(context->overlays[0]);
overlay_clear(context->overlays[1]);
context->overlay_id = 0;
}
static inline void
@ -407,30 +401,26 @@ unref_surface_cb(gpointer data, gpointer user_data)
GstVaapiSurface * const surface = GST_VAAPI_SURFACE(data);
gst_vaapi_surface_set_parent_context(surface, NULL);
g_object_unref(surface);
gst_vaapi_object_unref(surface);
}
static void
gst_vaapi_context_destroy_surfaces(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
gst_vaapi_context_destroy_overlay(context);
if (priv->surfaces) {
g_ptr_array_foreach(priv->surfaces, unref_surface_cb, NULL);
g_ptr_array_free(priv->surfaces, TRUE);
priv->surfaces = NULL;
if (context->surfaces) {
g_ptr_array_foreach(context->surfaces, unref_surface_cb, NULL);
g_ptr_array_free(context->surfaces, TRUE);
context->surfaces = NULL;
}
g_clear_object(&priv->surfaces_pool);
g_clear_object(&context->surfaces_pool);
}
static void
gst_vaapi_context_destroy(GstVaapiContext *context)
{
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
GstVaapiContextPrivate * const priv = context->priv;
VAContextID context_id;
VAStatus status;
@ -450,26 +440,24 @@ gst_vaapi_context_destroy(GstVaapiContext *context)
GST_VAAPI_OBJECT_ID(context) = VA_INVALID_ID;
}
if (priv->config_id != VA_INVALID_ID) {
if (context->config_id != VA_INVALID_ID) {
GST_VAAPI_DISPLAY_LOCK(display);
status = vaDestroyConfig(
GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->config_id
context->config_id
);
GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaDestroyConfig()"))
g_warning("failed to destroy config %" GST_VAAPI_ID_FORMAT,
GST_VAAPI_ID_ARGS(priv->config_id));
priv->config_id = VA_INVALID_ID;
GST_VAAPI_ID_ARGS(context->config_id));
context->config_id = VA_INVALID_ID;
}
}
static gboolean
gst_vaapi_context_create_overlay(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
if (!priv->overlays[0] || !priv->overlays[1])
if (!context->overlays[0] || !context->overlays[1])
return FALSE;
gst_vaapi_context_clear_overlay(context);
@ -479,7 +467,7 @@ gst_vaapi_context_create_overlay(GstVaapiContext *context)
static gboolean
gst_vaapi_context_create_surfaces(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
const GstVaapiContextInfo * const cip = &context->info;
GstCaps *caps;
GstVaapiSurface *surface;
guint i, num_surfaces;
@ -490,45 +478,45 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
if (!gst_vaapi_context_create_overlay(context))
return FALSE;
if (!priv->surfaces) {
priv->surfaces = g_ptr_array_new();
if (!priv->surfaces)
if (!context->surfaces) {
context->surfaces = g_ptr_array_new();
if (!context->surfaces)
return FALSE;
}
if (!priv->surfaces_pool) {
if (!context->surfaces_pool) {
caps = gst_caps_new_simple(
GST_VAAPI_SURFACE_CAPS_NAME,
"type", G_TYPE_STRING, "vaapi",
"width", G_TYPE_INT, priv->width,
"height", G_TYPE_INT, priv->height,
"width", G_TYPE_INT, cip->width,
"height", G_TYPE_INT, cip->height,
NULL
);
if (!caps)
return FALSE;
priv->surfaces_pool = gst_vaapi_surface_pool_new(
context->surfaces_pool = gst_vaapi_surface_pool_new(
GST_VAAPI_OBJECT_DISPLAY(context),
caps
);
gst_caps_unref(caps);
if (!priv->surfaces_pool)
if (!context->surfaces_pool)
return FALSE;
}
num_surfaces = priv->ref_frames + SCRATCH_SURFACES_COUNT;
gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, num_surfaces);
num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
gst_vaapi_video_pool_set_capacity(context->surfaces_pool, num_surfaces);
for (i = priv->surfaces->len; i < num_surfaces; i++) {
for (i = context->surfaces->len; i < num_surfaces; i++) {
surface = gst_vaapi_surface_new(
GST_VAAPI_OBJECT_DISPLAY(context),
GST_VAAPI_CHROMA_TYPE_YUV420,
priv->width, priv->height
cip->width, cip->height
);
if (!surface)
return FALSE;
gst_vaapi_surface_set_parent_context(surface, context);
g_ptr_array_add(priv->surfaces, surface);
if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface))
g_ptr_array_add(context->surfaces, surface);
if (!gst_vaapi_video_pool_add_object(context->surfaces_pool, surface))
return FALSE;
}
return TRUE;
@ -537,8 +525,8 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
static gboolean
gst_vaapi_context_create(GstVaapiContext *context)
{
const GstVaapiContextInfo * const cip = &context->info;
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
GstVaapiContextPrivate * const priv = context->priv;
VAProfile va_profile;
VAEntrypoint va_entrypoint;
VAConfigAttrib attrib;
@ -549,31 +537,32 @@ gst_vaapi_context_create(GstVaapiContext *context)
gboolean success = FALSE;
guint i;
if (!priv->surfaces && !gst_vaapi_context_create_surfaces(context))
if (!context->surfaces && !gst_vaapi_context_create_surfaces(context))
goto end;
surfaces = g_array_sized_new(
FALSE,
FALSE,
sizeof(VASurfaceID),
priv->surfaces->len
context->surfaces->len
);
if (!surfaces)
goto end;
for (i = 0; i < priv->surfaces->len; i++) {
GstVaapiSurface * const surface = g_ptr_array_index(priv->surfaces, i);
for (i = 0; i < context->surfaces->len; i++) {
GstVaapiSurface * const surface =
g_ptr_array_index(context->surfaces, i);
if (!surface)
goto end;
surface_id = GST_VAAPI_OBJECT_ID(surface);
g_array_append_val(surfaces, surface_id);
}
assert(surfaces->len == priv->surfaces->len);
assert(surfaces->len == context->surfaces->len);
if (!priv->profile || !priv->entrypoint)
if (!cip->profile || !cip->entrypoint)
goto end;
va_profile = gst_vaapi_profile_get_va_profile(priv->profile);
va_entrypoint = gst_vaapi_entrypoint_get_va_entrypoint(priv->entrypoint);
va_profile = gst_vaapi_profile_get_va_profile(cip->profile);
va_entrypoint = gst_vaapi_entrypoint_get_va_entrypoint(cip->entrypoint);
GST_VAAPI_DISPLAY_LOCK(display);
attrib.type = VAConfigAttribRTFormat;
@ -595,7 +584,7 @@ gst_vaapi_context_create(GstVaapiContext *context)
va_profile,
va_entrypoint,
&attrib, 1,
&priv->config_id
&context->config_id
);
GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaCreateConfig()"))
@ -604,8 +593,8 @@ gst_vaapi_context_create(GstVaapiContext *context)
GST_VAAPI_DISPLAY_LOCK(display);
status = vaCreateContext(
GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->config_id,
priv->width, priv->height,
context->config_id,
cip->width, cip->height,
VA_PROGRESSIVE,
(VASurfaceID *)surfaces->data, surfaces->len,
&context_id
@ -623,160 +612,25 @@ end:
return success;
}
static void
gst_vaapi_context_finalize(GObject *object)
static inline void
gst_vaapi_context_init(GstVaapiContext *context, const GstVaapiContextInfo *cip)
{
GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
GstVaapiContextPrivate * const priv = context->priv;
context->info = *cip;
context->config_id = VA_INVALID_ID;
context->overlays[0] = overlay_new();
context->overlays[1] = overlay_new();
}
overlay_destroy(&priv->overlays[0]);
overlay_destroy(&priv->overlays[1]);
static void
gst_vaapi_context_finalize(GstVaapiContext *context)
{
overlay_destroy(&context->overlays[0]);
overlay_destroy(&context->overlays[1]);
gst_vaapi_context_destroy(context);
gst_vaapi_context_destroy_surfaces(context);
G_OBJECT_CLASS(gst_vaapi_context_parent_class)->finalize(object);
}
static void
gst_vaapi_context_set_property(
GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec
)
{
GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
GstVaapiContextPrivate * const priv = context->priv;
switch (prop_id) {
case PROP_PROFILE:
gst_vaapi_context_set_profile(context, g_value_get_uint(value));
break;
case PROP_ENTRYPOINT:
priv->entrypoint = g_value_get_uint(value);
break;
case PROP_WIDTH:
priv->width = g_value_get_uint(value);
break;
case PROP_HEIGHT:
priv->height = g_value_get_uint(value);
break;
case PROP_REF_FRAMES:
priv->ref_frames = g_value_get_uint(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_context_get_property(
GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec
)
{
GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
GstVaapiContextPrivate * const priv = context->priv;
switch (prop_id) {
case PROP_PROFILE:
g_value_set_uint(value, gst_vaapi_context_get_profile(context));
break;
case PROP_ENTRYPOINT:
g_value_set_uint(value, gst_vaapi_context_get_entrypoint(context));
break;
case PROP_WIDTH:
g_value_set_uint(value, priv->width);
break;
case PROP_HEIGHT:
g_value_set_uint(value, priv->height);
break;
case PROP_REF_FRAMES:
g_value_set_uint(value, priv->ref_frames);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_context_class_init(GstVaapiContextClass *klass)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(GstVaapiContextPrivate));
object_class->finalize = gst_vaapi_context_finalize;
object_class->set_property = gst_vaapi_context_set_property;
object_class->get_property = gst_vaapi_context_get_property;
g_object_class_install_property
(object_class,
PROP_PROFILE,
g_param_spec_uint("profile",
"Profile",
"The profile used for decoding",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE));
g_object_class_install_property
(object_class,
PROP_ENTRYPOINT,
g_param_spec_uint("entrypoint",
"Entrypoint",
"The decoder entrypoint",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_WIDTH,
g_param_spec_uint("width",
"Width",
"The width of decoded surfaces",
0, G_MAXINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_HEIGHT,
g_param_spec_uint("height",
"Height",
"The height of the decoded surfaces",
0, G_MAXINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_REF_FRAMES,
g_param_spec_uint("ref-frames",
"Reference Frames",
"The number of reference frames",
0, G_MAXINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
}
static void
gst_vaapi_context_init(GstVaapiContext *context)
{
GstVaapiContextPrivate *priv = GST_VAAPI_CONTEXT_GET_PRIVATE(context);
context->priv = priv;
priv->config_id = VA_INVALID_ID;
priv->surfaces = NULL;
priv->surfaces_pool = NULL;
priv->overlays[0] = overlay_new();
priv->overlays[1] = overlay_new();
priv->profile = 0;
priv->entrypoint = 0;
priv->width = 0;
priv->height = 0;
priv->ref_frames = 0;
}
GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiContext, gst_vaapi_context)
/**
* gst_vaapi_context_new:
@ -822,32 +676,28 @@ gst_vaapi_context_new(
* Return value: the newly allocated #GstVaapiContext object
*/
GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip)
gst_vaapi_context_new_full(GstVaapiDisplay *display,
const GstVaapiContextInfo *cip)
{
GstVaapiContext *context;
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
g_return_val_if_fail(cip->profile, NULL);
g_return_val_if_fail(cip->entrypoint, NULL);
g_return_val_if_fail(cip->width > 0, NULL);
g_return_val_if_fail(cip->height > 0, NULL);
context = g_object_new(
GST_VAAPI_TYPE_CONTEXT,
"display", display,
"id", GST_VAAPI_ID(VA_INVALID_ID),
"profile", cip->profile,
"entrypoint", cip->entrypoint,
"width", cip->width,
"height", cip->height,
"ref-frames", cip->ref_frames,
NULL
);
if (!context->priv->is_constructed) {
g_object_unref(context);
context = gst_vaapi_object_new(gst_vaapi_context_class(), display);
if (!context)
return NULL;
}
gst_vaapi_context_init(context, cip);
if (!gst_vaapi_context_create(context))
goto error;
return context;
error:
gst_vaapi_object_unref(context);
return NULL;
}
/**
@ -872,14 +722,13 @@ gst_vaapi_context_reset(
unsigned int height
)
{
GstVaapiContextPrivate * const priv = context->priv;
GstVaapiContextInfo info;
info.profile = profile;
info.entrypoint = entrypoint;
info.width = width;
info.height = height;
info.ref_frames = priv->ref_frames;
info.ref_frames = context->info.ref_frames;
return gst_vaapi_context_reset_full(context, &info);
}
@ -887,32 +736,35 @@ gst_vaapi_context_reset(
/**
* gst_vaapi_context_reset_full:
* @context: a #GstVaapiContext
* @cip: a pointer to the new #GstVaapiContextInfo details
* @new_cip: a pointer to the new #GstVaapiContextInfo details
*
* Resets @context to the configuration specified by @cip, thus
* Resets @context to the configuration specified by @new_cip, thus
* including profile, entry-point, encoded size and maximum number of
* reference frames reported by the bitstream.
*
* Return value: %TRUE on success
*/
gboolean
gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip)
gst_vaapi_context_reset_full(GstVaapiContext *context,
const GstVaapiContextInfo *new_cip)
{
GstVaapiContextPrivate * const priv = context->priv;
GstVaapiContextInfo * const cip = &context->info;
gboolean size_changed, codec_changed;
size_changed = priv->width != cip->width || priv->height != cip->height;
size_changed = cip->width != new_cip->width ||
cip->height != new_cip->height;
if (size_changed) {
gst_vaapi_context_destroy_surfaces(context);
priv->width = cip->width;
priv->height = cip->height;
cip->width = new_cip->width;
cip->height = new_cip->height;
}
codec_changed = priv->profile != cip->profile || priv->entrypoint != cip->entrypoint;
codec_changed = cip->profile != new_cip->profile ||
cip->entrypoint != new_cip->entrypoint;
if (codec_changed) {
gst_vaapi_context_destroy(context);
priv->profile = cip->profile;
priv->entrypoint = cip->entrypoint;
cip->profile = new_cip->profile;
cip->entrypoint = new_cip->entrypoint;
}
if (size_changed && !gst_vaapi_context_create_surfaces(context))
@ -921,7 +773,6 @@ gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip)
if (codec_changed && !gst_vaapi_context_create(context))
return FALSE;
priv->is_constructed = TRUE;
return TRUE;
}
@ -954,7 +805,7 @@ gst_vaapi_context_get_profile(GstVaapiContext *context)
{
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
return context->priv->profile;
return context->info.profile;
}
/**
@ -977,9 +828,9 @@ gst_vaapi_context_set_profile(GstVaapiContext *context, GstVaapiProfile profile)
return gst_vaapi_context_reset(context,
profile,
context->priv->entrypoint,
context->priv->width,
context->priv->height);
context->info.entrypoint,
context->info.width,
context->info.height);
}
/**
@ -995,7 +846,7 @@ gst_vaapi_context_get_entrypoint(GstVaapiContext *context)
{
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
return context->priv->entrypoint;
return context->info.entrypoint;
}
/**
@ -1016,10 +867,10 @@ gst_vaapi_context_get_size(
g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
if (pwidth)
*pwidth = context->priv->width;
*pwidth = context->info.width;
if (pheight)
*pheight = context->priv->height;
*pheight = context->info.height;
}
/**
@ -1043,7 +894,7 @@ gst_vaapi_context_get_surface_proxy(GstVaapiContext *context)
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
return gst_vaapi_surface_proxy_new_from_pool(
GST_VAAPI_SURFACE_POOL(context->priv->surfaces_pool));
GST_VAAPI_SURFACE_POOL(context->surfaces_pool));
}
/**
@ -1059,7 +910,7 @@ gst_vaapi_context_get_surface_count(GstVaapiContext *context)
{
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
return gst_vaapi_video_pool_get_size(context->priv->surfaces_pool);
return gst_vaapi_video_pool_get_size(context->surfaces_pool);
}
/**
@ -1081,16 +932,13 @@ gst_vaapi_context_apply_composition(
GstVideoOverlayComposition *composition
)
{
GstVaapiContextPrivate *priv;
GPtrArray *curr_overlay, *next_overlay;
guint i, n_rectangles;
gboolean reassociate = FALSE;
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
priv = context->priv;
if (!priv->surfaces)
if (!context->surfaces)
return FALSE;
if (!composition) {
@ -1098,8 +946,8 @@ gst_vaapi_context_apply_composition(
return TRUE;
}
curr_overlay = priv->overlays[priv->overlay_id];
next_overlay = priv->overlays[priv->overlay_id ^ 1];
curr_overlay = context->overlays[context->overlay_id];
next_overlay = context->overlays[context->overlay_id ^ 1];
overlay_clear(next_overlay);
n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
@ -1126,7 +974,7 @@ gst_vaapi_context_apply_composition(
}
overlay_clear(curr_overlay);
priv->overlay_id ^= 1;
context->overlay_id ^= 1;
if (reassociate && !overlay_reassociate(next_overlay))
return FALSE;

View file

@ -31,34 +31,14 @@
G_BEGIN_DECLS
#define GST_VAAPI_TYPE_CONTEXT \
(gst_vaapi_context_get_type())
#define GST_VAAPI_CONTEXT(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContext))
#define GST_VAAPI_CONTEXT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContextClass))
((GstVaapiContext *)(obj))
#define GST_VAAPI_IS_CONTEXT(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_CONTEXT))
#define GST_VAAPI_IS_CONTEXT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_CONTEXT))
#define GST_VAAPI_CONTEXT_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), \
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContextClass))
((obj) != NULL)
typedef struct _GstVaapiContext GstVaapiContext;
typedef struct _GstVaapiContextInfo GstVaapiContextInfo;
typedef struct _GstVaapiContextPrivate GstVaapiContextPrivate;
typedef struct _GstVaapiContextClass GstVaapiContextClass;
/**
* GstVaapiContextInfo:
@ -75,31 +55,6 @@ struct _GstVaapiContextInfo {
guint ref_frames;
};
/**
* GstVaapiContext:
*
* A VA context wrapper.
*/
struct _GstVaapiContext {
/*< private >*/
GstVaapiObject parent_instance;
GstVaapiContextPrivate *priv;
};
/**
* GstVaapiContextClass:
*
* A VA context wrapper class.
*/
struct _GstVaapiContextClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
GType
gst_vaapi_context_get_type(void) G_GNUC_CONST;
GstVaapiContext *
gst_vaapi_context_new(
GstVaapiDisplay *display,
@ -110,7 +65,8 @@ gst_vaapi_context_new(
);
GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip);
gst_vaapi_context_new_full(GstVaapiDisplay *display,
const GstVaapiContextInfo *cip);
gboolean
gst_vaapi_context_reset(
@ -122,7 +78,8 @@ gst_vaapi_context_reset(
);
gboolean
gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip);
gst_vaapi_context_reset_full(GstVaapiContext *context,
const GstVaapiContextInfo *new_cip);
GstVaapiID
gst_vaapi_context_get_id(GstVaapiContext *context);

View file

@ -472,7 +472,7 @@ gst_vaapi_decoder_finalize(GObject *object)
priv->frames = NULL;
}
g_clear_object(&priv->context);
gst_vaapi_object_replace(&priv->context, NULL);
priv->va_context = VA_INVALID_ID;
g_clear_object(&priv->display);

View file

@ -30,19 +30,22 @@
#include "gstvaapicompat.h"
#include "gstvaapiutils.h"
#include "gstvaapiimage.h"
#include "gstvaapi_priv.h"
#include "gstvaapiobject_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, GST_VAAPI_TYPE_OBJECT)
typedef struct _GstVaapiImageClass GstVaapiImageClass;
#define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_IMAGE, \
GstVaapiImagePrivate))
/**
* GstVaapiImage:
*
* A VA image wrapper
*/
struct _GstVaapiImage {
/*< private >*/
GstVaapiObject parent_instance;
struct _GstVaapiImagePrivate {
VAImage internal_image;
VAImage image;
guchar *image_data;
@ -50,18 +53,17 @@ struct _GstVaapiImagePrivate {
GstVaapiImageFormat format;
guint width;
guint height;
guint create_image : 1;
guint is_constructed : 1;
guint is_linear : 1;
};
enum {
PROP_0,
PROP_IMAGE,
PROP_FORMAT,
PROP_WIDTH,
PROP_HEIGHT
/**
* GstVaapiImageClass:
*
* A VA image wrapper class
*/
struct _GstVaapiImageClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
#define SWAP_UINT(a, b) do { \
@ -83,35 +85,6 @@ _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)
{
@ -173,7 +146,6 @@ 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;
@ -188,30 +160,29 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
status = vaCreateImage(
GST_VAAPI_DISPLAY_VADISPLAY(display),
(VAImageFormat *)va_format,
priv->width,
priv->height,
&priv->internal_image
image->width,
image->height,
&image->internal_image
);
GST_VAAPI_DISPLAY_UNLOCK(display);
if (status != VA_STATUS_SUCCESS ||
priv->internal_image.format.fourcc != va_format->fourcc)
image->internal_image.format.fourcc != va_format->fourcc)
return FALSE;
priv->internal_format = format;
image->internal_format = format;
return TRUE;
}
static gboolean
gst_vaapi_image_create(GstVaapiImage *image)
gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format,
guint width, guint height)
{
GstVaapiImagePrivate * const priv = image->priv;
GstVaapiImageFormat format = priv->format;
const VAImageFormat *va_format;
VAImageID image_id;
if (!priv->create_image)
return (priv->image.image_id != VA_INVALID_ID &&
priv->image.buf != VA_INVALID_ID);
image->format = format;
image->width = width;
image->height = height;
if (!_gst_vaapi_image_create(image, format)) {
switch (format) {
@ -228,25 +199,25 @@ gst_vaapi_image_create(GstVaapiImage *image)
if (!format || !_gst_vaapi_image_create(image, format))
return FALSE;
}
priv->image = priv->internal_image;
image_id = priv->image.image_id;
image->image = image->internal_image;
image_id = image->image.image_id;
if (priv->format != priv->internal_format) {
switch (priv->format) {
if (image->format != image->internal_format) {
switch (image->format) {
case GST_VAAPI_IMAGE_YV12:
case GST_VAAPI_IMAGE_I420:
va_format = gst_vaapi_image_format_get_va_format(priv->format);
va_format = gst_vaapi_image_format_get_va_format(image->format);
if (!va_format)
return FALSE;
priv->image.format = *va_format;
SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
image->image.format = *va_format;
SWAP_UINT(image->image.offsets[1], image->image.offsets[2]);
SWAP_UINT(image->image.pitches[1], image->image.pitches[2]);
break;
default:
break;
}
}
priv->is_linear = vaapi_image_is_linear(&priv->image);
image->is_linear = vaapi_image_is_linear(&image->image);
GST_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
GST_VAAPI_OBJECT_ID(image) = image_id;
@ -254,168 +225,28 @@ gst_vaapi_image_create(GstVaapiImage *image)
}
static void
gst_vaapi_image_finalize(GObject *object)
gst_vaapi_image_init(GstVaapiImage *image)
{
gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object));
G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object);
}
static void
gst_vaapi_image_set_property(
GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec
)
{
GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
GstVaapiImagePrivate * const priv = image->priv;
switch (prop_id) {
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:
if (priv->create_image)
priv->format = g_value_get_uint(value);
break;
case PROP_WIDTH:
if (priv->create_image)
priv->width = g_value_get_uint(value);
break;
case PROP_HEIGHT:
if (priv->create_image)
priv->height = g_value_get_uint(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_image_get_property(
GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec
)
{
GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
switch (prop_id) {
case PROP_IMAGE:
g_value_set_boxed(value, &image->priv->image);
break;
case PROP_FORMAT:
g_value_set_uint(value, gst_vaapi_image_get_format(image));
break;
case PROP_WIDTH:
g_value_set_uint(value, gst_vaapi_image_get_width(image));
break;
case PROP_HEIGHT:
g_value_set_uint(value, gst_vaapi_image_get_height(image));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_image_constructed(GObject *object)
{
GstVaapiImage * const image = GST_VAAPI_IMAGE(object);
GObjectClass *parent_class;
image->priv->is_constructed = gst_vaapi_image_create(image);
parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class);
if (parent_class->constructed)
parent_class->constructed(object);
image->internal_image.image_id = VA_INVALID_ID;
image->internal_image.buf = VA_INVALID_ID;
image->image.image_id = VA_INVALID_ID;
image->image.buf = VA_INVALID_ID;
}
static void
gst_vaapi_image_class_init(GstVaapiImageClass *klass)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
GstVaapiObjectClass * const object_class =
GST_VAAPI_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate));
object_class->finalize = gst_vaapi_image_finalize;
object_class->set_property = gst_vaapi_image_set_property;
object_class->get_property = gst_vaapi_image_get_property;
object_class->constructed = gst_vaapi_image_constructed;
g_object_class_install_property
(object_class,
PROP_IMAGE,
g_param_spec_boxed("image",
"Image",
"The underlying VA image",
VAAPI_TYPE_IMAGE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_WIDTH,
g_param_spec_uint("width",
"width",
"The image width",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_HEIGHT,
g_param_spec_uint("height",
"heighr",
"The image height",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
/**
* GstVaapiImage:format:
*
* The #GstVaapiImageFormat of the image
*/
g_object_class_install_property
(object_class,
PROP_FORMAT,
g_param_spec_uint("format",
"Format",
"The underlying image format",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
object_class->init = (GstVaapiObjectInitFunc)gst_vaapi_image_init;
}
static void
gst_vaapi_image_init(GstVaapiImage *image)
{
GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
image->priv = priv;
priv->image_data = NULL;
priv->width = 0;
priv->height = 0;
priv->internal_format = 0;
priv->format = 0;
priv->create_image = TRUE;
priv->is_constructed = FALSE;
priv->is_linear = FALSE;
memset(&priv->internal_image, 0, sizeof(priv->internal_image));
priv->internal_image.image_id = VA_INVALID_ID;
priv->internal_image.buf = VA_INVALID_ID;
memset(&priv->image, 0, sizeof(priv->image));
priv->image.image_id = VA_INVALID_ID;
priv->image.buf = VA_INVALID_ID;
}
#define gst_vaapi_image_finalize gst_vaapi_image_destroy
GST_VAAPI_OBJECT_DEFINE_CLASS_WITH_CODE(
GstVaapiImage,
gst_vaapi_image,
gst_vaapi_image_class_init(&g_class))
/**
* gst_vaapi_image_new:
@ -439,30 +270,23 @@ gst_vaapi_image_new(
{
GstVaapiImage *image;
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
g_return_val_if_fail(width > 0, NULL);
g_return_val_if_fail(height > 0, NULL);
GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
GST_FOURCC_ARGS(format), width, height);
image = g_object_new(
GST_VAAPI_TYPE_IMAGE,
"display", display,
"id", GST_VAAPI_ID(VA_INVALID_ID),
"format", format,
"width", width,
"height", height,
NULL
);
image = gst_vaapi_object_new(gst_vaapi_image_class(), display);
if (!image)
return NULL;
if (!image->priv->is_constructed) {
g_object_unref(image);
return NULL;
}
if (!gst_vaapi_image_create(image, format, width, height))
goto error;
return image;
error:
gst_vaapi_object_unref(image);
return NULL;
}
/**
@ -482,7 +306,6 @@ 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);
@ -492,21 +315,17 @@ gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image)
GST_FOURCC_ARGS(va_image->format.fourcc),
va_image->width, va_image->height);
image = g_object_new(
GST_VAAPI_TYPE_IMAGE,
"display", display,
"id", GST_VAAPI_ID(va_image->image_id),
"image", va_image,
NULL
);
image = gst_vaapi_object_new(gst_vaapi_image_class(), display);
if (!image)
return NULL;
if (!image->priv->is_constructed) {
g_object_unref(image);
return NULL;
}
if (!_gst_vaapi_image_set_image(image, va_image))
goto error;
return image;
error:
gst_vaapi_object_unref(image);
return NULL;
}
/**
@ -521,7 +340,6 @@ GstVaapiID
gst_vaapi_image_get_id(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID);
g_return_val_if_fail(image->priv->is_constructed, VA_INVALID_ID);
return GST_VAAPI_OBJECT_ID(image);
}
@ -539,10 +357,9 @@ gboolean
gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
if (va_image)
*va_image = image->priv->image;
*va_image = image->image;
return TRUE;
}
@ -564,29 +381,26 @@ gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
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;
image->internal_image = *va_image;
image->internal_format = format;
image->is_linear = vaapi_image_is_linear(va_image);
image->image = *va_image;
image->format = format;
image->width = va_image->width;
image->height = va_image->height;
GST_VAAPI_OBJECT_ID(image) = va_image->image_id;
/* Try to linearize image */
if (!priv->is_linear) {
if (!image->is_linear) {
switch (format) {
case GST_VAAPI_IMAGE_I420:
format = GST_VAAPI_IMAGE_YV12;
@ -605,9 +419,9 @@ _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
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;
image->image = alt_va_image;
image->format = format;
image->is_linear = TRUE;
GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
GST_FOURCC_ARGS(format));
}
@ -628,9 +442,8 @@ GstVaapiImageFormat
gst_vaapi_image_get_format(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
g_return_val_if_fail(image->priv->is_constructed, 0);
return image->priv->format;
return image->format;
}
/**
@ -645,9 +458,8 @@ guint
gst_vaapi_image_get_width(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
g_return_val_if_fail(image->priv->is_constructed, 0);
return image->priv->width;
return image->width;
}
/**
@ -662,9 +474,8 @@ guint
gst_vaapi_image_get_height(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
g_return_val_if_fail(image->priv->is_constructed, 0);
return image->priv->height;
return image->height;
}
/**
@ -679,13 +490,12 @@ void
gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
{
g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
g_return_if_fail(image->priv->is_constructed);
if (pwidth)
*pwidth = image->priv->width;
*pwidth = image->width;
if (pheight)
*pheight = image->priv->height;
*pheight = image->height;
}
/**
@ -702,9 +512,8 @@ gboolean
gst_vaapi_image_is_linear(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->is_linear;
return image->is_linear;
}
/**
@ -718,14 +527,13 @@ gst_vaapi_image_is_linear(GstVaapiImage *image)
static inline gboolean
_gst_vaapi_image_is_mapped(GstVaapiImage *image)
{
return image->priv->image_data != NULL;
return image->image_data != NULL;
}
gboolean
gst_vaapi_image_is_mapped(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
return _gst_vaapi_image_is_mapped(image);
}
@ -743,7 +551,6 @@ gboolean
gst_vaapi_image_map(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
return _gst_vaapi_image_map(image, NULL);
}
@ -751,7 +558,6 @@ gst_vaapi_image_map(GstVaapiImage *image)
gboolean
_gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
{
GstVaapiImagePrivate * const priv = image->priv;
GstVaapiDisplay *display;
VAStatus status;
guint i;
@ -766,8 +572,8 @@ _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
GST_VAAPI_DISPLAY_LOCK(display);
status = vaMapBuffer(
GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->image.buf,
(void **)&priv->image_data
image->image.buf,
(void **)&image->image_data
);
GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaMapBuffer()"))
@ -775,13 +581,13 @@ _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
map_success:
if (raw_image) {
const VAImage * const va_image = &priv->image;
raw_image->format = priv->format;
const VAImage * const va_image = &image->image;
raw_image->format = image->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 *)priv->image_data +
raw_image->pixels[i] = (guchar *)image->image_data +
va_image->offsets[i];
raw_image->stride[i] = va_image->pitches[i];
}
@ -802,7 +608,6 @@ gboolean
gst_vaapi_image_unmap(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
return _gst_vaapi_image_unmap(image);
}
@ -823,13 +628,13 @@ _gst_vaapi_image_unmap(GstVaapiImage *image)
GST_VAAPI_DISPLAY_LOCK(display);
status = vaUnmapBuffer(
GST_VAAPI_DISPLAY_VADISPLAY(display),
image->priv->image.buf
image->image.buf
);
GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaUnmapBuffer()"))
return FALSE;
image->priv->image_data = NULL;
image->image_data = NULL;
return TRUE;
}
@ -846,10 +651,9 @@ guint
gst_vaapi_image_get_plane_count(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
return image->priv->image.num_planes;
return image->image.num_planes;
}
/**
@ -866,11 +670,10 @@ guchar *
gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL);
g_return_val_if_fail(plane < image->priv->image.num_planes, NULL);
g_return_val_if_fail(plane < image->image.num_planes, NULL);
return image->priv->image_data + image->priv->image.offsets[plane];
return image->image_data + image->image.offsets[plane];
}
/**
@ -887,11 +690,10 @@ guint
gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0);
g_return_val_if_fail(plane < image->priv->image.num_planes, 0);
g_return_val_if_fail(plane < image->image.num_planes, 0);
return image->priv->image.pitches[plane];
return image->image.pitches[plane];
}
/**
@ -908,9 +710,8 @@ guint
gst_vaapi_image_get_data_size(GstVaapiImage *image)
{
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
return image->priv->image.data_size;
return image->image.data_size;
}
#if GST_CHECK_VERSION(1,0,0)
@ -1175,21 +976,17 @@ gst_vaapi_image_get_buffer(
GstVaapiRectangle *rect
)
{
GstVaapiImagePrivate *priv;
GstVaapiImageRaw dst_image, src_image;
gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
priv = image->priv;
if (!init_image_from_buffer(&dst_image, buffer))
return FALSE;
if (dst_image.format != priv->format)
if (dst_image.format != image->format)
return FALSE;
if (dst_image.width != priv->width || dst_image.height != priv->height)
if (dst_image.width != image->width || dst_image.height != image->height)
return FALSE;
if (!_gst_vaapi_image_map(image, &src_image))
@ -1226,7 +1023,6 @@ gst_vaapi_image_get_raw(
gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
if (!_gst_vaapi_image_map(image, &src_image))
return FALSE;
@ -1258,21 +1054,17 @@ gst_vaapi_image_update_from_buffer(
GstVaapiRectangle *rect
)
{
GstVaapiImagePrivate *priv;
GstVaapiImageRaw dst_image, src_image;
gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
priv = image->priv;
if (!init_image_from_buffer(&src_image, buffer))
return FALSE;
if (src_image.format != priv->format)
if (src_image.format != image->format)
return FALSE;
if (src_image.width != priv->width || src_image.height != priv->height)
if (src_image.width != image->width || src_image.height != image->height)
return FALSE;
if (!_gst_vaapi_image_map(image, &dst_image))
@ -1310,7 +1102,6 @@ gst_vaapi_image_update_from_raw(
gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
if (!_gst_vaapi_image_map(image, &dst_image))
return FALSE;

View file

@ -30,29 +30,11 @@
G_BEGIN_DECLS
#define GST_VAAPI_TYPE_IMAGE \
(gst_vaapi_image_get_type())
#define GST_VAAPI_IMAGE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
GST_VAAPI_TYPE_IMAGE, \
GstVaapiImage))
#define GST_VAAPI_IMAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_IMAGE, \
GstVaapiImageClass))
((GstVaapiImage *)(obj))
#define GST_VAAPI_IS_IMAGE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_IMAGE))
#define GST_VAAPI_IS_IMAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_IMAGE))
#define GST_VAAPI_IMAGE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), \
GST_VAAPI_TYPE_IMAGE, \
GstVaapiImageClass))
((obj) != NULL)
/**
* GST_VAAPI_IMAGE_FORMAT:
@ -79,32 +61,8 @@ G_BEGIN_DECLS
#define GST_VAAPI_IMAGE_HEIGHT(image) gst_vaapi_image_get_height(image)
typedef struct _GstVaapiImage GstVaapiImage;
typedef struct _GstVaapiImagePrivate GstVaapiImagePrivate;
typedef struct _GstVaapiImageClass GstVaapiImageClass;
typedef struct _GstVaapiImageRaw GstVaapiImageRaw;
/**
* GstVaapiImage:
*
* A VA image wrapper
*/
struct _GstVaapiImage {
/*< private >*/
GstVaapiObject parent_instance;
GstVaapiImagePrivate *priv;
};
/**
* GstVaapiImageClass:
*
* A VA image wrapper class
*/
struct _GstVaapiImageClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
/**
* GstVaapiImageRaw:
*
@ -120,9 +78,6 @@ struct _GstVaapiImageRaw {
guint stride[3];
};
GType
gst_vaapi_image_get_type(void) G_GNUC_CONST;
GstVaapiImage *
gst_vaapi_image_new(
GstVaapiDisplay *display,

View file

@ -30,37 +30,41 @@
#include "gstvaapicompat.h"
#include "gstvaapiutils.h"
#include "gstvaapisubpicture.h"
#include "gstvaapi_priv.h"
#include "gstvaapiobject_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE(GstVaapiSubpicture, gst_vaapi_subpicture, GST_VAAPI_TYPE_OBJECT)
typedef struct _GstVaapiSubpictureClass GstVaapiSubpictureClass;
#define GST_VAAPI_SUBPICTURE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_SUBPICTURE, \
GstVaapiSubpicturePrivate))
/**
* GstVaapiSubpicture:
*
* A VA subpicture wrapper
*/
struct _GstVaapiSubpicture {
/*< private >*/
GstVaapiObject parent_instance;
struct _GstVaapiSubpicturePrivate {
GstVaapiImage *image;
guint flags;
gfloat global_alpha;
};
enum {
PROP_0,
PROP_FLAGS,
PROP_GLOBAL_ALPHA,
PROP_IMAGE
/**
* GstVaapiSubpictureClass:
*
* A VA subpicture wrapper class
*/
struct _GstVaapiSubpictureClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
static void
gst_vaapi_subpicture_destroy(GstVaapiSubpicture *subpicture)
{
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
GstVaapiSubpicturePrivate * const priv = subpicture->priv;
VASubpictureID subpicture_id;
VAStatus status;
@ -82,25 +86,21 @@ gst_vaapi_subpicture_destroy(GstVaapiSubpicture *subpicture)
}
GST_VAAPI_OBJECT_ID(subpicture) = VA_INVALID_ID;
}
g_clear_object(&priv->image);
gst_vaapi_object_replace(&subpicture->image, NULL);
}
static gboolean
gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture)
gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture,
GstVaapiImage *image)
{
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
GstVaapiSubpicturePrivate * const priv = subpicture->priv;
VASubpictureID subpicture_id;
VAStatus status;
if (!priv->image)
return FALSE;
GST_VAAPI_DISPLAY_LOCK(display);
status = vaCreateSubpicture(
GST_VAAPI_DISPLAY_VADISPLAY(display),
GST_VAAPI_OBJECT_ID(priv->image),
GST_VAAPI_OBJECT_ID(image),
&subpicture_id
);
GST_VAAPI_DISPLAY_UNLOCK(display);
@ -110,134 +110,12 @@ gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture)
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;
}
static void
gst_vaapi_subpicture_finalize(GObject *object)
{
gst_vaapi_subpicture_destroy(GST_VAAPI_SUBPICTURE(object));
G_OBJECT_CLASS(gst_vaapi_subpicture_parent_class)->finalize(object);
}
static void
gst_vaapi_subpicture_set_property(
GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec
)
{
GstVaapiSubpicture * const subpicture = GST_VAAPI_SUBPICTURE(object);
switch (prop_id) {
case PROP_FLAGS:
subpicture->priv->flags = g_value_get_uint(value);
break;
case PROP_GLOBAL_ALPHA:
gst_vaapi_subpicture_set_global_alpha(subpicture,
g_value_get_float(value));
break;
case PROP_IMAGE:
gst_vaapi_subpicture_set_image(subpicture, g_value_get_object(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_subpicture_get_property(
GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec
)
{
GstVaapiSubpicture * const subpicture = GST_VAAPI_SUBPICTURE(object);
switch (prop_id) {
case PROP_FLAGS:
g_value_set_uint(value, subpicture->priv->flags);
break;
case PROP_GLOBAL_ALPHA:
g_value_set_float(value,
gst_vaapi_subpicture_get_global_alpha(subpicture));
break;
case PROP_IMAGE:
g_value_set_object(value, gst_vaapi_subpicture_get_image(subpicture));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_subpicture_class_init(GstVaapiSubpictureClass *klass)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(GstVaapiSubpicturePrivate));
object_class->finalize = gst_vaapi_subpicture_finalize;
object_class->set_property = gst_vaapi_subpicture_set_property;
object_class->get_property = gst_vaapi_subpicture_get_property;
/**
* GstVaapiSubpicture:flags:
*
* The #GstVaapiSubpictureFlags this subpicture requires.
*/
g_object_class_install_property
(object_class,
PROP_FLAGS,
g_param_spec_uint("flags",
"Flags",
"The GstVaapiSubpictureFlags this subpicture requires",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
/**
* GstVaapiSubpicture:global-alpha:
*
* The global-alpha value associated with this subpicture.
*/
g_object_class_install_property
(object_class,
PROP_GLOBAL_ALPHA,
g_param_spec_float("global-alpha",
"Global Alpha",
"The global-alpha value associated with this subpicture",
0.0f, 1.0f, 1.0f,
G_PARAM_READWRITE));
/**
* GstVaapiSubpicture:image:
*
* The #GstVaapiImage this subpicture is bound to.
*/
g_object_class_install_property
(object_class,
PROP_IMAGE,
g_param_spec_object("image",
"Image",
"The GstVaapiImage this subpicture is bound to",
GST_VAAPI_TYPE_IMAGE,
G_PARAM_READWRITE));
}
static void
gst_vaapi_subpicture_init(GstVaapiSubpicture *subpicture)
{
GstVaapiSubpicturePrivate *priv = GST_VAAPI_SUBPICTURE_GET_PRIVATE(subpicture);
subpicture->priv = priv;
priv->image = NULL;
priv->global_alpha = 1.0f;
}
#define gst_vaapi_subpicture_finalize gst_vaapi_subpicture_destroy
GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiSubpicture, gst_vaapi_subpicture)
/**
* gst_vaapi_subpicture_new:
@ -252,6 +130,7 @@ gst_vaapi_subpicture_init(GstVaapiSubpicture *subpicture)
GstVaapiSubpicture *
gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags)
{
GstVaapiSubpicture *subpicture;
GstVaapiDisplay *display;
GstVaapiImageFormat format;
guint va_flags;
@ -268,13 +147,18 @@ gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags)
if (flags & ~va_flags)
return NULL;
return g_object_new(GST_VAAPI_TYPE_SUBPICTURE,
"display", GST_VAAPI_OBJECT_DISPLAY(image),
"id", GST_VAAPI_ID(VA_INVALID_ID),
"flags", flags,
"global-alpha", 1.0f,
"image", image,
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;
}
/**
@ -358,12 +242,12 @@ gst_vaapi_subpicture_new_from_overlay_rectangle(
raw_image.stride[0] = stride;
if (!gst_vaapi_image_update_from_raw(image, &raw_image, NULL)) {
GST_WARNING("could not update VA image with subtitle data");
g_object_unref(image);
gst_vaapi_object_unref(image);
return NULL;
}
subpicture = gst_vaapi_subpicture_new(image, flags);
g_object_unref(image);
gst_vaapi_object_unref(image);
#if GST_CHECK_VERSION(1,0,0)
gst_video_meta_unmap(vmeta, 0, &map_info);
#endif
@ -407,7 +291,7 @@ gst_vaapi_subpicture_get_flags(GstVaapiSubpicture *subpicture)
{
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), 0);
return subpicture->priv->flags;
return subpicture->flags;
}
/**
@ -423,7 +307,7 @@ gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture)
{
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), NULL);
return subpicture->priv->image;
return subpicture->image;
}
/**
@ -433,20 +317,18 @@ gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture)
*
* Binds a new #GstVaapiImage to the @subpicture. The reference to the
* previous image is released and a new one is acquired on @image.
*
* Return value: %TRUE on success
*/
void
gst_vaapi_subpicture_set_image(
GstVaapiSubpicture *subpicture,
GstVaapiImage *image
)
gboolean
gst_vaapi_subpicture_set_image(GstVaapiSubpicture *subpicture,
GstVaapiImage *image)
{
g_return_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture));
g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
gst_vaapi_subpicture_destroy(subpicture);
subpicture->priv->image = g_object_ref(image);
gst_vaapi_subpicture_create(subpicture);
return gst_vaapi_subpicture_create(subpicture, image);
}
/**
@ -462,7 +344,7 @@ gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture)
{
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), 1.0);
return subpicture->priv->global_alpha;
return subpicture->global_alpha;
}
/**
@ -480,18 +362,15 @@ gboolean
gst_vaapi_subpicture_set_global_alpha(GstVaapiSubpicture *subpicture,
gfloat global_alpha)
{
GstVaapiSubpicturePrivate *priv;
GstVaapiDisplay *display;
VAStatus status;
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
priv = subpicture->priv;
if (!(priv->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA))
if (!(subpicture->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA))
return FALSE;
if (priv->global_alpha == global_alpha)
if (subpicture->global_alpha == global_alpha)
return TRUE;
display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
@ -506,6 +385,6 @@ gst_vaapi_subpicture_set_global_alpha(GstVaapiSubpicture *subpicture,
if (!vaapi_check_status(status, "vaSetSubpictureGlobalAlpha()"))
return FALSE;
priv->global_alpha = global_alpha;
subpicture->global_alpha = global_alpha;
return TRUE;
}

View file

@ -30,33 +30,13 @@
G_BEGIN_DECLS
#define GST_VAAPI_TYPE_SUBPICTURE \
(gst_vaapi_subpicture_get_type())
#define GST_VAAPI_SUBPICTURE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
GST_VAAPI_TYPE_SUBPICTURE, \
GstVaapiSubpicture))
#define GST_VAAPI_SUBPICTURE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_SUBPICTURE, \
GstVaapiSubpictureClass))
((GstVaapiSubpicture *)(obj))
#define GST_VAAPI_IS_SUBPICTURE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SUBPICTURE))
#define GST_VAAPI_IS_SUBPICTURE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SUBPICTURE))
#define GST_VAAPI_SUBPICTURE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), \
GST_VAAPI_TYPE_SUBPICTURE, \
GstVaapiSubpictureClass))
((obj) != NULL)
typedef struct _GstVaapiSubpicture GstVaapiSubpicture;
typedef struct _GstVaapiSubpicturePrivate GstVaapiSubpicturePrivate;
typedef struct _GstVaapiSubpictureClass GstVaapiSubpictureClass;
/**
* GstVaapiSubpictureFlags:
@ -73,31 +53,6 @@ typedef enum {
GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA = (1 << 1),
} GstVaapiSubpictureFlags;
/**
* GstVaapiSubpicture:
*
* A VA subpicture wrapper
*/
struct _GstVaapiSubpicture {
/*< private >*/
GstVaapiObject parent_instance;
GstVaapiSubpicturePrivate *priv;
};
/**
* GstVaapiSubpictureClass:
*
* A VA subpicture wrapper class
*/
struct _GstVaapiSubpictureClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
GType
gst_vaapi_subpicture_get_type(void) G_GNUC_CONST;
GstVaapiSubpicture *
gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags);
@ -116,11 +71,9 @@ gst_vaapi_subpicture_get_flags(GstVaapiSubpicture *subpicture);
GstVaapiImage *
gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture);
void
gst_vaapi_subpicture_set_image(
GstVaapiSubpicture *subpicture,
GstVaapiImage *image
);
gboolean
gst_vaapi_subpicture_set_image(GstVaapiSubpicture *subpicture,
GstVaapiImage *image);
gfloat
gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture);

View file

@ -30,21 +30,24 @@
#include "gstvaapiutils.h"
#include "gstvaapisurface.h"
#include "gstvaapisurface_priv.h"
#include "gstvaapiobject_priv.h"
#include "gstvaapicontext.h"
#include "gstvaapiimage.h"
#include "gstvaapi_priv.h"
#define DEBUG 1
#include "gstvaapidebug.h"
G_DEFINE_TYPE(GstVaapiSurface, gst_vaapi_surface, GST_VAAPI_TYPE_OBJECT)
typedef struct _GstVaapiSurfaceClass GstVaapiSurfaceClass;
#define GST_VAAPI_SURFACE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_SURFACE, \
GstVaapiSurfacePrivate))
/**
* GstVaapiSurface:
*
* A VA surface wrapper.
*/
struct _GstVaapiSurface {
/*< private >*/
GstVaapiObject parent_instance;
struct _GstVaapiSurfacePrivate {
guint width;
guint height;
GstVaapiChromaType chroma_type;
@ -52,13 +55,14 @@ struct _GstVaapiSurfacePrivate {
GstVaapiContext *parent_context;
};
enum {
PROP_0,
PROP_WIDTH,
PROP_HEIGHT,
PROP_CHROMA_TYPE,
PROP_PARENT_CONTEXT
/**
* GstVaapiSurfaceClass:
*
* A VA surface wrapper class.
*/
struct _GstVaapiSurfaceClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
static gboolean
@ -79,18 +83,17 @@ static void
destroy_subpicture_cb(gpointer subpicture, gpointer surface)
{
_gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
g_object_unref(subpicture);
gst_vaapi_object_unref(subpicture);
}
static void
gst_vaapi_surface_destroy_subpictures(GstVaapiSurface *surface)
{
GstVaapiSurfacePrivate * const priv = surface->priv;
if (priv->subpictures) {
g_ptr_array_foreach(priv->subpictures, destroy_subpicture_cb, surface);
g_ptr_array_free(priv->subpictures, TRUE);
priv->subpictures = NULL;
if (surface->subpictures) {
g_ptr_array_foreach(surface->subpictures, destroy_subpicture_cb,
surface);
g_ptr_array_free(surface->subpictures, TRUE);
surface->subpictures = NULL;
}
}
@ -122,15 +125,15 @@ gst_vaapi_surface_destroy(GstVaapiSurface *surface)
}
static gboolean
gst_vaapi_surface_create(GstVaapiSurface *surface)
gst_vaapi_surface_create(GstVaapiSurface *surface,
GstVaapiChromaType chroma_type, guint width, guint height)
{
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
GstVaapiSurfacePrivate * const priv = surface->priv;
VASurfaceID surface_id;
VAStatus status;
guint format;
switch (priv->chroma_type) {
switch (chroma_type) {
case GST_VAAPI_CHROMA_TYPE_YUV420:
format = VA_RT_FORMAT_YUV420;
break;
@ -141,168 +144,31 @@ gst_vaapi_surface_create(GstVaapiSurface *surface)
format = VA_RT_FORMAT_YUV444;
break;
default:
GST_DEBUG("unsupported chroma-type %u\n", priv->chroma_type);
GST_DEBUG("unsupported chroma-type %u\n", chroma_type);
return FALSE;
}
GST_VAAPI_DISPLAY_LOCK(display);
status = vaCreateSurfaces(
GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->width,
priv->height,
format,
width, height, format,
1, &surface_id
);
GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaCreateSurfaces()"))
return FALSE;
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;
}
static void
gst_vaapi_surface_finalize(GObject *object)
{
gst_vaapi_surface_destroy(GST_VAAPI_SURFACE(object));
G_OBJECT_CLASS(gst_vaapi_surface_parent_class)->finalize(object);
}
static void
gst_vaapi_surface_set_property(
GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec
)
{
GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
GstVaapiSurfacePrivate * const priv = surface->priv;
switch (prop_id) {
case PROP_WIDTH:
priv->width = g_value_get_uint(value);
break;
case PROP_HEIGHT:
priv->height = g_value_get_uint(value);
break;
case PROP_CHROMA_TYPE:
priv->chroma_type = g_value_get_uint(value);
break;
case PROP_PARENT_CONTEXT:
gst_vaapi_surface_set_parent_context(surface, g_value_get_object(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_surface_get_property(
GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec
)
{
GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
switch (prop_id) {
case PROP_WIDTH:
g_value_set_uint(value, gst_vaapi_surface_get_width(surface));
break;
case PROP_HEIGHT:
g_value_set_uint(value, gst_vaapi_surface_get_height(surface));
break;
case PROP_CHROMA_TYPE:
g_value_set_uint(value, gst_vaapi_surface_get_chroma_type(surface));
break;
case PROP_PARENT_CONTEXT:
g_value_set_object(value, gst_vaapi_surface_get_parent_context(surface));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_surface_constructed(GObject *object)
{
GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
GObjectClass *parent_class;
gst_vaapi_surface_create(surface);
parent_class = G_OBJECT_CLASS(gst_vaapi_surface_parent_class);
if (parent_class->constructed)
parent_class->constructed(object);
}
static void
gst_vaapi_surface_class_init(GstVaapiSurfaceClass *klass)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(GstVaapiSurfacePrivate));
object_class->finalize = gst_vaapi_surface_finalize;
object_class->set_property = gst_vaapi_surface_set_property;
object_class->get_property = gst_vaapi_surface_get_property;
object_class->constructed = gst_vaapi_surface_constructed;
g_object_class_install_property
(object_class,
PROP_WIDTH,
g_param_spec_uint("width",
"Width",
"The width of the surface",
0, G_MAXINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_HEIGHT,
g_param_spec_uint("height",
"Height",
"The height of the surface",
0, G_MAXINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_CHROMA_TYPE,
g_param_spec_uint("chroma-type",
"Chroma type",
"The chroma type of the surface",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class,
PROP_PARENT_CONTEXT,
g_param_spec_object("parent-context",
"Parent Context",
"The parent context, if any",
GST_VAAPI_TYPE_CONTEXT,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
}
static void
gst_vaapi_surface_init(GstVaapiSurface *surface)
{
GstVaapiSurfacePrivate *priv = GST_VAAPI_SURFACE_GET_PRIVATE(surface);
surface->priv = priv;
priv->width = 0;
priv->height = 0;
priv->chroma_type = 0;
priv->subpictures = NULL;
priv->parent_context = NULL;
}
#define gst_vaapi_surface_finalize gst_vaapi_surface_destroy
GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiSurface, gst_vaapi_surface)
/**
* gst_vaapi_surface_new:
@ -324,15 +190,21 @@ gst_vaapi_surface_new(
guint height
)
{
GstVaapiSurface *surface;
GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type);
return g_object_new(GST_VAAPI_TYPE_SURFACE,
"display", display,
"id", GST_VAAPI_ID(VA_INVALID_ID),
"width", width,
"height", height,
"chroma-type", chroma_type,
NULL);
surface = gst_vaapi_object_new(gst_vaapi_surface_class(), display);
if (!surface)
return NULL;
if (!gst_vaapi_surface_create(surface, chroma_type, width, height))
goto error;
return surface;
error:
gst_vaapi_object_unref(surface);
return NULL;
}
/**
@ -364,7 +236,7 @@ gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface)
{
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
return surface->priv->chroma_type;
return surface->chroma_type;
}
/**
@ -380,7 +252,7 @@ gst_vaapi_surface_get_width(GstVaapiSurface *surface)
{
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
return surface->priv->width;
return surface->width;
}
/**
@ -396,7 +268,7 @@ gst_vaapi_surface_get_height(GstVaapiSurface *surface)
{
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
return surface->priv->height;
return surface->height;
}
/**
@ -438,16 +310,9 @@ gst_vaapi_surface_set_parent_context(
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_object_replace(&surface->parent_context, context);
}
/**
@ -465,7 +330,7 @@ gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface)
{
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
return surface->priv->parent_context;
return surface->parent_context;
}
/**
@ -487,7 +352,7 @@ gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface)
* 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().
* gst_vaapi_object_unref().
*
* Return value: the newly allocated #GstVaapiImage object, or %NULL
* on failure
@ -546,7 +411,7 @@ gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
return FALSE;
gst_vaapi_image_get_size(image, &width, &height);
if (width != surface->priv->width || height != surface->priv->height)
if (width != surface->width || height != surface->height)
return FALSE;
image_id = GST_VAAPI_OBJECT_ID(image);
@ -593,7 +458,7 @@ gst_vaapi_surface_put_image(GstVaapiSurface *surface, GstVaapiImage *image)
return FALSE;
gst_vaapi_image_get_size(image, &width, &height);
if (width != surface->priv->width || height != surface->priv->height)
if (width != surface->width || height != surface->height)
return FALSE;
image_id = GST_VAAPI_OBJECT_ID(image);
@ -646,15 +511,16 @@ gst_vaapi_surface_associate_subpicture(
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)
if (!surface->subpictures) {
surface->subpictures = g_ptr_array_new();
if (!surface->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 (g_ptr_array_remove_fast(surface->subpictures, subpicture)) {
success = _gst_vaapi_surface_deassociate_subpicture(surface,
subpicture);
gst_vaapi_object_unref(subpicture);
if (!success)
return FALSE;
}
@ -668,7 +534,7 @@ gst_vaapi_surface_associate_subpicture(
if (!success)
return FALSE;
g_ptr_array_add(surface->priv->subpictures, g_object_ref(subpicture));
g_ptr_array_add(surface->subpictures, gst_vaapi_object_ref(subpicture));
return TRUE;
}
@ -712,8 +578,8 @@ _gst_vaapi_surface_associate_subpicture(
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;
dst_rect_default.width = surface->width;
dst_rect_default.height = surface->height;
}
GST_VAAPI_DISPLAY_LOCK(display);
@ -752,11 +618,11 @@ gst_vaapi_surface_deassociate_subpicture(
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)
if (!surface->subpictures)
return TRUE;
/* First, check subpicture was really associated with this surface */
if (!g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
if (!g_ptr_array_remove_fast(surface->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)),
@ -765,7 +631,7 @@ gst_vaapi_surface_deassociate_subpicture(
}
success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
g_object_unref(subpicture);
gst_vaapi_object_unref(subpicture);
return success;
}
@ -894,11 +760,9 @@ gst_vaapi_surface_set_subpictures_from_composition(
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);
}
if (propagate_context && surface->parent_context)
return gst_vaapi_context_apply_composition(surface->parent_context,
composition);
display = GST_VAAPI_OBJECT_DISPLAY(surface);
if (!display)
@ -929,10 +793,10 @@ gst_vaapi_surface_set_subpictures_from_composition(
if (!gst_vaapi_surface_associate_subpicture (surface, subpicture,
NULL, &sub_rect)) {
GST_WARNING ("could not render overlay rectangle %p", rect);
g_object_unref (subpicture);
gst_vaapi_object_unref (subpicture);
return FALSE;
}
g_object_unref (subpicture);
gst_vaapi_object_unref (subpicture);
}
return TRUE;
}

View file

@ -112,60 +112,15 @@ typedef enum {
GST_VAAPI_COLOR_STANDARD_ITUR_BT_709 = 1 << 3,
} GstVaapiSurfaceRenderFlags;
#define GST_VAAPI_TYPE_SURFACE \
(gst_vaapi_surface_get_type())
#define GST_VAAPI_SURFACE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
GST_VAAPI_TYPE_SURFACE, \
GstVaapiSurface))
#define GST_VAAPI_SURFACE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_SURFACE, \
GstVaapiSurfaceClass))
((GstVaapiSurface *)(obj))
#define GST_VAAPI_IS_SURFACE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE))
#define GST_VAAPI_IS_SURFACE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SURFACE))
#define GST_VAAPI_SURFACE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), \
GST_VAAPI_TYPE_SURFACE, \
GstVaapiSurfaceClass))
((obj) != NULL)
typedef struct _GstVaapiSurface GstVaapiSurface;
typedef struct _GstVaapiSurfacePrivate GstVaapiSurfacePrivate;
typedef struct _GstVaapiSurfaceClass GstVaapiSurfaceClass;
typedef struct _GstVaapiSurfaceProxy GstVaapiSurfaceProxy;
/**
* GstVaapiSurface:
*
* A VA surface wrapper.
*/
struct _GstVaapiSurface {
/*< private >*/
GstVaapiObject parent_instance;
GstVaapiSurfacePrivate *priv;
};
/**
* GstVaapiSurfaceClass:
*
* A VA surface wrapper class.
*/
struct _GstVaapiSurfaceClass {
/*< private >*/
GstVaapiObjectClass parent_class;
};
GType
gst_vaapi_surface_get_type(void) G_GNUC_CONST;
GstVaapiSurface *
gst_vaapi_surface_new(
GstVaapiDisplay *display,

View file

@ -41,7 +41,7 @@ gst_vaapi_surface_proxy_finalize(GstVaapiSurfaceProxy *proxy)
if (proxy->surface) {
if (proxy->pool)
gst_vaapi_video_pool_put_object(proxy->pool, proxy->surface);
g_object_unref(proxy->surface);
gst_vaapi_object_unref(proxy->surface);
proxy->surface = NULL;
}
g_clear_object(&proxy->pool);
@ -76,7 +76,7 @@ gst_vaapi_surface_proxy_new_from_pool(GstVaapiSurfacePool *pool)
proxy->timestamp = GST_CLOCK_TIME_NONE;
proxy->duration = GST_CLOCK_TIME_NONE;
proxy->destroy_func = NULL;
g_object_ref(proxy->surface);
gst_vaapi_object_ref(proxy->surface);
return proxy;
error:

View file

@ -27,6 +27,7 @@
#include "sysdeps.h"
#include "gstvaapivideopool.h"
#include "gstvaapiobject.h"
#define DEBUG 1
#include "gstvaapidebug.h"
@ -75,13 +76,13 @@ gst_vaapi_video_pool_clear(GstVaapiVideoPool *pool)
for (list = priv->used_objects; list; list = next) {
next = list->next;
g_object_unref(list->data);
gst_vaapi_object_unref(list->data);
g_list_free_1(list);
}
priv->used_objects = NULL;
while ((object = g_queue_pop_head(&priv->free_objects)))
g_object_unref(object);
gst_vaapi_object_unref(object);
}
static void
@ -313,7 +314,7 @@ gst_vaapi_video_pool_get_object(GstVaapiVideoPool *pool)
++priv->used_count;
priv->used_objects = g_list_prepend(priv->used_objects, object);
return g_object_ref(object);
return gst_vaapi_object_ref(object);
}
/**
@ -333,14 +334,14 @@ gst_vaapi_video_pool_put_object(GstVaapiVideoPool *pool, gpointer object)
GList *elem;
g_return_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool));
g_return_if_fail(G_IS_OBJECT(object));
g_return_if_fail(GST_VAAPI_IS_OBJECT(object));
priv = pool->priv;
elem = g_list_find(priv->used_objects, object);
if (!elem)
return;
g_object_unref(object);
gst_vaapi_object_unref(object);
--priv->used_count;
priv->used_objects = g_list_delete_link(priv->used_objects, elem);
g_queue_push_tail(&priv->free_objects, object);
@ -361,9 +362,9 @@ gboolean
gst_vaapi_video_pool_add_object(GstVaapiVideoPool *pool, gpointer object)
{
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), FALSE);
g_return_val_if_fail(G_IS_OBJECT(object), FALSE);
g_return_val_if_fail(GST_VAAPI_IS_OBJECT(object), FALSE);
g_queue_push_tail(&pool->priv->free_objects, g_object_ref(object));
g_queue_push_tail(&pool->priv->free_objects, gst_vaapi_object_ref(object));
return TRUE;
}