mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-21 05:26:23 +00:00
compositor: Copy frames as-is when possible
The blend functions for alpha formats need to do more work than just doing a memcpy, so we can do a memcpy when we know that a blend is not actually needed. 1080p AYUV ! compositor background=transparent ! fakesink - 56% faster Specifically, when we don't draw the background and the first pad we draw completely covers the output frame, we can just copy it as-is. The rest of the pads (if any) will get composited on top normally.
This commit is contained in:
parent
eaade96409
commit
abd80b6561
1 changed files with 34 additions and 10 deletions
|
@ -861,19 +861,20 @@ _should_draw_background (GstVideoAggregator * vagg, gboolean bg_transparent)
|
||||||
return draw;
|
return draw;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlendFunction
|
static gboolean
|
||||||
_draw_background (GstVideoAggregator * vagg, GstVideoFrame * outframe)
|
_draw_background (GstVideoAggregator * vagg, GstVideoFrame * outframe,
|
||||||
|
BlendFunction * composite)
|
||||||
{
|
{
|
||||||
GstCompositor *comp = GST_COMPOSITOR (vagg);
|
GstCompositor *comp = GST_COMPOSITOR (vagg);
|
||||||
BlendFunction composite = comp->blend;
|
|
||||||
|
|
||||||
|
*composite = comp->blend;
|
||||||
/* If one of the frames to be composited completely obscures the background,
|
/* If one of the frames to be composited completely obscures the background,
|
||||||
* don't bother drawing the background at all. We can also always use the
|
* 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
|
* 'blend' BlendFunction in that case because it only changes if we have to
|
||||||
* overlay on top of a transparent background. */
|
* overlay on top of a transparent background. */
|
||||||
if (!_should_draw_background (vagg,
|
if (!_should_draw_background (vagg,
|
||||||
comp->background == COMPOSITOR_BACKGROUND_TRANSPARENT))
|
comp->background == COMPOSITOR_BACKGROUND_TRANSPARENT))
|
||||||
return composite;
|
return FALSE;
|
||||||
|
|
||||||
switch (comp->background) {
|
switch (comp->background) {
|
||||||
case COMPOSITOR_BACKGROUND_CHECKER:
|
case COMPOSITOR_BACKGROUND_CHECKER:
|
||||||
|
@ -905,12 +906,24 @@ _draw_background (GstVideoAggregator * vagg, GstVideoFrame * outframe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* use overlay to keep background transparent */
|
/* use overlay to keep background transparent */
|
||||||
composite = comp->overlay;
|
*composite = comp->overlay;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return composite;
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
frames_can_copy (const GstVideoFrame * frame1, const GstVideoFrame * frame2)
|
||||||
|
{
|
||||||
|
if (GST_VIDEO_FRAME_FORMAT (frame1) != GST_VIDEO_FRAME_FORMAT (frame2))
|
||||||
|
return FALSE;
|
||||||
|
if (GST_VIDEO_FRAME_HEIGHT (frame1) != GST_VIDEO_FRAME_HEIGHT (frame2))
|
||||||
|
return FALSE;
|
||||||
|
if (GST_VIDEO_FRAME_WIDTH (frame1) != GST_VIDEO_FRAME_WIDTH (frame2))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -919,6 +932,8 @@ gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
|
||||||
GList *l;
|
GList *l;
|
||||||
BlendFunction composite;
|
BlendFunction composite;
|
||||||
GstVideoFrame out_frame, *outframe;
|
GstVideoFrame out_frame, *outframe;
|
||||||
|
gboolean drew_background;
|
||||||
|
guint drawn_pads = 0;
|
||||||
|
|
||||||
if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf, GST_MAP_WRITE)) {
|
if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf, GST_MAP_WRITE)) {
|
||||||
GST_WARNING_OBJECT (vagg, "Could not map output buffer");
|
GST_WARNING_OBJECT (vagg, "Could not map output buffer");
|
||||||
|
@ -926,7 +941,7 @@ gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
outframe = &out_frame;
|
outframe = &out_frame;
|
||||||
composite = _draw_background (vagg, outframe);
|
drew_background = _draw_background (vagg, outframe, &composite);
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -952,9 +967,18 @@ gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prepared_frame != NULL) {
|
if (prepared_frame != NULL) {
|
||||||
composite (prepared_frame,
|
/* If this is the first pad we're drawing, and we didn't draw the
|
||||||
compo_pad->xpos,
|
* background, and @prepared_frame has the same format, height, and width
|
||||||
compo_pad->ypos, compo_pad->alpha, outframe, blend_mode);
|
* as @outframe, then we can just copy it as-is. Subsequent pads (if any)
|
||||||
|
* will be composited on top of it. */
|
||||||
|
if (drawn_pads == 0 && !drew_background &&
|
||||||
|
frames_can_copy (prepared_frame, outframe))
|
||||||
|
gst_video_frame_copy (outframe, prepared_frame);
|
||||||
|
else
|
||||||
|
composite (prepared_frame,
|
||||||
|
compo_pad->xpos,
|
||||||
|
compo_pad->ypos, compo_pad->alpha, outframe, blend_mode);
|
||||||
|
drawn_pads++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GST_OBJECT_UNLOCK (vagg);
|
GST_OBJECT_UNLOCK (vagg);
|
||||||
|
|
Loading…
Reference in a new issue