From 7824f4cf52dbc6221022edec2ed7402de72c993e Mon Sep 17 00:00:00 2001 From: Vineeth TM Date: Fri, 5 Jun 2015 08:58:03 +0900 Subject: simplevideomarkdetect: fix detect of videomark partially or fully outside video In case of the videomark being partially or fully outside, an error was bein thrown saying, mark width is more than video width. And when the width, offset properties are set to maximum it resulted in crash. Instead of throwing error, added logic to detect the mark in case of partial visibility or dont show the mark when it is outside. https://bugzilla.gnome.org/show_bug.cgi?id=743908 --- gst/videosignal/gstsimplevideomarkdetect.c | 87 +++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 14 deletions(-) (limited to 'gst/videosignal') diff --git a/gst/videosignal/gstsimplevideomarkdetect.c b/gst/videosignal/gstsimplevideomarkdetect.c index c04d90b82..d5f093f04 100644 --- a/gst/videosignal/gstsimplevideomarkdetect.c +++ b/gst/videosignal/gstsimplevideomarkdetect.c @@ -436,15 +436,27 @@ gst_video_detect_calc_brightness (GstSimpleVideoMarkDetect * return sum / (255.0 * width * height); } +static gint +calculate_pw (gint pw, gint x, gint width) +{ + if (x < 0) + pw += x; + else if ((x + pw) > width) + pw = width - x; + + return pw; +} + static void gst_video_detect_yuv (GstSimpleVideoMarkDetect * simplevideomarkdetect, GstVideoFrame * frame) { gdouble brightness; gint i, pw, ph, row_stride, pixel_stride; - gint width, height, req_width, req_height; + gint width, height, offset_calc, x, y; guint8 *d; guint64 pattern_data; + gint total_pattern; width = frame->info.width; height = frame->info.height; @@ -454,22 +466,44 @@ gst_video_detect_yuv (GstSimpleVideoMarkDetect * simplevideomarkdetect, row_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0); - req_width = - (simplevideomarkdetect->pattern_count + - simplevideomarkdetect->pattern_data_count) * pw + - simplevideomarkdetect->left_offset; - req_height = simplevideomarkdetect->bottom_offset + ph; - if (req_width > width || req_height > height) { - goto no_pattern; - } - d = GST_VIDEO_FRAME_COMP_DATA (frame, 0); /* move to start of bottom left, adjust for offsets */ - d += row_stride * (height - ph - simplevideomarkdetect->bottom_offset) + + offset_calc = + row_stride * (height - ph - simplevideomarkdetect->bottom_offset) + pixel_stride * simplevideomarkdetect->left_offset; + x = simplevideomarkdetect->left_offset; + y = height - ph - simplevideomarkdetect->bottom_offset; + + total_pattern = + simplevideomarkdetect->pattern_count + + simplevideomarkdetect->pattern_data_count; + /* If x and y offset values are outside the video, no need to analyze */ + if ((x + (pw * total_pattern)) < 0 || x > width || (y + height) < 0 + || y > height) { + GST_ERROR_OBJECT (simplevideomarkdetect, + "simplevideomarkdetect pattern is outside the video. Not Analyzing."); + return; + } + + /* Offset calculation less than 0, then reset to 0 */ + if (offset_calc < 0) + offset_calc = 0; + /* Y position of mark is negative or pattern exceeds the video height, + then recalculate pattern height for partial display */ + if (y < 0) + ph += y; + else if ((y + ph) > height) + ph = height - y; + /* If pattern height is less than 0, need not analyze anything */ + if (ph < 0) + return; + + /* move to start of bottom left */ + d += offset_calc; - /* analyse the bottom left pixels */ + /* analyze the bottom left pixels */ for (i = 0; i < simplevideomarkdetect->pattern_count; i++) { + gint draw_pw; /* calc brightness of width * height box */ brightness = gst_video_detect_calc_brightness (simplevideomarkdetect, d, pw, ph, @@ -493,8 +527,19 @@ gst_video_detect_yuv (GstSimpleVideoMarkDetect * simplevideomarkdetect, goto no_pattern; } + /* X position of mark is negative or pattern exceeds the video width, + then recalculate pattern width for partial display */ + draw_pw = calculate_pw (pw, x, width); + /* If pattern width is less than 0, continue with the next pattern */ + if (draw_pw < 0) + continue; + /* move to i-th pattern */ - d += pixel_stride * pw; + d += pixel_stride * draw_pw; + x += draw_pw; + + if ((x + (pw * (total_pattern - i - 1))) < 0 || x >= width) + break; } GST_DEBUG_OBJECT (simplevideomarkdetect, "found pattern"); @@ -502,6 +547,7 @@ gst_video_detect_yuv (GstSimpleVideoMarkDetect * simplevideomarkdetect, /* get the data of the pattern */ for (i = 0; i < simplevideomarkdetect->pattern_data_count; i++) { + gint draw_pw; /* calc brightness of width * height box */ brightness = gst_video_detect_calc_brightness (simplevideomarkdetect, d, pw, ph, @@ -510,8 +556,21 @@ gst_video_detect_yuv (GstSimpleVideoMarkDetect * simplevideomarkdetect, pattern_data <<= 1; if (brightness > simplevideomarkdetect->pattern_center) pattern_data |= 1; + + /* X position of mark is negative or pattern exceeds the video width, + then recalculate pattern width for partial display */ + draw_pw = calculate_pw (pw, x, width); + /* If pattern width is less than 0, continue with the next pattern */ + if (draw_pw < 0) + continue; + /* move to i-th pattern data */ - d += pixel_stride * pw; + d += pixel_stride * draw_pw; + x += draw_pw; + + if ((x + (pw * (simplevideomarkdetect->pattern_data_count - i - 1))) < 0 + || x >= width) + break; } GST_DEBUG_OBJECT (simplevideomarkdetect, "have data %" G_GUINT64_FORMAT, -- cgit v1.2.1