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; GstVaapiEntrypoint entrypoint;
guint width; guint width;
guint height; guint height;
guint ref_frames;
guint is_constructed : 1; guint is_constructed : 1;
}; };
@ -74,9 +75,22 @@ enum {
PROP_PROFILE, PROP_PROFILE,
PROP_ENTRYPOINT, PROP_ENTRYPOINT,
PROP_WIDTH, 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 * static GstVaapiOverlayRectangle *
overlay_rectangle_new(GstVaapiContext *context) overlay_rectangle_new(GstVaapiContext *context)
{ {
@ -218,7 +232,7 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
GstVaapiContextPrivate * const priv = context->priv; GstVaapiContextPrivate * const priv = context->priv;
GstCaps *caps; GstCaps *caps;
GstVaapiSurface *surface; GstVaapiSurface *surface;
guint i, num_ref_frames, num_surfaces; guint i, num_surfaces;
/* Number of scratch surfaces beyond those used as reference */ /* Number of scratch surfaces beyond those used as reference */
const guint SCRATCH_SURFACES_COUNT = 4; const guint SCRATCH_SURFACES_COUNT = 4;
@ -251,11 +265,7 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
return FALSE; return FALSE;
} }
num_ref_frames = 2; num_surfaces = priv->ref_frames + SCRATCH_SURFACES_COUNT;
if (gst_vaapi_profile_get_codec(priv->profile) == GST_VAAPI_CODEC_H264)
num_ref_frames = 16;
num_surfaces = num_ref_frames + SCRATCH_SURFACES_COUNT;
gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, num_surfaces); gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, num_surfaces);
for (i = priv->surfaces->len; i < num_surfaces; i++) { for (i = priv->surfaces->len; i < num_surfaces; i++) {
@ -397,6 +407,9 @@ gst_vaapi_context_set_property(
case PROP_HEIGHT: case PROP_HEIGHT:
priv->height = g_value_get_uint(value); priv->height = g_value_get_uint(value);
break; break;
case PROP_REF_FRAMES:
priv->ref_frames = g_value_get_uint(value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break; break;
@ -427,6 +440,9 @@ gst_vaapi_context_get_property(
case PROP_HEIGHT: case PROP_HEIGHT:
g_value_set_uint(value, priv->height); g_value_set_uint(value, priv->height);
break; break;
case PROP_REF_FRAMES:
g_value_set_uint(value, priv->ref_frames);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break; break;
@ -479,6 +495,15 @@ gst_vaapi_context_class_init(GstVaapiContextClass *klass)
"The height of the decoded surfaces", "The height of the decoded surfaces",
0, G_MAXINT32, 0, 0, G_MAXINT32, 0,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); 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 static void
@ -495,6 +520,7 @@ gst_vaapi_context_init(GstVaapiContext *context)
priv->entrypoint = 0; priv->entrypoint = 0;
priv->width = 0; priv->width = 0;
priv->height = 0; priv->height = 0;
priv->ref_frames = 0;
} }
/** /**
@ -515,26 +541,51 @@ gst_vaapi_context_new(
GstVaapiDisplay *display, GstVaapiDisplay *display,
GstVaapiProfile profile, GstVaapiProfile profile,
GstVaapiEntrypoint entrypoint, GstVaapiEntrypoint entrypoint,
unsigned int width, guint width,
unsigned int height 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; GstVaapiContext *context;
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL); g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
g_return_val_if_fail(profile, NULL); g_return_val_if_fail(cip->profile, NULL);
g_return_val_if_fail(entrypoint, NULL); g_return_val_if_fail(cip->entrypoint, NULL);
g_return_val_if_fail(width > 0, NULL); g_return_val_if_fail(cip->width > 0, NULL);
g_return_val_if_fail(height > 0, NULL); g_return_val_if_fail(cip->height > 0, NULL);
context = g_object_new( context = g_object_new(
GST_VAAPI_TYPE_CONTEXT, GST_VAAPI_TYPE_CONTEXT,
"display", display, "display", display,
"id", GST_VAAPI_ID(VA_INVALID_ID), "id", GST_VAAPI_ID(VA_INVALID_ID),
"profile", profile, "profile", cip->profile,
"entrypoint", entrypoint, "entrypoint", cip->entrypoint,
"width", width, "width", cip->width,
"height", height, "height", cip->height,
"ref-frames", cip->ref_frames,
NULL NULL
); );
if (!context->priv->is_constructed) { if (!context->priv->is_constructed) {
@ -565,22 +616,48 @@ gst_vaapi_context_reset(
unsigned int width, unsigned int width,
unsigned int height 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; GstVaapiContextPrivate * const priv = context->priv;
gboolean size_changed, codec_changed; 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) { if (size_changed) {
gst_vaapi_context_destroy_surfaces(context); gst_vaapi_context_destroy_surfaces(context);
priv->width = width; priv->width = cip->width;
priv->height = height; 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) { if (codec_changed) {
gst_vaapi_context_destroy(context); gst_vaapi_context_destroy(context);
priv->profile = profile; priv->profile = cip->profile;
priv->entrypoint = entrypoint; priv->entrypoint = cip->entrypoint;
} }
if (size_changed && !gst_vaapi_context_create_surfaces(context)) if (size_changed && !gst_vaapi_context_create_surfaces(context))

View file

@ -56,9 +56,25 @@ G_BEGIN_DECLS
GstVaapiContextClass)) GstVaapiContextClass))
typedef struct _GstVaapiContext GstVaapiContext; typedef struct _GstVaapiContext GstVaapiContext;
typedef struct _GstVaapiContextInfo GstVaapiContextInfo;
typedef struct _GstVaapiContextPrivate GstVaapiContextPrivate; typedef struct _GstVaapiContextPrivate GstVaapiContextPrivate;
typedef struct _GstVaapiContextClass GstVaapiContextClass; 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: * GstVaapiContext:
* *
@ -93,15 +109,21 @@ gst_vaapi_context_new(
guint height guint height
); );
GstVaapiContext *
gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip);
gboolean gboolean
gst_vaapi_context_reset( gst_vaapi_context_reset(
GstVaapiContext *context, GstVaapiContext *context,
GstVaapiProfile profile, GstVaapiProfile profile,
GstVaapiEntrypoint entrypoint, GstVaapiEntrypoint entrypoint,
unsigned int width, guint width,
unsigned int height guint height
); );
gboolean
gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip);
GstVaapiID GstVaapiID
gst_vaapi_context_get_id(GstVaapiContext *context); gst_vaapi_context_get_id(GstVaapiContext *context);