From 9032c12e690665a9b1f29ad014073261e7e6e799 Mon Sep 17 00:00:00 2001 From: Vineeth T M Date: Mon, 10 Nov 2014 16:36:35 +0530 Subject: [PATCH] video-blend: fix blending of rectangles partially or fully outside of the video In case of overlay being completely or partially outside the video frame, the offset calculations are not right, which resulted in the overlay not being displayed as expected, or crashes due to invalid memory access. When the overlay rectangle is completely outside, we need not render the overlay at all. For partial display of overlay rectangles, src_yoff was not being calculated, hence it was always clipping the bottom half of the overlay, By calculating the src_yoff, now the overlay is clipped properly. https://bugzilla.gnome.org/show_bug.cgi?id=739281 --- gst-libs/gst/video/video-blend.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/gst-libs/gst/video/video-blend.c b/gst-libs/gst/video/video-blend.c index a9433b1..dd17402 100644 --- a/gst-libs/gst/video/video-blend.c +++ b/gst-libs/gst/video/video-blend.c @@ -263,8 +263,8 @@ gboolean gst_video_blend (GstVideoFrame * dest, GstVideoFrame * src, gint x, gint y, gfloat global_alpha) { - guint i, j, global_alpha_val, src_width, src_height, dest_width, dest_height; - gint xoff; + gint i, j, global_alpha_val, src_width, src_height, dest_width, dest_height; + gint src_xoff = 0, src_yoff = 0; guint8 *tmpdestline = NULL, *tmpsrcline = NULL; gboolean src_premultiplied_alpha, dest_premultiplied_alpha; void (*matrix) (guint8 * tmpline, guint width); @@ -292,6 +292,12 @@ gst_video_blend (GstVideoFrame * dest, ensure_debug_category (); + /* In case overlay is completely outside the video, dont render */ + if (x + src_width <= 0 || y + src_height <= 0 + || x >= dest_width || y >= dest_height) { + goto nothing_to_do; + } + dinfo = gst_video_format_get_info (GST_VIDEO_FRAME_FORMAT (dest)); sinfo = gst_video_format_get_info (GST_VIDEO_FRAME_FORMAT (src)); @@ -326,17 +332,18 @@ gst_video_blend (GstVideoFrame * dest, } } - xoff = 0; - - /* adjust src pointers for negative sizes */ + /* If we're here we know that the overlay image fully or + * partially overlaps with the video frame */ + /* adjust src image for negative offsets */ if (x < 0) { - src_width -= -x; + src_xoff = -x; + src_width -= src_xoff; x = 0; - xoff = -x; } if (y < 0) { - src_height -= -y; + src_yoff = -y; + src_height -= src_yoff; y = 0; } @@ -348,12 +355,12 @@ gst_video_blend (GstVideoFrame * dest, src_height = dest_height - y; /* Mainloop doing the needed conversions, and blending */ - for (i = y; i < y + src_height; i++) { + for (i = y; i < y + src_height; i++, src_yoff++) { dinfo->unpack_func (dinfo, 0, tmpdestline, dest->data, dest->info.stride, 0, i, dest_width); sinfo->unpack_func (sinfo, 0, tmpsrcline, src->data, src->info.stride, - xoff, i - y, src_width - xoff); + src_xoff, src_yoff, src_width); matrix (tmpsrcline, src_width); @@ -428,4 +435,10 @@ unpack_format_not_supported: gst_video_format_to_string (dinfo->unpack_format)); return FALSE; } +nothing_to_do: + { + GST_LOG + ("Overlay completely outside the video surface, hence not rendering"); + return TRUE; + } } -- 2.7.4