diff options
Diffstat (limited to 'gst-libs/gst/vaapi/gstvaapicontext.c')
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapicontext.c | 403 |
1 files changed, 5 insertions, 398 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c index a4cc1fb8..8651e90a 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.c +++ b/gst-libs/gst/vaapi/gstvaapicontext.c @@ -30,6 +30,7 @@ #include "sysdeps.h" #include "gstvaapicompat.h" #include "gstvaapicontext.h" +#include "gstvaapicontext_overlay.h" #include "gstvaapidisplay_priv.h" #include "gstvaapiobject_priv.h" #include "gstvaapisurface.h" @@ -37,324 +38,11 @@ #include "gstvaapisurfacepool.h" #include "gstvaapisurfaceproxy.h" #include "gstvaapivideopool_priv.h" -#include "gstvaapiimage.h" -#include "gstvaapisubpicture.h" #include "gstvaapiutils.h" #define DEBUG 1 #include "gstvaapidebug.h" -typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle; -struct _GstVaapiOverlayRectangle -{ - GstVaapiContext *context; - GstVaapiSubpicture *subpicture; - GstVaapiRectangle render_rect; - guint seq_num; - guint layer_id; - GstBuffer *rect_buffer; - GstVideoOverlayRectangle *rect; - guint is_associated:1; -}; - -static inline void -gst_video_overlay_rectangle_replace (GstVideoOverlayRectangle ** old_rect_ptr, - GstVideoOverlayRectangle * new_rect) -{ - gst_mini_object_replace ((GstMiniObject **) old_rect_ptr, - GST_MINI_OBJECT_CAST (new_rect)); -} - -#define overlay_rectangle_ref(overlay) \ - gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(overlay)) - -#define overlay_rectangle_unref(overlay) \ - gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(overlay)) - -#define overlay_rectangle_replace(old_overlay_ptr, new_overlay) \ - gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_overlay_ptr), \ - (GstVaapiMiniObject *)(new_overlay)) - -static void overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay); - -static gboolean -overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay); - -static gboolean -overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay); - -static inline const GstVaapiMiniObjectClass * -overlay_rectangle_class (void) -{ - static const GstVaapiMiniObjectClass GstVaapiOverlayRectangleClass = { - sizeof (GstVaapiOverlayRectangle), - (GDestroyNotify) overlay_rectangle_finalize - }; - return &GstVaapiOverlayRectangleClass; -} - -static GstVaapiOverlayRectangle * -overlay_rectangle_new (GstVideoOverlayRectangle * rect, - GstVaapiContext * context, guint layer_id) -{ - GstVaapiOverlayRectangle *overlay; - GstVaapiRectangle *render_rect; - guint width, height, flags; - gint x, y; - - overlay = (GstVaapiOverlayRectangle *) - gst_vaapi_mini_object_new0 (overlay_rectangle_class ()); - if (!overlay) - return NULL; - - overlay->context = context; - overlay->seq_num = gst_video_overlay_rectangle_get_seqnum (rect); - overlay->layer_id = layer_id; - overlay->rect = gst_video_overlay_rectangle_ref (rect); - - flags = gst_video_overlay_rectangle_get_flags (rect); - gst_buffer_replace (&overlay->rect_buffer, - gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags)); - if (!overlay->rect_buffer) - goto error; - - overlay->subpicture = - gst_vaapi_subpicture_new_from_overlay_rectangle (GST_VAAPI_OBJECT_DISPLAY - (context), rect); - if (!overlay->subpicture) - goto error; - - gst_video_overlay_rectangle_get_render_rectangle (rect, - &x, &y, &width, &height); - render_rect = &overlay->render_rect; - render_rect->x = x; - render_rect->y = y; - render_rect->width = width; - render_rect->height = height; - return overlay; - -error: - overlay_rectangle_unref (overlay); - return NULL; -} - -static void -overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay) -{ - gst_buffer_replace (&overlay->rect_buffer, NULL); - gst_video_overlay_rectangle_unref (overlay->rect); - - if (overlay->subpicture) { - overlay_rectangle_deassociate (overlay); - gst_vaapi_object_unref (overlay->subpicture); - overlay->subpicture = NULL; - } -} - -static gboolean -overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay) -{ - GstVaapiSubpicture *const subpicture = overlay->subpicture; - GPtrArray *const surfaces = overlay->context->surfaces; - guint i, n_associated; - - if (overlay->is_associated) - return TRUE; - - n_associated = 0; - for (i = 0; i < surfaces->len; i++) { - GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i); - if (gst_vaapi_surface_associate_subpicture (surface, subpicture, - NULL, &overlay->render_rect)) - n_associated++; - } - - overlay->is_associated = TRUE; - return n_associated == surfaces->len; -} - -static gboolean -overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay) -{ - GstVaapiSubpicture *const subpicture = overlay->subpicture; - GPtrArray *const surfaces = overlay->context->surfaces; - guint i, n_associated; - - if (!overlay->is_associated) - return TRUE; - - n_associated = surfaces->len; - for (i = 0; i < surfaces->len; i++) { - GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i); - if (gst_vaapi_surface_deassociate_subpicture (surface, subpicture)) - n_associated--; - } - - overlay->is_associated = FALSE; - return n_associated == 0; -} - -static gboolean -overlay_rectangle_changed_pixels (GstVaapiOverlayRectangle * overlay, - GstVideoOverlayRectangle * rect) -{ - guint flags; - GstBuffer *buffer; - - if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum (rect)) - return FALSE; - - flags = - to_GstVideoOverlayFormatFlags (gst_vaapi_subpicture_get_flags - (overlay->subpicture)); - - buffer = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags); - if (!buffer) - return FALSE; -#if GST_CHECK_VERSION(1,0,0) - { - const guint n_blocks = gst_buffer_n_memory (buffer); - gsize ofs; - guint i; - - if (buffer == overlay->rect_buffer) - return TRUE; - - if (n_blocks != gst_buffer_n_memory (overlay->rect_buffer)) - return FALSE; - - for (i = 0; i < n_blocks; i++) { - GstMemory *const mem1 = gst_buffer_peek_memory (buffer, i); - GstMemory *const mem2 = gst_buffer_peek_memory (overlay->rect_buffer, i); - if (!gst_memory_is_span (mem1, mem2, &ofs)) - return FALSE; - } - } -#else - if (GST_BUFFER_DATA (overlay->rect_buffer) != GST_BUFFER_DATA (buffer)) - return FALSE; -#endif - return TRUE; -} - -static gboolean -overlay_rectangle_changed_render_rect (GstVaapiOverlayRectangle * overlay, - GstVideoOverlayRectangle * rect) -{ - GstVaapiRectangle *const render_rect = &overlay->render_rect; - guint width, height; - gint x, y; - - gst_video_overlay_rectangle_get_render_rectangle (rect, - &x, &y, &width, &height); - - if (x == render_rect->x && - y == render_rect->y && - width == render_rect->width && height == render_rect->height) - return FALSE; - - render_rect->x = x; - render_rect->y = y; - render_rect->width = width; - render_rect->height = height; - return TRUE; -} - -static inline gboolean -overlay_rectangle_update_global_alpha (GstVaapiOverlayRectangle * overlay, - GstVideoOverlayRectangle * rect) -{ -#ifdef HAVE_GST_VIDEO_OVERLAY_HWCAPS - const guint flags = gst_video_overlay_rectangle_get_flags (rect); - if (!(flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA)) - return TRUE; -#endif - return gst_vaapi_subpicture_set_global_alpha (overlay->subpicture, - gst_video_overlay_rectangle_get_global_alpha (rect)); -} - -static gboolean -overlay_rectangle_update (GstVaapiOverlayRectangle * overlay, - GstVideoOverlayRectangle * rect, gboolean * reassociate_ptr) -{ - if (overlay_rectangle_changed_pixels (overlay, rect)) - return FALSE; - if (overlay_rectangle_changed_render_rect (overlay, rect)) - *reassociate_ptr = TRUE; - if (!overlay_rectangle_update_global_alpha (overlay, rect)) - return FALSE; - gst_video_overlay_rectangle_replace (&overlay->rect, rect); - return TRUE; -} - -static inline GPtrArray * -overlay_new (void) -{ - return g_ptr_array_new_with_free_func ( - (GDestroyNotify) gst_vaapi_mini_object_unref); -} - -static void -overlay_destroy (GPtrArray ** overlay_ptr) -{ - GPtrArray *const overlay = *overlay_ptr; - - if (!overlay) - return; - g_ptr_array_unref (overlay); - *overlay_ptr = NULL; -} - -static void -overlay_clear (GPtrArray * overlay) -{ - if (overlay && overlay->len > 0) - g_ptr_array_remove_range (overlay, 0, overlay->len); -} - -static GstVaapiOverlayRectangle * -overlay_lookup (GPtrArray * overlays, GstVideoOverlayRectangle * rect) -{ - guint i; - - for (i = 0; i < overlays->len; i++) { - GstVaapiOverlayRectangle *const overlay = g_ptr_array_index (overlays, i); - - if (overlay->rect == rect) - return overlay; - } - return NULL; -} - -static gboolean -overlay_reassociate (GPtrArray * overlays) -{ - guint i; - - for (i = 0; i < overlays->len; i++) - overlay_rectangle_deassociate (g_ptr_array_index (overlays, i)); - - for (i = 0; i < overlays->len; i++) { - if (!overlay_rectangle_associate (g_ptr_array_index (overlays, i))) - return FALSE; - } - return TRUE; -} - -static void -context_clear_overlay (GstVaapiContext * context) -{ - overlay_clear (context->overlays[0]); - overlay_clear (context->overlays[1]); - context->overlay_id = 0; -} - -static inline void -context_destroy_overlay (GstVaapiContext * context) -{ - context_clear_overlay (context); -} - static void unref_surface_cb (GstVaapiSurface * surface) { @@ -365,7 +53,7 @@ unref_surface_cb (GstVaapiSurface * surface) static void context_destroy_surfaces (GstVaapiContext * context) { - context_destroy_overlay (context); + gst_vaapi_context_overlay_reset (context); if (context->surfaces) { g_ptr_array_unref (context->surfaces); @@ -406,16 +94,6 @@ context_destroy (GstVaapiContext * context) } static gboolean -context_create_overlay (GstVaapiContext * context) -{ - if (!context->overlays[0] || !context->overlays[1]) - return FALSE; - - context_clear_overlay (context); - return TRUE; -} - -static gboolean context_create_surfaces (GstVaapiContext * context) { const GstVaapiContextInfo *const cip = &context->info; @@ -426,7 +104,7 @@ context_create_surfaces (GstVaapiContext * context) /* Number of scratch surfaces beyond those used as reference */ const guint SCRATCH_SURFACES_COUNT = 4; - if (!context_create_overlay (context)) + if (!gst_vaapi_context_overlay_reset (context)) return FALSE; num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT; @@ -556,17 +234,15 @@ gst_vaapi_context_init (GstVaapiContext * context, { context->info = *cip; context->va_config = VA_INVALID_ID; - context->overlays[0] = overlay_new (); - context->overlays[1] = overlay_new (); + gst_vaapi_context_overlay_init (context); } static void gst_vaapi_context_finalize (GstVaapiContext * context) { - overlay_destroy (&context->overlays[0]); - overlay_destroy (&context->overlays[1]); context_destroy (context); context_destroy_surfaces (context); + gst_vaapi_context_overlay_finalize (context); } GST_VAAPI_OBJECT_DEFINE_CLASS (GstVaapiContext, gst_vaapi_context); @@ -719,75 +395,6 @@ gst_vaapi_context_get_surface_count (GstVaapiContext * context) } /** - * 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) -{ - GPtrArray *curr_overlay, *next_overlay; - guint i, n_rectangles; - gboolean reassociate = FALSE; - - g_return_val_if_fail (context != NULL, FALSE); - - if (!context->surfaces) - return FALSE; - - if (!composition) { - context_clear_overlay (context); - return TRUE; - } - - curr_overlay = context->overlays[context->overlay_id]; - next_overlay = context->overlays[context->overlay_id ^ 1]; - overlay_clear (next_overlay); - - n_rectangles = gst_video_overlay_composition_n_rectangles (composition); - for (i = 0; i < n_rectangles; i++) { - GstVideoOverlayRectangle *const rect = - gst_video_overlay_composition_get_rectangle (composition, i); - GstVaapiOverlayRectangle *overlay; - - overlay = overlay_lookup (curr_overlay, rect); - if (overlay && overlay_rectangle_update (overlay, rect, &reassociate)) { - overlay_rectangle_ref (overlay); - if (overlay->layer_id != i) - reassociate = TRUE; - } else { - overlay = overlay_rectangle_new (rect, context, i); - if (!overlay) { - GST_WARNING ("could not create VA overlay rectangle"); - goto error; - } - reassociate = TRUE; - } - g_ptr_array_add (next_overlay, overlay); - } - - overlay_clear (curr_overlay); - context->overlay_id ^= 1; - - if (reassociate && !overlay_reassociate (next_overlay)) - return FALSE; - return TRUE; - -error: - context_clear_overlay (context); - return FALSE; -} - -/** * gst_vaapi_context_get_attribute: * @context: a #GstVaapiContext * @type: a VA config attribute type |