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
This commit is contained in:
Vineeth T M 2014-11-10 16:36:35 +05:30 committed by Tim-Philipp Müller
parent 7f5aa9af04
commit 9032c12e69

View file

@ -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;
}
}