onvifoverlay: render polygons when present

This commit is contained in:
Mathieu Duponchelle 2022-06-03 18:30:15 +02:00 committed by Sebastian Dröge
parent 5dac064a49
commit 20d2a7d05b

View file

@ -21,6 +21,12 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
const DEFAULT_FONT_DESC: &str = "monospace 12"; const DEFAULT_FONT_DESC: &str = "monospace 12";
#[derive(Debug)]
struct Point {
x: u32,
y: u32,
}
// Shape description in cairo coordinates (0, 0) is top left // Shape description in cairo coordinates (0, 0) is top left
#[derive(Debug)] #[derive(Debug)]
struct Shape { struct Shape {
@ -28,6 +34,7 @@ struct Shape {
y: u32, y: u32,
width: u32, width: u32,
height: u32, height: u32,
points: Vec<Point>,
// Optional text rendered from top left of rectangle // Optional text rendered from top left of rectangle
tag: Option<String>, tag: Option<String>,
} }
@ -146,6 +153,7 @@ impl OnvifOverlay {
state: &mut State, state: &mut State,
width: u32, width: u32,
height: u32, height: u32,
points: &[Point],
tag: Option<&str>, tag: Option<&str>,
) -> Option<(gst::Buffer, u32, u32)> { ) -> Option<(gst::Buffer, u32, u32)> {
let mut text_width = 0; let mut text_width = 0;
@ -206,9 +214,10 @@ impl OnvifOverlay {
cr.set_source_rgba(0.0, 0.0, 0.0, 0.0); cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
cr.paint().ok()?; cr.paint().ok()?;
if points.is_empty() {
// Render bounding box
cr.save().ok()?; cr.save().ok()?;
// Now render the rectangle
cr.move_to(line_width, line_width); cr.move_to(line_width, line_width);
cr.line_to(line_width, height as f64 - line_width); cr.line_to(line_width, height as f64 - line_width);
cr.line_to(width as f64 - line_width, height as f64 - line_width); cr.line_to(width as f64 - line_width, height as f64 - line_width);
@ -219,6 +228,23 @@ impl OnvifOverlay {
let _ = cr.stroke(); let _ = cr.stroke();
cr.restore().ok()?; cr.restore().ok()?;
} else {
// Render polygon
cr.save().ok()?;
cr.move_to(points[0].x as f64, points[0].y as f64);
for point in &points[1..] {
cr.line_to(point.x as f64, point.y as f64)
}
cr.close_path();
cr.set_source_rgba(1., 0., 0., 1.);
cr.set_line_width(line_width);
let _ = cr.stroke();
cr.restore().ok()?;
}
// Finally render the text, if any // Finally render the text, if any
if let Some(layout) = layout { if let Some(layout) = layout {
@ -324,6 +350,7 @@ impl OnvifOverlay {
state, state,
shape.width, shape.width,
shape.height, shape.height,
&shape.points,
shape.tag.as_deref(), shape.tag.as_deref(),
) { ) {
Some(ret) => ret, Some(ret) => ret,
@ -534,11 +561,63 @@ impl OnvifOverlay {
let x2 = width / 2 + ((right * (width / 2) as f64) as i32); let x2 = width / 2 + ((right * (width / 2) as f64) as i32);
let y2 = height / 2 - ((bottom * (height / 2) as f64) as i32); let y2 = height / 2 - ((bottom * (height / 2) as f64) as i32);
let w = (x2 - x1) as u32;
let h = (y2 - y1) as u32;
let mut points = vec![];
if let Some(polygon) =
shape.get_child("Polygon", "http://www.onvif.org/ver10/schema")
{
for point in polygon.children() {
if point.is("Point", "http://www.onvif.org/ver10/schema") {
let px: f64 = match point
.attr("x")
.and_then(|val| val.parse().ok())
{
Some(val) => val,
None => {
gst::warning!(
CAT,
obj: element,
"Point with no x attribute"
);
continue;
}
};
let py: f64 = match point
.attr("y")
.and_then(|val| val.parse().ok())
{
Some(val) => val,
None => {
gst::warning!(
CAT,
obj: element,
"Point with no y attribute"
);
continue;
}
};
let px = width / 2 + ((px * (width / 2) as f64) as i32);
let px = (px as u32).saturating_sub(x1 as u32).min(w);
let py = height / 2 - ((py * (height / 2) as f64) as i32);
let py = (py as u32).saturating_sub(y1 as u32).min(h);
points.push(Point { x: px, y: py });
}
}
}
shapes.push(Shape { shapes.push(Shape {
x: x1 as u32, x: x1 as u32,
y: y1 as u32, y: y1 as u32,
width: (x2 - x1) as u32, width: w,
height: (y2 - y1) as u32, height: h,
points,
tag, tag,
}); });
} }