summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2011-12-14 14:35:13 +0100
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2011-12-14 14:35:13 +0100
commit17538a340e2e72e1770d40b563d6a0d89421b1f8 (patch)
tree1405f63745699eedfecc5ee628192291bcfd3bd6
parent0634dc768de6e6e9109f2e782253061ba41a807e (diff)
context: make it possible to apply composition globally.
-rw-r--r--docs/reference/libs/libs-sections.txt1
-rw-r--r--gst-libs/gst/vaapi/gstvaapicontext.c206
-rw-r--r--gst-libs/gst/vaapi/gstvaapicontext.h7
3 files changed, 214 insertions, 0 deletions
diff --git a/docs/reference/libs/libs-sections.txt b/docs/reference/libs/libs-sections.txt
index 48a928eb..751ba641 100644
--- a/docs/reference/libs/libs-sections.txt
+++ b/docs/reference/libs/libs-sections.txt
@@ -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
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c
index 63a8c74c..29654cd3 100644
--- a/gst-libs/gst/vaapi/gstvaapicontext.c
+++ b/gst-libs/gst/vaapi/gstvaapicontext.c
@@ -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);
@@ -130,6 +202,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)
{
GstVaapiContextPrivate * const priv = context->priv;
@@ -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;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.h b/gst-libs/gst/vaapi/gstvaapicontext.h
index d1b12608..457570c0 100644
--- a/gst-libs/gst/vaapi/gstvaapicontext.h
+++ b/gst-libs/gst/vaapi/gstvaapicontext.h
@@ -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 */