context: allow number of reference frames to be set.

Make it possible to specify the maximum number of references to use within
a single VA context. This helps reducing GPU memory allocations to the useful
number of references to be used.
This commit is contained in:
Gwenole Beauchesne 2012-09-10 18:15:02 +02:00
parent d895e17db8
commit 4ca1f3f47c
2 changed files with 124 additions and 25 deletions

View file

@ -65,6 +65,7 @@ struct _GstVaapiContextPrivate {
GstVaapiEntrypoint entrypoint;
guint width;
guint height;
guint ref_frames;
guint is_constructed : 1;
};
@ -74,9 +75,22 @@ enum {
PROP_PROFILE,
PROP_ENTRYPOINT,
PROP_WIDTH,
PROP_HEIGHT
PROP_HEIGHT,
PROP_REF_FRAMES
};
static guint
get_max_ref_frames(GstVaapiProfile profile)
{
guint ref_frames;
switch (gst_vaapi_profile_get_codec(profile)) {
case GST_VAAPI_CODEC_H264: ref_frames = 16; break;
default: ref_frames = 2; break;
}
return ref_frames;
}
static GstVaapiOverlayRectangle *
overlay_rectangle_new(GstVaapiContext *context)
{
@ -218,7 +232,7 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
GstVaapiContextPrivate * const priv = context->priv;
GstCaps *caps;
GstVaapiSurface *surface;
guint i, num_ref_frames, num_surfaces;
guint i, num_surfaces;
/* Number of scratch surfaces beyond those used as reference */
const guint SCRATCH_SURFACES_COUNT = 4;
@ -251,11 +265,7 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
return FALSE;
}
num_ref_frames = 2;
if (gst_vaapi_profile_get_codec(priv->profile) == GST_VAAPI_CODEC_H264)
num_ref_frames = 16;
num_surfaces = num_ref_frames + SCRATCH_SURFACES_COUNT;
num_surfaces = priv->ref_frames + SCRATCH_SURFACES_COUNT;
gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, num_surfaces);
for (i = priv->surfaces->len; i < num_surfaces; i++) {
@ -397,6 +407,9 @@ gst_vaapi_context_set_property(
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;
@ -427,6 +440,9 @@ gst_vaapi_context_get_property(
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;
@ -479,6 +495,15 @@ gst_vaapi_context_class_init(GstVaapiContextClass *klass)
"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
@ -495,6 +520,7 @@ gst_vaapi_context_init(GstVaapiContext *context)
priv->entrypoint = 0;
priv->width = 0;
priv->height = 0;
priv->ref_frames = 0;
}
/**
@ -515,26 +541,51 @@ gst_vaapi_context_new(
GstVaapiDisplay *display,
GstVaapiProfile profile,
GstVaapiEntrypoint entrypoint,
unsigned int width,
unsigned int height
guint width,
guint height
)
{
GstVaapiContextInfo info;
info.profile = profile;
info.entrypoint = entrypoint;
info.width = width;
info.height = height;
info.ref_frames = get_max_ref_frames(profile);
return gst_vaapi_context_new_full(display, &info);
}
/**
* gst_vaapi_context_new_full:
* @display: a #GstVaapiDisplay
* @cip: a pointer to the #GstVaapiContextInfo
*
* Creates a new #GstVaapiContext with the configuration specified by
* @cip, thus including profile, entry-point, encoded size and maximum
* number of reference frames reported by the bitstream.
*
* Return value: the newly allocated #GstVaapiContext object
*/
GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip)
{
GstVaapiContext *context;
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
g_return_val_if_fail(profile, NULL);
g_return_val_if_fail(entrypoint, NULL);
g_return_val_if_fail(width > 0, NULL);
g_return_val_if_fail(height > 0, 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", profile,
"entrypoint", entrypoint,
"width", width,
"height", height,
"profile", cip->profile,
"entrypoint", cip->entrypoint,
"width", cip->width,
"height", cip->height,
"ref-frames", cip->ref_frames,
NULL
);
if (!context->priv->is_constructed) {
@ -565,22 +616,48 @@ gst_vaapi_context_reset(
unsigned int width,
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;
return gst_vaapi_context_reset_full(context, &info);
}
/**
* gst_vaapi_context_reset_full:
* @context: a #GstVaapiContext
* @cip: a pointer to the new #GstVaapiContextInfo details
*
* Resets @context to the configuration specified by @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)
{
GstVaapiContextPrivate * const priv = context->priv;
gboolean size_changed, codec_changed;
size_changed = priv->width != width || priv->height != height;
size_changed = priv->width != cip->width || priv->height != cip->height;
if (size_changed) {
gst_vaapi_context_destroy_surfaces(context);
priv->width = width;
priv->height = height;
priv->width = cip->width;
priv->height = cip->height;
}
codec_changed = priv->profile != profile || priv->entrypoint != entrypoint;
codec_changed = priv->profile != cip->profile || priv->entrypoint != cip->entrypoint;
if (codec_changed) {
gst_vaapi_context_destroy(context);
priv->profile = profile;
priv->entrypoint = entrypoint;
priv->profile = cip->profile;
priv->entrypoint = cip->entrypoint;
}
if (size_changed && !gst_vaapi_context_create_surfaces(context))

View file

@ -56,9 +56,25 @@ G_BEGIN_DECLS
GstVaapiContextClass))
typedef struct _GstVaapiContext GstVaapiContext;
typedef struct _GstVaapiContextInfo GstVaapiContextInfo;
typedef struct _GstVaapiContextPrivate GstVaapiContextPrivate;
typedef struct _GstVaapiContextClass GstVaapiContextClass;
/**
* GstVaapiContextInfo:
*
* Structure holding VA context info like encoded size, decoder
* profile and entry-point to use, and maximum number of reference
* frames reported by the bitstream.
*/
struct _GstVaapiContextInfo {
GstVaapiProfile profile;
GstVaapiEntrypoint entrypoint;
guint width;
guint height;
guint ref_frames;
};
/**
* GstVaapiContext:
*
@ -93,15 +109,21 @@ gst_vaapi_context_new(
guint height
);
GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip);
gboolean
gst_vaapi_context_reset(
GstVaapiContext *context,
GstVaapiProfile profile,
GstVaapiEntrypoint entrypoint,
unsigned int width,
unsigned int height
guint width,
guint height
);
gboolean
gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip);
GstVaapiID
gst_vaapi_context_get_id(GstVaapiContext *context);