From 4ca1f3f47c44db2347adf5606f058250179f38c7 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Mon, 10 Sep 2012 18:15:02 +0200 Subject: [PATCH] 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. --- gst-libs/gst/vaapi/gstvaapicontext.c | 123 ++++++++++++++++++++++----- gst-libs/gst/vaapi/gstvaapicontext.h | 26 +++++- 2 files changed, 124 insertions(+), 25 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c index 5030a5299a..1862e38080 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.c +++ b/gst-libs/gst/vaapi/gstvaapicontext.c @@ -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)) diff --git a/gst-libs/gst/vaapi/gstvaapicontext.h b/gst-libs/gst/vaapi/gstvaapicontext.h index 1187c400d1..cffbd7ebb0 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.h +++ b/gst-libs/gst/vaapi/gstvaapicontext.h @@ -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);