context: make it possible to apply composition globally.

This commit is contained in:
Gwenole Beauchesne 2011-12-14 14:35:13 +01:00
parent 0634dc768d
commit 17538a340e
3 changed files with 214 additions and 0 deletions

View file

@ -439,6 +439,7 @@ gst_vaapi_context_get_surface
gst_vaapi_context_get_surface_count
gst_vaapi_context_put_surface
gst_vaapi_context_find_surface_by_id
gst_vaapi_context_apply_composition
<SUBSECTION Standard>
GST_VAAPI_CONTEXT
GST_VAAPI_IS_CONTEXT

View file

@ -31,6 +31,8 @@
#include "gstvaapisurface.h"
#include "gstvaapisurface_priv.h"
#include "gstvaapisurfacepool.h"
#include "gstvaapiimage.h"
#include "gstvaapisubpicture.h"
#include "gstvaapiutils.h"
#include "gstvaapi_priv.h"
@ -44,11 +46,20 @@ G_DEFINE_TYPE(GstVaapiContext, gst_vaapi_context, GST_VAAPI_TYPE_OBJECT);
GST_VAAPI_TYPE_CONTEXT, \
GstVaapiContextPrivate))
typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
struct _GstVaapiOverlayRectangle {
GstVaapiContext *context;
GstVaapiSubpicture *subpicture;
GstVaapiRectangle rect;
guint seq_num;
};
/* XXX: optimize for the effective number of reference frames */
struct _GstVaapiContextPrivate {
VAConfigID config_id;
GPtrArray *surfaces;
GstVaapiVideoPool *surfaces_pool;
GPtrArray *overlay;
GstVaapiProfile profile;
GstVaapiEntrypoint entrypoint;
guint width;
@ -65,6 +76,65 @@ enum {
PROP_HEIGHT
};
static GstVaapiOverlayRectangle *
overlay_rectangle_new(GstVaapiContext *context)
{
GstVaapiOverlayRectangle *overlay;
overlay = g_slice_new0(GstVaapiOverlayRectangle);
if (!overlay)
return NULL;
overlay->context = context;
return overlay;
}
static void
overlay_rectangle_destroy(GstVaapiOverlayRectangle *overlay)
{
GstVaapiContextPrivate *priv;
guint i;
if (!overlay)
return;
priv = overlay->context->priv;
if (overlay->subpicture) {
if (priv->surfaces) {
GstVaapiSubpicture * const subpicture = overlay->subpicture;
for (i = 0; i < priv->surfaces->len; i++) {
GstVaapiSurface * const surface =
g_ptr_array_index(priv->surfaces, i);
gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
}
}
g_object_unref(overlay->subpicture);
overlay->subpicture = NULL;
}
g_slice_free(GstVaapiOverlayRectangle, overlay);
}
static void
destroy_overlay_cb(gpointer data, gpointer user_data)
{
GstVaapiOverlayRectangle * const overlay = data;
overlay_rectangle_destroy(overlay);
}
static void
gst_vaapi_context_destroy_overlay(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
if (!priv->overlay)
return;
g_ptr_array_foreach(priv->overlay, destroy_overlay_cb, priv);
g_ptr_array_free(priv->overlay, TRUE);
priv->overlay = NULL;
}
static void
unref_surface_cb(gpointer data, gpointer user_data)
{
@ -79,6 +149,8 @@ gst_vaapi_context_destroy_surfaces(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
gst_vaapi_context_destroy_overlay(context);
if (priv->surfaces) {
g_ptr_array_foreach(priv->surfaces, unref_surface_cb, NULL);
g_ptr_array_free(priv->surfaces, TRUE);
@ -129,6 +201,19 @@ gst_vaapi_context_destroy(GstVaapiContext *context)
}
}
static gboolean
gst_vaapi_context_create_overlay(GstVaapiContext *context)
{
GstVaapiContextPrivate * const priv = context->priv;
if (!priv->overlay) {
priv->overlay = g_ptr_array_new();
if (!priv->overlay)
return FALSE;
}
return TRUE;
}
static gboolean
gst_vaapi_context_create_surfaces(GstVaapiContext *context)
{
@ -140,6 +225,9 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
/* Number of scratch surfaces beyond those used as reference */
const guint SCRATCH_SURFACES_COUNT = 4;
if (!gst_vaapi_context_create_overlay(context))
return FALSE;
if (!priv->surfaces) {
priv->surfaces = g_ptr_array_new();
if (!priv->surfaces)
@ -405,6 +493,7 @@ gst_vaapi_context_init(GstVaapiContext *context)
priv->config_id = VA_INVALID_ID;
priv->surfaces = NULL;
priv->surfaces_pool = NULL;
priv->overlay = NULL;
priv->profile = 0;
priv->entrypoint = 0;
priv->width = 0;
@ -684,3 +773,120 @@ gst_vaapi_context_find_surface_by_id(GstVaapiContext *context, GstVaapiID id)
}
return NULL;
}
/* Check if composition changed */
static gboolean
gst_vaapi_context_composition_changed(
GstVaapiContext *context,
GstVideoOverlayComposition *composition
)
{
GstVaapiContextPrivate * const priv = context->priv;
GstVaapiOverlayRectangle *overlay;
GstVideoOverlayRectangle *rect;
guint i, n_rectangles;
if (!priv->overlay || !composition)
return TRUE;
n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
if (priv->overlay->len != n_rectangles)
return TRUE;
for (i = 0; i < n_rectangles; i++) {
rect = gst_video_overlay_composition_get_rectangle(composition, i);
g_return_val_if_fail(rect, TRUE);
overlay = g_ptr_array_index(priv->overlay, i);
g_return_val_if_fail(overlay, TRUE);
if (overlay->seq_num != gst_video_overlay_rectangle_get_seqnum(rect))
return TRUE;
}
return FALSE;
}
/**
* gst_vaapi_context_apply_composition:
* @context: a #GstVaapiContext
* @composition: a #GstVideoOverlayComposition
*
* Applies video composition planes to all surfaces bound to @context.
* This helper function resets any additional subpictures the user may
* have associated himself. A %NULL @composition will also clear all
* the existing subpictures.
*
* Return value: %TRUE if all composition planes could be applied,
* %FALSE otherwise
*/
gboolean
gst_vaapi_context_apply_composition(
GstVaapiContext *context,
GstVideoOverlayComposition *composition
)
{
GstVaapiContextPrivate *priv;
GstVideoOverlayRectangle *rect;
GstVaapiOverlayRectangle *overlay = NULL;
GstVaapiDisplay *display;
guint i, j, n_rectangles;
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
priv = context->priv;
if (!priv->surfaces)
return FALSE;
display = GST_VAAPI_OBJECT_DISPLAY(context);
if (!display)
return FALSE;
if (!gst_vaapi_context_composition_changed(context, composition))
return TRUE;
gst_vaapi_context_destroy_overlay(context);
if (!composition)
return TRUE;
if (!gst_vaapi_context_create_overlay(context))
return FALSE;
n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
for (i = 0; i < n_rectangles; i++) {
rect = gst_video_overlay_composition_get_rectangle(composition, i);
overlay = overlay_rectangle_new(context);
if (!overlay) {
GST_WARNING("could not create VA overlay rectangle");
return FALSE;
}
overlay->seq_num = gst_video_overlay_rectangle_get_seqnum(rect);
overlay->subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle(
display,
rect
);
if (!overlay->subpicture) {
overlay_rectangle_destroy(overlay);
return FALSE;
}
gst_video_overlay_rectangle_get_render_rectangle(
rect,
(gint *)&overlay->rect.x,
(gint *)&overlay->rect.y,
&overlay->rect.width,
&overlay->rect.height
);
for (j = 0; j < priv->surfaces->len; j++) {
GstVaapiSurface * const surface =
g_ptr_array_index(priv->surfaces, j);
if (!gst_vaapi_surface_associate_subpicture(surface,
overlay->subpicture, NULL, &overlay->rect)) {
GST_WARNING("could not render overlay rectangle %p", rect);
overlay_rectangle_destroy(overlay);
return FALSE;
}
}
g_ptr_array_add(priv->overlay, overlay);
}
return TRUE;
}

View file

@ -26,6 +26,7 @@
#include <gst/vaapi/gstvaapiprofile.h>
#include <gst/vaapi/gstvaapidisplay.h>
#include <gst/vaapi/gstvaapisurface.h>
#include <gst/video/video-overlay-composition.h>
G_BEGIN_DECLS
@ -131,6 +132,12 @@ gst_vaapi_context_put_surface(GstVaapiContext *context, GstVaapiSurface *surface
GstVaapiSurface *
gst_vaapi_context_find_surface_by_id(GstVaapiContext *context, GstVaapiID id);
gboolean
gst_vaapi_context_apply_composition(
GstVaapiContext *context,
GstVideoOverlayComposition *composition
);
G_END_DECLS
#endif /* GST_VAAPI_CONTEXT_H */