mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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
This commit is contained in:
parent
15de547760
commit
7824f4cf52
1 changed files with 73 additions and 14 deletions
|
@ -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;
|
||||
|
||||
/* analyse the bottom left pixels */
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
|
|
Loading…
Reference in a new issue