}
}
+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 GstFlowReturn
gst_video_mark_yuv (GstSimpleVideoMark * simplevideomark, GstVideoFrame * frame)
{
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_shift;
guint8 color;
+ gint total_pattern;
width = frame->info.width;
height = frame->info.height;
row_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
- req_width =
- (simplevideomark->pattern_count +
- simplevideomark->pattern_data_count) * pw + simplevideomark->left_offset;
- req_height = simplevideomark->bottom_offset + ph;
- if (req_width > width || req_height > height) {
- GST_ELEMENT_ERROR (simplevideomark, STREAM, WRONG_TYPE, (NULL),
- ("simplevideomark pattern doesn't fit video, need at least %ix%i (stream has %ix%i)",
- req_width, req_height, width, height));
- return GST_FLOW_ERROR;
- }
-
d = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
- /* move to start of bottom left */
- d += row_stride * (height - ph - simplevideomark->bottom_offset) +
+ 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)
+ 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, pw, ph, row_stride,
+ gst_video_mark_draw_box (simplevideomark, d, draw_pw, ph, row_stride,
pixel_stride, color);
/* 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)
+ return GST_FLOW_OK;
}
pattern_shift =
/* 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;
- gst_video_mark_draw_box (simplevideomark, d, pw, ph, row_stride,
+ /* 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 * pw;
+ 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;