static void gst_video_detect_yuv (GstSimpleVideoMarkDetect * simplevideomarkdetect, GstVideoFrame * frame) { gdouble brightness; gint i, pw, ph, row_stride, pixel_stride; gint width, height, offset_calc, x, y; guint8 *d; guint64 pattern_data; gint total_pattern; width = frame->info.width; height = frame->info.height; pw = simplevideomarkdetect->pattern_width; ph = simplevideomarkdetect->pattern_height; row_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0); d = GST_VIDEO_FRAME_COMP_DATA (frame, 0); /* move to start of bottom left, adjust for offsets */ 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; /* 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, row_stride, pixel_stride); GST_DEBUG_OBJECT (simplevideomarkdetect, "brightness %f", brightness); if (i & 1) { /* odd pixels must be white, all pixels darker than the center + * sensitivity are considered wrong. */ if (brightness < (simplevideomarkdetect->pattern_center + simplevideomarkdetect->pattern_sensitivity)) goto no_pattern; } else { /* even pixels must be black, pixels lighter than the center - sensitivity * are considered wrong. */ if (brightness > (simplevideomarkdetect->pattern_center - simplevideomarkdetect->pattern_sensitivity)) 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 * draw_pw; x += draw_pw; if ((x + (pw * (total_pattern - i - 1))) < 0 || x >= width) break; } GST_DEBUG_OBJECT (simplevideomarkdetect, "found pattern"); pattern_data = 0; /* 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, row_stride, pixel_stride); /* update pattern, we just use the center to decide between black and white. */ 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 * 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, pattern_data); simplevideomarkdetect->in_pattern = TRUE; gst_video_detect_post_message (simplevideomarkdetect, frame->buffer, pattern_data); return; no_pattern: { GST_DEBUG_OBJECT (simplevideomarkdetect, "no pattern found"); if (simplevideomarkdetect->in_pattern) { simplevideomarkdetect->in_pattern = FALSE; gst_video_detect_post_message (simplevideomarkdetect, frame->buffer, 0); } return; } }
static GstFlowReturn gst_video_mark_yuv (GstSimpleVideoMark * simplevideomark, GstVideoFrame * frame) { gint i, pw, ph, row_stride, pixel_stride; gint width, height, offset_calc, x, y; guint8 *d; guint64 pattern_shift; guint8 color; gint total_pattern; width = frame->info.width; height = frame->info.height; pw = simplevideomark->pattern_width; ph = simplevideomark->pattern_height; row_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0); d = GST_VIDEO_FRAME_COMP_DATA (frame, 0); offset_calc = row_stride * (height - ph - simplevideomark->bottom_offset) + pixel_stride * simplevideomark->left_offset; x = simplevideomark->left_offset; y = height - ph - simplevideomark->bottom_offset; total_pattern = simplevideomark->pattern_count + simplevideomark->pattern_data_count; /* If x and y offset values are outside the video, no need to draw */ if ((x + (pw * total_pattern)) < 0 || x > width || (y + height) < 0 || y > height) { GST_ERROR_OBJECT (simplevideomark, "simplevideomark pattern is outside the video. Not drawing."); return GST_FLOW_OK; } /* 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 draw anything */ if (ph < 0) return GST_FLOW_OK; /* move to start of bottom left */ d += offset_calc; /* draw the bottom left pixels */ for (i = 0; i < simplevideomark->pattern_count; i++) { gint draw_pw; if (i & 1) /* odd pixels must be white */ color = 255; else color = 0; /* 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; /* draw box of width * height */ gst_video_mark_draw_box (simplevideomark, d, draw_pw, ph, row_stride, pixel_stride, color); /* move to i-th pattern */ d += pixel_stride * draw_pw; x += draw_pw; if ((x + (pw * (total_pattern - i - 1))) < 0 || x >= width) return GST_FLOW_OK; } pattern_shift = G_GUINT64_CONSTANT (1) << (simplevideomark->pattern_data_count - 1); /* get the data of the pattern */ for (i = 0; i < simplevideomark->pattern_data_count; i++) { gint draw_pw; if (simplevideomark->pattern_data & pattern_shift) color = 255; else color = 0; /* 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; gst_video_mark_draw_box (simplevideomark, d, draw_pw, ph, row_stride, pixel_stride, color); pattern_shift >>= 1; /* move to i-th pattern data */ d += pixel_stride * draw_pw; x += draw_pw; if ((x + (pw * (simplevideomark->pattern_data_count - i - 1))) < 0 || x >= width) return GST_FLOW_OK; } return GST_FLOW_OK; }