From ba4484c6a0be22a46fbb0ce52373605c216bddc1 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sun, 26 May 2019 17:47:20 +0200 Subject: [PATCH] compositor: Skip background if transparent and obscured If the background is transparent and obscured by a pad that may or may not have alpha, we can still skip drawing it entirely AYUV 1080p ! compositor background=transparent ! fakesink - 75% faster --- gst/compositor/compositor.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/gst/compositor/compositor.c b/gst/compositor/compositor.c index fee1936..6bd6fca 100644 --- a/gst/compositor/compositor.c +++ b/gst/compositor/compositor.c @@ -314,7 +314,7 @@ clamp_rectangle (gint x, gint y, gint w, gint h, gint outer_width, /* Call this with the lock taken */ static gboolean _pad_obscures_rectangle (GstVideoAggregator * vagg, GstVideoAggregatorPad * pad, - GstVideoRectangle rect) + GstVideoRectangle rect, gboolean rect_transparent) { GstVideoRectangle pad_rect; GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad); @@ -325,8 +325,10 @@ _pad_obscures_rectangle (GstVideoAggregator * vagg, GstVideoAggregatorPad * pad, /* Can't obscure if it's transparent and if the format has an alpha component * we'd have to inspect every pixel to know if the frame is opaque, so assume - * it doesn't obscure. */ - if (cpad->alpha != 1.0 || GST_VIDEO_INFO_HAS_ALPHA (&pad->info)) + * it doesn't obscure. As a bonus, if the rectangle is fully transparent, we + * can also obscure it if we have alpha components on the pad */ + if (!rect_transparent && + (cpad->alpha != 1.0 || GST_VIDEO_INFO_HAS_ALPHA (&pad->info))) return FALSE; pad_rect.x = cpad->xpos; @@ -393,7 +395,7 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad, * higher-zorder frames */ l = g_list_find (GST_ELEMENT (vagg)->sinkpads, pad)->next; for (; l; l = l->next) { - if (_pad_obscures_rectangle (vagg, l->data, frame_rect)) { + if (_pad_obscures_rectangle (vagg, l->data, frame_rect, FALSE)) { frame_obscured = TRUE; break; } @@ -837,7 +839,7 @@ _negotiated_caps (GstAggregator * agg, GstCaps * caps) } static gboolean -_should_draw_background (GstVideoAggregator * vagg) +_should_draw_background (GstVideoAggregator * vagg, gboolean bg_transparent) { GstVideoRectangle bg_rect; gboolean draw = TRUE; @@ -849,7 +851,7 @@ _should_draw_background (GstVideoAggregator * vagg) /* Check if the background is completely obscured by a pad * TODO: Also skip if it's obscured by a combination of pads */ for (GList * l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { - if (_pad_obscures_rectangle (vagg, l->data, bg_rect)) { + if (_pad_obscures_rectangle (vagg, l->data, bg_rect, bg_transparent)) { draw = FALSE; break; } @@ -865,8 +867,11 @@ _draw_background (GstVideoAggregator * vagg, GstVideoFrame * outframe) BlendFunction composite = comp->blend; /* If one of the frames to be composited completely obscures the background, - * don't bother drawing the background at all. */ - if (!_should_draw_background (vagg)) + * don't bother drawing the background at all. We can also always use the + * 'blend' BlendFunction in that case because it only changes if we have to + * overlay on top of a transparent background. */ + if (!_should_draw_background (vagg, + comp->background == COMPOSITOR_BACKGROUND_TRANSPARENT)) return composite; switch (comp->background) { -- 2.7.4