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 <assert.h>
#include "gstvaapicompat.h" #include "gstvaapicompat.h"
#include "gstvaapicontext.h" #include "gstvaapicontext.h"
#include "gstvaapiobject_priv.h"
#include "gstvaapisurface.h" #include "gstvaapisurface.h"
#include "gstvaapisurface_priv.h" #include "gstvaapisurface_priv.h"
#include "gstvaapisurfacepool.h" #include "gstvaapisurfacepool.h"
#include "gstvaapisurfaceproxy.h" #include "gstvaapisurfaceproxy.h"
#include "gstvaapiimage.h" #include "gstvaapiimage.h"
#include "gstvaapisubpicture.h" #include "gstvaapisubpicture.h"
#include "gstvaapiminiobject.h"
#include "gstvaapiutils.h" #include "gstvaapiutils.h"
#include "gstvaapi_priv.h"
#define DEBUG 1 #define DEBUG 1
#include "gstvaapidebug.h" #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), \ * GstVaapiContext:
GST_VAAPI_TYPE_CONTEXT, \ *
GstVaapiContextPrivate)) * 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; typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
struct _GstVaapiOverlayRectangle { struct _GstVaapiOverlayRectangle {
@ -61,31 +82,6 @@ struct _GstVaapiOverlayRectangle {
guint is_associated : 1; 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 static guint
get_max_ref_frames(GstVaapiProfile profile) get_max_ref_frames(GstVaapiProfile profile)
{ {
@ -188,7 +184,7 @@ overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay)
if (overlay->subpicture) { if (overlay->subpicture) {
overlay_rectangle_deassociate(overlay); overlay_rectangle_deassociate(overlay);
g_object_unref(overlay->subpicture); gst_vaapi_object_unref(overlay->subpicture);
overlay->subpicture = NULL; overlay->subpicture = NULL;
} }
} }
@ -197,7 +193,7 @@ static gboolean
overlay_rectangle_associate(GstVaapiOverlayRectangle *overlay) overlay_rectangle_associate(GstVaapiOverlayRectangle *overlay)
{ {
GstVaapiSubpicture * const subpicture = overlay->subpicture; GstVaapiSubpicture * const subpicture = overlay->subpicture;
GPtrArray * const surfaces = overlay->context->priv->surfaces; GPtrArray * const surfaces = overlay->context->surfaces;
guint i, n_associated; guint i, n_associated;
if (overlay->is_associated) if (overlay->is_associated)
@ -219,7 +215,7 @@ static gboolean
overlay_rectangle_deassociate(GstVaapiOverlayRectangle *overlay) overlay_rectangle_deassociate(GstVaapiOverlayRectangle *overlay)
{ {
GstVaapiSubpicture * const subpicture = overlay->subpicture; GstVaapiSubpicture * const subpicture = overlay->subpicture;
GPtrArray * const surfaces = overlay->context->priv->surfaces; GPtrArray * const surfaces = overlay->context->surfaces;
guint i, n_associated; guint i, n_associated;
if (!overlay->is_associated) if (!overlay->is_associated)
@ -388,11 +384,9 @@ overlay_reassociate(GPtrArray *overlays)
static void static void
gst_vaapi_context_clear_overlay(GstVaapiContext *context) gst_vaapi_context_clear_overlay(GstVaapiContext *context)
{ {
GstVaapiContextPrivate * const priv = context->priv; overlay_clear(context->overlays[0]);
overlay_clear(context->overlays[1]);
overlay_clear(priv->overlays[0]); context->overlay_id = 0;
overlay_clear(priv->overlays[1]);
priv->overlay_id = 0;
} }
static inline void static inline void
@ -407,30 +401,26 @@ unref_surface_cb(gpointer data, gpointer user_data)
GstVaapiSurface * const surface = GST_VAAPI_SURFACE(data); GstVaapiSurface * const surface = GST_VAAPI_SURFACE(data);
gst_vaapi_surface_set_parent_context(surface, NULL); gst_vaapi_surface_set_parent_context(surface, NULL);
g_object_unref(surface); gst_vaapi_object_unref(surface);
} }
static void static void
gst_vaapi_context_destroy_surfaces(GstVaapiContext *context) gst_vaapi_context_destroy_surfaces(GstVaapiContext *context)
{ {
GstVaapiContextPrivate * const priv = context->priv;
gst_vaapi_context_destroy_overlay(context); gst_vaapi_context_destroy_overlay(context);
if (priv->surfaces) { if (context->surfaces) {
g_ptr_array_foreach(priv->surfaces, unref_surface_cb, NULL); g_ptr_array_foreach(context->surfaces, unref_surface_cb, NULL);
g_ptr_array_free(priv->surfaces, TRUE); g_ptr_array_free(context->surfaces, TRUE);
priv->surfaces = NULL; context->surfaces = NULL;
} }
g_clear_object(&context->surfaces_pool);
g_clear_object(&priv->surfaces_pool);
} }
static void static void
gst_vaapi_context_destroy(GstVaapiContext *context) gst_vaapi_context_destroy(GstVaapiContext *context)
{ {
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
GstVaapiContextPrivate * const priv = context->priv;
VAContextID context_id; VAContextID context_id;
VAStatus status; VAStatus status;
@ -450,26 +440,24 @@ gst_vaapi_context_destroy(GstVaapiContext *context)
GST_VAAPI_OBJECT_ID(context) = VA_INVALID_ID; 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); GST_VAAPI_DISPLAY_LOCK(display);
status = vaDestroyConfig( status = vaDestroyConfig(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->config_id context->config_id
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaDestroyConfig()")) if (!vaapi_check_status(status, "vaDestroyConfig()"))
g_warning("failed to destroy config %" GST_VAAPI_ID_FORMAT, g_warning("failed to destroy config %" GST_VAAPI_ID_FORMAT,
GST_VAAPI_ID_ARGS(priv->config_id)); GST_VAAPI_ID_ARGS(context->config_id));
priv->config_id = VA_INVALID_ID; context->config_id = VA_INVALID_ID;
} }
} }
static gboolean static gboolean
gst_vaapi_context_create_overlay(GstVaapiContext *context) gst_vaapi_context_create_overlay(GstVaapiContext *context)
{ {
GstVaapiContextPrivate * const priv = context->priv; if (!context->overlays[0] || !context->overlays[1])
if (!priv->overlays[0] || !priv->overlays[1])
return FALSE; return FALSE;
gst_vaapi_context_clear_overlay(context); gst_vaapi_context_clear_overlay(context);
@ -479,7 +467,7 @@ gst_vaapi_context_create_overlay(GstVaapiContext *context)
static gboolean static gboolean
gst_vaapi_context_create_surfaces(GstVaapiContext *context) gst_vaapi_context_create_surfaces(GstVaapiContext *context)
{ {
GstVaapiContextPrivate * const priv = context->priv; const GstVaapiContextInfo * const cip = &context->info;
GstCaps *caps; GstCaps *caps;
GstVaapiSurface *surface; GstVaapiSurface *surface;
guint i, num_surfaces; guint i, num_surfaces;
@ -490,45 +478,45 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
if (!gst_vaapi_context_create_overlay(context)) if (!gst_vaapi_context_create_overlay(context))
return FALSE; return FALSE;
if (!priv->surfaces) { if (!context->surfaces) {
priv->surfaces = g_ptr_array_new(); context->surfaces = g_ptr_array_new();
if (!priv->surfaces) if (!context->surfaces)
return FALSE; return FALSE;
} }
if (!priv->surfaces_pool) { if (!context->surfaces_pool) {
caps = gst_caps_new_simple( caps = gst_caps_new_simple(
GST_VAAPI_SURFACE_CAPS_NAME, GST_VAAPI_SURFACE_CAPS_NAME,
"type", G_TYPE_STRING, "vaapi", "type", G_TYPE_STRING, "vaapi",
"width", G_TYPE_INT, priv->width, "width", G_TYPE_INT, cip->width,
"height", G_TYPE_INT, priv->height, "height", G_TYPE_INT, cip->height,
NULL NULL
); );
if (!caps) if (!caps)
return FALSE; return FALSE;
priv->surfaces_pool = gst_vaapi_surface_pool_new( context->surfaces_pool = gst_vaapi_surface_pool_new(
GST_VAAPI_OBJECT_DISPLAY(context), GST_VAAPI_OBJECT_DISPLAY(context),
caps caps
); );
gst_caps_unref(caps); gst_caps_unref(caps);
if (!priv->surfaces_pool) if (!context->surfaces_pool)
return FALSE; return FALSE;
} }
num_surfaces = priv->ref_frames + SCRATCH_SURFACES_COUNT; num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, num_surfaces); 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( surface = gst_vaapi_surface_new(
GST_VAAPI_OBJECT_DISPLAY(context), GST_VAAPI_OBJECT_DISPLAY(context),
GST_VAAPI_CHROMA_TYPE_YUV420, GST_VAAPI_CHROMA_TYPE_YUV420,
priv->width, priv->height cip->width, cip->height
); );
if (!surface) if (!surface)
return FALSE; return FALSE;
gst_vaapi_surface_set_parent_context(surface, context); gst_vaapi_surface_set_parent_context(surface, context);
g_ptr_array_add(priv->surfaces, surface); g_ptr_array_add(context->surfaces, surface);
if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface)) if (!gst_vaapi_video_pool_add_object(context->surfaces_pool, surface))
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
@ -537,8 +525,8 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
static gboolean static gboolean
gst_vaapi_context_create(GstVaapiContext *context) gst_vaapi_context_create(GstVaapiContext *context)
{ {
const GstVaapiContextInfo * const cip = &context->info;
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
GstVaapiContextPrivate * const priv = context->priv;
VAProfile va_profile; VAProfile va_profile;
VAEntrypoint va_entrypoint; VAEntrypoint va_entrypoint;
VAConfigAttrib attrib; VAConfigAttrib attrib;
@ -549,31 +537,32 @@ gst_vaapi_context_create(GstVaapiContext *context)
gboolean success = FALSE; gboolean success = FALSE;
guint i; guint i;
if (!priv->surfaces && !gst_vaapi_context_create_surfaces(context)) if (!context->surfaces && !gst_vaapi_context_create_surfaces(context))
goto end; goto end;
surfaces = g_array_sized_new( surfaces = g_array_sized_new(
FALSE, FALSE,
FALSE, FALSE,
sizeof(VASurfaceID), sizeof(VASurfaceID),
priv->surfaces->len context->surfaces->len
); );
if (!surfaces) if (!surfaces)
goto end; goto end;
for (i = 0; i < priv->surfaces->len; i++) { for (i = 0; i < context->surfaces->len; i++) {
GstVaapiSurface * const surface = g_ptr_array_index(priv->surfaces, i); GstVaapiSurface * const surface =
g_ptr_array_index(context->surfaces, i);
if (!surface) if (!surface)
goto end; goto end;
surface_id = GST_VAAPI_OBJECT_ID(surface); surface_id = GST_VAAPI_OBJECT_ID(surface);
g_array_append_val(surfaces, surface_id); 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; goto end;
va_profile = gst_vaapi_profile_get_va_profile(priv->profile); va_profile = gst_vaapi_profile_get_va_profile(cip->profile);
va_entrypoint = gst_vaapi_entrypoint_get_va_entrypoint(priv->entrypoint); va_entrypoint = gst_vaapi_entrypoint_get_va_entrypoint(cip->entrypoint);
GST_VAAPI_DISPLAY_LOCK(display); GST_VAAPI_DISPLAY_LOCK(display);
attrib.type = VAConfigAttribRTFormat; attrib.type = VAConfigAttribRTFormat;
@ -595,7 +584,7 @@ gst_vaapi_context_create(GstVaapiContext *context)
va_profile, va_profile,
va_entrypoint, va_entrypoint,
&attrib, 1, &attrib, 1,
&priv->config_id &context->config_id
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaCreateConfig()")) if (!vaapi_check_status(status, "vaCreateConfig()"))
@ -604,8 +593,8 @@ gst_vaapi_context_create(GstVaapiContext *context)
GST_VAAPI_DISPLAY_LOCK(display); GST_VAAPI_DISPLAY_LOCK(display);
status = vaCreateContext( status = vaCreateContext(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->config_id, context->config_id,
priv->width, priv->height, cip->width, cip->height,
VA_PROGRESSIVE, VA_PROGRESSIVE,
(VASurfaceID *)surfaces->data, surfaces->len, (VASurfaceID *)surfaces->data, surfaces->len,
&context_id &context_id
@ -623,160 +612,25 @@ end:
return success; return success;
} }
static void static inline void
gst_vaapi_context_finalize(GObject *object) gst_vaapi_context_init(GstVaapiContext *context, const GstVaapiContextInfo *cip)
{ {
GstVaapiContext * const context = GST_VAAPI_CONTEXT(object); context->info = *cip;
GstVaapiContextPrivate * const priv = context->priv; context->config_id = VA_INVALID_ID;
context->overlays[0] = overlay_new();
context->overlays[1] = overlay_new();
}
overlay_destroy(&priv->overlays[0]); static void
overlay_destroy(&priv->overlays[1]); 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(context);
gst_vaapi_context_destroy_surfaces(context); gst_vaapi_context_destroy_surfaces(context);
G_OBJECT_CLASS(gst_vaapi_context_parent_class)->finalize(object);
} }
static void GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiContext, gst_vaapi_context)
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_context_new: * gst_vaapi_context_new:
@ -822,32 +676,28 @@ gst_vaapi_context_new(
* Return value: the newly allocated #GstVaapiContext object * Return value: the newly allocated #GstVaapiContext object
*/ */
GstVaapiContext * GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip) gst_vaapi_context_new_full(GstVaapiDisplay *display,
const GstVaapiContextInfo *cip)
{ {
GstVaapiContext *context; 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->profile, NULL);
g_return_val_if_fail(cip->entrypoint, NULL); g_return_val_if_fail(cip->entrypoint, NULL);
g_return_val_if_fail(cip->width > 0, NULL); g_return_val_if_fail(cip->width > 0, NULL);
g_return_val_if_fail(cip->height > 0, NULL); g_return_val_if_fail(cip->height > 0, NULL);
context = g_object_new( context = gst_vaapi_object_new(gst_vaapi_context_class(), display);
GST_VAAPI_TYPE_CONTEXT, if (!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);
return NULL; return NULL;
}
gst_vaapi_context_init(context, cip);
if (!gst_vaapi_context_create(context))
goto error;
return context; return context;
error:
gst_vaapi_object_unref(context);
return NULL;
} }
/** /**
@ -872,14 +722,13 @@ gst_vaapi_context_reset(
unsigned int height unsigned int height
) )
{ {
GstVaapiContextPrivate * const priv = context->priv;
GstVaapiContextInfo info; GstVaapiContextInfo info;
info.profile = profile; info.profile = profile;
info.entrypoint = entrypoint; info.entrypoint = entrypoint;
info.width = width; info.width = width;
info.height = height; info.height = height;
info.ref_frames = priv->ref_frames; info.ref_frames = context->info.ref_frames;
return gst_vaapi_context_reset_full(context, &info); return gst_vaapi_context_reset_full(context, &info);
} }
@ -887,32 +736,35 @@ gst_vaapi_context_reset(
/** /**
* gst_vaapi_context_reset_full: * gst_vaapi_context_reset_full:
* @context: a #GstVaapiContext * @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 * including profile, entry-point, encoded size and maximum number of
* reference frames reported by the bitstream. * reference frames reported by the bitstream.
* *
* Return value: %TRUE on success * Return value: %TRUE on success
*/ */
gboolean 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; 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) { if (size_changed) {
gst_vaapi_context_destroy_surfaces(context); gst_vaapi_context_destroy_surfaces(context);
priv->width = cip->width; cip->width = new_cip->width;
priv->height = cip->height; 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) { if (codec_changed) {
gst_vaapi_context_destroy(context); gst_vaapi_context_destroy(context);
priv->profile = cip->profile; cip->profile = new_cip->profile;
priv->entrypoint = cip->entrypoint; cip->entrypoint = new_cip->entrypoint;
} }
if (size_changed && !gst_vaapi_context_create_surfaces(context)) 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)) if (codec_changed && !gst_vaapi_context_create(context))
return FALSE; return FALSE;
priv->is_constructed = TRUE;
return 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); 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, return gst_vaapi_context_reset(context,
profile, profile,
context->priv->entrypoint, context->info.entrypoint,
context->priv->width, context->info.width,
context->priv->height); 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); 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)); g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
if (pwidth) if (pwidth)
*pwidth = context->priv->width; *pwidth = context->info.width;
if (pheight) 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); g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
return gst_vaapi_surface_proxy_new_from_pool( 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); 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 GstVideoOverlayComposition *composition
) )
{ {
GstVaapiContextPrivate *priv;
GPtrArray *curr_overlay, *next_overlay; GPtrArray *curr_overlay, *next_overlay;
guint i, n_rectangles; guint i, n_rectangles;
gboolean reassociate = FALSE; gboolean reassociate = FALSE;
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE); g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
priv = context->priv; if (!context->surfaces)
if (!priv->surfaces)
return FALSE; return FALSE;
if (!composition) { if (!composition) {
@ -1098,8 +946,8 @@ gst_vaapi_context_apply_composition(
return TRUE; return TRUE;
} }
curr_overlay = priv->overlays[priv->overlay_id]; curr_overlay = context->overlays[context->overlay_id];
next_overlay = priv->overlays[priv->overlay_id ^ 1]; next_overlay = context->overlays[context->overlay_id ^ 1];
overlay_clear(next_overlay); overlay_clear(next_overlay);
n_rectangles = gst_video_overlay_composition_n_rectangles(composition); n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
@ -1126,7 +974,7 @@ gst_vaapi_context_apply_composition(
} }
overlay_clear(curr_overlay); overlay_clear(curr_overlay);
priv->overlay_id ^= 1; context->overlay_id ^= 1;
if (reassociate && !overlay_reassociate(next_overlay)) if (reassociate && !overlay_reassociate(next_overlay))
return FALSE; return FALSE;

View file

@ -31,34 +31,14 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_VAAPI_TYPE_CONTEXT \
(gst_vaapi_context_get_type())
#define GST_VAAPI_CONTEXT(obj) \ #define GST_VAAPI_CONTEXT(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \ ((GstVaapiContext *)(obj))
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContext))
#define GST_VAAPI_CONTEXT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContextClass))
#define GST_VAAPI_IS_CONTEXT(obj) \ #define GST_VAAPI_IS_CONTEXT(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_CONTEXT)) ((obj) != NULL)
#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))
typedef struct _GstVaapiContext GstVaapiContext; typedef struct _GstVaapiContext GstVaapiContext;
typedef struct _GstVaapiContextInfo GstVaapiContextInfo; typedef struct _GstVaapiContextInfo GstVaapiContextInfo;
typedef struct _GstVaapiContextPrivate GstVaapiContextPrivate;
typedef struct _GstVaapiContextClass GstVaapiContextClass;
/** /**
* GstVaapiContextInfo: * GstVaapiContextInfo:
@ -75,31 +55,6 @@ struct _GstVaapiContextInfo {
guint ref_frames; 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 * GstVaapiContext *
gst_vaapi_context_new( gst_vaapi_context_new(
GstVaapiDisplay *display, GstVaapiDisplay *display,
@ -110,7 +65,8 @@ gst_vaapi_context_new(
); );
GstVaapiContext * GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip); gst_vaapi_context_new_full(GstVaapiDisplay *display,
const GstVaapiContextInfo *cip);
gboolean gboolean
gst_vaapi_context_reset( gst_vaapi_context_reset(
@ -122,7 +78,8 @@ gst_vaapi_context_reset(
); );
gboolean gboolean
gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip); gst_vaapi_context_reset_full(GstVaapiContext *context,
const GstVaapiContextInfo *new_cip);
GstVaapiID GstVaapiID
gst_vaapi_context_get_id(GstVaapiContext *context); gst_vaapi_context_get_id(GstVaapiContext *context);

View file

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

View file

@ -30,19 +30,22 @@
#include "gstvaapicompat.h" #include "gstvaapicompat.h"
#include "gstvaapiutils.h" #include "gstvaapiutils.h"
#include "gstvaapiimage.h" #include "gstvaapiimage.h"
#include "gstvaapi_priv.h" #include "gstvaapiobject_priv.h"
#define DEBUG 1 #define DEBUG 1
#include "gstvaapidebug.h" #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), \ * GstVaapiImage:
GST_VAAPI_TYPE_IMAGE, \ *
GstVaapiImagePrivate)) * A VA image wrapper
*/
struct _GstVaapiImage {
/*< private >*/
GstVaapiObject parent_instance;
struct _GstVaapiImagePrivate {
VAImage internal_image; VAImage internal_image;
VAImage image; VAImage image;
guchar *image_data; guchar *image_data;
@ -50,18 +53,17 @@ struct _GstVaapiImagePrivate {
GstVaapiImageFormat format; GstVaapiImageFormat format;
guint width; guint width;
guint height; guint height;
guint create_image : 1;
guint is_constructed : 1;
guint is_linear : 1; guint is_linear : 1;
}; };
enum { /**
PROP_0, * GstVaapiImageClass:
*
PROP_IMAGE, * A VA image wrapper class
PROP_FORMAT, */
PROP_WIDTH, struct _GstVaapiImageClass {
PROP_HEIGHT /*< private >*/
GstVaapiObjectClass parent_class;
}; };
#define SWAP_UINT(a, b) do { \ #define SWAP_UINT(a, b) do { \
@ -83,35 +85,6 @@ _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image);
* VAImage wrapper * 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 static gboolean
vaapi_image_is_linear(const VAImage *va_image) vaapi_image_is_linear(const VAImage *va_image)
{ {
@ -173,7 +146,6 @@ static gboolean
_gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format) _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
{ {
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
GstVaapiImagePrivate * const priv = image->priv;
const VAImageFormat *va_format; const VAImageFormat *va_format;
VAStatus status; VAStatus status;
@ -188,30 +160,29 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
status = vaCreateImage( status = vaCreateImage(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
(VAImageFormat *)va_format, (VAImageFormat *)va_format,
priv->width, image->width,
priv->height, image->height,
&priv->internal_image &image->internal_image
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
if (status != VA_STATUS_SUCCESS || if (status != VA_STATUS_SUCCESS ||
priv->internal_image.format.fourcc != va_format->fourcc) image->internal_image.format.fourcc != va_format->fourcc)
return FALSE; return FALSE;
priv->internal_format = format; image->internal_format = format;
return TRUE; return TRUE;
} }
static gboolean 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; const VAImageFormat *va_format;
VAImageID image_id; VAImageID image_id;
if (!priv->create_image) image->format = format;
return (priv->image.image_id != VA_INVALID_ID && image->width = width;
priv->image.buf != VA_INVALID_ID); image->height = height;
if (!_gst_vaapi_image_create(image, format)) { if (!_gst_vaapi_image_create(image, format)) {
switch (format) { switch (format) {
@ -228,25 +199,25 @@ gst_vaapi_image_create(GstVaapiImage *image)
if (!format || !_gst_vaapi_image_create(image, format)) if (!format || !_gst_vaapi_image_create(image, format))
return FALSE; return FALSE;
} }
priv->image = priv->internal_image; image->image = image->internal_image;
image_id = priv->image.image_id; image_id = image->image.image_id;
if (priv->format != priv->internal_format) { if (image->format != image->internal_format) {
switch (priv->format) { switch (image->format) {
case GST_VAAPI_IMAGE_YV12: case GST_VAAPI_IMAGE_YV12:
case GST_VAAPI_IMAGE_I420: 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) if (!va_format)
return FALSE; return FALSE;
priv->image.format = *va_format; image->image.format = *va_format;
SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]); SWAP_UINT(image->image.offsets[1], image->image.offsets[2]);
SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]); SWAP_UINT(image->image.pitches[1], image->image.pitches[2]);
break; break;
default: default:
break; 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_DEBUG("image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(image_id));
GST_VAAPI_OBJECT_ID(image) = image_id; GST_VAAPI_OBJECT_ID(image) = image_id;
@ -254,168 +225,28 @@ gst_vaapi_image_create(GstVaapiImage *image)
} }
static void static void
gst_vaapi_image_finalize(GObject *object) gst_vaapi_image_init(GstVaapiImage *image)
{ {
gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object)); image->internal_image.image_id = VA_INVALID_ID;
image->internal_image.buf = VA_INVALID_ID;
G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object); image->image.image_id = VA_INVALID_ID;
} image->image.buf = VA_INVALID_ID;
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);
} }
static void static void
gst_vaapi_image_class_init(GstVaapiImageClass *klass) 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->init = (GstVaapiObjectInitFunc)gst_vaapi_image_init;
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));
} }
static void #define gst_vaapi_image_finalize gst_vaapi_image_destroy
gst_vaapi_image_init(GstVaapiImage *image) GST_VAAPI_OBJECT_DEFINE_CLASS_WITH_CODE(
{ GstVaapiImage,
GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image); gst_vaapi_image,
gst_vaapi_image_class_init(&g_class))
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;
}
/** /**
* gst_vaapi_image_new: * gst_vaapi_image_new:
@ -439,30 +270,23 @@ gst_vaapi_image_new(
{ {
GstVaapiImage *image; 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(width > 0, NULL);
g_return_val_if_fail(height > 0, NULL); g_return_val_if_fail(height > 0, NULL);
GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u", GST_DEBUG("format %" GST_FOURCC_FORMAT ", size %ux%u",
GST_FOURCC_ARGS(format), width, height); GST_FOURCC_ARGS(format), width, height);
image = g_object_new( image = gst_vaapi_object_new(gst_vaapi_image_class(), display);
GST_VAAPI_TYPE_IMAGE,
"display", display,
"id", GST_VAAPI_ID(VA_INVALID_ID),
"format", format,
"width", width,
"height", height,
NULL
);
if (!image) if (!image)
return NULL; return NULL;
if (!image->priv->is_constructed) { if (!gst_vaapi_image_create(image, format, width, height))
g_object_unref(image); goto error;
return NULL;
}
return image; 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; 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, NULL);
g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, 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); 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), GST_FOURCC_ARGS(va_image->format.fourcc),
va_image->width, va_image->height); va_image->width, va_image->height);
image = g_object_new( image = gst_vaapi_object_new(gst_vaapi_image_class(), display);
GST_VAAPI_TYPE_IMAGE,
"display", display,
"id", GST_VAAPI_ID(va_image->image_id),
"image", va_image,
NULL
);
if (!image) if (!image)
return NULL; return NULL;
if (!image->priv->is_constructed) { if (!_gst_vaapi_image_set_image(image, va_image))
g_object_unref(image); goto error;
return NULL;
}
return image; return image;
error:
gst_vaapi_object_unref(image);
return NULL;
} }
/** /**
@ -521,7 +340,6 @@ GstVaapiID
gst_vaapi_image_get_id(GstVaapiImage *image) 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(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); return GST_VAAPI_OBJECT_ID(image);
} }
@ -539,10 +357,9 @@ gboolean
gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image) 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(GST_VAAPI_IS_IMAGE(image), FALSE);
g_return_val_if_fail(image->priv->is_constructed, FALSE);
if (va_image) if (va_image)
*va_image = image->priv->image; *va_image = image->image;
return TRUE; return TRUE;
} }
@ -564,29 +381,26 @@ gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
gboolean gboolean
_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image) _gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image)
{ {
GstVaapiImagePrivate * const priv = image->priv;
GstVaapiImageFormat format; GstVaapiImageFormat format;
VAImage alt_va_image; VAImage alt_va_image;
const VAImageFormat *alt_va_format; const VAImageFormat *alt_va_format;
if (!va_image)
return FALSE;
format = gst_vaapi_image_format(&va_image->format); format = gst_vaapi_image_format(&va_image->format);
if (!format) if (!format)
return FALSE; return FALSE;
priv->create_image = FALSE; image->internal_image = *va_image;
priv->internal_image = *va_image; image->internal_format = format;
priv->internal_format = format; image->is_linear = vaapi_image_is_linear(va_image);
priv->is_linear = vaapi_image_is_linear(va_image); image->image = *va_image;
priv->image = *va_image; image->format = format;
priv->format = format; image->width = va_image->width;
priv->width = va_image->width; image->height = va_image->height;
priv->height = va_image->height;
GST_VAAPI_OBJECT_ID(image) = va_image->image_id;
/* Try to linearize image */ /* Try to linearize image */
if (!priv->is_linear) { if (!image->is_linear) {
switch (format) { switch (format) {
case GST_VAAPI_IMAGE_I420: case GST_VAAPI_IMAGE_I420:
format = GST_VAAPI_IMAGE_YV12; 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.offsets[1], alt_va_image.offsets[2]);
SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]); SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]);
if (vaapi_image_is_linear(&alt_va_image)) { if (vaapi_image_is_linear(&alt_va_image)) {
priv->image = alt_va_image; image->image = alt_va_image;
priv->format = format; image->format = format;
priv->is_linear = TRUE; image->is_linear = TRUE;
GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format", GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format",
GST_FOURCC_ARGS(format)); GST_FOURCC_ARGS(format));
} }
@ -628,9 +442,8 @@ GstVaapiImageFormat
gst_vaapi_image_get_format(GstVaapiImage *image) gst_vaapi_image_get_format(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); 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) gst_vaapi_image_get_width(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); 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) gst_vaapi_image_get_height(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); 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) gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
{ {
g_return_if_fail(GST_VAAPI_IS_IMAGE(image)); g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
g_return_if_fail(image->priv->is_constructed);
if (pwidth) if (pwidth)
*pwidth = image->priv->width; *pwidth = image->width;
if (pheight) if (pheight)
*pheight = image->priv->height; *pheight = image->height;
} }
/** /**
@ -702,9 +512,8 @@ gboolean
gst_vaapi_image_is_linear(GstVaapiImage *image) gst_vaapi_image_is_linear(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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 static inline gboolean
_gst_vaapi_image_is_mapped(GstVaapiImage *image) _gst_vaapi_image_is_mapped(GstVaapiImage *image)
{ {
return image->priv->image_data != NULL; return image->image_data != NULL;
} }
gboolean gboolean
gst_vaapi_image_is_mapped(GstVaapiImage *image) gst_vaapi_image_is_mapped(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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); return _gst_vaapi_image_is_mapped(image);
} }
@ -743,7 +551,6 @@ gboolean
gst_vaapi_image_map(GstVaapiImage *image) gst_vaapi_image_map(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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); return _gst_vaapi_image_map(image, NULL);
} }
@ -751,7 +558,6 @@ gst_vaapi_image_map(GstVaapiImage *image)
gboolean gboolean
_gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image) _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
{ {
GstVaapiImagePrivate * const priv = image->priv;
GstVaapiDisplay *display; GstVaapiDisplay *display;
VAStatus status; VAStatus status;
guint i; guint i;
@ -766,8 +572,8 @@ _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
GST_VAAPI_DISPLAY_LOCK(display); GST_VAAPI_DISPLAY_LOCK(display);
status = vaMapBuffer( status = vaMapBuffer(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->image.buf, image->image.buf,
(void **)&priv->image_data (void **)&image->image_data
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaMapBuffer()")) if (!vaapi_check_status(status, "vaMapBuffer()"))
@ -775,13 +581,13 @@ _gst_vaapi_image_map(GstVaapiImage *image, GstVaapiImageRaw *raw_image)
map_success: map_success:
if (raw_image) { if (raw_image) {
const VAImage * const va_image = &priv->image; const VAImage * const va_image = &image->image;
raw_image->format = priv->format; raw_image->format = image->format;
raw_image->width = va_image->width; raw_image->width = va_image->width;
raw_image->height = va_image->height; raw_image->height = va_image->height;
raw_image->num_planes = va_image->num_planes; raw_image->num_planes = va_image->num_planes;
for (i = 0; i < raw_image->num_planes; i++) { 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]; va_image->offsets[i];
raw_image->stride[i] = va_image->pitches[i]; raw_image->stride[i] = va_image->pitches[i];
} }
@ -802,7 +608,6 @@ gboolean
gst_vaapi_image_unmap(GstVaapiImage *image) gst_vaapi_image_unmap(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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); return _gst_vaapi_image_unmap(image);
} }
@ -823,13 +628,13 @@ _gst_vaapi_image_unmap(GstVaapiImage *image)
GST_VAAPI_DISPLAY_LOCK(display); GST_VAAPI_DISPLAY_LOCK(display);
status = vaUnmapBuffer( status = vaUnmapBuffer(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
image->priv->image.buf image->image.buf
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaUnmapBuffer()")) if (!vaapi_check_status(status, "vaUnmapBuffer()"))
return FALSE; return FALSE;
image->priv->image_data = NULL; image->image_data = NULL;
return TRUE; return TRUE;
} }
@ -846,10 +651,9 @@ guint
gst_vaapi_image_get_plane_count(GstVaapiImage *image) gst_vaapi_image_get_plane_count(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); 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(_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) 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(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(_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) 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(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(_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) gst_vaapi_image_get_data_size(GstVaapiImage *image)
{ {
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); 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) #if GST_CHECK_VERSION(1,0,0)
@ -1175,21 +976,17 @@ gst_vaapi_image_get_buffer(
GstVaapiRectangle *rect GstVaapiRectangle *rect
) )
{ {
GstVaapiImagePrivate *priv;
GstVaapiImageRaw dst_image, src_image; GstVaapiImageRaw dst_image, src_image;
gboolean success; gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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); g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
priv = image->priv;
if (!init_image_from_buffer(&dst_image, buffer)) if (!init_image_from_buffer(&dst_image, buffer))
return FALSE; return FALSE;
if (dst_image.format != priv->format) if (dst_image.format != image->format)
return FALSE; 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; return FALSE;
if (!_gst_vaapi_image_map(image, &src_image)) if (!_gst_vaapi_image_map(image, &src_image))
@ -1226,7 +1023,6 @@ gst_vaapi_image_get_raw(
gboolean success; gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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)) if (!_gst_vaapi_image_map(image, &src_image))
return FALSE; return FALSE;
@ -1258,21 +1054,17 @@ gst_vaapi_image_update_from_buffer(
GstVaapiRectangle *rect GstVaapiRectangle *rect
) )
{ {
GstVaapiImagePrivate *priv;
GstVaapiImageRaw dst_image, src_image; GstVaapiImageRaw dst_image, src_image;
gboolean success; gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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); g_return_val_if_fail(GST_IS_BUFFER(buffer), FALSE);
priv = image->priv;
if (!init_image_from_buffer(&src_image, buffer)) if (!init_image_from_buffer(&src_image, buffer))
return FALSE; return FALSE;
if (src_image.format != priv->format) if (src_image.format != image->format)
return FALSE; 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; return FALSE;
if (!_gst_vaapi_image_map(image, &dst_image)) if (!_gst_vaapi_image_map(image, &dst_image))
@ -1310,7 +1102,6 @@ gst_vaapi_image_update_from_raw(
gboolean success; gboolean success;
g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); 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)) if (!_gst_vaapi_image_map(image, &dst_image))
return FALSE; return FALSE;

View file

@ -30,29 +30,11 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_VAAPI_TYPE_IMAGE \
(gst_vaapi_image_get_type())
#define GST_VAAPI_IMAGE(obj) \ #define GST_VAAPI_IMAGE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \ ((GstVaapiImage *)(obj))
GST_VAAPI_TYPE_IMAGE, \
GstVaapiImage))
#define GST_VAAPI_IMAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_IMAGE, \
GstVaapiImageClass))
#define GST_VAAPI_IS_IMAGE(obj) \ #define GST_VAAPI_IS_IMAGE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_IMAGE)) ((obj) != NULL)
#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))
/** /**
* GST_VAAPI_IMAGE_FORMAT: * GST_VAAPI_IMAGE_FORMAT:
@ -79,32 +61,8 @@ G_BEGIN_DECLS
#define GST_VAAPI_IMAGE_HEIGHT(image) gst_vaapi_image_get_height(image) #define GST_VAAPI_IMAGE_HEIGHT(image) gst_vaapi_image_get_height(image)
typedef struct _GstVaapiImage GstVaapiImage; typedef struct _GstVaapiImage GstVaapiImage;
typedef struct _GstVaapiImagePrivate GstVaapiImagePrivate;
typedef struct _GstVaapiImageClass GstVaapiImageClass;
typedef struct _GstVaapiImageRaw GstVaapiImageRaw; 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: * GstVaapiImageRaw:
* *
@ -120,9 +78,6 @@ struct _GstVaapiImageRaw {
guint stride[3]; guint stride[3];
}; };
GType
gst_vaapi_image_get_type(void) G_GNUC_CONST;
GstVaapiImage * GstVaapiImage *
gst_vaapi_image_new( gst_vaapi_image_new(
GstVaapiDisplay *display, GstVaapiDisplay *display,

View file

@ -30,37 +30,41 @@
#include "gstvaapicompat.h" #include "gstvaapicompat.h"
#include "gstvaapiutils.h" #include "gstvaapiutils.h"
#include "gstvaapisubpicture.h" #include "gstvaapisubpicture.h"
#include "gstvaapi_priv.h" #include "gstvaapiobject_priv.h"
#define DEBUG 1 #define DEBUG 1
#include "gstvaapidebug.h" #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), \ * GstVaapiSubpicture:
GST_VAAPI_TYPE_SUBPICTURE, \ *
GstVaapiSubpicturePrivate)) * A VA subpicture wrapper
*/
struct _GstVaapiSubpicture {
/*< private >*/
GstVaapiObject parent_instance;
struct _GstVaapiSubpicturePrivate {
GstVaapiImage *image; GstVaapiImage *image;
guint flags; guint flags;
gfloat global_alpha; gfloat global_alpha;
}; };
enum { /**
PROP_0, * GstVaapiSubpictureClass:
*
PROP_FLAGS, * A VA subpicture wrapper class
PROP_GLOBAL_ALPHA, */
PROP_IMAGE struct _GstVaapiSubpictureClass {
/*< private >*/
GstVaapiObjectClass parent_class;
}; };
static void static void
gst_vaapi_subpicture_destroy(GstVaapiSubpicture *subpicture) gst_vaapi_subpicture_destroy(GstVaapiSubpicture *subpicture)
{ {
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
GstVaapiSubpicturePrivate * const priv = subpicture->priv;
VASubpictureID subpicture_id; VASubpictureID subpicture_id;
VAStatus status; VAStatus status;
@ -82,25 +86,21 @@ gst_vaapi_subpicture_destroy(GstVaapiSubpicture *subpicture)
} }
GST_VAAPI_OBJECT_ID(subpicture) = VA_INVALID_ID; GST_VAAPI_OBJECT_ID(subpicture) = VA_INVALID_ID;
} }
gst_vaapi_object_replace(&subpicture->image, NULL);
g_clear_object(&priv->image);
} }
static gboolean static gboolean
gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture) gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture,
GstVaapiImage *image)
{ {
GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
GstVaapiSubpicturePrivate * const priv = subpicture->priv;
VASubpictureID subpicture_id; VASubpictureID subpicture_id;
VAStatus status; VAStatus status;
if (!priv->image)
return FALSE;
GST_VAAPI_DISPLAY_LOCK(display); GST_VAAPI_DISPLAY_LOCK(display);
status = vaCreateSubpicture( status = vaCreateSubpicture(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
GST_VAAPI_OBJECT_ID(priv->image), GST_VAAPI_OBJECT_ID(image),
&subpicture_id &subpicture_id
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
@ -110,134 +110,12 @@ gst_vaapi_subpicture_create(GstVaapiSubpicture *subpicture)
GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT, GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT,
GST_VAAPI_ID_ARGS(subpicture_id)); GST_VAAPI_ID_ARGS(subpicture_id));
GST_VAAPI_OBJECT_ID(subpicture) = subpicture_id; GST_VAAPI_OBJECT_ID(subpicture) = subpicture_id;
subpicture->image = gst_vaapi_object_ref(image);
return TRUE; return TRUE;
} }
static void #define gst_vaapi_subpicture_finalize gst_vaapi_subpicture_destroy
gst_vaapi_subpicture_finalize(GObject *object) GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiSubpicture, gst_vaapi_subpicture)
{
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;
}
/** /**
* gst_vaapi_subpicture_new: * gst_vaapi_subpicture_new:
@ -252,6 +130,7 @@ gst_vaapi_subpicture_init(GstVaapiSubpicture *subpicture)
GstVaapiSubpicture * GstVaapiSubpicture *
gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags) gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags)
{ {
GstVaapiSubpicture *subpicture;
GstVaapiDisplay *display; GstVaapiDisplay *display;
GstVaapiImageFormat format; GstVaapiImageFormat format;
guint va_flags; guint va_flags;
@ -268,13 +147,18 @@ gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags)
if (flags & ~va_flags) if (flags & ~va_flags)
return NULL; return NULL;
return g_object_new(GST_VAAPI_TYPE_SUBPICTURE, subpicture = gst_vaapi_object_new(gst_vaapi_subpicture_class(), display);
"display", GST_VAAPI_OBJECT_DISPLAY(image), if (!subpicture)
"id", GST_VAAPI_ID(VA_INVALID_ID), return NULL;
"flags", flags,
"global-alpha", 1.0f, subpicture->global_alpha = 1.0f;
"image", image, if (!gst_vaapi_subpicture_set_image(subpicture, image))
NULL); 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; raw_image.stride[0] = stride;
if (!gst_vaapi_image_update_from_raw(image, &raw_image, NULL)) { if (!gst_vaapi_image_update_from_raw(image, &raw_image, NULL)) {
GST_WARNING("could not update VA image with subtitle data"); GST_WARNING("could not update VA image with subtitle data");
g_object_unref(image); gst_vaapi_object_unref(image);
return NULL; return NULL;
} }
subpicture = gst_vaapi_subpicture_new(image, flags); subpicture = gst_vaapi_subpicture_new(image, flags);
g_object_unref(image); gst_vaapi_object_unref(image);
#if GST_CHECK_VERSION(1,0,0) #if GST_CHECK_VERSION(1,0,0)
gst_video_meta_unmap(vmeta, 0, &map_info); gst_video_meta_unmap(vmeta, 0, &map_info);
#endif #endif
@ -407,7 +291,7 @@ gst_vaapi_subpicture_get_flags(GstVaapiSubpicture *subpicture)
{ {
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), 0); 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); 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 * Binds a new #GstVaapiImage to the @subpicture. The reference to the
* previous image is released and a new one is acquired on @image. * previous image is released and a new one is acquired on @image.
*
* Return value: %TRUE on success
*/ */
void gboolean
gst_vaapi_subpicture_set_image( gst_vaapi_subpicture_set_image(GstVaapiSubpicture *subpicture,
GstVaapiSubpicture *subpicture, GstVaapiImage *image)
GstVaapiImage *image
)
{ {
g_return_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture)); g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
g_return_if_fail(GST_VAAPI_IS_IMAGE(image)); g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
gst_vaapi_subpicture_destroy(subpicture); gst_vaapi_subpicture_destroy(subpicture);
return gst_vaapi_subpicture_create(subpicture, image);
subpicture->priv->image = g_object_ref(image);
gst_vaapi_subpicture_create(subpicture);
} }
/** /**
@ -462,7 +344,7 @@ gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture)
{ {
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), 1.0); 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, gst_vaapi_subpicture_set_global_alpha(GstVaapiSubpicture *subpicture,
gfloat global_alpha) gfloat global_alpha)
{ {
GstVaapiSubpicturePrivate *priv;
GstVaapiDisplay *display; GstVaapiDisplay *display;
VAStatus status; VAStatus status;
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE); g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
priv = subpicture->priv; if (!(subpicture->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA))
if (!(priv->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA))
return FALSE; return FALSE;
if (priv->global_alpha == global_alpha) if (subpicture->global_alpha == global_alpha)
return TRUE; return TRUE;
display = GST_VAAPI_OBJECT_DISPLAY(subpicture); display = GST_VAAPI_OBJECT_DISPLAY(subpicture);
@ -506,6 +385,6 @@ gst_vaapi_subpicture_set_global_alpha(GstVaapiSubpicture *subpicture,
if (!vaapi_check_status(status, "vaSetSubpictureGlobalAlpha()")) if (!vaapi_check_status(status, "vaSetSubpictureGlobalAlpha()"))
return FALSE; return FALSE;
priv->global_alpha = global_alpha; subpicture->global_alpha = global_alpha;
return TRUE; return TRUE;
} }

View file

@ -30,33 +30,13 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_VAAPI_TYPE_SUBPICTURE \
(gst_vaapi_subpicture_get_type())
#define GST_VAAPI_SUBPICTURE(obj) \ #define GST_VAAPI_SUBPICTURE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \ ((GstVaapiSubpicture *)(obj))
GST_VAAPI_TYPE_SUBPICTURE, \
GstVaapiSubpicture))
#define GST_VAAPI_SUBPICTURE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_SUBPICTURE, \
GstVaapiSubpictureClass))
#define GST_VAAPI_IS_SUBPICTURE(obj) \ #define GST_VAAPI_IS_SUBPICTURE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SUBPICTURE)) ((obj) != NULL)
#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))
typedef struct _GstVaapiSubpicture GstVaapiSubpicture; typedef struct _GstVaapiSubpicture GstVaapiSubpicture;
typedef struct _GstVaapiSubpicturePrivate GstVaapiSubpicturePrivate;
typedef struct _GstVaapiSubpictureClass GstVaapiSubpictureClass;
/** /**
* GstVaapiSubpictureFlags: * GstVaapiSubpictureFlags:
@ -73,31 +53,6 @@ typedef enum {
GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA = (1 << 1), GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA = (1 << 1),
} GstVaapiSubpictureFlags; } 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 * GstVaapiSubpicture *
gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags); gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags);
@ -116,11 +71,9 @@ gst_vaapi_subpicture_get_flags(GstVaapiSubpicture *subpicture);
GstVaapiImage * GstVaapiImage *
gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture); gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture);
void gboolean
gst_vaapi_subpicture_set_image( gst_vaapi_subpicture_set_image(GstVaapiSubpicture *subpicture,
GstVaapiSubpicture *subpicture, GstVaapiImage *image);
GstVaapiImage *image
);
gfloat gfloat
gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture); gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture);

View file

@ -30,21 +30,24 @@
#include "gstvaapiutils.h" #include "gstvaapiutils.h"
#include "gstvaapisurface.h" #include "gstvaapisurface.h"
#include "gstvaapisurface_priv.h" #include "gstvaapisurface_priv.h"
#include "gstvaapiobject_priv.h"
#include "gstvaapicontext.h" #include "gstvaapicontext.h"
#include "gstvaapiimage.h" #include "gstvaapiimage.h"
#include "gstvaapi_priv.h"
#define DEBUG 1 #define DEBUG 1
#include "gstvaapidebug.h" #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), \ * GstVaapiSurface:
GST_VAAPI_TYPE_SURFACE, \ *
GstVaapiSurfacePrivate)) * A VA surface wrapper.
*/
struct _GstVaapiSurface {
/*< private >*/
GstVaapiObject parent_instance;
struct _GstVaapiSurfacePrivate {
guint width; guint width;
guint height; guint height;
GstVaapiChromaType chroma_type; GstVaapiChromaType chroma_type;
@ -52,13 +55,14 @@ struct _GstVaapiSurfacePrivate {
GstVaapiContext *parent_context; GstVaapiContext *parent_context;
}; };
enum { /**
PROP_0, * GstVaapiSurfaceClass:
*
PROP_WIDTH, * A VA surface wrapper class.
PROP_HEIGHT, */
PROP_CHROMA_TYPE, struct _GstVaapiSurfaceClass {
PROP_PARENT_CONTEXT /*< private >*/
GstVaapiObjectClass parent_class;
}; };
static gboolean static gboolean
@ -79,18 +83,17 @@ static void
destroy_subpicture_cb(gpointer subpicture, gpointer surface) destroy_subpicture_cb(gpointer subpicture, gpointer surface)
{ {
_gst_vaapi_surface_deassociate_subpicture(surface, subpicture); _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
g_object_unref(subpicture); gst_vaapi_object_unref(subpicture);
} }
static void static void
gst_vaapi_surface_destroy_subpictures(GstVaapiSurface *surface) gst_vaapi_surface_destroy_subpictures(GstVaapiSurface *surface)
{ {
GstVaapiSurfacePrivate * const priv = surface->priv; if (surface->subpictures) {
g_ptr_array_foreach(surface->subpictures, destroy_subpicture_cb,
if (priv->subpictures) { surface);
g_ptr_array_foreach(priv->subpictures, destroy_subpicture_cb, surface); g_ptr_array_free(surface->subpictures, TRUE);
g_ptr_array_free(priv->subpictures, TRUE); surface->subpictures = NULL;
priv->subpictures = NULL;
} }
} }
@ -122,15 +125,15 @@ gst_vaapi_surface_destroy(GstVaapiSurface *surface)
} }
static gboolean 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); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
GstVaapiSurfacePrivate * const priv = surface->priv;
VASurfaceID surface_id; VASurfaceID surface_id;
VAStatus status; VAStatus status;
guint format; guint format;
switch (priv->chroma_type) { switch (chroma_type) {
case GST_VAAPI_CHROMA_TYPE_YUV420: case GST_VAAPI_CHROMA_TYPE_YUV420:
format = VA_RT_FORMAT_YUV420; format = VA_RT_FORMAT_YUV420;
break; break;
@ -141,168 +144,31 @@ gst_vaapi_surface_create(GstVaapiSurface *surface)
format = VA_RT_FORMAT_YUV444; format = VA_RT_FORMAT_YUV444;
break; break;
default: default:
GST_DEBUG("unsupported chroma-type %u\n", priv->chroma_type); GST_DEBUG("unsupported chroma-type %u\n", chroma_type);
return FALSE; return FALSE;
} }
GST_VAAPI_DISPLAY_LOCK(display); GST_VAAPI_DISPLAY_LOCK(display);
status = vaCreateSurfaces( status = vaCreateSurfaces(
GST_VAAPI_DISPLAY_VADISPLAY(display), GST_VAAPI_DISPLAY_VADISPLAY(display),
priv->width, width, height, format,
priv->height,
format,
1, &surface_id 1, &surface_id
); );
GST_VAAPI_DISPLAY_UNLOCK(display); GST_VAAPI_DISPLAY_UNLOCK(display);
if (!vaapi_check_status(status, "vaCreateSurfaces()")) if (!vaapi_check_status(status, "vaCreateSurfaces()"))
return FALSE; 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_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
GST_VAAPI_OBJECT_ID(surface) = surface_id; GST_VAAPI_OBJECT_ID(surface) = surface_id;
return TRUE; return TRUE;
} }
static void #define gst_vaapi_surface_finalize gst_vaapi_surface_destroy
gst_vaapi_surface_finalize(GObject *object) GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiSurface, gst_vaapi_surface)
{
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;
}
/** /**
* gst_vaapi_surface_new: * gst_vaapi_surface_new:
@ -324,15 +190,21 @@ gst_vaapi_surface_new(
guint height guint height
) )
{ {
GstVaapiSurface *surface;
GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type); GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type);
return g_object_new(GST_VAAPI_TYPE_SURFACE, surface = gst_vaapi_object_new(gst_vaapi_surface_class(), display);
"display", display, if (!surface)
"id", GST_VAAPI_ID(VA_INVALID_ID), return NULL;
"width", width,
"height", height, if (!gst_vaapi_surface_create(surface, chroma_type, width, height))
"chroma-type", chroma_type, goto error;
NULL); 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); 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); 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); 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 GstVaapiContext *context
) )
{ {
GstVaapiSurfacePrivate *priv;
g_return_if_fail(GST_VAAPI_IS_SURFACE(surface)); g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
priv = surface->priv; gst_vaapi_object_replace(&surface->parent_context, context);
g_clear_object(&priv->parent_context);
if (context)
priv->parent_context = g_object_ref(context);
} }
/** /**
@ -465,7 +330,7 @@ gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface)
{ {
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL); 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 * unreferenced when it's no longer needed. The image and image buffer
* data structures will be destroyed. However, the surface contents * data structures will be destroyed. However, the surface contents
* will remain unchanged until destroyed through the last call to * 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 * Return value: the newly allocated #GstVaapiImage object, or %NULL
* on failure * on failure
@ -546,7 +411,7 @@ gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
return FALSE; return FALSE;
gst_vaapi_image_get_size(image, &width, &height); 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; return FALSE;
image_id = GST_VAAPI_OBJECT_ID(image); image_id = GST_VAAPI_OBJECT_ID(image);
@ -593,7 +458,7 @@ gst_vaapi_surface_put_image(GstVaapiSurface *surface, GstVaapiImage *image)
return FALSE; return FALSE;
gst_vaapi_image_get_size(image, &width, &height); 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; return FALSE;
image_id = GST_VAAPI_OBJECT_ID(image); 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_SURFACE(surface), FALSE);
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE); g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
if (!surface->priv->subpictures) { if (!surface->subpictures) {
surface->priv->subpictures = g_ptr_array_new(); surface->subpictures = g_ptr_array_new();
if (!surface->priv->subpictures) if (!surface->subpictures)
return FALSE; return FALSE;
} }
if (g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) { if (g_ptr_array_remove_fast(surface->subpictures, subpicture)) {
success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture); success = _gst_vaapi_surface_deassociate_subpicture(surface,
g_object_unref(subpicture); subpicture);
gst_vaapi_object_unref(subpicture);
if (!success) if (!success)
return FALSE; return FALSE;
} }
@ -668,7 +534,7 @@ gst_vaapi_surface_associate_subpicture(
if (!success) if (!success)
return FALSE; 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; return TRUE;
} }
@ -712,8 +578,8 @@ _gst_vaapi_surface_associate_subpicture(
dst_rect = &dst_rect_default; dst_rect = &dst_rect_default;
dst_rect_default.x = 0; dst_rect_default.x = 0;
dst_rect_default.y = 0; dst_rect_default.y = 0;
dst_rect_default.width = surface->priv->width; dst_rect_default.width = surface->width;
dst_rect_default.height = surface->priv->height; dst_rect_default.height = surface->height;
} }
GST_VAAPI_DISPLAY_LOCK(display); 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_SURFACE(surface), FALSE);
g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE); g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
if (!surface->priv->subpictures) if (!surface->subpictures)
return TRUE; return TRUE;
/* First, check subpicture was really associated with this surface */ /* 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 " GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT " was not bound to "
"surface %" GST_VAAPI_ID_FORMAT, "surface %" GST_VAAPI_ID_FORMAT,
GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(subpicture)), 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); success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
g_object_unref(subpicture); gst_vaapi_object_unref(subpicture);
return success; return success;
} }
@ -894,11 +760,9 @@ gst_vaapi_surface_set_subpictures_from_composition(
g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE); g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
if (propagate_context) { if (propagate_context && surface->parent_context)
GstVaapiContext * const context = surface->priv->parent_context; return gst_vaapi_context_apply_composition(surface->parent_context,
if (context) composition);
return gst_vaapi_context_apply_composition(context, composition);
}
display = GST_VAAPI_OBJECT_DISPLAY(surface); display = GST_VAAPI_OBJECT_DISPLAY(surface);
if (!display) if (!display)
@ -929,10 +793,10 @@ gst_vaapi_surface_set_subpictures_from_composition(
if (!gst_vaapi_surface_associate_subpicture (surface, subpicture, if (!gst_vaapi_surface_associate_subpicture (surface, subpicture,
NULL, &sub_rect)) { NULL, &sub_rect)) {
GST_WARNING ("could not render overlay rectangle %p", rect); GST_WARNING ("could not render overlay rectangle %p", rect);
g_object_unref (subpicture); gst_vaapi_object_unref (subpicture);
return FALSE; return FALSE;
} }
g_object_unref (subpicture); gst_vaapi_object_unref (subpicture);
} }
return TRUE; return TRUE;
} }

View file

@ -112,60 +112,15 @@ typedef enum {
GST_VAAPI_COLOR_STANDARD_ITUR_BT_709 = 1 << 3, GST_VAAPI_COLOR_STANDARD_ITUR_BT_709 = 1 << 3,
} GstVaapiSurfaceRenderFlags; } GstVaapiSurfaceRenderFlags;
#define GST_VAAPI_TYPE_SURFACE \
(gst_vaapi_surface_get_type())
#define GST_VAAPI_SURFACE(obj) \ #define GST_VAAPI_SURFACE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \ ((GstVaapiSurface *)(obj))
GST_VAAPI_TYPE_SURFACE, \
GstVaapiSurface))
#define GST_VAAPI_SURFACE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_SURFACE, \
GstVaapiSurfaceClass))
#define GST_VAAPI_IS_SURFACE(obj) \ #define GST_VAAPI_IS_SURFACE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE)) ((obj) != NULL)
#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))
typedef struct _GstVaapiSurface GstVaapiSurface; typedef struct _GstVaapiSurface GstVaapiSurface;
typedef struct _GstVaapiSurfacePrivate GstVaapiSurfacePrivate;
typedef struct _GstVaapiSurfaceClass GstVaapiSurfaceClass;
typedef struct _GstVaapiSurfaceProxy GstVaapiSurfaceProxy; 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 * GstVaapiSurface *
gst_vaapi_surface_new( gst_vaapi_surface_new(
GstVaapiDisplay *display, GstVaapiDisplay *display,

View file

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

View file

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