mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 02:02:26 +00:00
compositor: Skip the background when not visible
We don't need to waste time drawing the background when one of the pads completely covers the output and there's no alpha on the pad or in the video format. Speedups: I420 1080p ! compositor ! fakesink - 72% faster I420 1080p ! compositor background=black ! fakesink - 45% faster
This commit is contained in:
parent
65615a841d
commit
ba20aec539
1 changed files with 55 additions and 23 deletions
|
@ -313,13 +313,14 @@ clamp_rectangle (gint x, gint y, gint w, gint h, gint outer_width,
|
||||||
|
|
||||||
/* Call this with the lock taken */
|
/* Call this with the lock taken */
|
||||||
static gboolean
|
static gboolean
|
||||||
_pad_obscures_rectangle (GstVideoAggregatorPad * pad, GstVideoRectangle rect)
|
_pad_obscures_rectangle (GstVideoAggregator * vagg, GstVideoAggregatorPad * pad,
|
||||||
|
GstVideoRectangle rect)
|
||||||
{
|
{
|
||||||
GstVideoRectangle pad_rect;
|
GstVideoRectangle pad_rect;
|
||||||
GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
|
GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
|
||||||
|
|
||||||
/* No buffer to obscure the rectangle with */
|
/* No buffer to obscure the rectangle with */
|
||||||
if (gst_video_aggregator_pad_has_current_buffer (pad))
|
if (!gst_video_aggregator_pad_has_current_buffer (pad))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Can't obscure if it's transparent and if the format has an alpha component
|
/* Can't obscure if it's transparent and if the format has an alpha component
|
||||||
|
@ -349,7 +350,6 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
|
||||||
GstVideoAggregator * vagg, GstBuffer * buffer,
|
GstVideoAggregator * vagg, GstBuffer * buffer,
|
||||||
GstVideoFrame * prepared_frame)
|
GstVideoFrame * prepared_frame)
|
||||||
{
|
{
|
||||||
GstCompositor *comp = GST_COMPOSITOR (vagg);
|
|
||||||
GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
|
GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
|
||||||
gint width, height;
|
gint width, height;
|
||||||
gboolean frame_obscured = FALSE;
|
gboolean frame_obscured = FALSE;
|
||||||
|
@ -393,7 +393,7 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
|
||||||
* higher-zorder frames */
|
* higher-zorder frames */
|
||||||
l = g_list_find (GST_ELEMENT (vagg)->sinkpads, pad)->next;
|
l = g_list_find (GST_ELEMENT (vagg)->sinkpads, pad)->next;
|
||||||
for (; l; l = l->next) {
|
for (; l; l = l->next) {
|
||||||
if (_pad_obscures_rectangle (l->data, frame_rect)) {
|
if (_pad_obscures_rectangle (vagg, l->data, frame_rect)) {
|
||||||
frame_obscured = TRUE;
|
frame_obscured = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,6 @@ static void
|
||||||
gst_compositor_pad_create_conversion_info (GstVideoAggregatorConvertPad * pad,
|
gst_compositor_pad_create_conversion_info (GstVideoAggregatorConvertPad * pad,
|
||||||
GstVideoAggregator * vagg, GstVideoInfo * conversion_info)
|
GstVideoAggregator * vagg, GstVideoInfo * conversion_info)
|
||||||
{
|
{
|
||||||
GstCompositor *comp = GST_COMPOSITOR (vagg);
|
|
||||||
GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
|
GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
|
||||||
|
@ -837,33 +836,48 @@ _negotiated_caps (GstAggregator * agg, GstCaps * caps)
|
||||||
return GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps);
|
return GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static gboolean
|
||||||
gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
|
_should_draw_background (GstVideoAggregator * vagg)
|
||||||
{
|
{
|
||||||
GList *l;
|
GstVideoRectangle bg_rect;
|
||||||
GstCompositor *self = GST_COMPOSITOR (vagg);
|
gboolean draw = TRUE;
|
||||||
BlendFunction composite;
|
bg_rect.x = bg_rect.y = 0;
|
||||||
GstVideoFrame out_frame, *outframe;
|
|
||||||
|
|
||||||
if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf, GST_MAP_WRITE)) {
|
GST_OBJECT_LOCK (vagg);
|
||||||
GST_WARNING_OBJECT (vagg, "Could not map output buffer");
|
bg_rect.w = GST_VIDEO_INFO_WIDTH (&vagg->info);
|
||||||
return GST_FLOW_ERROR;
|
bg_rect.h = GST_VIDEO_INFO_HEIGHT (&vagg->info);
|
||||||
|
/* 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)) {
|
||||||
|
draw = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
GST_OBJECT_UNLOCK (vagg);
|
||||||
|
return draw;
|
||||||
|
}
|
||||||
|
|
||||||
outframe = &out_frame;
|
static BlendFunction
|
||||||
/* default to blending */
|
_draw_background (GstVideoAggregator * vagg, GstVideoFrame * outframe)
|
||||||
composite = self->blend;
|
{
|
||||||
/* TODO: If the frames to be composited completely obscure the background,
|
GstCompositor *comp = GST_COMPOSITOR (vagg);
|
||||||
|
BlendFunction composite = comp->blend;
|
||||||
|
|
||||||
|
/* If one of the frames to be composited completely obscures the background,
|
||||||
* don't bother drawing the background at all. */
|
* don't bother drawing the background at all. */
|
||||||
switch (self->background) {
|
if (!_should_draw_background (vagg))
|
||||||
|
return composite;
|
||||||
|
|
||||||
|
switch (comp->background) {
|
||||||
case COMPOSITOR_BACKGROUND_CHECKER:
|
case COMPOSITOR_BACKGROUND_CHECKER:
|
||||||
self->fill_checker (outframe);
|
comp->fill_checker (outframe);
|
||||||
break;
|
break;
|
||||||
case COMPOSITOR_BACKGROUND_BLACK:
|
case COMPOSITOR_BACKGROUND_BLACK:
|
||||||
self->fill_color (outframe, 16, 128, 128);
|
comp->fill_color (outframe, 16, 128, 128);
|
||||||
break;
|
break;
|
||||||
case COMPOSITOR_BACKGROUND_WHITE:
|
case COMPOSITOR_BACKGROUND_WHITE:
|
||||||
self->fill_color (outframe, 240, 128, 128);
|
comp->fill_color (outframe, 240, 128, 128);
|
||||||
break;
|
break;
|
||||||
case COMPOSITOR_BACKGROUND_TRANSPARENT:
|
case COMPOSITOR_BACKGROUND_TRANSPARENT:
|
||||||
{
|
{
|
||||||
|
@ -885,11 +899,29 @@ gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* use overlay to keep background transparent */
|
/* use overlay to keep background transparent */
|
||||||
composite = self->overlay;
|
composite = comp->overlay;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
BlendFunction composite;
|
||||||
|
GstVideoFrame out_frame, *outframe;
|
||||||
|
|
||||||
|
if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf, GST_MAP_WRITE)) {
|
||||||
|
GST_WARNING_OBJECT (vagg, "Could not map output buffer");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
outframe = &out_frame;
|
||||||
|
composite = _draw_background (vagg, outframe);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (vagg);
|
GST_OBJECT_LOCK (vagg);
|
||||||
for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
|
for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
|
||||||
GstVideoAggregatorPad *pad = l->data;
|
GstVideoAggregatorPad *pad = l->data;
|
||||||
|
|
Loading…
Reference in a new issue